[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), &reg, 4);
> +
> +	mdelay(FSI_LINK_ENABLE_SETUP_TIME);
> +
> +	fsi_device_read(hub->upstream, FSI_MENP0 + (4 * idx), &reg, 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