spi: Get basic SPI commands working

This commit is contained in:
Sean Cross 2014-09-12 16:46:11 +08:00
parent 8d0e780508
commit 43a1517aec
8 changed files with 118 additions and 77 deletions

View file

@ -15,11 +15,13 @@ SRC_C = \
cmd-peekpoke.c \ cmd-peekpoke.c \
cmd-reboot.c \ cmd-reboot.c \
cmd-sleep.c \ cmd-sleep.c \
cmd-spi.c \
emi.c \ emi.c \
irq.c \ irq.c \
main.c \ main.c \
scriptic.c \ scriptic.c \
serial.c \ serial.c \
spi.c \
utils.c \ utils.c \
vectors.c \ vectors.c \
vsprintf.c vsprintf.c
@ -27,6 +29,8 @@ SRC_C = \
SRC_S = \ SRC_S = \
scriptic/set-plls.S \ scriptic/set-plls.S \
scriptic/enable-psram.S \ scriptic/enable-psram.S \
scriptic/spi.S \
scriptic/spi-blockmode.S \
_udivsi3.S \ _udivsi3.S \
_divsi3.S \ _divsi3.S \
start.S start.S

View file

@ -4,30 +4,30 @@
#include "printf.h" #include "printf.h"
#include "spi.h" #include "spi.h"
#define SPI_CSEL 0
int cmd_spi(int argc, char **argv) int cmd_spi(int argc, char **argv)
{ {
uint32_t recv_bytes_count; uint32_t recv_bytes_count;
uint8_t xmit_bytes[argc - 1]; uint8_t xmit_bytes[argc - 1];
int i; int i;
if (argc == 1 && !_strcasecmp(argv[0], "loop")) { if (argc > 0 && !_strcasecmp(argv[0], "id")) {
printf("Repeatedly sending 0x9f -- id\n"); uint8_t out[1] = {0x9f};
while(1) { uint8_t in[3];
uint8_t out[1] = {0x9f};
uint8_t in[3]; spi_cmd_txrx(sizeof(out), sizeof(in), out, in);
spi_cmd_txrx(0, sizeof(out), sizeof(in), out, in);
printf("ID: "); printf("ID: %02x %02x %02x\n", in[0], in[1], in[2]);
serial_print_hex(in, sizeof(in));
} return 0;
} }
if (argc < 2) { if (argc < 2) {
printf("Send SPI bytes out and read the response.\n"); printf("Send SPI bytes out and read the response.\n");
printf("Usage: spi [count] [byte 1] [byte 2] ...\n"); printf("Usage:\n");
printf(" Where \"count\" is the number of bytes to expect" printf(" spi [count] [byte 1] [byte 2] ...\n");
" in response.\n"); printf(" Where \"count\" is the number of bytes to expect"
" in response.\n");
printf(" spi id -- get device id\n");
return 1; return 1;
} }
@ -41,7 +41,7 @@ int cmd_spi(int argc, char **argv)
sizeof(xmit_bytes), sizeof(recv_bytes)); sizeof(xmit_bytes), sizeof(recv_bytes));
serial_print_hex(xmit_bytes, sizeof(xmit_bytes)); serial_print_hex(xmit_bytes, sizeof(xmit_bytes));
spi_cmd_txrx(SPI_CSEL, sizeof(xmit_bytes), sizeof(recv_bytes), spi_cmd_txrx(sizeof(xmit_bytes), sizeof(recv_bytes),
xmit_bytes, recv_bytes); xmit_bytes, recv_bytes);
printf("Response:\n"); printf("Response:\n");

View file

@ -2,6 +2,7 @@
#ifndef __SPI_H__ #ifndef __SPI_H__
#define __SPI_H__ #define __SPI_H__
#define SPI_ADDR 0xa0140000 int spi_cmd_txrx(uint8_t tx_size, uint8_t rx_size,
uint8_t *tx_buf, uint8_t *rx_buf);
#endif /* __SPI_H__ */ #endif /* __SPI_H__ */

19
main.c
View file

