[PATCH] fsi: master: Add link_disable function
Eddie James
eajames at linux.ibm.com
Tue Feb 18 07:05:47 AEDT 2020
On 2/17/20 2:04 PM, Eddie James wrote:
> The master driver needs to disable links that don't have slaves or links
> that fail to be accessed. To do this, add a link_disable function and
> use it in the failure path for slave break and init.
Totally botched the patch... will resend.
Eddie
>
> Signed-off-by: Eddie James <eajames at linux.ibm.com>
> ---
> drivers/fsi/fsi-core.c | 13 ++++++-
> drivers/fsi/fsi-master-aspeed.c | 30 ++++++++++++++++
> drivers/fsi/fsi-master-hub.c | 22 ++++++++++++
> drivers/fsi/fsi-master.h | 1 +
> drivers/fsi/fsi2spim.c | 63 +++++++++++++++++++++++++++++++++
> 5 files changed, 128 insertions(+), 1 deletion(-)
> create mode 100644 drivers/fsi/fsi2spim.c
>
> diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
> index 8244da8a7241..d81ee9f582a5 100644
> --- a/drivers/fsi/fsi-core.c
> +++ b/drivers/fsi/fsi-core.c
> @@ -1154,6 +1154,14 @@ static int fsi_master_write(struct fsi_master *master, int link,
> return rc;
> }
>
> +static int fsi_master_link_disable(struct fsi_master *master, int link)
> +{
> + if (master->link_disable)
> + return master->link_disable(master, link);
> +
> + return 0;
> +}
> +
> static int fsi_master_link_enable(struct fsi_master *master, int link)
> {
> if (master->link_enable)
> @@ -1194,10 +1202,13 @@ static int fsi_master_scan(struct fsi_master *master)
> if (rc) {
> dev_dbg(&master->dev,
> "break to link %d failed: %d\n", link, rc);
> + fsi_master_link_disable(master, link);
> continue;
> }
>
> - fsi_slave_init(master, link, 0);
> + rc = fsi_slave_init(master, link, 0);
> + if (rc)
> + fsi_master_link_disable(master, link);
> }
>
> return 0;
> diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
> index f49742b310c2..7ce5d9eb6c78 100644
> --- a/drivers/fsi/fsi-master-aspeed.c
> +++ b/drivers/fsi/fsi-master-aspeed.c
> @@ -299,6 +299,35 @@ static int aspeed_master_write(struct fsi_master *master, int link,
> return 0;
> }
>
> +static int aspeed_master_link_disable(struct fsi_master *master, int link)
> +{
> + struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
> + int idx, bit, ret;
> + __be32 reg, result;
> +
> + idx = link / 32;
> + bit = link % 32;
> +
> + reg = cpu_to_be32(0x80000000 >> bit);
> +
> + ret = opb_writel(aspeed, ctrl_base + FSI_MCENP0 + (4 * idx), reg);
> + if (ret)
> + return ret;
> +
> + mdelay(FSI_LINK_ENABLE_SETUP_TIME);
> +
> + ret = opb_readl(aspeed, ctrl_base + FSI_MENP0 + (4 * idx), &result);
> + if (ret)
> + return ret;
> +
> + if (result & reg) {
> + dev_err(aspeed->dev, "%s failed: %08x\n", __func__, result);
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> static int aspeed_master_link_enable(struct fsi_master *master, int link)
> {
> struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
> @@ -491,6 +520,7 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
> aspeed->master.write = aspeed_master_write;
> aspeed->master.send_break = aspeed_master_break;
> aspeed->master.term = aspeed_master_term;
> + aspeed->master.link_disable = aspeed_master_link_disable;
> aspeed->master.link_enable = aspeed_master_link_enable;
>
> dev_set_drvdata(&pdev->dev, aspeed);
> diff --git a/drivers/fsi/fsi-master-hub.c b/drivers/fsi/fsi-master-hub.c
> index def35cf92571..26617fd5e2de 100644
> --- a/drivers/fsi/fsi-master-hub.c
> +++ b/drivers/fsi/fsi-master-hub.c
> @@ -77,6 +77,27 @@ static int hub_master_break(struct fsi_master *master, int link)
> return hub_master_write(master, link, 0, addr, &cmd, sizeof(cmd));
> }
>
> +static int hub_master_link_disable(struct fsi_master *master, int link)
> +{
> + struct fsi_master_hub *hub = to_fsi_master_hub(master);
> + int idx, bit;
> + __be32 reg;
> + int rc;
> +
> + idx = link / 32;
> + bit = link % 32;
> +
> + reg = cpu_to_be32(0x80000000 >> bit);
> +
> + rc = fsi_device_write(hub->upstream, FSI_MCENP0 + (4 * idx), ®, 4);
> +
> + mdelay(FSI_LINK_ENABLE_SETUP_TIME);
> +
> + fsi_device_read(hub->upstream, FSI_MENP0 + (4 * idx), ®, 4);
> +
> + return rc;
> +}
> +
> static int hub_master_link_enable(struct fsi_master *master, int link)
> {
> struct fsi_master_hub *hub = to_fsi_master_hub(master);
> @@ -228,6 +249,7 @@ static int hub_master_probe(struct device *dev)
> hub->master.read = hub_master_read;
> hub->master.write = hub_master_write;
> hub->master.send_break = hub_master_break;
> + hub->master.link_disable = hub_master_link_disable;
> hub->master.link_enable = hub_master_link_enable;
>
> dev_set_drvdata(dev, hub);
> diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
> index 6e8d4d4d5149..7ecb86a678f9 100644
> --- a/drivers/fsi/fsi-master.h
> +++ b/drivers/fsi/fsi-master.h
> @@ -130,6 +130,7 @@ struct fsi_master {
> uint32_t addr, const void *val, size_t size);
> int (*term)(struct fsi_master *, int link, uint8_t id);
> int (*send_break)(struct fsi_master *, int link);
> + int (*link_disable)(struct fsi_master *, int link);
> int (*link_enable)(struct fsi_master *, int link);
> int (*link_config)(struct fsi_master *, int link,
> u8 t_send_delay, u8 t_echo_delay);
> diff --git a/drivers/fsi/fsi2spim.c b/drivers/fsi/fsi2spim.c
> new file mode 100644
> index 000000000000..88a34468ef3b
> --- /dev/null
> +++ b/drivers/fsi/fsi2spim.c
> @@ -0,0 +1,63 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) IBM Corporation 2020
> + */
> +
> +#include <linux/fsi.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#define FSI_ENGID_FSI2SPIM 0x23
> +
> +static int fsi2spim_probe(struct device *dev)
> +{
> + int rc;
> + struct spi_controller *ctlr;
> + struct fsi_spi *ctx;
> +
> + ctlr = spi_alloc_master(dev, sizeof(*ctx));
> + if (!ctlr)
> + return -ENOMEM;
> +
> + ctlr->dev.of_node = dev->of_node;
> + ctlr->num_chipselect = 4;
> + ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX;
> + ctlr->max_transfer_size = fsi_spi_max_transfer_size;
> + ctlr->transfer_one_message = fsi_spi_transfer_one_message;
> +
> + ctx = spi_controller_get_devdata(ctlr);
> + ctx->dev = &ctlr->dev;
> + ctx->fsi = to_fsi_dev(dev);
> +
> + rc = devm_spi_register_controller(dev, ctlr);
> + if (rc)
> + spi_controller_put(ctlr);
> +
> + return rc;
> +}
> +
> +static int fsi2spim_remove(struct device *dev)
> +{
> + return 0;
> +}
> +
> +static const struct fsi_device_id fsi2spim_ids[] = {
> + { FSI_ENGID_FSI2SPIM, FSI_VERSION_ANY },
> + { }
> +};
> +
> +static struct fsi_driver fsi2spim_driver = {
> + .id_table = fsi2spim_ids,
> + .drv = {
> + .name = "fsi2spim",
> + .bus = &fsi_bus_type,
> + .probe = fsi2spim_probe,
> + .remove = fsi2spim_remove,
> + },
> +};
> +
> +module_fsi_driver(fsi2spim_driver);
> +
> +MODULE_AUTHOR("Eddie James <eajames at linux.ibm.com>");
> +MODULE_DESCRIPTION("FSI2SPIM Bridge Driver");
> +MODULE_LICENSE("GPL");
More information about the openbmc
mailing list