Commit 6b3a03e1 authored by Allen Martin's avatar Allen Martin Committed by Tom Warren
Browse files

tegra20: spi: move fdt probe to spi_init



Make the tegra20 SPI driver similar to the tegra30 (and soon to be
tegra114) SPI drivers in preparation of common fdt SPI driver front
end.
Signed-off-by: default avatarAllen Martin <amartin@nvidia.com>
Signed-off-by: default avatarTom Warren <twarren@nvidia.com>
Reviewed-by: default avatarStephen Warren <swarren@nvidia.com>
parent 7a49ba6e
/*
* 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,14 +80,22 @@ 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);
......@@ -106,7 +114,6 @@ struct spi_slave *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",
......@@ -127,41 +134,19 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
}
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__);
spi->ctrl = &spi_ctrls[bus];
if (!spi->ctrl) {
printf("SPI error: could not find controller for bus %d\n",
bus);
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__);
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;
}
......@@ -175,17 +160,54 @@ void spi_free_slave(struct spi_slave *slave)
void spi_init(void)
{
/* do nothing */
struct tegra_spi_ctrl *ctrl;
int i;
int node = 0;
int count;
int node_list[1];
count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
COMPAT_NVIDIA_TEGRA20_SFLASH,
node_list,
1);
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;
debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
__func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
}
}
int 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 | \
......@@ -196,8 +218,8 @@ int spi_claim_bus(struct spi_slave *slave)
/*
* 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(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
......@@ -227,24 +249,26 @@ void spi_release_bus(struct spi_slave *slave)
void 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(&regs->command, SPI_CMD_CS_VAL);
}
void 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(&regs->command, SPI_CMD_CS_VAL);
}
int 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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment