X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fspi%2Ftegra20_sflash.c;h=7c3a3fc35b1aec9ae445af9e9cbe40c20c102e89;hb=fbbbc86e8ebac4f42f4ca39ceba80cea27c983bc;hp=6e72c8ee5ec227dc7aa9e26830514599da00558c;hpb=7a49ba6e5b81713c5c8f8275a7ecd1036ca583d4;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c index 6e72c8e..7c3a3fc 100644 --- a/drivers/spi/tegra20_sflash.c +++ b/drivers/spi/tegra20_sflash.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 NVIDIA Corporation + * Copyright (c) 2010-2013 NVIDIA Corporation * With help from the mpc8xxx SPI driver * With more help from omap3_spi SPI driver * @@ -80,20 +80,28 @@ struct spi_regs { u32 rx_fifo; /* SPI_RX_FIFO_0 register */ }; -struct tegra_spi_slave { - struct spi_slave slave; +struct tegra_spi_ctrl { struct spi_regs *regs; unsigned int freq; unsigned int mode; int periph_id; + int valid; }; +struct tegra_spi_slave { + struct spi_slave slave; + struct tegra_spi_ctrl *ctrl; +}; + +/* tegra20 only supports one SFLASH controller */ +static struct tegra_spi_ctrl spi_ctrls[1]; + static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave) { return container_of(slave, struct tegra_spi_slave, slave); } -int spi_cs_is_valid(unsigned int bus, unsigned int cs) +int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs) { /* Tegra20 SPI-Flash - only 1 device ('bus/cs') */ if (bus != 0 || cs != 0) @@ -102,11 +110,10 @@ int spi_cs_is_valid(unsigned int bus, unsigned int cs) return 1; } -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) { struct tegra_spi_slave *spi; - int node; if (!spi_cs_is_valid(bus, cs)) { printf("SPI error: unsupported bus %d / chip select %d\n", @@ -120,88 +127,98 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return NULL; } - spi = malloc(sizeof(struct tegra_spi_slave)); + spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs); if (!spi) { printf("SPI error: malloc of SPI structure failed\n"); return NULL; } - spi->slave.bus = bus; - spi->slave.cs = cs; - - node = fdtdec_next_compatible(gd->fdt_blob, 0, - COMPAT_NVIDIA_TEGRA20_SFLASH); - if (node < 0) { - debug("%s: cannot locate sflash node\n", __func__); - return NULL; - } - if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) { - debug("%s: sflash is disabled\n", __func__); - return NULL; - } - spi->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); - if ((fdt_addr_t)spi->regs == FDT_ADDR_T_NONE) { - debug("%s: no sflash register found\n", __func__); - return NULL; - } - spi->freq = fdtdec_get_int(gd->fdt_blob, node, "spi-max-frequency", 0); - if (!spi->freq) { - debug("%s: no sflash max frequency found\n", __func__); + spi->ctrl = &spi_ctrls[bus]; + if (!spi->ctrl) { + printf("SPI error: could not find controller for bus %d\n", + bus); return NULL; } - spi->periph_id = clock_decode_periph_id(gd->fdt_blob, node); - if (spi->periph_id == PERIPH_ID_NONE) { - debug("%s: could not decode periph id\n", __func__); - return NULL; - } - if (max_hz < spi->freq) { + + if (max_hz < spi->ctrl->freq) { debug("%s: limiting frequency from %u to %u\n", __func__, - spi->freq, max_hz); - spi->freq = max_hz; + spi->ctrl->freq, max_hz); + spi->ctrl->freq = max_hz; } - debug("%s: controller initialized at %p, freq = %u, periph_id = %d\n", - __func__, spi->regs, spi->freq, spi->periph_id); - spi->mode = mode; + spi->ctrl->mode = mode; return &spi->slave; } -void spi_free_slave(struct spi_slave *slave) +void tegra20_spi_free_slave(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); free(spi); } -void spi_init(void) +int tegra20_spi_init(int *node_list, int count) { - /* do nothing */ + struct tegra_spi_ctrl *ctrl; + int i; + int node = 0; + int found = 0; + + for (i = 0; i < count; i++) { + ctrl = &spi_ctrls[i]; + node = node_list[i]; + + ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); + if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) { + debug("%s: no slink register found\n", __func__); + continue; + } + ctrl->freq = fdtdec_get_int(gd->fdt_blob, node, + "spi-max-frequency", 0); + if (!ctrl->freq) { + debug("%s: no slink max frequency found\n", __func__); + continue; + } + + ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node); + if (ctrl->periph_id == PERIPH_ID_NONE) { + debug("%s: could not decode periph id\n", __func__); + continue; + } + ctrl->valid = 1; + found = 1; + + debug("%s: found controller at %p, freq = %u, periph_id = %d\n", + __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); + } + return !found; } -int spi_claim_bus(struct spi_slave *slave) +int tegra20_spi_claim_bus(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct spi_regs *regs = spi->regs; + struct spi_regs *regs = spi->ctrl->regs; u32 reg; /* Change SPI clock to correct frequency, PLLP_OUT0 source */ - clock_start_periph_pll(spi->periph_id, CLOCK_ID_PERIPH, spi->freq); + clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH, + spi->ctrl->freq); /* Clear stale status here */ reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \ SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF; writel(reg, ®s->status); - debug("spi_init: STATUS = %08x\n", readl(®s->status)); + debug("%s: STATUS = %08x\n", __func__, readl(®s->status)); /* * Use sw-controlled CS, so we can clock in data after ReadID, etc. */ - reg = (spi->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT; - if (spi->mode & 2) + reg = (spi->ctrl->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT; + if (spi->ctrl->mode & 2) reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT; clrsetbits_le32(®s->command, SPI_CMD_ACTIVE_SCLK_MASK | SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg); - debug("spi_init: COMMAND = %08x\n", readl(®s->command)); + debug("%s: COMMAND = %08x\n", __func__, readl(®s->command)); /* * SPI pins on Tegra20 are muxed - change pinmux later due to UART @@ -214,37 +231,29 @@ int spi_claim_bus(struct spi_slave *slave) return 0; } -void spi_release_bus(struct spi_slave *slave) -{ - /* - * We can't release UART_DISABLE and set pinmux to UART4 here since - * some code (e,g, spi_flash_probe) uses printf() while the SPI - * bus is held. That is arguably bad, but it has the advantage of - * already being in the source tree. - */ -} - -void spi_cs_activate(struct spi_slave *slave) +void tegra20_spi_cs_activate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct spi_regs *regs = spi->ctrl->regs; /* CS is negated on Tegra, so drive a 1 to get a 0 */ - setbits_le32(&spi->regs->command, SPI_CMD_CS_VAL); + setbits_le32(®s->command, SPI_CMD_CS_VAL); } -void spi_cs_deactivate(struct spi_slave *slave) +void tegra20_spi_cs_deactivate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct spi_regs *regs = spi->ctrl->regs; /* CS is negated on Tegra, so drive a 0 to get a 1 */ - clrbits_le32(&spi->regs->command, SPI_CMD_CS_VAL); + clrbits_le32(®s->command, SPI_CMD_CS_VAL); } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, +int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, void *data_in, unsigned long flags) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct spi_regs *regs = spi->regs; + struct spi_regs *regs = spi->ctrl->regs; u32 reg, tmpdout, tmpdin = 0; const u8 *dout = data_out; u8 *din = data_in;