X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fspi%2Fdesignware_spi.c;h=c9b14f90292ec2898dce6471385d6ac390b7138a;hb=abdbefba2a4e9666f798de13b4b88021f23b19f3;hp=5e2d290ddcf6e34f552e68afe9917fdc62c26691;hpb=9b14ac5cc2294ac3eaae92421abff27ed3e6caae;p=oweals%2Fu-boot.git diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 5e2d290ddc..c9b14f9029 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Designware master SPI core controller driver * @@ -6,24 +7,24 @@ * Very loosely based on the Linux driver: * drivers/spi/spi-dw.c, which is: * Copyright (c) 2009, Intel Corporation. - * - * SPDX-License-Identifier: GPL-2.0 */ -#include #include +#include +#include #include #include #include #include #include #include +#include +#include +#include #include #include #include -DECLARE_GLOBAL_DATA_PTR; - /* Register offsets */ #define DW_SPI_CTRL0 0x00 #define DW_SPI_CTRL1 0x04 @@ -112,6 +113,8 @@ struct dw_spi_priv { void *tx_end; void *rx; void *rx_end; + + struct reset_ctl_bulk resets; }; static inline u32 dw_read(struct dw_spi_priv *priv, u32 offset) @@ -126,7 +129,7 @@ static inline void dw_write(struct dw_spi_priv *priv, u32 offset, u32 val) static int request_gpio_cs(struct udevice *bus) { -#if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD) +#if CONFIG_IS_ENABLED(DM_GPIO) && !defined(CONFIG_SPL_BUILD) struct dw_spi_priv *priv = dev_get_priv(bus); int ret; @@ -153,14 +156,12 @@ static int request_gpio_cs(struct udevice *bus) static int dw_spi_ofdata_to_platdata(struct udevice *bus) { struct dw_spi_platdata *plat = bus->platdata; - const void *blob = gd->fdt_blob; - int node = dev_of_offset(bus); plat->regs = (struct dw_spi *)devfdt_get_addr(bus); /* Use 500KHz as a suitable default */ - plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", - 500000); + plat->frequency = dev_read_u32_default(bus, "spi-max-frequency", + 500000); debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs, plat->frequency); @@ -232,6 +233,34 @@ err_rate: return -EINVAL; } +static int dw_spi_reset(struct udevice *bus) +{ + int ret; + struct dw_spi_priv *priv = dev_get_priv(bus); + + ret = reset_get_bulk(bus, &priv->resets); + if (ret) { + /* + * Return 0 if error due to !CONFIG_DM_RESET and reset + * DT property is not present. + */ + if (ret == -ENOENT || ret == -ENOTSUPP) + return 0; + + dev_warn(bus, "Can't get reset: %d\n", ret); + return ret; + } + + ret = reset_deassert_bulk(&priv->resets); + if (ret) { + reset_release_bulk(&priv->resets); + dev_err(bus, "Failed to reset: %d\n", ret); + return ret; + } + + return 0; +} + static int dw_spi_probe(struct udevice *bus) { struct dw_spi_platdata *plat = dev_get_platdata(bus); @@ -245,6 +274,10 @@ static int dw_spi_probe(struct udevice *bus) if (ret) return ret; + ret = dw_spi_reset(bus); + if (ret) + return ret; + /* Currently only bits_per_word == 8 supported */ priv->bits_per_word = 8; @@ -335,9 +368,15 @@ static int poll_transfer(struct dw_spi_priv *priv) return 0; } -static void external_cs_manage(struct udevice *dev, bool on) +/* + * We define external_cs_manage function as 'weak' as some targets + * (like MSCC Ocelot) don't control the external CS pin using a GPIO + * controller. These SoCs use specific registers to control by + * software the SPI pins (and especially the CS). + */ +__weak void external_cs_manage(struct udevice *dev, bool on) { -#if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD) +#if CONFIG_IS_ENABLED(DM_GPIO) && !defined(CONFIG_SPL_BUILD) struct dw_spi_priv *priv = dev_get_priv(dev->parent); if (!dm_gpio_is_valid(&priv->cs_gpio)) @@ -479,6 +518,27 @@ static int dw_spi_set_mode(struct udevice *bus, uint mode) return 0; } +static int dw_spi_remove(struct udevice *bus) +{ + struct dw_spi_priv *priv = dev_get_priv(bus); + int ret; + + ret = reset_release_bulk(&priv->resets); + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_disable(&priv->clk); + if (ret) + return ret; + + ret = clk_free(&priv->clk); + if (ret) + return ret; +#endif + return 0; +} + static const struct dm_spi_ops dw_spi_ops = { .xfer = dw_spi_xfer, .set_speed = dw_spi_set_speed, @@ -503,4 +563,5 @@ U_BOOT_DRIVER(dw_spi) = { .platdata_auto_alloc_size = sizeof(struct dw_spi_platdata), .priv_auto_alloc_size = sizeof(struct dw_spi_priv), .probe = dw_spi_probe, + .remove = dw_spi_remove, };