dragon-nx32: add initial 65spi code
authorAlan Cox <alan@linux.intel.com>
Thu, 4 Jun 2015 22:00:50 +0000 (23:00 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 4 Jun 2015 22:00:50 +0000 (23:00 +0100)
Kernel/platform-dragon-nx32/spi.s [new file with mode: 0644]

diff --git a/Kernel/platform-dragon-nx32/spi.s b/Kernel/platform-dragon-nx32/spi.s
new file mode 100644 (file)
index 0000000..502647d
--- /dev/null
@@ -0,0 +1,161 @@
+;
+;      SPI interface for the 65SPI on the NX32 with SPI
+;
+
+       .module dragonspi
+
+       .globl _spi_setup
+       .globl _sd_spi_clock
+       .globl _sds_spi_transmit_byte
+       .globl _sd_spi_lower_cs
+       .globl _sd_spi_raise_cs
+       .globl _sd_spi_transmit_byte
+       .globl _sd_spi_receive_byte
+       .globl _sd_spi_receive_sector
+       .globl _sd_spi_transmit_sector
+
+       .globl _blk_op
+
+        include "kernel.def"
+        include "../kernel09.def"
+
+       .area .text
+
+_spi_setup:
+       clra
+       sta SPICTRL             ; just in case
+       lda #0x0F
+       sta SPISIE              ; selects off, IRQs off
+       cmpa SPISIE
+       beq nospi
+       lda SPIDATA             ; clear TC
+       lda SPISTATUS
+       bpl nospi               ; TC not clear -> no spi present
+       sta SPIDATA             ; start a transmit, TC should now be clear
+       lda SPISTATUS
+       bmi spigood
+nospi: clrb
+       rts
+spigood:
+       ldb #1
+       rts
+
+
+;
+;      May need to switch clocks too
+;
+_sd_spi_clock:
+       cmpb #0                 
+       beq slow
+       ldd #0x0401             ; external 45MHz clock on, divide by 3
+       bra clkset
+slow:  ldd #0x0003             ; internal clock, phi/5 -> 2MHz/5 = 400Khz
+clkset:        std SPICTRL
+       rts
+
+;
+;      For multiple cards these need to look at the card #
+;
+_sd_spi_lower_cs:
+       lda SPISIE
+       ora #SPICS
+       sta SPISIE
+       rts
+
+_sd_spi_raise_cs:
+       lda SPISIE
+       anda #0xFF-SPICS
+       sta SPISIE
+       rts
+
+;
+;      We must check for busy as these methods are used at low speed
+;
+_sd_spi_transmit_byte:
+       stb SPIDATA
+txwait:
+       lda SPISTATUS
+       anda #0x40
+       bne txwait
+       rts
+
+_sd_spi_receive_byte:
+       lda #0xFF
+       sta SPIDATA
+rxwait:
+       lda SPISTATUS           ; wait for bit 7 to set
+       bpl rxwait
+       ldb SPIDATA
+       rts
+
+       .area .common
+
+;
+;      Swap not done yet.
+;
+;      The SPI clock must be in fast mode here as we don't poll the busy
+;      bits but know that by the time the CPU arrives at the next byte
+;      the transaction is done. Note - we don't have to worry about the
+;      interrupt situation here, we drive the clocks so if we go off for
+;      an interrupt all is fine.
+;
+_sd_spi_receive_sector:
+       pshs y,dp
+       lda #0xFF
+       tfr a,dp
+       lda _blk_op + 2
+       beq rdspi
+       jsr map_process_always
+rdspi: ldx _blk_op
+       leay 512,x
+       sty endspi
+       lda #0x44               ; FRX on, external clock on
+read8:
+       lda <SPIDATA
+       ldb <SPIDATA
+       std ,x++
+       lda <SPIDATA
+       ldb <SPIDATA
+       std ,x++
+       lda <SPIDATA
+       ldb <SPIDATA
+       std ,x++
+       lda <SPIDATA
+       ldb <SPIDATA
+       std ,x++
+       cmpx endspi
+       bne read8
+       jsr map_kernel
+       lda #0x04
+       sta SPICTRL             ; FRX off, external clock on
+       puls y,dp,pc
+
+_sd_spi_transmit_sector:
+       pshs y,dp
+       lda #0xFF
+       tfr a,dp
+       lda _blk_op + 2
+       beq wrspi
+       jsr map_process_always
+wrspi: ldx _blk_op
+       leay 512,x
+       sty endspi
+write8:
+       ldd ,x++
+       sta <SPIDATA
+       stb <SPIDATA
+       ldd ,x++
+       sta <SPIDATA
+       stb <SPIDATA
+       ldd ,x++
+       sta <SPIDATA
+       stb <SPIDATA
+       ldd ,x++
+       sta <SPIDATA
+       stb <SPIDATA
+       cmpx endspi
+       bne write8
+       jsr map_kernel
+       puls y,dp,pc
+
+endspi:        .dw 0