|
@@ -9,6 +9,7 @@
|
|
#include <dm.h>
|
|
#include <dm.h>
|
|
#include <malloc.h>
|
|
#include <malloc.h>
|
|
#include <spi.h>
|
|
#include <spi.h>
|
|
|
|
+#include <clk.h>
|
|
#include <wait_bit.h>
|
|
#include <wait_bit.h>
|
|
#include <asm/io.h>
|
|
#include <asm/io.h>
|
|
|
|
|
|
@@ -21,9 +22,8 @@ DECLARE_GLOBAL_DATA_PTR;
|
|
#define MVEBU_SPI_A3700_CLK_POL BIT(7)
|
|
#define MVEBU_SPI_A3700_CLK_POL BIT(7)
|
|
#define MVEBU_SPI_A3700_FIFO_EN BIT(17)
|
|
#define MVEBU_SPI_A3700_FIFO_EN BIT(17)
|
|
#define MVEBU_SPI_A3700_SPI_EN_0 BIT(16)
|
|
#define MVEBU_SPI_A3700_SPI_EN_0 BIT(16)
|
|
-#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT 0
|
|
|
|
-#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK \
|
|
|
|
- (0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
|
|
|
|
|
|
+#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK 0x1f
|
|
|
|
+
|
|
|
|
|
|
/* SPI registers */
|
|
/* SPI registers */
|
|
struct spi_reg {
|
|
struct spi_reg {
|
|
@@ -35,8 +35,7 @@ struct spi_reg {
|
|
|
|
|
|
struct mvebu_spi_platdata {
|
|
struct mvebu_spi_platdata {
|
|
struct spi_reg *spireg;
|
|
struct spi_reg *spireg;
|
|
- unsigned int frequency;
|
|
|
|
- unsigned int clock;
|
|
|
|
|
|
+ struct clk clk;
|
|
};
|
|
};
|
|
|
|
|
|
static void spi_cs_activate(struct spi_reg *reg, int cs)
|
|
static void spi_cs_activate(struct spi_reg *reg, int cs)
|
|
@@ -177,17 +176,18 @@ static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
|
|
{
|
|
{
|
|
struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
|
|
struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
|
|
struct spi_reg *reg = plat->spireg;
|
|
struct spi_reg *reg = plat->spireg;
|
|
- u32 data;
|
|
|
|
|
|
+ u32 data, prescale;
|
|
|
|
|
|
data = readl(®->cfg);
|
|
data = readl(®->cfg);
|
|
|
|
|
|
- /* Set Prescaler */
|
|
|
|
- data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
|
|
|
|
|
|
+ prescale = DIV_ROUND_UP(clk_get_rate(&plat->clk), hz);
|
|
|
|
+ if (prescale > 0x1f)
|
|
|
|
+ prescale = 0x1f;
|
|
|
|
+ else if (prescale > 0xf)
|
|
|
|
+ prescale = 0x10 + (prescale + 1) / 2;
|
|
|
|
|
|
- /* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
|
|
|
|
- if (hz > plat->frequency)
|
|
|
|
- hz = plat->frequency;
|
|
|
|
- data |= plat->clock / hz;
|
|
|
|
|
|
+ data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
|
|
|
|
+ data |= prescale & MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
|
|
|
|
|
|
writel(data, ®->cfg);
|
|
writel(data, ®->cfg);
|
|
|
|
|
|
@@ -251,21 +251,24 @@ static int mvebu_spi_probe(struct udevice *bus)
|
|
static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
|
|
static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
|
|
{
|
|
{
|
|
struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
|
|
struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
|
|
|
|
+ int ret;
|
|
|
|
|
|
plat->spireg = (struct spi_reg *)devfdt_get_addr(bus);
|
|
plat->spireg = (struct spi_reg *)devfdt_get_addr(bus);
|
|
|
|
|
|
- /*
|
|
|
|
- * FIXME
|
|
|
|
- * Right now, mvebu does not have a clock infrastructure in U-Boot
|
|
|
|
- * which should be used to query the input clock to the SPI
|
|
|
|
- * controller. Once this clock driver is integrated into U-Boot
|
|
|
|
- * it should be used to read the input clock and the DT property
|
|
|
|
- * can be removed.
|
|
|
|
- */
|
|
|
|
- plat->clock = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
|
|
|
|
- "clock-frequency", 160000);
|
|
|
|
- plat->frequency = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
|
|
|
|
- "spi-max-frequency", 40000);
|
|
|
|
|
|
+ ret = clk_get_by_index(bus, 0, &plat->clk);
|
|
|
|
+ if (ret) {
|
|
|
|
+ dev_err(bus, "cannot get clock\n");
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int mvebu_spi_remove(struct udevice *bus)
|
|
|
|
+{
|
|
|
|
+ struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
|
|
|
|
+
|
|
|
|
+ clk_free(&plat->clk);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -293,4 +296,5 @@ U_BOOT_DRIVER(mvebu_spi) = {
|
|
.ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
|
|
.ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
|
|
.platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
|
|
.platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
|
|
.probe = mvebu_spi_probe,
|
|
.probe = mvebu_spi_probe,
|
|
|
|
+ .remove = mvebu_spi_remove,
|
|
};
|
|
};
|