eeprom: draft out firmware interfaces
authorAlan Cox <alan@linux.intel.com>
Sat, 25 Jul 2015 21:20:17 +0000 (22:20 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 25 Jul 2015 21:20:17 +0000 (22:20 +0100)
Kernel/platform-68hc11test/cpu.def [new file with mode: 0644]
Kernel/platform-68hc11test/eeprom.def [new file with mode: 0644]
Kernel/platform-68hc11test/eeprom.s [new file with mode: 0644]

diff --git a/Kernel/platform-68hc11test/cpu.def b/Kernel/platform-68hc11test/cpu.def
new file mode 100644 (file)
index 0000000..a4e333a
--- /dev/null
@@ -0,0 +1,69 @@
+;
+;      Probably belongs somewhere more general eventually
+;
+
+.equ porta,  iobase + 0x00
+; reserved 0x01
+.equ pioc,   iobase + 0x02
+.equ portc,  iobase + 0x03
+.equ portb,  iobase + 0x04
+.equ portcl, iobase + 0x05
+; reserved 0x06
+.equ ddrc,   iobase + 0x07
+.equ portd,  iobase + 0x08
+.equ ddrd,   iobase + 0x09
+.equ porte,  iobase + 0x0A
+.equ cforc,  iobase + 0x0B
+.equ oc1m,   iobase + 0x0C
+.equ oc1d,   iobase + 0x0D
+.equ tcnth,  iobase + 0x0E
+.equ tcntl,  iobase + 0x0F
+.equ tic1h,  iobase + 0x10
+.equ tic1l,  iobase + 0x11
+.equ tic2h,  iobase + 0x12
+.equ tic2l,  iobase + 0x13
+.equ tic3h,  iobase + 0x14
+.equ tic3l,  iobase + 0x15
+.equ toc1h,  iobase + 0x16
+.equ toc1l,  iobase + 0x17
+.equ toc2h,  iobase + 0x18
+.equ toc2l,  iobase + 0x19
+.equ toc3h,  iobase + 0x1a
+.equ toc3l,  iobase + 0x1b
+.equ toc4h,  iobase + 0x1c
+.equ toc4l,  iobase + 0x1d
+.equ ti4o5h, iobase + 0x1e
+.equ ti405l, iobase + 0x1f
+.equ tctl1,  iobase + 0x20
+.equ tctl2,  iobase + 0x21
+.equ tmsk1,  iobase + 0x22
+.equ tflg1,  iobase + 0x23
+.equ tmsk2,  iobase + 0x24
+.equ tflg2,  iobase + 0x25
+.equ pactl,  iobase + 0x26
+.equ pacnt,  iobase + 0x27
+.equ spcr,   iobase + 0x28
+.equ spsr,   iobase + 0x29
+.equ spdr,   iobase + 0x2A
+.equ baud,   iobase + 0x2B
+.equ sccr1,  iobase + 0x2C
+.equ sccr2,  iobase + 0x2D
+.equ scsr,   iobase + 0x2E
+.equ scdr,   iobase + 0x2F
+.equ adctl,  iobase + 0x30
+.equ adr1,   iobase + 0x31
+.equ adr2,   iobase + 0x32
+.equ adr3,   iobase + 0x33
+.equ adr4,   iobase + 0x34
+.equ bprot,  iobase + 0x35
+.equ eprog,  iobase + 0x36
+; reserved 0x37
+; reserved 0x38
+.equ option, iobase + 0x39
+.equ coprst, iobase + 0x3A
+.equ pprog,  iobase + 0x3B
+.equ hprio,  iobase + 0x3C
+.equ init,   iobase + 0x3D
+; reserved 0x3E
+.equ config, iobase + 0x3F
+
diff --git a/Kernel/platform-68hc11test/eeprom.def b/Kernel/platform-68hc11test/eeprom.def
new file mode 100644 (file)
index 0000000..bf97302
--- /dev/null
@@ -0,0 +1,61 @@
+;
+;      Shared definitions for EEPROM functions and mappings
+;
+.equ   iobase,         0xF000
+.equ   rambase,        0xF040
+
+       include "cpu.def"
+
+;
+;      Unbanked memory
+;
+.equ spibuf,           rambase + 0x00  ;       Used during boot, overlays
+                                       ;       tmp and post boot bits
+.equ tmp1,             rambase + 0x00  ;       First four words
+.equ tmp2,             rambase + 0x02  ;       also used for scratch spi
+.equ tmp3,             rambase + 0x04  ;       buffers etc
+.equ ret_d,            rambase + 0x06  ;       For far calls. Do not assume
+.equ ret_x,            rambase + 0x08  ;       values in rambase preserved
+.equ ret_y,            rambase + 0x0A  ;
+.equ ramsize,          rambase + 0x10  ;       RAM size in KB
+.equ eclock            rambase + 0x12  ;       E clock in KHz
+.equ unbanked_user,    rambase + 0x40  ;       128 bytes of unbanked
+                                       ;       RAM owned by the OS
+
+
+;
+;      Trap indirections. These can live in unbanked memory space.
+;
+.equ vector_sci, 0xF7B0
+.equ vector_spi, 0xF7B4
+.equ vector_pai, 0xF7B8
+.equ vector_pao, 0xF7BC
+.equ vector_to,  0xF7C0
+.equ vector_toc5,0xF7C4
+.equ vector_toc4,0xF7C8
+.equ vector_toc3,0xF7CC
+.equ vector_toc2,0xF7D0
+.equ vector_toc1,0xF7D4
+.equ vector_tic3,0xF7D8
+.equ vector_tic2,0xF7DC
+.equ vector_tic1,0xF7E0
+.equ vector_rti, 0xF7E4
+.equ vector_irq, 0xF7E8
+.equ vector_xirq,0xF7EC
+.equ vector_swi, 0xF7F0
+.equ vector_ill, 0xF7F4
+.equ vector_cop, 0xF7F8
+.equ vector_cmf, 0xF7FC
+
+
+.equ blocktype, 0xF7A0         ; block device types (16 bytes for)
+
+.equ   BDEV_NONE,              0x00
+.equ   BDEV_MMC,               0x01
+.equ   BDEV_SD1,               0x02
+.equ   BDEV_SD2,               0x04
+.equ   BDEV_SDC,               0x06
+.equ   BDEV_ATA,               0x10
+.equ   BDEVF_LBA,              0x80
+
+
diff --git a/Kernel/platform-68hc11test/eeprom.s b/Kernel/platform-68hc11test/eeprom.s
new file mode 100644 (file)
index 0000000..21b8812
--- /dev/null
@@ -0,0 +1,655 @@
+;
+;      EEPROM firmware for the 68HC811E2
+;
+;      TODO
+;      - any debug/testing 8)
+;
+;      Vector table for functions
+;      Add functions for spi block copy to/from banks
+;      Add description of SPI attached devices for OS
+;      Make serial mode ask if you want serial or retry SD
+;      Set up RTI timer and use interrupt to trap out of SPI layer
+;      on a timeout
+;
+;      Export outchar/outstr and friends so OS can use them (duplicated
+;      right now). Ditto for inchar, inchar/wait type stuff
+;
+;      Provide 'read block' 'write block' block device helpers so that
+;      the boot block can be tighter ?
+;
+;
+       .globl _start
+
+       include "eeprom.def"
+
+       .sect .text
+;
+_start:
+       lds #0xF100     ;       Stack in unbanked internal ram
+       ldaa #0xFF
+       staa init       ;       Move the internal RAM and I/O to Fxxx
+       stab porta      ;       clear output controls
+       ldaa #0x88
+       staa pactl      ;       Port A bit 7 and bit 3 to output
+;
+;      Real RAM is now definitely in bank 0
+;
+       ldaa #0x30      ;       9600 baud
+       staa baud
+       ldy #boot1      ;       say hello
+       jsr outstr
+       ldd #0xff55
+       ldy #0x1000     
+       staa ,y         ;       arbitrary real RAM if we set up right
+       cmpa ,y         ;       should match
+       bne ramfucked
+       dec ,y          ;       zero
+       tst ,y          ;       check
+       bne ramfucked
+;
+;      OK we seem to have RAM wired to do 00 and FF
+;
+       stab 1,y        ;       0x55
+       ldaa ,y         ;       should be unchanged
+       cmpa #0xff      ;       address bus not working ?
+       bne ramfucked2
+;
+;      Promising !
+;
+       clrb
+writepgs:              ;       write the page ident into each bank
+       stab ,x         ;       select this RAM bank
+       stab ,y
+       addb #0x08
+       cmpb #0xF8
+       bne writepgs
+       clrb
+readpgs:               ;       read the page ident from each bank
+       stab ,x         ;       select this RAM bank
+       cmpb ,y         ;       should match
+       bne ramfucked3  ;       bank bits busted
+       addb #0x08
+       cmpb #0xF8
+       bne readpgs
+;
+;      We could size the RAM if we needed to be flexible in future but
+;      for now we don't so cheat
+;
+       ldy #boot2
+       jsr outstr
+
+       ldx #rambase
+       ldd #0xC0
+wipelow:
+       staa ,x
+       inx
+       deca
+       bne wipelow
+
+       ; Save RAM size (fixed for now)
+       ldd #512
+       std ramsize
+       ; Set for board (FIXME - .equ for this)
+       ldd #2048
+       std eclock
+;
+;      Serial works, RAM seems to work, it's time to whack the SD card
+;
+       jsr sdboot
+;
+;      If not then we try a serial boot
+;
+       jsr serboot
+       ldx #bootfail
+       jsr outstr
+       ldaa #0xA0
+       bra fail
+
+ramfucked:
+       ldaa #0x88
+       bra fail
+ramfucked2:
+       ldaa #0x90
+       bra fail
+ramfucked3:
+       ldaa #0x98
+fail:
+       jsr outcharhex          ; print the hex code
+       staa ,x                 ; assert it on the bank control pins
+failloop:
+       staa 0xDEAD             ; keep asserting DEAD on the address bus
+       bra failloop            ; and the error on data
+
+outcharhex:
+       pshb
+       lsrb
+       lsrb
+       lsrb
+       lsrb
+       bsr outnibble
+       pulb
+       pshb
+       bsr outnibble
+       pulb
+       rts
+
+outnibble:
+       andb #0x0F
+       cmpb #0x0A
+       ble outh2
+       addb #0x07
+outh2: addb #0x30
+outchar:
+       psha
+outchar1:
+       ldaa scsr
+       anda #0x80
+       beq outchar1
+       stab scdr
+       pula
+outsdone:
+       rts
+
+outstr:
+       ldab ,x
+       beq outsdone
+       bsr outchar
+       inx
+       bra outstr
+
+;
+;      Send an extended command - CMD 55 then the actual cmd. If the CMD55
+;      is rejected the then ACMD is rejected
+;
+spi_send_acmdxy:
+       pshb
+       pshx
+       pshy
+       ldab #55
+       bsr spi_send_cmd
+       cmpb #1
+       bgt acmd_fail
+       puly
+       pulx
+       pulb
+       bra spi_send_cmd
+acmd_fail:
+       rts
+;
+;      Read a byte, only uses B
+;
+spi_rx:
+       ldab #0xFF
+spi_tx:
+       stab spdr
+spi_rx_w:
+       ldab spsr
+       andb #0x80
+       beq spi_rx_w            ; Fixme - timeout handling
+       ldab spdr
+       rts
+
+sd_spi_wait_ff:                        ; Timeouts!
+       bsr spi_rx
+       cmpb #0xff
+       beq sd_spi_wait_ff
+       rts
+
+sd_spi_wait:                   ; Ditto
+       bsr spi_rx
+       cmpb #0xff
+       bne sd_spi_wait
+       rts
+
+;
+;      Chip selects for SD card
+;
+spi_cs_hi:
+       psha                    ; other bits are not write bits so be slack
+       ldaa #0x40
+       staa portd
+       pula
+       rts
+
+spi_cs_lo:
+       clr portd
+       rts
+
+spi_send_cmd:
+       ldx #0
+spi_send_cmdx:
+       ldy #0
+spi_send_cmdxy:
+       addb #0x40              ; command number to code
+       bsr spi_cs_hi
+       bsr spi_rx              ; clocks
+       bsr spi_cs_lo
+       bsr sd_spi_wait_ff
+       tsta
+       bne sdfail
+       pshb
+       bsr spi_tx              ; send acc B
+       xgdy
+       pshb
+       tab
+       bsr spi_tx
+       pulb
+       bsr spi_tx
+       xgdx
+       pshb
+       tab
+       bsr spi_tx
+       pulb
+       bsr spi_tx
+       pulb                    ; get the cmd back
+       pshb
+       ldaa #0x01              ; dummy + stop
+       cmpb #0x40              ; special cases
+       bne ncrc_cmd0
+       ldaa #0x95
+       bra tx_crc
+ncrc_cmd0:
+       cmpb #0x48
+       bne tx_crc
+       ldaa #0x87
+tx_crc:        tab
+       bsr spi_tx
+       pulb
+       cmpb #0x4C
+       bne no_rx_dummy
+       bsr spi_rx
+no_rx_dummy:
+       ldaa #0x14
+rx_waitr:
+       bsr spi_rx
+       bitb #0x80
+       beq cmd_rx_done
+       deca
+       bne rx_waitr
+cmd_rx_done:
+       rts
+
+
+sdfail:
+       ldab #0xFF
+       rts
+sdboot:
+       ldd #0x523F
+       staa spcr               ; SPI on, master, SPI(0,0), 125KHz
+       stab ddrd               ; Port 5 is output (not !SS)
+       bsr spi_cs_hi
+       ldaa #0x20
+sdboot1:
+       bsr spi_rx              ; send clocks
+       deca
+       bne sdboot1
+       clrb                    ; CMD 0
+       bsr spi_send_cmd
+       cmpa #1                 ; 1 indicates OK
+       bne sdfail
+       ldx #spi_probe1
+       jsr outstr              ; display indication of probing
+                               ; as we have a card of some form
+       ldab #8
+       ldx #0x01AA
+       bsr spi_send_cmdx
+       cmpb #1                 ; if CMD 8 fails it's not SDHC
+       bne try_mmc
+       ;
+       ;       Looks like we are an SDHC card
+       ;
+       ldx #spibuf
+       ldab #4
+       jsr spi_rx              ; should be four data bytes
+       ldd #0x01AA
+       cmpa spibuf+2           ; and should end with 0x01AA
+       bne bad_card_v          ; bad voltage ?
+       cmpb spibuf+3
+       bne bad_card_v
+       ;
+       ;       Ok looks good now see if it will wake up
+       ;       FIXME: timeout needed
+       ;
+spinidle:
+       ldy #0x4000
+       ldx #0
+       ldab #41
+       jsr spi_send_acmdxy     ; wait for the card to exit idle
+       tsta
+       bne spinidle
+       ldab #58
+       jsr spi_send_cmd
+       ldab #4
+       ldx #spibuf
+       jsr spi_rx
+       ldab spibuf
+       ldaa #BDEV_SD2
+       andb #0x40
+       beq notblock
+       oraa #BDEVF_LBA
+notblock:
+       staa blocktype
+       ldx #boot_sdhc
+       jsr outstr
+       bra sd_valid
+
+bad_card_v:
+       ldx #spi_badcardv
+       jmp outstr
+
+try_mmc:
+       ldab #41
+       ldx #0
+       ldy #0
+       jsr spi_send_acmdxy
+       cmpa #1
+       ble is_sdv1
+       ldx #boot_mmc
+       jsr outstr
+       ldaa #BDEV_MMC
+       bra det_ok
+is_sdv1:
+       ldx #boot_sdv1
+       jsr outstr
+       ldaa #BDEV_SD1
+det_ok:
+       staa blocktype
+sd_valid:
+       ldaa #0x50
+       staa spcr               ; SPI to full speed
+
+       ldx #0                  ; Block or byte 0 - we don't care about LBA!
+       ldy #0
+       ldab #17                ; Read
+       jsr spi_send_cmdxy
+       tsta                    ; Read command worked
+       bne spi_rx_fail
+       ldd #0xFE               ; FIXME: check
+       jsr sd_spi_wait
+       tsta
+       bne spi_rx_fail
+       ldx #0xE000
+       ldab #0x00
+sd_rx_l:
+       staa spdr               ; any value will do
+sd_rx_w:
+       ldaa spcr               ; are we done yet
+       anda #0x80
+       beq sd_rx_w
+       ldaa spdr               ; SPI data byte
+       staa ,x
+       inx
+       decb
+       bne sd_rx_l
+;
+;      Success
+;
+       ldx 0xE000
+       cpx #0xC0DE
+       bne notbootable
+       ldx #sdbooting
+       jsr outstr
+       jmp 0xE002              ; jmp to boot block
+
+spi_rx_fail:
+       ldx #ioerror
+       bra sdretry
+
+notbootable:
+       ldx #notbootmedia
+sdretry:
+       jsr outstr
+       jsr hitnl
+       jmp sdboot              ; try again
+       
+
+;
+;      Serial input
+;
+
+hitnl: bsr waitkey
+       cmpa #13
+       beq nlok
+       cmpa #10
+       bne hitnl
+nlok:  rts
+
+waitkey:
+       ldab scsr
+       andb #0x20
+       beq waitkey
+       ldab scdr
+       rts
+
+serboot:
+       ldx #sergo
+       jsr outstr
+       ldx #0xE000
+serbootl:
+       bsr waitkey
+       stab ,x
+       inx
+       cmpx #0xE200
+       bne serbootl
+       ldd #0xE000
+       cmpa #0xC0
+       bne serbad
+       cmpb #0xDE
+       bne serbad
+       jmp 0xE002
+serbad:
+       rts
+
+;
+;      Service Routines.
+;
+bankcomp:
+       ldab porta
+       pshb
+       andb #0xC0              ; preserve other controls
+       aba                     ; we know the bank in A will have the other
+                               ; bits clear
+       pulb                    ; B gets us back
+       rts
+       
+fargetw:
+       bsr bankcomp
+       staa porta              ; switch bank
+       ldx  ,x                 ; get the word
+       stab porta              ; and back
+       xgdx                    ; result in D
+       rts
+
+fargetb:
+       bsr fargetw
+       tab                     ; big endian so we want high half in low
+       clra
+       rts
+
+farputw:
+       bsr bankcomp
+       staa porta
+       sty ,x
+       stab porta
+       rts
+
+farputb:
+       xgdy
+       bsr bankcomp
+       staa porta
+       xgdy                    ; b is now the value
+       stab ,x
+       xgdy                    ; b is now the bank restore
+       stab porta
+       rts
+
+; FIXME - optimise for 2 bytes at a time ?
+
+farzero:
+       bsr bankcomp
+       staa porta
+farzl:
+       clr ,x
+       inx
+       dey
+       cmpy #0
+       bne farzl
+       stab porta
+       rts
+
+;
+;      FIXME: optimise!
+;
+farcopy:
+       ; FIXME: - set up bank regs
+
+copywl:
+       ldaa tmp2
+       staa porta
+       ldaa ,x
+       stab porta
+       staa ,y
+       inx
+       iny
+       dec tmp1
+       bne copywl
+       ldaa tmp3               ; saved original bank
+       staa porta
+       rts
+
+; FIXME: to do
+farzcopy:
+       rts
+
+
+farcall:
+       tpa
+       psha
+       sei             ; interrupts off a minute
+       staa tmp2       ; save irq flags
+       sts tmp1        ; save stack
+       jsr farcall2    ; we need a helper on the return path
+       ; we come back on the new stack
+       puly            ; old sp
+       pulb            ; old bank
+       pula            ; flags (irq state)
+       sei             ; stack will be invalid for an instruction
+       tys             ; back to old stack
+       stab porta      ; and old bank
+       tap             ; irq flags back to entry state
+       rts
+
+
+farcall2:
+       bsr bankcomp
+       staa porta
+       tys                     ; new stack now valid
+       ldy tmp1                ; old stack
+       ldaa tmp2               ; restore irq state
+       tap
+       psha
+       pshb                    ; save old bank code on new stack
+       pshy                    ; save old stack on new stack
+       pshx                    ; target address
+       ldy ret_y               ; set up registers
+       ldx ret_x
+       ldd ret_d
+       rts
+
+
+farjump:
+       tap
+       sei
+       staa tmp2
+       bsr bankcomp
+       staa porta
+       tys                     ; new stack valid
+       ldaa tmp2
+       tap                     ; irq status back
+       pshx
+       ldy ret_y
+       ldx ret_x
+       ldd ret_d
+       rts
+
+reboot:
+       sei
+       jmp 0xF800
+
+;
+;      Make a cross domain IRQ handler call (X = descriptor)
+;
+;      We stack the registers on the current stack, then switch to bank 0
+;      and invoke the handler (with interrupts still disabled) in bank 0.
+;      Upon completion we switch back to the old stack and recover
+;
+interrupt:
+       tsy                     ; save old stack frame
+       ldab porta              ; old bank
+       tba
+       andb #0x3F              ; bank bits only
+       anda #0xC0              ; control bits
+       staa porta              ; now in kernel bank
+       ;
+       ;       Don't read the vectors until we switch bank. The vectors
+       ;       can then live in bank 0 space, not precious 
+       ;
+       lds 2,x                 ; IRQ stack vector (set by OS)
+       pshy                    ; save old stack
+       pshb                    ; save bank bits
+       ldx ,x                  ; vector is (func, stack)
+       jsr ,x                  ; call
+       pulb                    ; old bank
+       puly                    ; old stack pointer
+       ldaa porta
+       anda #0xC0
+       aba
+       staa porta              ; back to calling bank
+       tys                     ; back to old stack
+       rti
+
+boot1: .ascii "68HC811 Bootware"
+       .byte 13,10,0
+boot2: .byte 13,10
+       .ascii "512Kb RAM"
+       .byte 13,10,0
+bootfail:
+       .byte 13,10
+       .ascii "No boot device found"
+       .byte 13,10,0
+spi_probe1:
+       .byte 13,10
+       .ascii "sd0: "
+       .byte 0
+spi_badcardv:
+       .ascii "Invalid voltage"
+       .byte 13,10,0
+ioerror:
+       .ascii "I/O error"
+       .byte 13,10,0
+boot_sdhc:
+       .ascii "SDHC"
+       .byte 0
+boot_sdv1:
+       .ascii "SD"
+       .byte 0
+boot_mmc:
+       .ascii "MMC"
+       .byte 0
+notbootmedia:
+       .ascii " - not bootable"
+       .byte 13,10,0
+sdbooting:
+       .ascii " - bootable",
+       .byte 13,10,13,10,0
+hitnewline:
+       .ascii "Hit newline to retry boot"
+newline:
+       .byte 13,10,0
+sergo:
+       .ascii "Serial boot: being download"
+       .byte 13,10
+       .ascii ">"
+       .byte 0
+
+