Branch "uflash" imported from GoogleCode.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1986 Regents of the University of California.
|
||||
* All rights reserved. The Berkeley software License Agreement
|
||||
* specifies the terms and conditions for redistribution.
|
||||
*
|
||||
* @(#)gpio.h 1.4 (2.11BSD GTE) 1997/3/28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ioctl definitions
|
||||
*/
|
||||
#ifndef _UFLASH_H
|
||||
#define _UFLASH_H
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#define UFLASH_LOAD (IOC_VOID | 1 << 16 | 'u'<<8) /* configure as input */
|
||||
|
||||
#define UFLASH_MAGIC 0x24
|
||||
|
||||
struct uflash_head
|
||||
{
|
||||
unsigned magic;
|
||||
char name[31];
|
||||
};
|
||||
|
||||
#define UFLASH_HEADPTR ((struct uflash_head*)0x7d030000)
|
||||
|
||||
typedef void (*_startp)(int, char **, char **);
|
||||
#define UFLASH_STARTPTR ((_startp)0x7d030030)
|
||||
|
||||
#ifdef KERNEL
|
||||
int uflash_open (dev_t dev, int flag, int mode);
|
||||
int uflash_close (dev_t dev, int flag, int mode);
|
||||
int uflash_read (dev_t dev, struct uio *uio, int flag);
|
||||
int uflash_write (dev_t dev, struct uio *uio, int flag);
|
||||
int uflash_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
# Programs that live in subdirectories, and have makefiles of their own.
|
||||
#
|
||||
SUBDIR = baremetal dip duinomite explorer16 max32 max32-eth maximite meb \
|
||||
pinguino-micro starter-kit ubw32 ubw32-uart ubw32-uart-sdramswap usbboot
|
||||
pinguino-micro starter-kit ubw32 ubw32-uart usbboot
|
||||
|
||||
default:
|
||||
|
||||
|
||||
+1
-1
@@ -62,8 +62,8 @@ int adc_open(dev_t dev, int flag, int mode)
|
||||
AD1CON2 = 0b0000010000111100;
|
||||
AD1CON3 = 0b0000011100000111;
|
||||
AD1CON1 = 0b1000000011100110;
|
||||
IPC(6) = 0b00000100000000000000000000000000;
|
||||
IECSET(1) = 1<<(PIC32_IRQ_AD1-32);
|
||||
IPC(6) = 0x04040404;
|
||||
}
|
||||
nactive++;
|
||||
return 0;
|
||||
|
||||
@@ -37,7 +37,13 @@ DEFS += -DLED_AUX_PORT=TRISG -DLED_AUX_PIN=13
|
||||
DRIVER_GPIO = yes
|
||||
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
DRIVER_ADC = yes
|
||||
|
||||
DRIVER_OC = yes
|
||||
DRIVER_GLCD = yes
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "clist.h"
|
||||
#include "tty.h"
|
||||
#include "systm.h"
|
||||
#include "errno.h"
|
||||
|
||||
#ifdef GPIO_ENABLED
|
||||
#include "gpio.h"
|
||||
@@ -35,6 +36,10 @@
|
||||
#include "oc.h"
|
||||
#endif
|
||||
|
||||
#ifdef UFLASH_ENABLED
|
||||
#include "uflash.h"
|
||||
#endif
|
||||
|
||||
#ifndef SWAPDEV
|
||||
#define swopen nulldev
|
||||
#define swstrategy nostrategy
|
||||
@@ -50,6 +55,14 @@ nulldev ()
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifndef UFLASH_ENABLED
|
||||
static int
|
||||
faildev ()
|
||||
{
|
||||
return (EPERM);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
norw (dev, uio, flag)
|
||||
dev_t dev;
|
||||
@@ -179,6 +192,19 @@ const struct cdevsw cdevsw[] = {
|
||||
nostrategy, },
|
||||
#endif
|
||||
|
||||
// UFLASH = 12
|
||||
#ifdef UFLASH_ENABLED
|
||||
{
|
||||
uflash_open, uflash_close, uflash_read, uflash_write,
|
||||
uflash_ioctl, nulldev, 0, seltrue,
|
||||
nostrategy, },
|
||||
#else
|
||||
{
|
||||
faildev, nulldev, norw, norw,
|
||||
noioctl, nulldev, 0, seltrue,
|
||||
nostrategy, },
|
||||
#endif
|
||||
|
||||
};
|
||||
const int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -3,6 +3,11 @@ ifeq ($(DRIVER_GPIO),yes)
|
||||
DEFS += -DGPIO_ENABLED
|
||||
endif
|
||||
|
||||
ifeq ($(DRIVER_UFLASH),yes)
|
||||
KERNOBJ += uflash.o
|
||||
DEFS += -DUFLASH_ENABLED
|
||||
endif
|
||||
|
||||
ifeq ($(DRIVER_POWER),yes)
|
||||
KERNOBJ += power_control.o
|
||||
POWER_LED_PORT ?= TRISG
|
||||
|
||||
@@ -51,6 +51,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -53,6 +53,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -39,6 +39,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -30,10 +30,13 @@ DEFS += -DSD_CS0_PORT=TRISG -DSD_CS0_PIN=9
|
||||
DEFS += -DLED_KERNEL_PORT=TRISE -DLED_KERNEL_PIN=5
|
||||
|
||||
# Include or exclude drivers
|
||||
DRIVER_GPIO = yes # General Purpose I/O
|
||||
DRIVER_ADC = yes # Basic ADC interface
|
||||
DRIVER_SPI = yes # Generic SPI interface
|
||||
DRIVER_OC = yes # Output Compare driver
|
||||
DRIVER_GPIO = yes
|
||||
DRIVER_ADC = yes
|
||||
DRIVER_SPI = yes
|
||||
DRIVER_OC = yes
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
|
||||
DEPFLAGS = -MT $@ -MD -MP -MF .deps/$*.dep
|
||||
CFLAGS = -O $(DEFS) $(DEPFLAGS)
|
||||
|
||||
+5
-30
@@ -134,17 +134,9 @@ startup()
|
||||
mips_write_c0_register (C0_CAUSE, 0, CA_IV);
|
||||
|
||||
/* Setup memory. */
|
||||
BMXPUPBA = 512 << 10; /* Kernel Flash memory size */
|
||||
|
||||
#ifdef KERNEL_EXECUTABLE_RAM
|
||||
extern void _keram_start(), _keram_end();
|
||||
unsigned keram_size_k = ((char*)&_keram_end-(char*)&_keram_start)/1024;
|
||||
BMXDKPBA = (32-keram_size_k) << 10; /* Kernel RAM size */
|
||||
BMXDUDBA = BMXDKPBA+(keram_size_k<<10); /* 2k executable RAM in kernel */
|
||||
#else
|
||||
BMXPUPBA = 192 << 10; /* Kernel Flash memory size */
|
||||
BMXDKPBA = 32 << 10; /* Kernel RAM size */
|
||||
BMXDUDBA = BMXDKPBA; /* Zero executable RAM in kernel */
|
||||
#endif
|
||||
BMXDUDBA = BMXDKPBA; /* No executable RAM in kernel */
|
||||
BMXDUPBA = BMXDUDBA; /* All user RAM is executable */
|
||||
|
||||
/*
|
||||
@@ -159,7 +151,9 @@ startup()
|
||||
IPC(8) = IPC(9) = IPC(10) = IPC(11) =
|
||||
IPC(12) =
|
||||
PIC32_IPC_IP0(1) | PIC32_IPC_IP1(1) |
|
||||
PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1);
|
||||
PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) |
|
||||
PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) |
|
||||
PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ;
|
||||
|
||||
/*
|
||||
* Setup wait states.
|
||||
@@ -243,25 +237,6 @@ startup()
|
||||
/*printf ("copy %08x from (%08x) to (%08x)\n", *src, src, dest);*/
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
#ifdef KERNEL_EXECUTABLE_RAM
|
||||
/* Copy code that must run out of ram (due to timing restrictions)
|
||||
* from flash to the executable section of kernel ram.
|
||||
* This was added to support swap on sdram */
|
||||
|
||||
extern void _ramfunc_image_begin();
|
||||
extern void _ramfunc_begin();
|
||||
extern void _ramfunc_end();
|
||||
|
||||
unsigned *src1 = (unsigned*) &_ramfunc_image_begin;
|
||||
unsigned *dest1 = (unsigned*)&_ramfunc_begin;
|
||||
unsigned *limit1 = (unsigned*)&_ramfunc_end;
|
||||
/*printf ("copy from (%08x) to (%08x)\n", src1, dest1);*/
|
||||
while (dest1 < limit1) {
|
||||
*dest1++ = *src1++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Setup UART registers.
|
||||
|
||||
@@ -63,12 +63,7 @@
|
||||
#define DATA_SIZE (128*1024)
|
||||
|
||||
#define KERNEL_FLASH_SIZE (192*1024)
|
||||
|
||||
#ifdef KERNEL_EXECUTABLE_RAM
|
||||
#define KERNEL_DATA_SIZE (30*1024)
|
||||
#else
|
||||
#define KERNEL_DATA_SIZE (32*1024)
|
||||
#endif
|
||||
|
||||
#define KERNEL_FLASH_START 0x9d000000
|
||||
#define USER_FLASH_START (KERNEL_FLASH_START + KERNEL_FLASH_SIZE)
|
||||
@@ -76,13 +71,7 @@
|
||||
|
||||
#define KERNEL_DATA_START 0x80000000
|
||||
#define KERNEL_DATA_END (KERNEL_DATA_START + KERNEL_DATA_SIZE)
|
||||
|
||||
#ifdef KERNEL_EXECUTABLE_RAM
|
||||
#define USER_DATA_START (0x7f000000 + KERNEL_DATA_SIZE+2048)
|
||||
#else
|
||||
#define USER_DATA_START (0x7f000000 + KERNEL_DATA_SIZE)
|
||||
#endif
|
||||
|
||||
#define USER_DATA_END (0x7f000000 + DATA_SIZE)
|
||||
|
||||
#define stacktop(siz) (USER_DATA_END)
|
||||
|
||||
@@ -47,6 +47,9 @@ DRIVER_SPI = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = yes
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -42,10 +42,13 @@ DEFS += -DLED_TTY_PORT=TRISA -DLED_TTY_PIN=3
|
||||
# Include or exclude drivers
|
||||
|
||||
# General Purpose I/O
|
||||
DRIVER_GPIO = yes
|
||||
DRIVER_GPIO = no
|
||||
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = yes
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = yes
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
|
||||
@@ -50,6 +50,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -55,6 +55,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -48,6 +48,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = yes
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -40,6 +40,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = yes
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -1,735 +0,0 @@
|
||||
/*
|
||||
* SDRAM Access Routines for PIC32.
|
||||
*
|
||||
* Retromaster - 10.05.2010
|
||||
*
|
||||
* This file is in the public domain. You can use, modify, and distribute the source code
|
||||
* and executable programs based on the source code. This file is provided "as is" and
|
||||
* without any express or implied warranties whatsoever. Use at your own risk!
|
||||
*
|
||||
* Changes by madscifi for inclusion in the retrobsd project.
|
||||
*/
|
||||
|
||||
/* SDRAM Pin to PIC32 Pin Mapping:
|
||||
* SDRAM PIC32
|
||||
* ------ ------
|
||||
* notes, the order of An to RBn DOES matter
|
||||
* At the moment it is a bit of a mess and
|
||||
* needs to be cleaned up.
|
||||
* A0 23 RB11
|
||||
* A1 24 RB12
|
||||
* A2 25 RB13
|
||||
* A3 26 RB14
|
||||
* A4 29 RB5
|
||||
* A5 30 RB4
|
||||
* A6 31 RB3
|
||||
* A7 32 RB2
|
||||
* A8 33 RB6
|
||||
* A9 34 RB7
|
||||
* A10 22? RB15
|
||||
* A11 35 RB9
|
||||
* BA0 20 RD15
|
||||
* BA1 21 RD14
|
||||
*
|
||||
* note, the order of DQn to RAn does not matter
|
||||
* DQ0 2 RA6
|
||||
* DQ1 4 RA1
|
||||
* DQ2 5 RA7
|
||||
* DQ3 7 RA2
|
||||
* DQ4 8 RA3
|
||||
* DQ5 10 RA4
|
||||
* DQ6 11 RA5
|
||||
* DQ7 13 RA0
|
||||
|
||||
* CLK 38 OC4-RD3
|
||||
* CKE 37 A10
|
||||
* CS 19 RF4
|
||||
* WE 16 RF0
|
||||
* CAS 17 RF1
|
||||
* RAS 18 RF5
|
||||
*
|
||||
* SDRam 42, 44, 45, 47, 48, 50, 51, 53 - pullup (d8-d15)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Retrobsd does not currently contain a good header
|
||||
* for pulling the pic32 port addresses into an assembly
|
||||
* file, so define some needed registers here for the moment.
|
||||
*/
|
||||
|
||||
#define TRISA 0xBF886000
|
||||
#define T2CON 0xBF800800
|
||||
#define TMR2 0xBF800810
|
||||
#define PR2 0xBF800820
|
||||
#define T2CONSET 0xBF800808
|
||||
#define OC4CON 0xBF803600
|
||||
#define OC4RS 0xBF803620
|
||||
#define OC4R 0xBF803610
|
||||
#define AD1PCFGSET 0xBF809068
|
||||
|
||||
/* Offsets (from TRISA) for the io ports */
|
||||
#define SDR_OFFSET_A 0
|
||||
#define SDR_OFFSET_B 0x40
|
||||
#define SDR_OFFSET_C 0x80
|
||||
#define SDR_OFFSET_D 0xc0
|
||||
#define SDR_OFFSET_E 0x100
|
||||
#define SDR_OFFSET_F 0x140
|
||||
#define SDR_OFFSET_G 0x180
|
||||
|
||||
/* Offsets (from TRISA) for the various port control registers */
|
||||
#define TRIS_OFFSET 0x0
|
||||
#define PORT_OFFSET 0x10
|
||||
#define LAT_OFFSET 0x20
|
||||
#define ODCF_OFFSET 0x30
|
||||
|
||||
/* Offsets (from TRISA) for the various io port bit manipulator registers */
|
||||
#define NOP_OP_OFFSET 0x0
|
||||
#define CLR_OP_OFFSET 0x4
|
||||
#define SET_OP_OFFSET 0x8
|
||||
#define INV_OP_OFFSET 0xc
|
||||
|
||||
|
||||
/*
|
||||
* Specific assignments of ports ports used
|
||||
* Note: In general, it is not sufficient to
|
||||
* change the constants below - corresponding
|
||||
* changes to the code below will likely be
|
||||
* required if any of the following values
|
||||
* are changed.
|
||||
*/
|
||||
|
||||
/* DATA_PORT_TRIS must be assigned to a TRIS of the port
|
||||
* that has the low 8 bits tied the 8 data bits on the ram.
|
||||
*/
|
||||
#define SDR_DATA_IO SDR_OFFSET_A
|
||||
#define SDR_DATA_TRIS SDR_OFFSET_A
|
||||
|
||||
#define SDR_ADDRESS_IO SDR_OFFSET_B
|
||||
#define SDR_ADDRESS_TRIS SDR_OFFSET_B
|
||||
#define ADDRESS_MASK 0xfafc
|
||||
|
||||
#define SDR_BANK_IO SDR_OFFSET_D
|
||||
#define SDR_BANK_TRIS SDR_OFFSET_D
|
||||
#define BANK_0_BIT 14
|
||||
#define BANK_1_BIT 15
|
||||
|
||||
#define SDR_CONTROL_IO SDR_OFFSET_F
|
||||
#define SDR_CONTROL_TRIS SDR_OFFSET_F
|
||||
#define CONTROL_WE_BIT 0
|
||||
#define CONTROL_CAS_BIT 1
|
||||
#define CONTROL_CS_BIT 4
|
||||
#define CONTROL_RAS_BIT 5
|
||||
|
||||
#define SDR_CKE_IO SDR_OFFSET_A
|
||||
#define SDR_CKE_TRIS SDR_OFFSET_A
|
||||
#define CKE_BIT 10
|
||||
|
||||
#define CONTROL_ALL_MASK ( (1<<CONTROL_CS_BIT) | (1<<CONTROL_RAS_BIT) | (1<<CONTROL_CAS_BIT) | (1<<CONTROL_WE_BIT) )
|
||||
#define BANK_ALL_MASK ( (1 << BANK_1_BIT) | ( 1 << BANK_0_BIT ) )
|
||||
|
||||
/* Global Symbols */
|
||||
.globl sdram_init
|
||||
.globl sdram_read
|
||||
.globl sdram_write
|
||||
.globl sdram_active
|
||||
.globl sdram_auto_refresh
|
||||
.globl sdram_precharge
|
||||
.globl sdram_precharge_all
|
||||
.globl sdram_sleep
|
||||
.globl sdram_wake
|
||||
.globl sdram_bank
|
||||
|
||||
.type sdram_init, @function
|
||||
.type sdram_read, @function
|
||||
.type sdram_write, @function
|
||||
.type sdram_active, @function
|
||||
.type sdram_auto_refresh, @function
|
||||
.type sdram_precharge, @function
|
||||
.type sdram_precharge_all, @function
|
||||
.type sdram_sleep, @function
|
||||
.type sdram_wake, @function
|
||||
.type sdram_bank, @function
|
||||
|
||||
/*
|
||||
* This code MUST execute from ram and the ram MUST be configured
|
||||
* for zero wait states. Interrupts should be disabled before
|
||||
* calling any of these functions, and any DMA should also be
|
||||
* disabled.
|
||||
*
|
||||
* Also, the peripheral bus divisor must be set to 1.
|
||||
*/
|
||||
|
||||
.section .ramfunc,"ax",@progbits
|
||||
|
||||
/* No instruction reordering */
|
||||
|
||||
.set noreorder
|
||||
|
||||
#define clock4 \
|
||||
nop;nop;nop;nop
|
||||
|
||||
#define clock3 \
|
||||
nop;nop;nop
|
||||
|
||||
#define clock2 \
|
||||
nop;nop
|
||||
|
||||
#define clock1 \
|
||||
nop
|
||||
|
||||
/*
|
||||
* The SDRAM clock is output from the output compare unit.
|
||||
* This macro synchronizes with that clock so that we are
|
||||
* sure to have at least two clock cycles to issue control
|
||||
* line changes and access the data bus before the rising
|
||||
* edge.
|
||||
*/
|
||||
|
||||
|
||||
#define sync_clock \
|
||||
la $t8, TMR2; \
|
||||
li $v0, 2; \
|
||||
lw $v1, ($t8); \
|
||||
bge $v1, $v0, 1f; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop; \
|
||||
1: \
|
||||
nop;
|
||||
|
||||
#define output_column \
|
||||
and $t5, $a0, 0x1f; \
|
||||
sll $t5, 2; \
|
||||
and $t6, $a0, 0x20; \
|
||||
sll $t6, 9; \
|
||||
or $t5, $t6; \
|
||||
lw $t6, SDR_ADDRESS_TRIS + LAT_OFFSET($t0); \
|
||||
and $t6, ~ADDRESS_MASK; \
|
||||
or $t6, $t5; \
|
||||
sw $t6, SDR_ADDRESS_TRIS + LAT_OFFSET($t0);
|
||||
|
||||
#define output_address \
|
||||
sll $t5, $a0, 2; \
|
||||
and $t5, ADDRESS_MASK; \
|
||||
and $t6, $a0, 0x40; \
|
||||
sll $t6, 8; \
|
||||
or $t5, $t6; \
|
||||
and $t6, $a0, 0x100; \
|
||||
sll $t6, 7; \
|
||||
or $t5, $t6; \
|
||||
lw $t6, SDR_ADDRESS_TRIS + LAT_OFFSET($t0); \
|
||||
and $t6, ~ADDRESS_MASK; \
|
||||
or $t6, $t5; \
|
||||
sw $t6, SDR_ADDRESS_TRIS + LAT_OFFSET($t0);
|
||||
|
||||
/*.ent sdram_init*/
|
||||
|
||||
/*
|
||||
* Initializes the SDRAM.
|
||||
* Should be called once sometime after startup
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_init();
|
||||
*/
|
||||
|
||||
sdram_init:
|
||||
|
||||
/* Initialize address lines */
|
||||
la $t0, TRISA /* base of io addresses */
|
||||
li $t1, ADDRESS_MASK
|
||||
sw $t1, SDR_ADDRESS_IO + TRIS_OFFSET + CLR_OP_OFFSET($t0)
|
||||
|
||||
li $t1, 0xFFFF
|
||||
sw $t1, AD1PCFGSET
|
||||
|
||||
li $t1, BANK_ALL_MASK
|
||||
sw $t1, SDR_BANK_IO + TRIS_OFFSET + CLR_OP_OFFSET($t0)
|
||||
|
||||
/* All address lines low */
|
||||
li $t1, ADDRESS_MASK
|
||||
sw $t1, SDR_ADDRESS_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
|
||||
|
||||
li $t1, BANK_ALL_MASK
|
||||
sw $t1, SDR_BANK_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
|
||||
|
||||
/* Initialize data lines */
|
||||
li $t1, 0xFF
|
||||
sw $t1, SDR_DATA_IO + TRIS_OFFSET + SET_OP_OFFSET($t0)
|
||||
|
||||
/* Initialize SDRAM control lines */
|
||||
li $t1, CONTROL_ALL_MASK
|
||||
sw $t1, SDR_CONTROL_IO + TRIS_OFFSET + CLR_OP_OFFSET($t0)
|
||||
|
||||
/* Command Inhibit */
|
||||
li $t1, CONTROL_ALL_MASK
|
||||
sw $t1, SDR_CONTROL_IO + LAT_OFFSET + SET_OP_OFFSET($t0)
|
||||
|
||||
/* Initialize CKE line */
|
||||
li $t1, (1<<CKE_BIT)
|
||||
sw $t1, SDR_CKE_IO + TRIS_OFFSET + CLR_OP_OFFSET($t0)
|
||||
|
||||
/* CKE low */
|
||||
li $t1, (1<<CKE_BIT)
|
||||
sw $t1, SDR_CKE_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
|
||||
|
||||
/* SDRAM clock output */
|
||||
|
||||
/* Initialize Timer2 */
|
||||
sw $zero, T2CON
|
||||
sw $zero, TMR2
|
||||
li $t1, 3
|
||||
sw $t1, PR2
|
||||
li $t1, 0x8000
|
||||
sw $t1, T2CONSET
|
||||
|
||||
/* Initialize OC4 */
|
||||
sw $zero, OC4CON
|
||||
li $t1, 1
|
||||
sw $t1, OC4RS
|
||||
li $t1, 3
|
||||
sw $t1, OC4R
|
||||
li $t1, 0x8005
|
||||
sw $t1, OC4CON
|
||||
|
||||
/* Clock output starts here */
|
||||
|
||||
/* SD-RAM initialization delay */
|
||||
li $t2, 500
|
||||
move $t1, $zero
|
||||
|
||||
sdram_init_delay_1:
|
||||
addi $t1, $t1, 1
|
||||
bne $t1, $t2, sdram_init_delay_1
|
||||
nop
|
||||
|
||||
/* CKE high */
|
||||
li $t1, (1<<CKE_BIT)
|
||||
sw $t1, SDR_CKE_IO + LAT_OFFSET + SET_OP_OFFSET($t0)
|
||||
|
||||
/* Delay some more */
|
||||
li $t2, 3000
|
||||
move $t1, $zero
|
||||
|
||||
sdram_init_delay_2:
|
||||
addi $t1, $t1, 1
|
||||
bne $t1, $t2, sdram_init_delay_2
|
||||
nop
|
||||
|
||||
/* Get ready for the commands we are about to issue. */
|
||||
li $t4, (1<<CONTROL_CAS_BIT)
|
||||
li $t5, (1<<CONTROL_WE_BIT)
|
||||
li $t6, 0x1810 /* Mode Register: CL:2, BL:8 (0x23) */
|
||||
li $t7, CONTROL_ALL_MASK
|
||||
li $t8, 0x8000 /* A10 */
|
||||
|
||||
sw $t8, SDR_ADDRESS_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* A10 = 1 for Precharge ALL */
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Precharge All */
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + CLR_OP_OFFSET($t0) /* LLLL */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* LLHL */
|
||||
clock2
|
||||
|
||||
/* Auto Refresh 1 */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + CLR_OP_OFFSET($t0) /* LLLL */
|
||||
sw $t5, SDR_CONTROL_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* LLLH */
|
||||
clock2
|
||||
|
||||
/* Auto Refresh 2 */
|
||||
clock4
|
||||
|
||||
/* Auto Refresh 3 */
|
||||
clock4
|
||||
|
||||
/* Auto Refresh 4 */
|
||||
clock4
|
||||
|
||||
/* Auto Refresh 5 */
|
||||
clock4
|
||||
|
||||
/* Auto Refresh 6 */
|
||||
clock4
|
||||
|
||||
/* Auto Refresh 7 */
|
||||
clock4
|
||||
|
||||
/* Auto Refresh 8 */
|
||||
li $t4, ADDRESS_MASK
|
||||
sw $t4, SDR_ADDRESS_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
|
||||
clock2
|
||||
|
||||
/* Load Mode Register */
|
||||
sw $t6, SDR_ADDRESS_IO + LAT_OFFSET + SET_OP_OFFSET($t0)
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
|
||||
clock2
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + SET_OP_OFFSET($t0)
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
clock4
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
/*.end sdram_init*/
|
||||
|
||||
|
||||
/*
|
||||
* Sends ACTIVE command
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_active(uint16_t rowaddr);
|
||||
*/
|
||||
sdram_active:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
li $t7, (1<<CONTROL_CS_BIT)|(1<<CONTROL_RAS_BIT)
|
||||
|
||||
/* Set row */
|
||||
output_address
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Active */
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0)
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0)
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
clock4
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
|
||||
/*
|
||||
* Sends WRITE command
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_write(uint16_t pseudocoladdr, uint64_t val);
|
||||
* Each pseudo column contains 8 bytes of data (consists of 8 ram columns)
|
||||
*/
|
||||
|
||||
sdram_write:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
li $t4, 0xFF
|
||||
li $t7, (1<<CONTROL_CS_BIT) | (1<<CONTROL_CAS_BIT) | (1<<CONTROL_WE_BIT)
|
||||
|
||||
/* Set column */
|
||||
output_column
|
||||
|
||||
/* Set data lines */
|
||||
srl $t5, $a2, 24
|
||||
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0)
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Write */
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LHLL */
|
||||
sw $t4, SDR_DATA_IO + TRIS_OFFSET + INV_OP_OFFSET($t0) /* 1 - enable data lines */
|
||||
srl $t5, $a2, 16
|
||||
clock1
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* HHHH */
|
||||
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 2 */
|
||||
srl $t5, $a2, 8
|
||||
clock1
|
||||
|
||||
/* Command Inhibit */
|
||||
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 3 */
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
sb $a2, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 4 */
|
||||
srl $t5, $a3, 24
|
||||
clock2
|
||||
|
||||
/* Command Inhibit */
|
||||
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 5 */
|
||||
srl $t5, $a3, 16
|
||||
clock2
|
||||
|
||||
/* Command Inhibit */
|
||||
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 6 */
|
||||
srl $t5, $a3, 8
|
||||
clock2
|
||||
|
||||
/* Command Inhibit */
|
||||
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 7 */
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
sb $a3, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 8 */
|
||||
clock3
|
||||
|
||||
sw $t4, SDR_DATA_IO + TRIS_OFFSET + INV_OP_OFFSET($t0) /* Data lines input again */
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
|
||||
/*
|
||||
* Sends READ command
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) uint64_t sdram_read(uint16_t pseudocoladdr);
|
||||
* Each pseudo column contains 8 bytes of data (consists of 8 ram columns)
|
||||
*/
|
||||
sdram_read:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
li $t7, (1<<CONTROL_CS_BIT) | (1<<CONTROL_CAS_BIT)
|
||||
|
||||
/* Set column */
|
||||
output_column
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Read */
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LHLH */
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* HHHH */
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
clock3
|
||||
lbu $v0, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 1 */
|
||||
|
||||
/* Command Inhibit */
|
||||
clock3
|
||||
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 2 */
|
||||
|
||||
/* Command Inhibit */
|
||||
sll $v0, $v0, 8
|
||||
or $v0, $v0, $t5
|
||||
clock1
|
||||
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 3 */
|
||||
|
||||
/* Command Inhibit */
|
||||
sll $v0, $v0, 8
|
||||
or $v0, $v0, $t5
|
||||
clock1
|
||||
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 4 */
|
||||
|
||||
/* Command Inhibit */
|
||||
sll $v0, $v0, 8
|
||||
or $v0, $v0, $t5
|
||||
clock1
|
||||
lbu $v1, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 5 */
|
||||
|
||||
/* Command Inhibit */
|
||||
clock3
|
||||
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 6 */
|
||||
|
||||
/* Command Inhibit */
|
||||
sll $v1, $v1, 8
|
||||
or $v1, $v1, $t5
|
||||
clock1
|
||||
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 7 */
|
||||
|
||||
/* Command Inhibit */
|
||||
sll $v1, $v1, 8
|
||||
or $v1, $v1, $t5
|
||||
clock1
|
||||
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 8 */
|
||||
|
||||
/* Command Inhibit */
|
||||
sll $v1, $v1, 8
|
||||
or $v1, $v1, $t5
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
|
||||
/*
|
||||
* Sends PRECHARGE ALL command
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_precharge_all(void);
|
||||
*/
|
||||
sdram_precharge_all:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
li $t3, 0x8000 /* A10 */
|
||||
li $t4, (1<<CONTROL_CS_BIT) | (1<<CONTROL_RAS_BIT) | (1<<CONTROL_WE_BIT)
|
||||
|
||||
sw $t3, SDR_ADDRESS_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* A10 = 1 for Precharge ALL */
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Precharge All */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLHL */
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLL */
|
||||
clock3
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
|
||||
/*
|
||||
* Sends PRECHARGE command
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_precharge(void);
|
||||
*/
|
||||
sdram_precharge:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
li $t3, 0x8000 /* A10 */
|
||||
li $t4, (1<<CONTROL_CS_BIT) | (1<<CONTROL_RAS_BIT) | (1<<CONTROL_WE_BIT)
|
||||
|
||||
sw $t3, SDR_ADDRESS_IO + LAT_OFFSET + CLR_OP_OFFSET($t0) /* A10 = 0 for Precharge */
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Precharge All */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLHL */
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLL */
|
||||
clock3
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
|
||||
/*
|
||||
* Sends AUTO REFRESH command
|
||||
* All banks must be in PRECHARGEd state
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_auto_refresh(void);
|
||||
*/
|
||||
sdram_auto_refresh:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
li $t4, (1<<CONTROL_CS_BIT)|(1<<CONTROL_RAS_BIT)|(1<<CONTROL_CAS_BIT)
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Auto Refresh */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLH */
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLL */
|
||||
clock3
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
/*
|
||||
* Puts the SDRAM into the self refresh mode.
|
||||
* SDRAM retains data in this state.
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_sleep(void);
|
||||
*/
|
||||
sdram_sleep:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
li $t1, (1<<CKE_BIT)
|
||||
li $t4, (1<<CONTROL_CS_BIT)|(1<<CONTROL_RAS_BIT)|(1<<CONTROL_CAS_BIT)
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Auto Refresh */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLH */
|
||||
sw $t1, SDR_CKE_IO + LAT_OFFSET + CLR_OP_OFFSET($t0) /* CKE low */
|
||||
clock2
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLL */
|
||||
clock3
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
/*
|
||||
* Takes the SDRAM out of the self refresh mode.
|
||||
* Parameters: none
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_wake(void);
|
||||
*/
|
||||
sdram_wake:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
li $t1, (1<<CKE_BIT)
|
||||
|
||||
sync_clock
|
||||
|
||||
.set nomacro
|
||||
|
||||
/* Command Inhibit */
|
||||
sw $t1, SDR_CKE_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* CKE low */
|
||||
clock3
|
||||
|
||||
/* Command Inhibit */
|
||||
clock4
|
||||
|
||||
/* Command Inhibit */
|
||||
clock4
|
||||
|
||||
.set macro
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
|
||||
/*
|
||||
* Selects the bank to which commands are issued
|
||||
* Parameters:
|
||||
* C Prototype:
|
||||
* extern __attribute__((far)) void sdram_bank(uint8_t bank);
|
||||
* (only lower 2 bits are of bank are currently significant)
|
||||
*/
|
||||
sdram_bank:
|
||||
|
||||
la $t0, TRISA /* Port Base */
|
||||
lw $t1, SDR_BANK_IO + LAT_OFFSET + NOP_OP_OFFSET($t0);
|
||||
and $t1, ~BANK_ALL_MASK
|
||||
sll $t2, $a0, BANK_0_BIT
|
||||
or $t1, $t2
|
||||
sw $t1, SDR_BANK_IO + LAT_OFFSET + NOP_OP_OFFSET($t0);
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* SDRAM Access Routines for PIC32.
|
||||
*
|
||||
* Retromaster - 10.05.2010
|
||||
*
|
||||
* This file is in the public domain. You can use, modify, and distribute the source code
|
||||
* and executable programs based on the source code. This file is provided "as is" and
|
||||
* without any express or implied warranties whatsoever. Use at your own risk!
|
||||
*
|
||||
* Changes by madscifi for inclusion in the retrobsd project.
|
||||
*/
|
||||
|
||||
#ifndef SDRAM_H
|
||||
#define SDRAM_H
|
||||
|
||||
//#include <inttypes.h>
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
extern __attribute__((far)) void sdram_init();
|
||||
extern __attribute__((far)) void sdram_active(uint16_t rowaddr);
|
||||
extern __attribute__((far)) void sdram_write(uint16_t pseudocoladdr, uint64_t val);
|
||||
extern __attribute__((far)) uint64_t sdram_read(uint16_t pseudocoladdr);
|
||||
extern __attribute__((far)) void sdram_auto_refresh(void);
|
||||
extern __attribute__((far)) void sdram_precharge(void);
|
||||
extern __attribute__((far)) void sdram_precharge_all(void);
|
||||
extern __attribute__((far)) void sdram_sleep(void);
|
||||
extern __attribute__((far)) void sdram_wake(void);
|
||||
extern __attribute__((far)) void sdram_bank(uint8_t bank);
|
||||
|
||||
#endif
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Driver for external SDRAM-based swap device.
|
||||
*
|
||||
* See sdram.S for information on interface to sdram
|
||||
*
|
||||
* This code could use a bit of optimization.
|
||||
*/
|
||||
|
||||
#include "param.h"
|
||||
#include "systm.h"
|
||||
#include "buf.h"
|
||||
#include "errno.h"
|
||||
#include "dk.h"
|
||||
#include "sdram.h"
|
||||
|
||||
int sw_dkn = -1; /* Statistics slot number */
|
||||
|
||||
/*
|
||||
* physical specs of SDRAM chip
|
||||
*/
|
||||
#define RAM_COLS 512
|
||||
#define RAM_ROWS 4096
|
||||
#define RAM_BANKS 4
|
||||
|
||||
|
||||
/*
|
||||
* RAM_BURST_COUNT MUST be match the number of bytes
|
||||
* read/written by each call to sdram_read/sdram_write
|
||||
*/
|
||||
#define RAM_BURST_COUNT 8
|
||||
|
||||
/*
|
||||
* CHUNK_SIZE number of bytes in each "chunk"
|
||||
*/
|
||||
#define CHUNK_SIZE 128
|
||||
|
||||
#define RAM_BURST_GROUP_COUNT 8
|
||||
|
||||
#define BLOCKS_PER_ROW ( RAM_COLS / CHUNK_SIZE )
|
||||
|
||||
static char swaptemp[CHUNK_SIZE];
|
||||
|
||||
static void
|
||||
read_chunk_from_sdram( uint64_t* dest, unsigned int blockNumber )
|
||||
{
|
||||
int startColumn = ( ( blockNumber & ( BLOCKS_PER_ROW - 1 ) ) * CHUNK_SIZE ) / RAM_BURST_COUNT;
|
||||
int rowAndBank = blockNumber / BLOCKS_PER_ROW;
|
||||
int row = rowAndBank & ( RAM_ROWS - 1 );
|
||||
int bank = rowAndBank / RAM_ROWS;
|
||||
int col = startColumn;
|
||||
|
||||
while( col < startColumn + CHUNK_SIZE/RAM_BURST_COUNT ) {
|
||||
int x = mips_intr_disable();
|
||||
sdram_wake();
|
||||
sdram_bank(bank);
|
||||
sdram_active(row);
|
||||
int i;
|
||||
for( i = 0; i < RAM_BURST_GROUP_COUNT; i++ ) {
|
||||
*dest++ = sdram_read( col );
|
||||
col += 1; //RAM_BURST_COUNT;
|
||||
}
|
||||
sdram_precharge();
|
||||
sdram_precharge_all();
|
||||
sdram_sleep();
|
||||
|
||||
mips_intr_restore (x);
|
||||
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_chunk_to_sdram( uint64_t* src, unsigned int blockNumber )
|
||||
{
|
||||
int startColumn = ( ( blockNumber & ( BLOCKS_PER_ROW - 1 ) ) * CHUNK_SIZE ) / RAM_BURST_COUNT;
|
||||
int rowAndBank = blockNumber / BLOCKS_PER_ROW;
|
||||
int row = rowAndBank & ( RAM_ROWS - 1 );
|
||||
int bank = rowAndBank / RAM_ROWS;
|
||||
|
||||
int col = startColumn;
|
||||
while( col < startColumn + CHUNK_SIZE/RAM_BURST_COUNT ) {
|
||||
int x = mips_intr_disable();
|
||||
|
||||
sdram_wake();
|
||||
sdram_bank(bank);
|
||||
sdram_active(row);
|
||||
int i;
|
||||
for( i = 0; i < RAM_BURST_GROUP_COUNT; i++ ) {
|
||||
sdram_write( col, *src++ );
|
||||
col += 1; //RAM_BURST_COUNT;
|
||||
}
|
||||
sdram_precharge();
|
||||
sdram_precharge_all();
|
||||
sdram_sleep();
|
||||
|
||||
mips_intr_restore (x);
|
||||
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read a block of data.
|
||||
*/
|
||||
static void
|
||||
dev_read(unsigned blockno, char* data, unsigned nbytes)
|
||||
{
|
||||
blockno = blockno * (DEV_BSIZE/CHUNK_SIZE);
|
||||
|
||||
while( nbytes >= CHUNK_SIZE ) {
|
||||
read_chunk_from_sdram( (uint64_t*) swaptemp, blockno );
|
||||
bcopy( swaptemp, data, CHUNK_SIZE );
|
||||
data += CHUNK_SIZE;
|
||||
blockno += 1;
|
||||
nbytes -= CHUNK_SIZE;
|
||||
}
|
||||
|
||||
if( nbytes ) {
|
||||
read_chunk_from_sdram( (uint64_t*) swaptemp, blockno );
|
||||
bcopy( swaptemp, data, nbytes );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a block of data.
|
||||
*/
|
||||
static void
|
||||
dev_write (unsigned blockno, char *data, unsigned nbytes)
|
||||
{
|
||||
blockno = blockno * (DEV_BSIZE/CHUNK_SIZE);
|
||||
|
||||
while( nbytes >= CHUNK_SIZE ) {
|
||||
bcopy( data, swaptemp, CHUNK_SIZE );
|
||||
write_chunk_to_sdram( (uint64_t*) swaptemp, blockno );
|
||||
data += CHUNK_SIZE;
|
||||
blockno += 1;
|
||||
nbytes -= CHUNK_SIZE;
|
||||
}
|
||||
if( nbytes ) {
|
||||
read_chunk_from_sdram( (uint64_t*) swaptemp, blockno );
|
||||
bcopy( data, swaptemp, nbytes );
|
||||
write_chunk_to_sdram( (uint64_t*) swaptemp, blockno );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
swopen(dev_t dev, int flag, int mode)
|
||||
{
|
||||
static int has_been_opened = 0;
|
||||
|
||||
if (!has_been_opened) {
|
||||
int x = mips_intr_disable();
|
||||
sdram_init();
|
||||
mips_intr_restore(x);
|
||||
has_been_opened = 1;
|
||||
|
||||
#ifdef UCB_METER
|
||||
/* Allocate statistics slot */
|
||||
dk_alloc (&sw_dkn, 1, "sw");
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
swstrategy(register struct buf *bp)
|
||||
{
|
||||
int s;
|
||||
|
||||
#if 0
|
||||
printf ("sw0: %s block %u, length %u bytes, addr %p\n",
|
||||
(bp->b_flags & B_READ) ? "read" : "write",
|
||||
bp->b_blkno, bp->b_bcount, bp->b_addr);
|
||||
#endif
|
||||
led_control (LED_AUX, 1);
|
||||
s = splbio();
|
||||
#ifdef UCB_METER
|
||||
if (sw_dkn >= 0) {
|
||||
dk_busy |= 1 << sw_dkn;
|
||||
dk_xfer[sw_dkn]++;
|
||||
dk_bytes[sw_dkn] += bp->b_bcount;
|
||||
}
|
||||
#endif
|
||||
unsigned adj = 0;
|
||||
if (minor(bp->b_dev)==1) {
|
||||
adj = SWAPSZ;
|
||||
}
|
||||
if (bp->b_flags & B_READ) {
|
||||
dev_read (bp->b_blkno+adj, bp->b_addr, bp->b_bcount);
|
||||
} else {
|
||||
dev_write (bp->b_blkno+adj, bp->b_addr, bp->b_bcount);
|
||||
}
|
||||
#if 0
|
||||
printf (" %02x", (unsigned char) bp->b_addr[0]);
|
||||
int i;
|
||||
for (i=1; i<bp->b_bcount; i++)
|
||||
printf ("-%02x", (unsigned char) bp->b_addr[i]);
|
||||
printf ("\n");
|
||||
#endif
|
||||
biodone (bp);
|
||||
led_control (LED_AUX, 0);
|
||||
splx (s);
|
||||
#ifdef UCB_METER
|
||||
if (sw_dkn >= 0)
|
||||
dk_busy &= ~(1 << sw_dkn);
|
||||
#endif
|
||||
}
|
||||
@@ -48,7 +48,7 @@ DEFS += -DSD_PORT=SPI1CON -DSD_MHZ=10
|
||||
DEFS += -DSD_CS0_PORT=TRISB -DSD_CS0_PIN=1
|
||||
|
||||
# LEDs at pins D0 (red), D1 (yellow), D2 (green)
|
||||
DEFS += -DLED_TTY_PORT=TRISD -DLED_TTY_PIN=0
|
||||
# Pin D0 is used for SD/MMC as signal SDO1
|
||||
DEFS += -DLED_DISK_PORT=TRISD -DLED_DISK_PIN=1
|
||||
DEFS += -DLED_KERNEL_PORT=TRISD -DLED_KERNEL_PIN=2
|
||||
|
||||
@@ -60,6 +60,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = yes
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 1988 Regents of the University of California.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms are permitted
|
||||
# provided that this notice is preserved and that due credit is given
|
||||
# to the University of California at Berkeley. The name of the University
|
||||
# may not be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission. This software
|
||||
# is provided ``as is'' without express or implied warranty.
|
||||
#
|
||||
H = ../../include
|
||||
M = ..
|
||||
S = ../../kernel
|
||||
|
||||
vpath %.c $(M):$(S)
|
||||
vpath %.S $(M):$(S)
|
||||
|
||||
# Kernel options.
|
||||
DEFS += -I. -I$(H) -DKERNEL -DUCB_METER -DPIC32MX7
|
||||
|
||||
# CPU frequency 80 MHz.
|
||||
DEFS += -DCPU_KHZ=80000
|
||||
DEFS += -DBUS_KHZ=80000
|
||||
|
||||
#
|
||||
# UBW32 board
|
||||
# ===========
|
||||
#
|
||||
# Console on UART1
|
||||
DEFS += -DCONSOLE_UART1
|
||||
|
||||
# SD/MMC card driver on SPI1
|
||||
# /CS0 at pin A9 (and optional /CS1 at pin A10)
|
||||
DEFS += -DSD_PORT=SPI1CON -DSD_MHZ=8
|
||||
DEFS += -DSD_CS0_PORT=TRISA -DSD_CS0_PIN=9
|
||||
DEFS += -DSD_CS1_PORT=TRISA -DSD_CS1_PIN=10
|
||||
|
||||
# LEDs at pins E0, E1, E2, E3
|
||||
DEFS += -DLED_AUX_PORT=TRISE -DLED_AUX_PIN=0 -DLED_AUX_INVERT
|
||||
DEFS += -DLED_DISK_PORT=TRISE -DLED_DISK_PIN=1 -DLED_DISK_INVERT
|
||||
DEFS += -DLED_KERNEL_PORT=TRISE -DLED_KERNEL_PIN=2 -DLED_KERNEL_INVERT
|
||||
DEFS += -DLED_TTY_PORT=TRISE -DLED_TTY_PIN=3 -DLED_TTY_INVERT
|
||||
|
||||
# Swap on sdram
|
||||
DEFS += -DSWAPDEV=0x0100 -DSWAPSZ=2048
|
||||
DEFS += -DKERNEL_EXECUTABLE_RAM
|
||||
|
||||
#DEFS += -DSW_DATA_PORT=TRISE -DSW_DATA_PIN=0
|
||||
#DEFS += -DSW_RD_PORT=TRISE -DSW_RD_PIN=8
|
||||
#DEFS += -DSW_WR_PORT=TRISE -DSW_WR_PIN=9
|
||||
#DEFS += -DSW_LDA_PORT=TRISC -DSW_LDA_PIN=1
|
||||
|
||||
# Include or exclude drivers
|
||||
|
||||
# General Purpose I/O
|
||||
DRIVER_GPIO = no
|
||||
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
POWER_LED_PORT = TRISG
|
||||
POWER_LED_PIN = 12
|
||||
POWER_SWITCH_PORT = TRISG
|
||||
POWER_SWITCH_PIN = 0
|
||||
POWER_CONTROL_PORT = TRISE
|
||||
POWER_CONTROL_PIN = 9
|
||||
|
||||
DEPFLAGS = -MT $@ -MD -MP -MF .deps/$*.dep
|
||||
CFLAGS = -O $(DEFS) $(DEPFLAGS)
|
||||
ASFLAGS = $(DEFS) $(DEPFLAGS)
|
||||
|
||||
include ../gcc-config.mk
|
||||
|
||||
CC = $(GCCPREFIX)gcc -EL -g -mips32r2
|
||||
CC += -nostdinc -fno-builtin -Werror -Wall -fno-dwarf2-cfi-asm
|
||||
LDFLAGS += -nostdlib -T using-bootloader.ld -Wl,-Map=unix.map
|
||||
SIZE = $(GCCPREFIX)size
|
||||
OBJDUMP = $(GCCPREFIX)objdump
|
||||
OBJCOPY = $(GCCPREFIX)objcopy
|
||||
|
||||
# Machine-dependent files:
|
||||
# startup.o MUST be loaded first.
|
||||
KERNOBJ = startup.o clock.o devsw.o sysctl.o \
|
||||
signal.o machdep.o mem.o exception.o
|
||||
|
||||
KERNOBJ += cons.o
|
||||
|
||||
# swap on sdram - this is incompatible with swap.o
|
||||
KERNOBJ += sdram.o sdramp.o
|
||||
|
||||
# Kernel.
|
||||
KERNOBJ += init_main.o init_sysent.o kern_clock.o \
|
||||
kern_descrip.o kern_exec.o kern_exit.o kern_fork.o \
|
||||
kern_mman.o kern_proc.o kern_prot.o \
|
||||
kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o \
|
||||
kern_subr.o kern_synch.o kern_sysctl.o kern_time.o \
|
||||
subr_log.o subr_prf.o subr_rmap.o \
|
||||
sys_generic.o sys_inode.o syscalls.o \
|
||||
sys_pipe.o sys_process.o tty.o tty_conf.o \
|
||||
tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o \
|
||||
ufs_bmap.o ufs_dsort.o ufs_fio.o \
|
||||
ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o \
|
||||
ufs_syscalls.o ufs_syscalls2.o vfs_vnops.o \
|
||||
vm_sched.o vm_swap.o vm_swp.o kern_glob.o
|
||||
|
||||
# Drivers.
|
||||
KERNOBJ += sd.o
|
||||
|
||||
# Configuration-dependent files.
|
||||
KERNOBJ += vers.o
|
||||
|
||||
# This makefile does the work including the right files and options for the drivers
|
||||
include ../drivers.mk
|
||||
|
||||
all: .deps sys machine unix.elf
|
||||
$(SIZE) unix.elf
|
||||
|
||||
clean:
|
||||
rm -rf .deps *.o *.elf *.bin *.dis *.map *.srec core \
|
||||
mklog assym.h vers.c genassym sys machine
|
||||
|
||||
.deps:
|
||||
mkdir .deps
|
||||
|
||||
sys:
|
||||
ln -s ../../include $@
|
||||
|
||||
machine:
|
||||
ln -s .. $@
|
||||
|
||||
unix.elf: $(KERNOBJ) using-bootloader.ld
|
||||
$(CC) $(LDFLAGS) $(KERNOBJ) -o $@
|
||||
chmod -x $@
|
||||
$(OBJDUMP) -d -S -z $@ > unix.dis
|
||||
$(OBJCOPY) -O binary $@ unix.bin
|
||||
$(OBJCOPY) -O ihex --change-addresses=0x80000000 $@ unix.hex
|
||||
chmod -x $@ unix.bin
|
||||
|
||||
load: unix.elf
|
||||
pic32prog -p unix.hex
|
||||
|
||||
vers.o: ../newvers.sh $(H)/*.h $(M)/*.[ch] $(S)/*.c
|
||||
sh ../newvers.sh > vers.c
|
||||
$(CC) -c vers.c
|
||||
|
||||
.SUFFIXES: .i .srec .hex .dis .cpp .cxx .bin .elf
|
||||
|
||||
.o.dis:
|
||||
$(OBJDUMP) -d -z -S $< > $@
|
||||
|
||||
ifeq (.deps, $(wildcard .deps))
|
||||
-include .deps/*.dep
|
||||
endif
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Linker script for PIC32 firmware using HID bootloader.
|
||||
*/
|
||||
OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips",
|
||||
"elf32-littlemips")
|
||||
OUTPUT_ARCH(mips)
|
||||
ENTRY(_reset_vector_)
|
||||
MEMORY
|
||||
{
|
||||
flash (rx) : ORIGIN = 0x9d005000, LENGTH = 492K
|
||||
ram (rw!x): ORIGIN = 0x80000000, LENGTH = 24K
|
||||
u0area (rw!x): ORIGIN = 0x80006000, LENGTH = 3K
|
||||
uarea (rw!x): ORIGIN = 0x80006C00, LENGTH = 3K
|
||||
keram (rwx) : ORIGIN = 0x80007800, LENGTH = 2K
|
||||
|
||||
/* Required by Microchip C32 linker */
|
||||
kseg0_program_mem (rx) : ORIGIN = 0x9D000000, LENGTH = 0x80000
|
||||
kseg0_boot_mem : ORIGIN = 0x9FC00490, LENGTH = 0x970
|
||||
exception_mem : ORIGIN = 0x9FC01000, LENGTH = 0x1000
|
||||
kseg1_boot_mem : ORIGIN = 0xBFC00000, LENGTH = 0x490
|
||||
kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x20000
|
||||
}
|
||||
|
||||
/* higher address of the user mode stack */
|
||||
u0 = ORIGIN(u0area);
|
||||
u = ORIGIN(uarea);
|
||||
u_end = ORIGIN(uarea) + LENGTH(uarea);
|
||||
|
||||
_keram_start = ORIGIN(keram);
|
||||
_keram_end = ORIGIN(keram) + LENGTH(keram);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text ORIGIN(flash) :
|
||||
{
|
||||
/* Exception handlers. */
|
||||
*(.exception)
|
||||
. = 0x1000;
|
||||
/* Execution starts here. */
|
||||
*(.startup)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.glue_7t) *(.glue_7)
|
||||
__rodata_start = . ;
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.* .rel.dyn)
|
||||
*(.dinit)
|
||||
/* Align here to ensure that the .text section ends on word boundary. */
|
||||
. = ALIGN (32 / 8);
|
||||
_etext = .;
|
||||
} > flash
|
||||
|
||||
/* Start data (internal SRAM). */
|
||||
.data : AT (ADDR (.text) + SIZEOF (.text))
|
||||
{
|
||||
__data_start = . ;
|
||||
_gp = .; /* We use only 32k RAM for kernel, so no need for 0x8000 offset. */
|
||||
/* We want the small data sections together, so single-instruction offsets
|
||||
can access them all, and initialized data all before uninitialized, so
|
||||
we can shorten the on-disk segment size. */
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.eh_frame)
|
||||
_edata = .;
|
||||
} > ram
|
||||
|
||||
.bss ADDR (.data) + SIZEOF (.data) (NOLOAD) :
|
||||
{
|
||||
__bss_start = .;
|
||||
*(.dynbss)
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections. */
|
||||
. = ALIGN (32 / 8);
|
||||
} > ram
|
||||
__bss_end = . ;
|
||||
_end = .;
|
||||
|
||||
/*
|
||||
* RAM functions go at the end of our stack and heap allocation.
|
||||
* Alignment of 2K required by the boundary register (BMXDKPBA).
|
||||
*/
|
||||
.ramfunc : AT (LOADADDR (.data) + SIZEOF (.data))
|
||||
{
|
||||
_ramfunc_begin = . ;
|
||||
*(.ramfunc .ramfunc.*)
|
||||
. = ALIGN(4) ;
|
||||
_ramfunc_end = . ;
|
||||
} >keram
|
||||
_ramfunc_image_begin = LOADADDR(.ramfunc) ;
|
||||
_ramfunc_length = SIZEOF(.ramfunc) ;
|
||||
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
}
|
||||
@@ -61,6 +61,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = yes
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -52,6 +52,9 @@ DRIVER_GPIO = yes
|
||||
# Basic ADC interface
|
||||
DRIVER_ADC = no
|
||||
|
||||
# Support userland program in flash
|
||||
DRIVER_UFLASH = no
|
||||
|
||||
# Power control (power LED, and soft power-off by button)
|
||||
# requires supported PSU (ATX)
|
||||
DRIVER_POWER = no
|
||||
|
||||
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* uflash driver for PIC32.
|
||||
*
|
||||
* Based on GPIO driver:
|
||||
* Copyright (C) 2012 Serge Vakulenko, <serge@vak.ru>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software
|
||||
* and its documentation for any purpose and without fee is hereby
|
||||
* granted, provided that the above copyright notice appear in all
|
||||
* copies and that both that the copyright notice and this
|
||||
* permission notice and warranty disclaimer appear in supporting
|
||||
* documentation, and that the name of the author not be used in
|
||||
* advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission.
|
||||
*
|
||||
* The author disclaim all warranties with regard to this
|
||||
* software, including all implied warranties of merchantability
|
||||
* and fitness. In no event shall the author be liable for any
|
||||
* special, indirect or consequential damages or any damages
|
||||
* whatsoever resulting from loss of use, data or profits, whether
|
||||
* in an action of contract, negligence or other tortious action,
|
||||
* arising out of or in connection with the use or performance of
|
||||
* this software.
|
||||
*/
|
||||
#include "param.h"
|
||||
#include "conf.h"
|
||||
#include "user.h"
|
||||
#include "ioctl.h"
|
||||
#include "uflash.h"
|
||||
#include "systm.h"
|
||||
#include "uio.h"
|
||||
#include "stat.h"
|
||||
|
||||
#include "map.h"
|
||||
#include "proc.h"
|
||||
#include "buf.h"
|
||||
#include "inode.h"
|
||||
#include "namei.h"
|
||||
#include "fs.h"
|
||||
#include "mount.h"
|
||||
#include "file.h"
|
||||
#include "signalvar.h"
|
||||
|
||||
/* TODO: some sort of interlock is needed so that the contents
|
||||
* of flash are not replaced while a processing that depends
|
||||
* on the contents is executing.
|
||||
*/
|
||||
|
||||
#define MINOR_UNIT 0x07 /* Minor mask: unit number */
|
||||
|
||||
#define FLASH_PAGE_SIZE 4096
|
||||
#define FLASH_BUFFER_INT_COUNT 4
|
||||
|
||||
static void flashErasePage(unsigned addrPage);
|
||||
static void flashWriteUint32(unsigned addrUint32, unsigned *rgu32Data, unsigned cu32Data);
|
||||
|
||||
// Flash operations
|
||||
#define NVMOP_WORD_PGM 0x4001 // Word program operation
|
||||
#define NVMOP_ROW_PGM 0x4003 // Row write
|
||||
#define NVMOP_PAGE_ERASE 0x4004 // Page erase operation
|
||||
|
||||
#define USE_USER_FLASH_START (USER_FLASH_START-0x20000000UL)
|
||||
|
||||
/*
|
||||
* To enable debug output, comment out the first line,
|
||||
* and uncomment the second line.
|
||||
*/
|
||||
#define PRINTDBG(...) /*empty*/
|
||||
//#define PRINTDBG printf
|
||||
|
||||
char targetToFlash[31] = "";
|
||||
|
||||
int
|
||||
uflash_open (dev, flag, mode)
|
||||
dev_t dev;
|
||||
{
|
||||
if (u.u_uid != 0)
|
||||
return EPERM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
uflash_close (dev, flag, mode)
|
||||
dev_t dev;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
uflash_read (dev, uio, flag)
|
||||
dev_t dev;
|
||||
struct uio *uio;
|
||||
int flag;
|
||||
{
|
||||
register struct iovec *iov;
|
||||
register u_int cnt;
|
||||
char *buf = targetToFlash;
|
||||
|
||||
cnt = strlen(targetToFlash);
|
||||
|
||||
/* I/o size should be large enough. */
|
||||
iov = uio->uio_iov;
|
||||
if (iov->iov_len < cnt)
|
||||
return EIO;
|
||||
|
||||
/* Read only cnt bytes. */
|
||||
if (uio->uio_offset >= cnt)
|
||||
return 0;
|
||||
|
||||
cnt -= uio->uio_offset;
|
||||
|
||||
|
||||
/* Print port status to buffer. */
|
||||
//PRINTDBG ("uflash_read -> %s", buf);
|
||||
|
||||
bcopy (buf + uio->uio_offset, iov->iov_base, cnt);
|
||||
iov->iov_base += cnt;
|
||||
iov->iov_len -= cnt;
|
||||
uio->uio_resid -= cnt;
|
||||
uio->uio_offset += cnt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
uflash_write (dev, uio, flag)
|
||||
dev_t dev;
|
||||
struct uio *uio;
|
||||
int flag;
|
||||
{
|
||||
register struct iovec *iov = uio->uio_iov;
|
||||
register u_int cnt = 30;
|
||||
char * buf = targetToFlash;
|
||||
|
||||
/* I/o size should be large enough. */
|
||||
if (iov->iov_len > cnt)
|
||||
return EIO;
|
||||
|
||||
if( iov->iov_len < cnt ) cnt = iov->iov_len;
|
||||
|
||||
cnt -= uio->uio_offset;
|
||||
bcopy (iov->iov_base, buf+uio->uio_offset, cnt);
|
||||
buf[uio->uio_offset+cnt]=0;
|
||||
|
||||
iov->iov_base += cnt;
|
||||
iov->iov_len -= cnt;
|
||||
uio->uio_resid -= cnt;
|
||||
uio->uio_offset += cnt;
|
||||
|
||||
//PRINTDBG ("uflash_read ('%s')\n", buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Commands:
|
||||
* UFLASH_LOAD - load the program specified into user flash
|
||||
*/
|
||||
|
||||
int
|
||||
uflash_ioctl (dev, cmd, addr, flag)
|
||||
dev_t dev;
|
||||
register u_int cmd;
|
||||
caddr_t addr;
|
||||
{
|
||||
int result = 0;
|
||||
struct inode *ip;
|
||||
|
||||
//unsigned unit = cmd & 0xff;
|
||||
cmd &= ~0xff;
|
||||
|
||||
if( cmd != UFLASH_LOAD )
|
||||
return EINVAL;
|
||||
|
||||
struct nameidata nd;
|
||||
register struct nameidata *ndp = &nd;
|
||||
|
||||
//printf ("uflash_ioctl ('%s', ['%s', '%s', ...])\n", uap->fname, uap->argp[0], uap->argp[1]);
|
||||
|
||||
NDINIT (ndp, LOOKUP, FOLLOW, targetToFlash);
|
||||
ip = namei (ndp);
|
||||
if (ip == NULL) {
|
||||
result = EACCES;
|
||||
goto done;
|
||||
}
|
||||
|
||||
struct stat sb;
|
||||
int err = ino_stat (ip, &sb);
|
||||
if( err ) {
|
||||
result = err;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Erase Pages */
|
||||
|
||||
unsigned address = USE_USER_FLASH_START;
|
||||
int remaining = (int)sb.st_size;
|
||||
|
||||
while( remaining > 0 ) {
|
||||
flashErasePage( address );
|
||||
address += 4096;
|
||||
remaining -= 4096;
|
||||
}
|
||||
|
||||
/* TODO: reorgainize writing so that everything except the first
|
||||
* couple of bytes is written to flash and verified before
|
||||
* writing and verifying the first couple of bytes. The purpose
|
||||
* would be to leave the uflash area in an invalid state so that
|
||||
* the stub code would not attempt to execute it.
|
||||
*/
|
||||
|
||||
/* Write bin */
|
||||
|
||||
address = USE_USER_FLASH_START;
|
||||
remaining = (int)sb.st_size;
|
||||
|
||||
unsigned buffer[FLASH_BUFFER_INT_COUNT];
|
||||
|
||||
while( remaining ) {
|
||||
unsigned readsize = FLASH_BUFFER_INT_COUNT * sizeof(unsigned);
|
||||
if( readsize > remaining ) readsize = remaining;
|
||||
|
||||
int resid;
|
||||
err = rdwri (UIO_READ, ip, (caddr_t)buffer, readsize, (off_t) address - USE_USER_FLASH_START, IO_UNIT, &resid);
|
||||
|
||||
if( err ) {
|
||||
result = err;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if( resid ) {
|
||||
result = EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
flashWriteUint32(address, buffer, FLASH_BUFFER_INT_COUNT);
|
||||
|
||||
address += readsize;
|
||||
remaining -= readsize;
|
||||
}
|
||||
|
||||
/* Verify bin */
|
||||
|
||||
address = USE_USER_FLASH_START;
|
||||
remaining = (int)sb.st_size;
|
||||
|
||||
while( remaining ) {
|
||||
unsigned readsize = FLASH_BUFFER_INT_COUNT * sizeof(unsigned);
|
||||
if( readsize > remaining ) readsize = remaining;
|
||||
|
||||
int resid;
|
||||
err = rdwri (UIO_READ, ip, (caddr_t)buffer, readsize, (off_t) address - (unsigned)USE_USER_FLASH_START, IO_UNIT, &resid);
|
||||
|
||||
if( err ) {
|
||||
result = err;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if( resid ) {
|
||||
result = EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
int i;
|
||||
for( i = 0; i < readsize; ++i ) {
|
||||
if( ((char*)address)[i] != ((char*)buffer)[i] ) {
|
||||
result = EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
address += readsize;
|
||||
remaining -= readsize;
|
||||
}
|
||||
|
||||
done:
|
||||
if (ip)
|
||||
iput(ip);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*** void flashOperation(unsigned nvmop, unsigned addr, unsigned data)
|
||||
**
|
||||
** Synopsis:
|
||||
** Performs either a page erase, word write, or row write
|
||||
**
|
||||
** Parameters:
|
||||
** nvmop either NVMOP_PAGE_ERASE, NVMOP_WORD_PGM, or NVMOP_ROW_PGM
|
||||
** addr the unsigned_t flash address of: the page to erase, word location to write, or row location to write
|
||||
** data a unsigned_t of data to write, or the unsigned_t of the SRAM address containing the array of data to write to the row
|
||||
**
|
||||
** Return Values:
|
||||
** True if successful, false if failed
|
||||
**
|
||||
** Errors:
|
||||
** None
|
||||
**
|
||||
** Notes:
|
||||
** data has no meaning when page erase is specified and should be set to 0ul
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
* nvm_operation is borrowed from usb_boot.c and is controlled
|
||||
* by the following copyright:
|
||||
*
|
||||
* USB HID bootloader for PIC32 microcontroller.
|
||||
*
|
||||
* Based on Microchip sources.
|
||||
* Heavily rewritten by Serge Vakulenko, <serge@vak.ru>.
|
||||
*
|
||||
* The software supplied herewith by Microchip Technology Incorporated
|
||||
* (the 'Company') for its PIC(R) Microcontroller is intended and
|
||||
* supplied to you, the Company's customer, for use solely and
|
||||
* exclusively on Microchip PIC Microcontroller products. The
|
||||
* software is owned by the Company and/or its supplier, and is
|
||||
* protected under applicable copyright laws. All rights are reserved.
|
||||
* Any use in violation of the foregoing restrictions may subject the
|
||||
* user to criminal sanctions under applicable laws, as well as to
|
||||
* civil liability for the breach of the terms and conditions of this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED IN AN 'AS IS' CONDITION. NO WARRANTIES,
|
||||
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
|
||||
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
|
||||
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
|
||||
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||||
*/
|
||||
static void nvm_operation (unsigned op, unsigned address, unsigned data)
|
||||
{
|
||||
int x;
|
||||
|
||||
// Convert virtual address to physical
|
||||
NVMADDR = address & 0x1fffffff;
|
||||
NVMDATA = data;
|
||||
|
||||
// Disable interrupts
|
||||
x = mips_intr_disable();
|
||||
|
||||
// Enable Flash Write/Erase Operations
|
||||
NVMCON = PIC32_NVMCON_WREN | op;
|
||||
|
||||
// Data sheet prescribes 6us delay for LVD to become stable.
|
||||
// To be on the safer side, we shall set 7us delay.
|
||||
udelay (7);
|
||||
|
||||
NVMKEY = 0xAA996655;
|
||||
NVMKEY = 0x556699AA;
|
||||
NVMCONSET = PIC32_NVMCON_WR;
|
||||
|
||||
// Wait for WR bit to clear
|
||||
while (NVMCON & PIC32_NVMCON_WR)
|
||||
continue;
|
||||
|
||||
// Disable Flash Write/Erase operations
|
||||
NVMCONCLR = PIC32_NVMCON_WREN;
|
||||
|
||||
// Enable interrupts
|
||||
mips_intr_restore (x);
|
||||
#if 0
|
||||
// Check error status
|
||||
if (NVMCON & (PIC32_NVMCON_WRERR | PIC32_NVMCON_LVDERR)) {
|
||||
TODO;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// flashErasePage and flashWriteUint32 where originally from the file flash.c
|
||||
// implements the low level flash control and access.
|
||||
//
|
||||
// flash.c originated from the cpustick.com skeleton project from
|
||||
// http://www.cpustick.com/downloads.htm and was originally written
|
||||
// by Rich Testardi; please preserve this reference and share bug
|
||||
// fixes with rich@testardi.com.
|
||||
/*** void flashErasePage(unsigned addrPage)
|
||||
**
|
||||
** Synopsis:
|
||||
** Erases the page starting at the page address.
|
||||
*
|
||||
** Parameters:
|
||||
** addrPage The virtual address of the page to erase
|
||||
**
|
||||
** Return Values:
|
||||
** None
|
||||
**
|
||||
** Errors:
|
||||
** None
|
||||
**
|
||||
** Notes:
|
||||
**
|
||||
** addrPage must be page aligned.
|
||||
**
|
||||
*/
|
||||
static void flashErasePage(unsigned addrPage)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
unsigned x = ~0;
|
||||
unsigned *rgUint32 = (unsigned *) addrPage;
|
||||
|
||||
// we learned that just because the flash does not successfully
|
||||
// erase on the first attempt, it might on another. We found that
|
||||
// we can double the life of flash by attempting to
|
||||
// erase the flash up to 5 times before quitting.
|
||||
for(j=0; j<5; j++) {
|
||||
// first check to see if the page needs to be erased
|
||||
for (i = 0; i < FLASH_PAGE_SIZE/sizeof(unsigned); i++) {
|
||||
x &= rgUint32[i];
|
||||
}
|
||||
|
||||
// flash erased, we are done.
|
||||
if(x == ~0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Unlock and Erase Page
|
||||
nvm_operation(NVMOP_PAGE_ERASE, addrPage, 0);
|
||||
}
|
||||
|
||||
// at this point, we don't care if the flash ever actually erased as
|
||||
// as we will catch the failure when we verify the programming.
|
||||
}
|
||||
|
||||
|
||||
/*** void flashWriteUint32(unsigned addrUint32, unsigned *rgu32Data, unsigned cu32Data)
|
||||
**
|
||||
** Synopsis:
|
||||
** Writes an array to unsigned to flash
|
||||
*
|
||||
** Parameters:
|
||||
** rgu32Data Pointer to an array of unsigned
|
||||
** cu32Data The number of unsigned to write
|
||||
**
|
||||
** Return Values:
|
||||
** None
|
||||
**
|
||||
** Errors:
|
||||
** None
|
||||
**
|
||||
** Notes:
|
||||
**
|
||||
** Assumes the pages have already been erased.
|
||||
**
|
||||
*/
|
||||
static void flashWriteUint32(unsigned addrUint32, unsigned *rgu32Data, unsigned cu32Data)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for(i=0; i < cu32Data; i++) {
|
||||
// only do this if the data is not what is already in flash
|
||||
if(rgu32Data[i] != ~0) {
|
||||
// Write the data
|
||||
nvm_operation(NVMOP_WORD_PGM, addrUint32, rgu32Data[i]);
|
||||
}
|
||||
addrUint32 += sizeof(unsigned);
|
||||
}
|
||||
}
|
||||
@@ -563,7 +563,7 @@ int main()
|
||||
CHECONSET = 0x30;
|
||||
|
||||
/* Disable JTAG port, to use it for i/o. */
|
||||
DDPCON = 0;
|
||||
/*DDPCON = 0;*/
|
||||
|
||||
/* Config register: enable kseg0 caching. */
|
||||
mips_write_c0_register (C0_CONFIG, 0,
|
||||
|
||||
@@ -45,8 +45,10 @@ void cninit()
|
||||
IECSET(1) = 1 << (PIC32_IRQ_USB - 32);
|
||||
|
||||
/* Wait for any user input. */
|
||||
led_control (LED_KERNEL, 1);
|
||||
while (! cdc_consume(0))
|
||||
usb_device_tasks();
|
||||
led_control (LED_KERNEL, 0);
|
||||
}
|
||||
|
||||
void cnidentify()
|
||||
|
||||
@@ -42,10 +42,10 @@ I = ..
|
||||
#CFLAGS += -DDIP -DFLASH_JUMP=0x9d000000
|
||||
|
||||
# Microchip USB/Ethernet Starter Kit
|
||||
#CFLAGS += -DSTARTERKIT -DFLASH_JUMP=0x9d000000
|
||||
CFLAGS += -DSTARTERKIT -DFLASH_JUMP=0x9d000000
|
||||
|
||||
# Fubarino
|
||||
CFLAGS += -DFUBARINO -DFLASH_JUMP=0x9d000000
|
||||
#CFLAGS += -DFUBARINO -DFLASH_JUMP=0x9d000000
|
||||
|
||||
all: usbboot.hex usbboot.elf
|
||||
$(SIZE) usbboot.elf
|
||||
|
||||
Reference in New Issue
Block a user