|
|
|
@ -56,6 +56,8 @@ struct zynq_spi_platdata { |
|
|
|
|
struct zynq_spi_regs *regs; |
|
|
|
|
u32 frequency; /* input frequency */ |
|
|
|
|
u32 speed_hz; |
|
|
|
|
uint deactivate_delay_us; /* Delay to wait after deactivate */ |
|
|
|
|
uint activate_delay_us; /* Delay to wait after activate */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/* zynq spi priv */ |
|
|
|
@ -63,6 +65,7 @@ struct zynq_spi_priv { |
|
|
|
|
struct zynq_spi_regs *regs; |
|
|
|
|
u8 cs; |
|
|
|
|
u8 mode; |
|
|
|
|
ulong last_transaction_us; /* Time of last transaction end */ |
|
|
|
|
u8 fifo_depth; |
|
|
|
|
u32 freq; /* required frequency */ |
|
|
|
|
}; |
|
|
|
@ -78,6 +81,10 @@ static int zynq_spi_ofdata_to_platdata(struct udevice *bus) |
|
|
|
|
/* FIXME: Use 250MHz as a suitable default */ |
|
|
|
|
plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", |
|
|
|
|
250000000); |
|
|
|
|
plat->deactivate_delay_us = fdtdec_get_int(blob, node, |
|
|
|
|
"spi-deactivate-delay", 0); |
|
|
|
|
plat->activate_delay_us = fdtdec_get_int(blob, node, |
|
|
|
|
"spi-activate-delay", 0); |
|
|
|
|
plat->speed_hz = plat->frequency / 2; |
|
|
|
|
|
|
|
|
|
debug("%s: regs=%p max-frequency=%d\n", __func__, |
|
|
|
@ -133,10 +140,19 @@ static int zynq_spi_probe(struct udevice *bus) |
|
|
|
|
static void spi_cs_activate(struct udevice *dev) |
|
|
|
|
{ |
|
|
|
|
struct udevice *bus = dev->parent; |
|
|
|
|
struct zynq_spi_platdata *plat = bus->platdata; |
|
|
|
|
struct zynq_spi_priv *priv = dev_get_priv(bus); |
|
|
|
|
struct zynq_spi_regs *regs = priv->regs; |
|
|
|
|
u32 cr; |
|
|
|
|
|
|
|
|
|
/* If it's too soon to do another transaction, wait */ |
|
|
|
|
if (plat->deactivate_delay_us && priv->last_transaction_us) { |
|
|
|
|
ulong delay_us; /* The delay completed so far */ |
|
|
|
|
delay_us = timer_get_us() - priv->last_transaction_us; |
|
|
|
|
if (delay_us < plat->deactivate_delay_us) |
|
|
|
|
udelay(plat->deactivate_delay_us - delay_us); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
clrbits_le32(®s->cr, ZYNQ_SPI_CR_CS_MASK); |
|
|
|
|
cr = readl(®s->cr); |
|
|
|
|
/*
|
|
|
|
@ -147,15 +163,23 @@ static void spi_cs_activate(struct udevice *dev) |
|
|
|
|
*/ |
|
|
|
|
cr |= (~(1 << priv->cs) << ZYNQ_SPI_CR_SS_SHIFT) & ZYNQ_SPI_CR_CS_MASK; |
|
|
|
|
writel(cr, ®s->cr); |
|
|
|
|
|
|
|
|
|
if (plat->activate_delay_us) |
|
|
|
|
udelay(plat->activate_delay_us); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void spi_cs_deactivate(struct udevice *dev) |
|
|
|
|
{ |
|
|
|
|
struct udevice *bus = dev->parent; |
|
|
|
|
struct zynq_spi_platdata *plat = bus->platdata; |
|
|
|
|
struct zynq_spi_priv *priv = dev_get_priv(bus); |
|
|
|
|
struct zynq_spi_regs *regs = priv->regs; |
|
|
|
|
|
|
|
|
|
setbits_le32(®s->cr, ZYNQ_SPI_CR_CS_MASK); |
|
|
|
|
|
|
|
|
|
/* Remember time of this transaction so we can honour the bus delay */ |
|
|
|
|
if (plat->deactivate_delay_us) |
|
|
|
|
priv->last_transaction_us = timer_get_us(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int zynq_spi_claim_bus(struct udevice *dev) |
|
|
|
|