X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fspi%2Fmvebu_a3700_spi.c;h=feeafdceaa618680de3f41a5c8945b4e200a124a;hb=ac7e14ae0d36023dd32400a8eab9433a54e77b83;hp=d1708a8d56c8a18564efaaff87905d9abd93218c;hpb=fc04bd84b34e049286bcfc6791e9bb29123ec1ea;p=oweals%2Fu-boot.git diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c index d1708a8d56..feeafdceaa 100644 --- a/drivers/spi/mvebu_a3700_spi.c +++ b/drivers/spi/mvebu_a3700_spi.c @@ -1,15 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2015 Marvell International Ltd. * * Copyright (C) 2016 Stefan Roese - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include +#include #include #include @@ -22,9 +22,8 @@ DECLARE_GLOBAL_DATA_PTR; #define MVEBU_SPI_A3700_CLK_POL BIT(7) #define MVEBU_SPI_A3700_FIFO_EN BIT(17) #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 */ struct spi_reg { @@ -36,8 +35,7 @@ struct spi_reg { struct mvebu_spi_platdata { struct spi_reg *spireg; - unsigned int frequency; - unsigned int clock; + struct clk clk; }; static void spi_cs_activate(struct spi_reg *reg, int cs) @@ -178,17 +176,18 @@ static int mvebu_spi_set_speed(struct udevice *bus, uint hz) { struct mvebu_spi_platdata *plat = dev_get_platdata(bus); struct spi_reg *reg = plat->spireg; - u32 data; + u32 data, prescale; 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); @@ -252,21 +251,24 @@ static int mvebu_spi_probe(struct udevice *bus) static int mvebu_spi_ofdata_to_platdata(struct udevice *bus) { struct mvebu_spi_platdata *plat = dev_get_platdata(bus); + int ret; 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; } @@ -294,4 +296,5 @@ U_BOOT_DRIVER(mvebu_spi) = { .ofdata_to_platdata = mvebu_spi_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata), .probe = mvebu_spi_probe, + .remove = mvebu_spi_remove, };