soc/marvell/armada38x: Add spi driver for armada38x
Port spi driver from uboot to coreboot BUG=chrome-os-partner:47462 TEST=None BRANCH=tot Change-Id: I747be7001f4cfb8eec33e8e5bdef3fe5bb0eb2ca Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 9fbc5c2feb6ffacb54ed94e5c7b94b38be2b2ded Original-Change-Id: Ibea9a050ac8bdab6ce4eeb07accde53aeadade5f Original-Signed-off-by: Ruilin Hao <rlhao@marvell.com> Original-Reviewed-on: https://chromium-review.googlesource.com/313340 Original-Commit-Ready: Kan Yan <kyan@google.com> Original-Tested-by: Kan Yan <kyan@google.com> Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org> Original-Reviewed-by: Kan Yan <kyan@google.com> Original-Reviewed-by: Yuji Sasaki <sasakiy@chromium.org> Reviewed-on: https://review.coreboot.org/13111 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
2c8b0b1373
commit
5b429ac2b2
|
@ -2,6 +2,7 @@ ifeq ($(CONFIG_SOC_MARVELL_ARMADA38X),y)
|
|||
|
||||
bootblock-y += bootblock.c
|
||||
bootblock-y += bootblock_asm.S
|
||||
bootblock-y += spi.c
|
||||
bootblock-y += monotonic_timer.c
|
||||
ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y)
|
||||
bootblock-$(CONFIG_DRIVERS_UART) += uart.c
|
||||
|
@ -9,11 +10,14 @@ endif
|
|||
|
||||
verstage-$(CONFIG_DRIVERS_UART) += uart.c
|
||||
verstage-y += monotonic_timer.c
|
||||
verstage-y += spi.c
|
||||
|
||||
romstage-y += spi.c
|
||||
romstage-y += cbmem.c
|
||||
romstage-y += monotonic_timer.c
|
||||
romstage-$(CONFIG_DRIVERS_UART) += uart.c
|
||||
|
||||
ramstage-y += spi.c
|
||||
ramstage-y += cbmem.c
|
||||
ramstage-y += monotonic_timer.c
|
||||
ramstage-y += soc.c
|
||||
|
|
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2015 Marvell Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <delay.h>
|
||||
#include <spi_flash.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <console/console.h>
|
||||
#include <soc/common.h>
|
||||
|
||||
/******************************************************************************
|
||||
base type define
|
||||
*******************************************************************************/
|
||||
#define MV_SPI_REG_READ mrvl_reg_read
|
||||
#define MV_SPI_REG_WRITE mrvl_reg_write
|
||||
#define MV_SPI_REG_BIT_SET mrvl_reg_bit_set
|
||||
#define MV_SPI_REG_BIT_RESET mrvl_reg_bit_reset
|
||||
|
||||
#define MV_SPI_REGS_OFFSET(unit) (0x10600 + (unit * 0x80))
|
||||
#define MV_SPI_REGS_BASE(unit) (MV_SPI_REGS_OFFSET(unit))
|
||||
#define MV_SPI_IF_CONFIG_REG(spi_id) (MV_SPI_REGS_BASE(spi_id) + 0x04)
|
||||
#define MV_SPI_SPR_OFFSET 0
|
||||
#define MV_SPI_SPR_MASK (0xF << MV_SPI_SPR_OFFSET)
|
||||
#define MV_SPI_SPPR_0_OFFSET 4
|
||||
#define MV_SPI_SPPR_0_MASK (0x1 << MV_SPI_SPPR_0_OFFSET)
|
||||
#define MV_SPI_SPPR_HI_OFFSET 6
|
||||
#define MV_SPI_SPPR_HI_MASK (0x3 << MV_SPI_SPPR_HI_OFFSET)
|
||||
|
||||
#define MV_SPI_BYTE_LENGTH_OFFSET 5 /* bit 5 */
|
||||
#define MV_SPI_BYTE_LENGTH_MASK (0x1 << MV_SPI_BYTE_LENGTH_OFFSET)
|
||||
|
||||
#define MV_SPI_IF_CTRL_REG(spi_id) (MV_SPI_REGS_BASE(spi_id) + 0x00)
|
||||
#define MV_SPI_CS_ENABLE_OFFSET 0 /* bit 0 */
|
||||
#define MV_SPI_CS_ENABLE_MASK (0x1 << MV_SPI_CS_ENABLE_OFFSET)
|
||||
|
||||
#define MV_SPI_CS_NUM_OFFSET 2
|
||||
#define MV_SPI_CS_NUM_MASK (0x7 << MV_SPI_CS_NUM_OFFSET)
|
||||
#define MV_SPI_CPOL_OFFSET 11
|
||||
#define MV_SPI_CPOL_MASK (0x1 << MV_SPI_CPOL_OFFSET)
|
||||
#define MV_SPI_CPHA_OFFSET 12
|
||||
#define MV_SPI_CPHA_MASK (0x1 << MV_SPI_CPHA_OFFSET)
|
||||
#define MV_SPI_TXLSBF_OFFSET 13
|
||||
#define MV_SPI_TXLSBF_MASK (0x1 << MV_SPI_TXLSBF_OFFSET)
|
||||
#define MV_SPI_RXLSBF_OFFSET 14
|
||||
#define MV_SPI_RXLSBF_MASK (0x1 << MV_SPI_RXLSBF_OFFSET)
|
||||
|
||||
/* SPI transfer flags */
|
||||
#define SPI_XFER_BEGIN 0x01
|
||||
#define SPI_XFER_END 0x02
|
||||
|
||||
#define MV_SPI_INT_CAUSE_REG(spi_id) (MV_SPI_REGS_BASE(spi_id) + 0x10)
|
||||
#define MV_SPI_DATA_OUT_REG(spi_id) (MV_SPI_REGS_BASE(spi_id) + 0x08)
|
||||
#define MV_SPI_WAIT_RDY_MAX_LOOP 100000
|
||||
#define MV_SPI_DATA_IN_REG(spi_id) (MV_SPI_REGS_BASE(spi_id) + 0x0c)
|
||||
|
||||
#define MV_SPI_TMNG_PARAMS_REG(spi_id) (MV_SPI_REGS_BASE(spi_id) + 0x18)
|
||||
#define MV_SPI_TMISO_SAMPLE_OFFSET 6
|
||||
#define MV_SPI_TMISO_SAMPLE_MASK (0x3 << MV_SPI_TMISO_SAMPLE_OFFSET)
|
||||
|
||||
#define CONFIG_ENV_SPI_MAX_HZ 50000000
|
||||
#define CONFIG_SF_DEFAULT_SPEED CONFIG_ENV_SPI_MAX_HZ
|
||||
|
||||
#define CMD_READ_ARRAY_FAST 0x0b
|
||||
|
||||
/******************************************************************************
|
||||
base type define end
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
struct define
|
||||
*******************************************************************************/
|
||||
typedef enum {
|
||||
SPI_TYPE_FLASH = 0,
|
||||
SPI_TYPE_SLIC_ZARLINK_SILABS,
|
||||
SPI_TYPE_SLIC_LANTIQ,
|
||||
SPI_TYPE_SLIC_ZSI,
|
||||
SPI_TYPE_SLIC_ISI
|
||||
} MV_SPI_TYPE;
|
||||
|
||||
typedef struct {
|
||||
unsigned short ctrl_model;
|
||||
unsigned int tclk;
|
||||
} MV_SPI_HAL_DATA;
|
||||
|
||||
typedef struct {
|
||||
int clock_pol_low;
|
||||
enum { SPI_CLK_HALF_CYC, SPI_CLK_BEGIN_CYC } clock_phase;
|
||||
int tx_msb_first;
|
||||
int rx_msb_first;
|
||||
} MV_SPI_IF_PARAMS;
|
||||
|
||||
typedef struct {
|
||||
/* Does this device support 16 bits access */
|
||||
int en16_bit;
|
||||
/* should we assert / disassert CS for each byte we read / write */
|
||||
int byte_cs_asrt;
|
||||
int clock_pol_low;
|
||||
unsigned int baud_rate;
|
||||
unsigned int clk_phase;
|
||||
} MV_SPI_TYPE_INFO;
|
||||
|
||||
/******************************************************************************
|
||||
struct define end
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
param define
|
||||
*******************************************************************************/
|
||||
static MV_SPI_HAL_DATA spi_hal_data;
|
||||
static MV_SPI_TYPE_INFO *curr_spi_info = NULL;
|
||||
static MV_SPI_TYPE_INFO spi_types[] = { {.en16_bit = MV_TRUE,
|
||||
.clock_pol_low = MV_TRUE,
|
||||
.byte_cs_asrt = MV_FALSE,
|
||||
.baud_rate = (20 << 20), /* 20_m */
|
||||
.clk_phase = SPI_CLK_BEGIN_CYC},
|
||||
{.en16_bit = MV_FALSE,
|
||||
.clock_pol_low = MV_TRUE,
|
||||
.byte_cs_asrt = MV_TRUE,
|
||||
.baud_rate = 0x00800000,
|
||||
.clk_phase = SPI_CLK_BEGIN_CYC},
|
||||
{.en16_bit = MV_FALSE,
|
||||
.clock_pol_low = MV_TRUE,
|
||||
.byte_cs_asrt = MV_FALSE,
|
||||
.baud_rate = 0x00800000,
|
||||
.clk_phase = SPI_CLK_BEGIN_CYC},
|
||||
{.en16_bit = MV_FALSE,
|
||||
.clock_pol_low = MV_TRUE,
|
||||
.byte_cs_asrt = MV_TRUE,
|
||||
.baud_rate = 0x00800000,
|
||||
.clk_phase = SPI_CLK_HALF_CYC},
|
||||
{.en16_bit = MV_FALSE,
|
||||
.clock_pol_low = MV_FALSE,
|
||||
.byte_cs_asrt = MV_TRUE,
|
||||
.baud_rate = 0x00200000,
|
||||
.clk_phase = SPI_CLK_HALF_CYC} };
|
||||
|
||||
/******************************************************************************
|
||||
param define end
|
||||
*******************************************************************************/
|
||||
|
||||
static struct spi_slave s_spi;
|
||||
|
||||
static int mv_spi_baud_rate_set(unsigned char spi_id,
|
||||
unsigned int serial_baud_rate);
|
||||
static void mv_spi_cs_deassert(unsigned char spi_id);
|
||||
static int mv_spi_cs_set(unsigned char spi_id, unsigned char cs_id);
|
||||
static int mv_spi_if_config_set(unsigned char spi_id,
|
||||
MV_SPI_IF_PARAMS *if_params);
|
||||
static int mv_spi_params_set(unsigned char spi_id,
|
||||
unsigned char cs_id,
|
||||
MV_SPI_TYPE type);
|
||||
static int mv_spi_init(unsigned char spi_id,
|
||||
unsigned char cs_id,
|
||||
unsigned int serial_baud_rate,
|
||||
MV_SPI_HAL_DATA *hal_data);
|
||||
static int mv_spi_sys_init(unsigned char spi_id,
|
||||
unsigned char cs_id,
|
||||
unsigned int serial_baud_rate);
|
||||
static void mv_spi_cs_assert(unsigned char spi_id);
|
||||
static int mv_spi_8bit_data_tx_rx(unsigned char spi_id,
|
||||
unsigned char tx_data,
|
||||
unsigned char *p_rx_data);
|
||||
|
||||
int mv_spi_baud_rate_set(unsigned char spi_id, unsigned int serial_baud_rate)
|
||||
{
|
||||
unsigned int spr, sppr;
|
||||
unsigned int divider;
|
||||
unsigned int best_spr = 0, best_sppr = 0;
|
||||
unsigned char exact_match = 0;
|
||||
unsigned int min_baud_offset = 0xFFFFFFFF;
|
||||
unsigned int cpu_clk = spi_hal_data.tclk; /*mv_cpu_pclk_get();*/
|
||||
unsigned int temp_reg;
|
||||
|
||||
assert(cpu_clk != serial_baud_rate);
|
||||
/* Find the best prescale configuration - less or equal */
|
||||
for (spr = 1; spr <= 15; spr++) {
|
||||
for (sppr = 0; sppr <= 7; sppr++) {
|
||||
divider = spr * (1 << sppr);
|
||||
/* check for higher - irrelevant */
|
||||
if ((cpu_clk / divider) > serial_baud_rate)
|
||||
continue;
|
||||
|
||||
/* check for exact fit */
|
||||
if ((cpu_clk / divider) == serial_baud_rate) {
|
||||
best_spr = spr;
|
||||
best_sppr = sppr;
|
||||
exact_match = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check if this is better than the previous one */
|
||||
if ((serial_baud_rate - (cpu_clk / divider)) <
|
||||
min_baud_offset) {
|
||||
min_baud_offset =
|
||||
serial_baud_rate - cpu_clk / divider;
|
||||
best_spr = spr;
|
||||
best_sppr = sppr;
|
||||
}
|
||||
}
|
||||
|
||||
if (exact_match == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (best_spr == 0) {
|
||||
printk(BIOS_INFO, "%s ERROR: SPI baud rate prescale error!\n",
|
||||
__func__);
|
||||
return MV_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
/* configure the Prescale */
|
||||
temp_reg = MV_SPI_REG_READ(MV_SPI_IF_CONFIG_REG(spi_id)) &
|
||||
~(MV_SPI_SPR_MASK | MV_SPI_SPPR_0_MASK | MV_SPI_SPPR_HI_MASK);
|
||||
temp_reg |= ((best_spr << MV_SPI_SPR_OFFSET) |
|
||||
((best_sppr & 0x1) << MV_SPI_SPPR_0_OFFSET) |
|
||||
((best_sppr >> 1) << MV_SPI_SPPR_HI_OFFSET));
|
||||
MV_SPI_REG_WRITE(MV_SPI_IF_CONFIG_REG(spi_id), temp_reg);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
void mv_spi_cs_deassert(unsigned char spi_id)
|
||||
{
|
||||
MV_SPI_REG_BIT_RESET(MV_SPI_IF_CTRL_REG(spi_id), MV_SPI_CS_ENABLE_MASK);
|
||||
}
|
||||
|
||||
int mv_spi_cs_set(unsigned char spi_id, unsigned char cs_id)
|
||||
{
|
||||
unsigned int ctrl_reg;
|
||||
static unsigned char last_cs_id = 0xFF;
|
||||
static unsigned char last_spi_id = 0xFF;
|
||||
|
||||
if (cs_id > 7)
|
||||
return MV_BAD_PARAM;
|
||||
|
||||
if ((last_spi_id == spi_id) && (last_cs_id == cs_id))
|
||||
return MV_OK;
|
||||
|
||||
ctrl_reg = MV_SPI_REG_READ(MV_SPI_IF_CTRL_REG(spi_id));
|
||||
ctrl_reg &= ~MV_SPI_CS_NUM_MASK;
|
||||
ctrl_reg |= (cs_id << MV_SPI_CS_NUM_OFFSET);
|
||||
MV_SPI_REG_WRITE(MV_SPI_IF_CTRL_REG(spi_id), ctrl_reg);
|
||||
|
||||
last_spi_id = spi_id;
|
||||
last_cs_id = cs_id;
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int mv_spi_if_config_set(unsigned char spi_id, MV_SPI_IF_PARAMS *if_params)
|
||||
{
|
||||
unsigned int ctrl_reg;
|
||||
|
||||
ctrl_reg = MV_SPI_REG_READ(MV_SPI_IF_CONFIG_REG(spi_id));
|
||||
|
||||
/* Set Clock Polarity */
|
||||
ctrl_reg &= ~(MV_SPI_CPOL_MASK | MV_SPI_CPHA_MASK | MV_SPI_TXLSBF_MASK |
|
||||
MV_SPI_RXLSBF_MASK);
|
||||
if (if_params->clock_pol_low)
|
||||
ctrl_reg |= MV_SPI_CPOL_MASK;
|
||||
|
||||
if (if_params->clock_phase == SPI_CLK_BEGIN_CYC)
|
||||
ctrl_reg |= MV_SPI_CPHA_MASK;
|
||||
|
||||
if (if_params->tx_msb_first)
|
||||
ctrl_reg |= MV_SPI_TXLSBF_MASK;
|
||||
|
||||
if (if_params->rx_msb_first)
|
||||
ctrl_reg |= MV_SPI_RXLSBF_MASK;
|
||||
|
||||
MV_SPI_REG_WRITE(MV_SPI_IF_CONFIG_REG(spi_id), ctrl_reg);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int mv_spi_params_set(unsigned char spi_id,
|
||||
unsigned char cs_id,
|
||||
MV_SPI_TYPE type)
|
||||
{
|
||||
MV_SPI_IF_PARAMS if_params;
|
||||
|
||||
if (MV_OK != mv_spi_cs_set(spi_id, cs_id)) {
|
||||
printk(BIOS_INFO, "Error, setting SPI CS failed\n");
|
||||
return MV_ERROR;
|
||||
}
|
||||
|
||||
if (curr_spi_info != (&(spi_types[type]))) {
|
||||
curr_spi_info = &(spi_types[type]);
|
||||
mv_spi_baud_rate_set(spi_id, curr_spi_info->baud_rate);
|
||||
|
||||
if_params.clock_pol_low = curr_spi_info->clock_pol_low;
|
||||
if_params.clock_phase = curr_spi_info->clk_phase;
|
||||
if_params.tx_msb_first = MV_FALSE;
|
||||
if_params.rx_msb_first = MV_FALSE;
|
||||
mv_spi_if_config_set(spi_id, &if_params);
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int mv_spi_init(unsigned char spi_id,
|
||||
unsigned char cs_id,
|
||||
unsigned int serial_baud_rate,
|
||||
MV_SPI_HAL_DATA *hal_data)
|
||||
{
|
||||
int ret;
|
||||
unsigned int timing_reg;
|
||||
|
||||
spi_hal_data.ctrl_model = hal_data->ctrl_model;
|
||||
spi_hal_data.tclk = hal_data->tclk;
|
||||
|
||||
/* Set the serial clock */
|
||||
ret = mv_spi_baud_rate_set(spi_id, serial_baud_rate);
|
||||
if (ret != MV_OK)
|
||||
return ret;
|
||||
|
||||
/* Configure the default SPI mode to be 8bit */
|
||||
MV_SPI_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG(spi_id),
|
||||
MV_SPI_BYTE_LENGTH_MASK);
|
||||
|
||||
timing_reg = MV_SPI_REG_READ(MV_SPI_TMNG_PARAMS_REG(spi_id));
|
||||
timing_reg &= ~MV_SPI_TMISO_SAMPLE_MASK;
|
||||
timing_reg |= (0x2) << MV_SPI_TMISO_SAMPLE_OFFSET;
|
||||
MV_SPI_REG_WRITE(MV_SPI_TMNG_PARAMS_REG(spi_id), timing_reg);
|
||||
|
||||
/* Verify that the CS is deasserted */
|
||||
mv_spi_cs_deassert(spi_id);
|
||||
|
||||
mv_spi_params_set(spi_id, cs_id, SPI_TYPE_FLASH);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int mv_spi_sys_init(unsigned char spi_id,
|
||||
unsigned char cs_id,
|
||||
unsigned int serial_baud_rate)
|
||||
{
|
||||
MV_SPI_HAL_DATA hal_data;
|
||||
|
||||
hal_data.ctrl_model = MV_6810_DEV_ID;
|
||||
hal_data.tclk = MV_BOARD_TCLK_250MHZ;
|
||||
|
||||
return mv_spi_init(spi_id, cs_id, serial_baud_rate, &hal_data);
|
||||
}
|
||||
|
||||
void mv_spi_cs_assert(unsigned char spi_id)
|
||||
{
|
||||
MV_SPI_REG_BIT_SET(MV_SPI_IF_CTRL_REG(spi_id), MV_SPI_CS_ENABLE_MASK);
|
||||
}
|
||||
|
||||
int mv_spi_8bit_data_tx_rx(unsigned char spi_id,
|
||||
unsigned char tx_data,
|
||||
unsigned char *p_rx_data)
|
||||
{
|
||||
unsigned int i;
|
||||
int ready = MV_FALSE;
|
||||
|
||||
if (curr_spi_info->byte_cs_asrt)
|
||||
mv_spi_cs_assert(spi_id);
|
||||
|
||||
/* First clear the bit in the interrupt cause register */
|
||||
MV_SPI_REG_WRITE(MV_SPI_INT_CAUSE_REG(spi_id), 0x0);
|
||||
|
||||
/* Transmit data */
|
||||
MV_SPI_REG_WRITE(MV_SPI_DATA_OUT_REG(spi_id), tx_data);
|
||||
|
||||
/* wait with timeout for memory ready */
|
||||
for (i = 0; i < MV_SPI_WAIT_RDY_MAX_LOOP; i++) {
|
||||
if (MV_SPI_REG_READ(MV_SPI_INT_CAUSE_REG(spi_id))) {
|
||||
ready = MV_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ready) {
|
||||
if (curr_spi_info->byte_cs_asrt) {
|
||||
mv_spi_cs_deassert(spi_id);
|
||||
/* WA to compansate Zarlink SLIC CS off time */
|
||||
udelay(4);
|
||||
}
|
||||
return MV_TIMEOUT;
|
||||
}
|
||||
|
||||
/* check that the RX data is needed */
|
||||
if (p_rx_data)
|
||||
*p_rx_data = MV_SPI_REG_READ(MV_SPI_DATA_IN_REG(spi_id));
|
||||
|
||||
if (curr_spi_info->byte_cs_asrt) {
|
||||
mv_spi_cs_deassert(spi_id);
|
||||
/* WA to compansate Zarlink SLIC CS off time */
|
||||
udelay(4);
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
static int mrvl_spi_xfer(struct spi_slave *slave,
|
||||
unsigned int bitlen,
|
||||
const void *dout,
|
||||
void *din)
|
||||
{
|
||||
int ret;
|
||||
unsigned char *pdout = (unsigned char *)dout;
|
||||
unsigned char *pdin = (unsigned char *)din;
|
||||
int tmp_bitlen = bitlen;
|
||||
unsigned char tmp_dout = 0;
|
||||
|
||||
/* Verify that the SPI mode is in 8bit mode */
|
||||
MV_SPI_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG(slave->bus),
|
||||
MV_SPI_BYTE_LENGTH_MASK);
|
||||
|
||||
while (tmp_bitlen > 0) {
|
||||
if (pdout)
|
||||
tmp_dout = (*pdout) & 0xff;
|
||||
|
||||
/* Transmitted and wait for the transfer to be completed */
|
||||
ret = mv_spi_8bit_data_tx_rx(slave->bus, tmp_dout, pdin);
|
||||
if (ret != MV_OK)
|
||||
return ret;
|
||||
|
||||
/* increment the pointers */
|
||||
if (pdin)
|
||||
pdin++;
|
||||
if (pdout)
|
||||
pdout++;
|
||||
|
||||
tmp_bitlen -= 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
|
||||
{
|
||||
struct spi_slave *slave = &s_spi;
|
||||
|
||||
slave->bus = bus;
|
||||
slave->cs = cs;
|
||||
mv_spi_sys_init(bus, cs, CONFIG_SF_DEFAULT_SPEED);
|
||||
return slave;
|
||||
}
|
||||
|
||||
int spi_claim_bus(struct spi_slave *slave)
|
||||
{
|
||||
mv_spi_cs_set(slave->bus, slave->cs);
|
||||
mv_spi_cs_assert(slave->bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spi_release_bus(struct spi_slave *slave)
|
||||
{
|
||||
mv_spi_cs_deassert(slave->bus);
|
||||
}
|
||||
|
||||
unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
|
||||
{
|
||||
return buf_len;
|
||||
}
|
||||
|
||||
int spi_xfer(struct spi_slave *slave,
|
||||
const void *dout,
|
||||
unsigned out_bytes,
|
||||
void *din,
|
||||
unsigned in_bytes)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (out_bytes)
|
||||
ret = mrvl_spi_xfer(slave, out_bytes * 8, dout, din);
|
||||
else if (in_bytes)
|
||||
ret = mrvl_spi_xfer(slave, in_bytes * 8, dout, din);
|
||||
else
|
||||
die("Unexpected condition in spi_xfer\n");
|
||||
return ret;
|
||||
}
|
Loading…
Reference in New Issue