diff options
author | Ley Foon Tan <ley.foon.tan@intel.com> | 2018-09-07 14:25:29 +0800 |
---|---|---|
committer | Jagan Teki <jagan@amarulasolutions.com> | 2018-10-02 22:13:58 +0530 |
commit | 6ac5909f51fb4e50604f1a89d0535aefcc51f476 (patch) | |
tree | f313cc5a30840777da11ff1e4f00bb825215e637 /drivers | |
parent | 938db6fe5da3581ed2c17d64c7e016a7a8df5237 (diff) | |
download | u-boot-6ac5909f51fb4e50604f1a89d0535aefcc51f476.tar.gz |
spi: designware_spi: Add reset ctrl to driver
Add code to reset all reset signals as in SPI DT node. A reset property
is an optional feature, so only print out a warning and do not fail if a
reset property is not present.
If a reset property is discovered, then use it to deassert, thus
bringing the IP out of reset.
Release reset when _remove().
Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
Acked-by: Marek Vasut <marex@denx.de>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/designware_spi.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index d8b73ea326..5cca414486 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -17,6 +17,7 @@ #include <malloc.h> #include <spi.h> #include <fdtdec.h> +#include <reset.h> #include <linux/compat.h> #include <linux/iopoll.h> #include <asm/io.h> @@ -111,6 +112,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) @@ -231,6 +234,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); @@ -244,6 +275,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; @@ -478,6 +513,13 @@ 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); + + return reset_release_bulk(&priv->resets); +} + static const struct dm_spi_ops dw_spi_ops = { .xfer = dw_spi_xfer, .set_speed = dw_spi_set_speed, @@ -502,4 +544,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, }; |