aboutsummaryrefslogtreecommitdiff
path: root/src/soc/imgtec/pistachio/spi.c
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2019-10-30 16:12:24 -0700
committerPatrick Georgi <pgeorgi@google.com>2019-11-20 10:10:44 +0000
commit63c444a69b98bc8a86719699423b3273cc5759e8 (patch)
tree6bd90603b343103bdcd730eb5f9aca6c4500fb6f /src/soc/imgtec/pistachio/spi.c
parent5027ecfb1987cf06efc772a0bee0a1fe1dc38049 (diff)
Remove imgtec/pistachio SoC
After removing urara no board still uses this SoC, and there are no plans to add any in the future (I'm not sure if the chip really exists tbh...). Change-Id: Ic4628fdfacc9fb19b6210394d96431fdb5f8e8f1 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/36491 Reviewed-by: Arthur Heymans <arthur@aheymans.xyz> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc/imgtec/pistachio/spi.c')
-rw-r--r--src/soc/imgtec/pistachio/spi.c587
1 files changed, 0 insertions, 587 deletions
diff --git a/src/soc/imgtec/pistachio/spi.c b/src/soc/imgtec/pistachio/spi.c
deleted file mode 100644
index acbbd909bd..0000000000
--- a/src/soc/imgtec/pistachio/spi.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2014 Imagination Technologies
- *
- * 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 <console/console.h>
-#include <device/mmio.h>
-#include <soc/cpu.h>
-#include <soc/spi.h>
-#include <spi_flash.h>
-#include <spi-generic.h>
-#include <stdlib.h>
-#include <string.h>
-#include <timer.h>
-
-/* Imgtec controller uses 16 bit packet length. */
-#define IMGTEC_SPI_MAX_TRANSFER_SIZE ((1 << 16) - 1)
-
-struct img_spi_slave {
- /* SPIM instance device parameters */
- struct spim_device_parameters device_parameters;
- /* SPIM instance base address */
- u32 base;
- /* Boolean property that is TRUE if API has been initialised */
- int initialised;
-};
-
-/* Allocate memory for the maximum number of devices */
-static struct
-img_spi_slave img_spi_slaves[SPIM_NUM_BLOCKS*SPIM_NUM_PORTS_PER_BLOCK];
-
-/*
- * Wait for the bit at the shift position to be set in reg
- * If the bit is not set in SPI_TIMEOUT_VALUE_US return with error
- */
-static int wait_status(u32 reg, u32 shift)
-{
- struct stopwatch sw;
-
- stopwatch_init_usecs_expire(&sw, SPI_TIMEOUT_VALUE_US);
- while (!(read32_x(reg) & (1 << shift))) {
- if (stopwatch_expired(&sw))
- return -SPIM_TIMEOUT;
- }
- return SPIM_OK;
-}
-
-static struct img_spi_slave *get_img_slave(const struct spi_slave *slave)
-{
- return img_spi_slaves + slave->bus * SPIM_NUM_PORTS_PER_BLOCK +
- slave->cs;
-}
-
-/* Transmitter function. Fills TX FIFO with data before enabling SPIM */
-static int transmitdata(const struct spi_slave *slave, u8 *buffer, u32 size)
-{
- u32 blocksize, base, write_data;
- int ret;
- struct img_spi_slave *img_slave = get_img_slave(slave);
-
- base = img_slave->base;
- while (size) {
- /* Wait until FIFO empty */
- write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_SDE_MASK);
- ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
- SPFI_SDE_SHIFT);
- if (ret)
- return ret;
-
- /*
- * Write to FIFO in blocks of 16 words (64 bytes)
- * Do 32bit writes first.
- */
- blocksize = SPIM_MAX_BLOCK_BYTES;
- while ((size >= sizeof(u32)) && blocksize) {
- memcpy(&write_data, buffer, sizeof(u32));
- write32_x(base + SPFI_SEND_LONG_REG_OFFSET, write_data);
- buffer += sizeof(u32);
- size -= sizeof(u32);
- blocksize -= sizeof(u32);
- }
- while (size && blocksize) {
- write32_x(base + SPFI_SEND_BYTE_REG_OFFSET, *buffer);
- buffer++;
- size--;
- blocksize--;
- }
- }
- return SPIM_OK;
-}
-
-/* Receiver function */
-static int receivedata(const struct spi_slave *slave, u8 *buffer, u32 size)
-{
- u32 read_data, base;
- int ret;
- struct img_spi_slave *img_slave = get_img_slave(slave);
-
- base = img_slave->base;
- /*
- * Do 32bit reads first. Clear status GDEX32BIT here so that the first
- * status reg. read gets the actual bit state
- */
- write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX32BIT_MASK);
- while (size >= sizeof(u32)) {
- ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
- SPFI_GDEX32BIT_SHIFT);
- if (ret)
- return ret;
- read_data = read32_x(base + SPFI_GET_LONG_REG_OFFSET);
- memcpy(buffer, &read_data, sizeof(u32));
- buffer += sizeof(u32);
- size -= sizeof(u32);
- /* Clear interrupt status on GDEX32BITL */
- write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX32BIT_MASK);
- }
-
- /*
- * Do the remaining 8bit reads. Clear status GDEX8BIT here so that
- * the first status reg. read gets the actual bit state
- */
- write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX8BIT_MASK);
- while (size) {
- ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
- SPFI_GDEX8BIT_SHIFT);
- if (ret)
- return ret;
- *buffer = read32_x(base + SPFI_GET_BYTE_REG_OFFSET);
- buffer++;
- size--;
- /* Clear interrupt status on SPFI_GDEX8BIT */
- write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX8BIT_MASK);
- }
- return SPIM_OK;
-}
-
-/* Sets port parameters in port state register. */
-static void setparams(const struct spi_slave *slave, u32 port,
- struct spim_device_parameters *params)
-{
- u32 spim_parameters, port_state, base;
- struct img_spi_slave *img_slave = get_img_slave(slave);
-
- base = img_slave->base;
- spim_parameters = 0;
- port_state = read32_x(base + SPFI_PORT_STATE_REG_OFFSET);
- port_state &= ~((SPIM_PORT0_MASK>>port)|SPFI_PORT_SELECT_MASK);
- port_state |= params->cs_idle_level<<(SPIM_CS0_IDLE_SHIFT-port);
- port_state |=
- params->data_idle_level<<(SPIM_DATA0_IDLE_SHIFT-port);
-
- /* Clock idle level and phase */
- switch (params->spi_mode) {
- case SPIM_MODE_0:
- break;
- case SPIM_MODE_1:
- port_state |= (1 << (SPIM_CLOCK0_PHASE_SHIFT - port));
- break;
- case SPIM_MODE_2:
- port_state |= (1 << (SPIM_CLOCK0_IDLE_SHIFT - port));
- break;
- case SPIM_MODE_3:
- port_state |= (1 << (SPIM_CLOCK0_IDLE_SHIFT - port)) |
- (1 << (SPIM_CLOCK0_PHASE_SHIFT - port));
- break;
- }
- /* Set port state register */
- write32_x(base + SPFI_PORT_STATE_REG_OFFSET, port_state);
-
- /* Set up values to be written to device parameter register */
- spim_parameters |= params->bitrate << SPIM_CLK_DIVIDE_SHIFT;
- spim_parameters |= params->cs_setup << SPIM_CS_SETUP_SHIFT;
- spim_parameters |= params->cs_hold << SPIM_CS_HOLD_SHIFT;
- spim_parameters |= params->cs_delay << SPIM_CS_DELAY_SHIFT;
-
- write32_x(base + SPFI_PORT_0_PARAM_REG_OFFSET + 4 * port,
- spim_parameters);
-}
-
-/* Sets up transaction register */
-static u32 transaction_reg_setup(struct spim_buffer *first,
- struct spim_buffer *second)
-{
- u32 reg = 0;
-
- /* 2nd transfer exists? */
- if (second) {
- /*
- * If second transfer exists, it's a "command followed by data"
- * type of transfer and first transfer is defined by
- * CMD_LENGTH, ADDR_LENGTH, DUMMY_LENGTH... fields of
- * transaction register
- */
- reg = spi_write_reg_field(reg, SPFI_CMD_LENGTH, 1);
- reg = spi_write_reg_field(reg, SPFI_ADDR_LENGTH,
- first->size - 1);
- reg = spi_write_reg_field(reg, SPFI_DUMMY_LENGTH, 0);
- /* Set data size (size of the second transfer) */
- reg = spi_write_reg_field(reg, SPFI_TSIZE, second->size);
- } else {
- /* Set data size, in this case size of the 1st transfer */
- reg = spi_write_reg_field(reg, SPFI_TSIZE, first->size);
- }
- return reg;
-}
-
-/* Sets up control register */
-static u32 control_reg_setup(struct spim_buffer *first,
- struct spim_buffer *second)
-{
- u32 reg;
-
- /* Enable SPFI */
- reg = SPFI_EN_MASK;
- reg |= first->inter_byte_delay ? SPIM_BYTE_DELAY_MASK : 0;
-
- /* Set up the transfer mode */
- reg = spi_write_reg_field(reg, SPFI_TRNSFR_MODE_DQ, SPIM_CMD_MODE_0);
- reg = spi_write_reg_field(reg, SPFI_TRNSFR_MODE, SPIM_DMODE_SINGLE);
- reg = spi_write_reg_field(reg, SPIM_EDGE_TX_RX, 1);
-
- if (second) {
- /* Set TX bit if the 2nd transaction is 'send' */
- reg = spi_write_reg_field(reg, SPFI_TX_RX,
- second->isread ? 0 : 1);
- /*
- * Set send/get DMA for both transactions
- * (first is always 'send')
- */
- reg = spi_write_reg_field(reg, SPIM_SEND_DMA, 1);
- if (second->isread)
- reg = spi_write_reg_field(reg, SPIM_GET_DMA, 1);
-
- } else {
- /* Set TX bit if the 1st transaction is 'send' */
- reg |= first->isread ? 0 : SPFI_TX_RX_MASK;
- /* Set send/get DMA */
- reg |= first->isread ? SPIM_GET_DMA_MASK : SPIM_SEND_DMA_MASK;
- }
- return reg;
-}
-
-/* Checks the given buffer information */
-static int check_buffers(const struct spi_slave *slave, struct spim_buffer *first,
- struct spim_buffer *second){
-
- struct img_spi_slave *img_slave = get_img_slave(slave);
-
- if (!(img_slave->initialised))
- return -SPIM_API_NOT_INITIALISED;
- /*
- * First operation must always be defined
- * It can be either a read or a write and its size cannot be bigge
- * than SPIM_MAX_TANSFER_BYTES = 64KB - 1 (0xFFFF)
- */
- if (!first)
- return -SPIM_INVALID_READ_WRITE;
- if (first->size > SPIM_MAX_TRANSFER_BYTES)
- return -SPIM_INVALID_SIZE;
- if (first->isread > 1)
- return -SPIM_INVALID_READ_WRITE;
- /* Check operation parameters for 'second' */
- if (second) {
- /*
- * If the second operation is defined it must be a read
- * operation and its size must not be bigger than
- * SPIM_MAX_TANSFER_BYTES = 64KB - 1 (0xFFFF)
- */
- if (second->size > SPIM_MAX_TRANSFER_BYTES)
- return -SPIM_INVALID_SIZE;
- if (!second->isread)
- return -SPIM_INVALID_READ_WRITE;
- /*
- * If the second operations is defined, the first operation
- * must be a write and its size cannot be bigger than
- * SPIM_MAX_FLASH_COMMAND_BYTES(8): command size (1) +
- * address size (7).
- */
- if (first->isread)
- return -SPIM_INVALID_READ_WRITE;
- if (first->size > SPIM_MAX_FLASH_COMMAND_BYTES)
- return -SPIM_INVALID_SIZE;
-
- }
- return SPIM_OK;
-}
-
-/* Checks the set bitrate */
-static int check_bitrate(u32 rate)
-{
- /* Bitrate must be 1, 2, 4, 8, 16, 32, 64, or 128 */
- switch (rate) {
- case 1:
- case 2:
- case 4:
- case 8:
- case 16:
- case 32:
- case 64:
- case 128:
- return SPIM_OK;
- default:
- return -SPIM_INVALID_BIT_RATE;
- }
- return -SPIM_INVALID_BIT_RATE;
-}
-
-/* Checks device parameters for errors */
-static int check_device_params(struct spim_device_parameters *pdev_param)
-{
- if (pdev_param->spi_mode < SPIM_MODE_0 ||
- pdev_param->spi_mode > SPIM_MODE_3)
- return -SPIM_INVALID_SPI_MODE;
- if (check_bitrate(pdev_param->bitrate) != SPIM_OK)
- return -SPIM_INVALID_BIT_RATE;
- if (pdev_param->cs_idle_level > 1)
- return -SPIM_INVALID_CS_IDLE_LEVEL;
- if (pdev_param->data_idle_level > 1)
- return -SPIM_INVALID_DATA_IDLE_LEVEL;
- return SPIM_OK;
-}
-
-/* Function that carries out read/write operations */
-static int spim_io(const struct spi_slave *slave, struct spim_buffer *first,
- struct spim_buffer *second)
-{
- u32 reg, base;
- int i, trans_count, ret;
- struct spim_buffer *transaction[2];
- struct img_spi_slave *img_slave = get_img_slave(slave);
-
- base = img_slave->base;
-
- ret = check_buffers(slave, first, second);
- if (ret)
- return ret;
-
- /*
- * Soft reset peripheral internals, this will terminate any
- * pending transactions
- */
- write32_x(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK);
- write32_x(base + SPFI_CONTROL_REG_OFFSET, 0);
- /* Port state register */
- reg = read32_x(base + SPFI_PORT_STATE_REG_OFFSET);
- reg = spi_write_reg_field(reg, SPFI_PORT_SELECT, slave->cs);
- write32_x(base + SPFI_PORT_STATE_REG_OFFSET, reg);
- /* Set transaction register */
- reg = transaction_reg_setup(first, second);
- write32_x(base + SPFI_TRANSACTION_REG_OFFSET, reg);
- /* Clear status */
- write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, 0xffffffff);
- /* Set control register */
- reg = control_reg_setup(first, second);
- write32_x(base + SPFI_CONTROL_REG_OFFSET, reg);
- /* First transaction always exists */
- transaction[0] = first;
- trans_count = 1;
- /* Is there a second transaction? */
- if (second) {
- transaction[1] = second;
- trans_count++;
- }
- /* Now write/read FIFO's */
- for (i = 0; i < trans_count; i++)
- /* Which transaction to execute, "Send" or "Get"? */
- if (transaction[i]->isread) {
- /* Get */
- ret = receivedata(slave, transaction[i]->buffer,
- transaction[i]->size);
- if (ret) {
- printk(BIOS_ERR,
- "%s: Error: receive data failed.\n",
- __func__);
- return ret;
- }
- } else {
- /* Send */
- ret = transmitdata(slave, transaction[i]->buffer,
- transaction[i]->size);
- if (ret) {
- printk(BIOS_ERR,
- "%s: Error: transmit data failed.\n",
- __func__);
- return ret;
- }
- }
-
- /* Wait for end of the transaction */
- ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
- SPFI_ALLDONE_SHIFT);
- if (ret)
- return ret;
- /*
- * Soft reset peripheral internals, this will terminate any
- * pending transactions
- */
- write32_x(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK);
- write32_x(base + SPFI_CONTROL_REG_OFFSET, 0);
-
- return SPIM_OK;
-}
-
-/* Claim the bus and prepare it for communication */
-static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
-{
- int ret;
- struct img_spi_slave *img_slave;
-
- if (!slave) {
- printk(BIOS_ERR, "%s: Error: slave was not set up.\n",
- __func__);
- return -SPIM_API_NOT_INITIALISED;
- }
- img_slave = get_img_slave(slave);
- if (img_slave->initialised)
- return SPIM_OK;
- /* Check device parameters */
- ret = check_device_params(&(img_slave->device_parameters));
- if (ret) {
- printk(BIOS_ERR, "%s: Error: incorrect device parameters.\n",
- __func__);
- return ret;
- }
- /* Set device parameters */
- setparams(slave, slave->cs, &(img_slave->device_parameters));
- /* Soft reset peripheral internals */
- write32_x(img_slave->base + SPFI_CONTROL_REG_OFFSET,
- SPIM_SOFT_RESET_MASK);
- write32_x(img_slave->base + SPFI_CONTROL_REG_OFFSET, 0);
- img_slave->initialised = IMG_TRUE;
- return SPIM_OK;
-}
-
-/* Release the SPI bus */
-static void spi_ctrlr_release_bus(const struct spi_slave *slave)
-{
- struct img_spi_slave *img_slave;
-
- if (!slave) {
- printk(BIOS_ERR, "%s: Error: slave was not set up.\n",
- __func__);
- return;
- }
- img_slave = get_img_slave(slave);
- img_slave->initialised = IMG_FALSE;
- /* Soft reset peripheral internals */
- write32_x(img_slave->base + SPFI_CONTROL_REG_OFFSET,
- SPIM_SOFT_RESET_MASK);
- write32_x(img_slave->base + SPFI_CONTROL_REG_OFFSET, 0);
-}
-
-/* SPI transfer */
-static int do_spi_xfer(const struct spi_slave *slave, const void *dout,
- size_t bytesout, void *din, size_t bytesin)
-{
- struct spim_buffer buff_0;
- struct spim_buffer buff_1;
-
- /* If we only have a read or a write operation
- * the parameters for it will be put in the first buffer
- */
- buff_0.buffer = (dout) ? (void *)dout : (void *)din;
- buff_0.size = (dout) ? bytesout : bytesin;
- buff_0.isread = (dout) ? IMG_FALSE : IMG_TRUE;
- buff_0.inter_byte_delay = 0;
-
- if (dout && din) {
- /* Set up the read buffer to receive our data */
- buff_1.buffer = din;
- buff_1.size = bytesin;
- buff_1.isread = IMG_TRUE;
- buff_1.inter_byte_delay = 0;
- }
- return spim_io(slave, &buff_0, (dout && din) ? &buff_1 : NULL);
-}
-
-static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
- size_t bytesout, void *din, size_t bytesin)
-{
- unsigned int in_sz, out_sz;
- int ret;
-
- if (!slave) {
- printk(BIOS_ERR, "%s: Error: slave was not set up.\n",
- __func__);
- return -SPIM_API_NOT_INITIALISED;
- }
- if (!dout && !din) {
- printk(BIOS_ERR, "%s: Error: both buffers are NULL.\n",
- __func__);
- return -SPIM_INVALID_TRANSFER_DESC;
- }
-
- while (bytesin || bytesout) {
- in_sz = min(IMGTEC_SPI_MAX_TRANSFER_SIZE, bytesin);
- out_sz = min(IMGTEC_SPI_MAX_TRANSFER_SIZE, bytesout);
-
- ret = do_spi_xfer(slave, dout, out_sz, din, in_sz);
- if (ret)
- return ret;
-
- bytesin -= in_sz;
- bytesout -= out_sz;
-
- if (bytesin)
- din += in_sz;
- else
- din = NULL;
-
- if (bytesout)
- dout += out_sz;
- else
- dout = NULL;
- }
-
- return SPIM_OK;
-}
-
-static int spi_ctrlr_setup(const struct spi_slave *slave)
-{
- struct img_spi_slave *img_slave = NULL;
- struct spim_device_parameters *device_parameters;
- u32 base;
-
- switch (slave->bus) {
- case 0:
- base = IMG_SPIM0_BASE_ADDRESS;
- break;
- case 1:
- base = IMG_SPIM1_BASE_ADDRESS;
- break;
- default:
- printk(BIOS_ERR, "%s: Error: unsupported bus.\n",
- __func__);
- return -1;
- }
- if (slave->cs > SPIM_DEVICE4) {
- printk(BIOS_ERR, "%s: Error: unsupported chipselect.\n",
- __func__);
- return -1;
- }
-
- img_slave = get_img_slave(slave);
- device_parameters = &(img_slave->device_parameters);
-
- img_slave->base = base;
-
- device_parameters->bitrate = 64;
- device_parameters->cs_setup = 0;
- device_parameters->cs_hold = 0;
- device_parameters->cs_delay = 0;
- device_parameters->spi_mode = SPIM_MODE_0;
- device_parameters->cs_idle_level = 1;
- device_parameters->data_idle_level = 0;
- img_slave->initialised = IMG_FALSE;
-
- return 0;
-}
-
-static const struct spi_ctrlr spi_ctrlr = {
- .setup = spi_ctrlr_setup,
- .claim_bus = spi_ctrlr_claim_bus,
- .release_bus = spi_ctrlr_release_bus,
- .xfer = spi_ctrlr_xfer,
- .max_xfer_size = IMGTEC_SPI_MAX_TRANSFER_SIZE,
-};
-
-const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
- {
- .ctrlr = &spi_ctrlr,
- .bus_start = 0,
- .bus_end = 1,
- },
-};
-
-const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);