@ -184,8 +184,6 @@ static int list_registers(void)
static int do_init(void) static int do_init(void)
{ {
const struct scriptic *script;
list_registers(); list_registers();
/* Disable system watchdog */ /* Disable system watchdog */
@ -197,11 +195,8 @@ static int do_init(void)
/* Disable battery watchdog */ /* Disable battery watchdog */
writew(0x2, PMIC_CTRL9); writew(0x2, PMIC_CTRL9);
script = scriptic_get("set_plls"); scriptic_run("set_plls");
scriptic_execute(script); scriptic_run("enable_psram");
script = scriptic_get("enable_psram");
scriptic_execute(script);
serial_puts("\n\nFernly shell\n"); serial_puts("\n\nFernly shell\n");
@ -337,12 +332,13 @@ static int loop(void)
static int cmd_help(int argc, char **argv); static int cmd_help(int argc, char **argv);
extern int cmd_hex(int argc, char **argv); extern int cmd_hex(int argc, char **argv);
extern int cmd_irq(int argc, char **argv);
extern int cmd_msleep(int argc, char **argv);
extern int cmd_peek(int argc, char **argv); extern int cmd_peek(int argc, char **argv);
extern int cmd_poke(int argc, char **argv); extern int cmd_poke(int argc, char **argv);
extern int cmd_spi(int argc, char **argv);
extern int cmd_swi(int argc, char **argv); extern int cmd_swi(int argc, char **argv);
extern int cmd_reboot(int argc, char **argv); extern int cmd_reboot(int argc, char **argv);
extern int cmd_msleep(int argc, char **argv);
extern int cmd_irq(int argc, char **argv);
static const struct { static const struct {
int (*func)(int argc, char **argv); int (*func)(int argc, char **argv);
@ -384,6 +380,11 @@ static const struct {
.name = "irq", .name = "irq",
.help = "Manipulate IRQs", .help = "Manipulate IRQs",
}, },
{
.func = cmd_spi,
.name = "spi",
.help = "Manipulate on-board SPI",
},
{ {
.func = cmd_swi, .func = cmd_swi,
.name = "swi", .name = "swi",

View file

@ -3,14 +3,19 @@
#include "bionic.h" #include "bionic.h"
#include "memio.h" #include "memio.h"
#define SCRIPTIC_DEBUG /* Enable this to print commands as they're executed */ //#define SCRIPTIC_DEBUG /* Enable this to print commands as they're executed */
extern struct scriptic set_plls; extern struct scriptic set_plls;
extern struct scriptic enable_psram; extern struct scriptic enable_psram;
extern struct scriptic spi_run;
extern struct scriptic spi_run;
extern struct scriptic spi_init;
static struct scriptic *scripts[] = { static struct scriptic *scripts[] = {
&set_plls, &set_plls,
&enable_psram, &enable_psram,
&spi_run,
&spi_init,
}; };
#ifdef SCRIPTIC_DEBUG #ifdef SCRIPTIC_DEBUG

View file

@ -2,7 +2,7 @@
#include "fernvale-spi.h" #include "fernvale-spi.h"
/* Enable block mode for SPI CS0 */ /* Enable block mode for SPI CS0 */
sc_new "spi_run_cs0", 1, 0, 0 sc_new "spi_run", 1, 0, 0
/* Wait for channel 2 to be idle */ /* Wait for channel 2 to be idle */
sc_write32 SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3 sc_write32 SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3
@ -15,7 +15,7 @@
/* Trigger the transfer */ /* Trigger the transfer */
sc_write32 \ sc_write32 \
SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS0, \ SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS0, \
SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS0, \ SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS, \
SPI_BLOCKMODE SPI_BLOCKMODE
/* Wait for the device to prepare itself */ /* Wait for the device to prepare itself */
@ -25,48 +25,7 @@
sc_read32 0, SPI_BLOCKMODE_BUSY, SPI_BLOCKMODE sc_read32 0, SPI_BLOCKMODE_BUSY, SPI_BLOCKMODE
/* Stop the transfer */ /* Stop the transfer */
sc_write32 0, SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS0, SPI_BLOCKMODE sc_write32 0, SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS, SPI_BLOCKMODE
/* Wait for it to be disabled */
sc_read32 0, SPI_BLOCKMODE_PREP, SPI_BLOCKMODE
/* Exit block mode */
sc_write32 0, SPI_BLOCKMODE_ENABLE, SPI_BLOCKMODE
/* Wait for the chip to actually exit block mode */
sc_read32 0, SPI_BLOCKMODE_ENABLE, SPI_BLOCKMODE
/* Allow channel 2 to contain data */
sc_write32 0, SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3
sc_end
/* Enable block mode for SPI CS1 */
sc_new "spi_run_cs1", 1, 0, 0
/* Wait for channel 2 to be idle */
sc_write32 SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3
sc_read32 SPI_CTRL3_CHANNEL2_IDLE, SPI_CTRL3_CHANNEL2_IDLE, SPI_CTRL3
sc_read32 SPI_CTRL1_BUS_IDLE, SPI_CTRL1_BUS_IDLE, SPI_CTRL1
/* Turn on block mode */
sc_write32 SPI_BLOCKMODE_ENABLE, SPI_BLOCKMODE_ENABLE, SPI_BLOCKMODE
/* Trigger the transfer */
sc_write32 \
SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS1, \
SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS1, \
SPI_BLOCKMODE
/* Wait for the device to prepare itself */
sc_read32 SPI_BLOCKMODE_PREP, SPI_BLOCKMODE_PREP, SPI_BLOCKMODE
/* Wait for it to finish */
sc_read32 0, SPI_BLOCKMODE_BUSY, SPI_BLOCKMODE
/* Stop the transfer */
sc_write32 0, SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS1, SPI_BLOCKMODE
/* Wait for it to be disabled */ /* Wait for it to be disabled */
sc_read32 0, SPI_BLOCKMODE_PREP, SPI_BLOCKMODE sc_read32 0, SPI_BLOCKMODE_PREP, SPI_BLOCKMODE

View file

@ -1,22 +1,57 @@
#include "scriptic.h" #include "scriptic.h"
#include "fernvale-spi.h" #include "fernvale-spi.h"
#include "fernvale-gpio.h"
sc_new "spi_init", 1, 0, 0 sc_new "spi_init", 1, 0, 0
/* Ungate the clock */ /* Ungate the clock */
sc_write16 0x800, 0x800, 0x80000320 sc_write16 0x800, 0x800, 0x80000320
/* Switch to SPI NOR */ /* (XXX Might need to invert this) */ /* Switch to SPI NOR */
sc_write16 0, 1, 0x80000230 sc_write16 0, 1, 0x80000230
/* Remap GPIOs to be SPI */ /* Remap GPIOs to be SPI */
sc_write32 0x11111100, 0x77777700, 0xa0020c80 sc_write32 \
sc_write32 0x00000011, 0x00000077, 0xa0020c90 GPIO_CTRL_MODE8_IO66_SFCS1 | \
GPIO_CTRL_MODE8_IO67_SFWP | \
GPIO_CTRL_MODE8_IO68_SFCS0 | \
GPIO_CTRL_MODE8_IO69_SFCK | \
GPIO_CTRL_MODE8_IO70_SFIN | \
GPIO_CTRL_MODE8_IO71_SFOUT, \
GPIO_CTRL_MODE8_IO66_MASK | \
GPIO_CTRL_MODE8_IO67_MASK | \
GPIO_CTRL_MODE8_IO68_MASK | \
GPIO_CTRL_MODE8_IO69_MASK | \
GPIO_CTRL_MODE8_IO70_MASK | \
GPIO_CTRL_MODE8_IO71_MASK, \
GPIO_CTRL_MODE8
sc_write32 \
GPIO_CTRL_MODE9_IO72_SFSHOLD, \
GPIO_CTRL_MODE9_IO72_MASK, \
GPIO_CTRL_MODE9
/* Enable high-impedence for GPIO mode */ /* Enable high-impedence for GPIO mode */
sc_write16 0, 0x3fff, 0xa0020b10 sc_write16 0, \
sc_write16 0, 0x3fff, 0xa0020b40 GPIO_CTRL_PULL_CTRL1_IO66 | \
sc_write16 0, 0xdff1, 0xa0020b20 GPIO_CTRL_PULL_CTRL1_IO67 | \
sc_write16 0, 0xdff1, 0xa0020b50 GPIO_CTRL_PULL_CTRL1_IO72, \
GPIO_CTRL_RESEN1_R0
sc_write16 0, \
GPIO_CTRL_PULL_CTRL1_IO66 | \
GPIO_CTRL_PULL_CTRL1_IO67 | \
GPIO_CTRL_PULL_CTRL1_IO72, \
GPIO_CTRL_RESEN1_R1
sc_write16 0, \
GPIO_CTRL_PULL_CTRL2_IO68 | \
GPIO_CTRL_PULL_CTRL2_IO69 | \
GPIO_CTRL_PULL_CTRL2_IO70 | \
GPIO_CTRL_PULL_CTRL2_IO71, \
GPIO_CTRL_RESEN2_R0
sc_write16 0, \
GPIO_CTRL_PULL_CTRL2_IO68 | \
GPIO_CTRL_PULL_CTRL2_IO69 | \
GPIO_CTRL_PULL_CTRL2_IO70 | \
GPIO_CTRL_PULL_CTRL2_IO71, \
GPIO_CTRL_RESEN2_R1
sc_end sc_end

36
spi.c Normal file
View file

@ -0,0 +1,36 @@
#include <stdint.h>
#include <string.h>
#include "printf.h"
#include "bionic.h"
#include "memio.h"
#include "spi.h"
#include "fernvale-spi.h"
#include "scriptic.h"
static void spi_init(void)
{
static int spi_initted = 0;
if (spi_initted)
return;
spi_initted = 1;
scriptic_run("spi_init");
}
int spi_cmd_txrx(uint8_t tx_size, uint8_t rx_size,
uint8_t *tx_buf, uint8_t *rx_buf)
{
spi_init();
_memcpy(SPI_DATA, tx_buf, tx_size);
writel(tx_size, SPI_WRITE_COUNT);
writel(rx_size, SPI_READ_COUNT);
scriptic_run("spi_run");
_memcpy(rx_buf, SPI_DATA + tx_size, rx_size);
return 0;
}