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-reboot.c \
cmd-sleep.c \
cmd-spi.c \
emi.c \
irq.c \
main.c \
scriptic.c \
serial.c \
spi.c \
utils.c \
vectors.c \
vsprintf.c
@ -27,6 +29,8 @@ SRC_C = \
SRC_S = \
scriptic/set-plls.S \
scriptic/enable-psram.S \
scriptic/spi.S \
scriptic/spi-blockmode.S \
_udivsi3.S \
_divsi3.S \
start.S

View file

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

View file

@ -2,6 +2,7 @@
#ifndef __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__ */

19
main.c
View file

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

View file

@ -3,14 +3,19 @@
#include "bionic.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 enable_psram;
extern struct scriptic spi_run;
extern struct scriptic spi_run;
extern struct scriptic spi_init;
static struct scriptic *scripts[] = {
&set_plls,
&enable_psram,
&spi_run,
&spi_init,
};
#ifdef SCRIPTIC_DEBUG

View file

@ -2,7 +2,7 @@
#include "fernvale-spi.h"
/* 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 */
sc_write32 SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3_CHANNEL2_MASK, SPI_CTRL3
@ -15,7 +15,7 @@
/* Trigger the transfer */
sc_write32 \
SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS0, \
SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS0, \
SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS, \
SPI_BLOCKMODE
/* Wait for the device to prepare itself */
@ -25,48 +25,7 @@
sc_read32 0, SPI_BLOCKMODE_BUSY, SPI_BLOCKMODE
/* Stop the transfer */
sc_write32 0, SPI_BLOCKMODE_TRIGGER | SPI_BLOCKMODE_CS0, 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
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

View file

@ -1,22 +1,57 @@
#include "scriptic.h"
#include "fernvale-spi.h"
#include "fernvale-gpio.h"
sc_new "spi_init", 1, 0, 0
/* Ungate the clock */
sc_write16 0x800, 0x800, 0x80000320
/* Switch to SPI NOR */ /* (XXX Might need to invert this) */
/* Switch to SPI NOR */
sc_write16 0, 1, 0x80000230
/* Remap GPIOs to be SPI */
sc_write32 0x11111100, 0x77777700, 0xa0020c80
sc_write32 0x00000011, 0x00000077, 0xa0020c90
sc_write32 \
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 */
sc_write16 0, 0x3fff, 0xa0020b10
sc_write16 0, 0x3fff, 0xa0020b40
sc_write16 0, 0xdff1, 0xa0020b20
sc_write16 0, 0xdff1, 0xa0020b50
sc_write16 0, \
GPIO_CTRL_PULL_CTRL1_IO66 | \
GPIO_CTRL_PULL_CTRL1_IO67 | \
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

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;
}