aboutsummaryrefslogtreecommitdiff
path: root/src/soc/marvell/armada38x/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/marvell/armada38x/spi.c')
-rw-r--r--src/soc/marvell/armada38x/spi.c488
1 files changed, 0 insertions, 488 deletions
diff --git a/src/soc/marvell/armada38x/spi.c b/src/soc/marvell/armada38x/spi.c
deleted file mode 100644
index 47631f4c69..0000000000
--- a/src/soc/marvell/armada38x/spi.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * 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>
-#include <soc/clock.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 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_tclk_get();
-
- 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(const struct spi_slave *slave,
- size_t 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;
-}
-
-static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
-{
- mv_spi_cs_set(slave->bus, slave->cs);
- mv_spi_cs_assert(slave->bus);
- return 0;
-}
-
-static void spi_ctrlr_release_bus(const struct spi_slave *slave)
-{
- mv_spi_cs_deassert(slave->bus);
-}
-
-static int spi_ctrlr_xfer(const struct spi_slave *slave,
- const void *dout,
- size_t out_bytes,
- void *din,
- size_t 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;
-}
-
-static const spi_ctrlr spi_ctrlr = {
- .claim_bus = spi_ctrlr_claim_bus,
- .release_bus = spi_ctrlr_release_bus,
- .xfer = spi_ctrlr_xfer,
- .max_xfer_size = SPI_CTRLR_DEFAULT_MAX_XFER_SIZE,
-};
-
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
- slave->bus = bus;
- slave->cs = cs;
- slave->ctrlr = &spi_ctrlr;
- mv_spi_sys_init(bus, cs, CONFIG_SF_DEFAULT_SPEED);
- return 0;
-}