mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
fsi: Aspeed: Add mutex to protect HW access
There is nothing to prevent multiple commands being executed
simultaneously. Add a mutex to prevent this.
Fixes: 606397d67f
("fsi: Add ast2600 master driver")
Reviewed-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Milton Miller <miltonm@us.ibm.com>
Signed-off-by: Eddie James <eajames@linux.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
Link: https://lore.kernel.org/r/20201120004929.185239-1-joel@jms.id.au
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
fe34761d9f
commit
dfd7f2c1c5
@@ -8,6 +8,7 @@
|
|||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/mfd/syscon.h>
|
#include <linux/mfd/syscon.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
|
|
||||||
struct fsi_master_aspeed {
|
struct fsi_master_aspeed {
|
||||||
struct fsi_master master;
|
struct fsi_master master;
|
||||||
|
struct mutex lock; /* protect HW access */
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
@@ -254,6 +256,8 @@ static int aspeed_master_read(struct fsi_master *master, int link,
|
|||||||
addr |= id << 21;
|
addr |= id << 21;
|
||||||
addr += link * FSI_HUB_LINK_SIZE;
|
addr += link * FSI_HUB_LINK_SIZE;
|
||||||
|
|
||||||
|
mutex_lock(&aspeed->lock);
|
||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
ret = opb_readb(aspeed, fsi_base + addr, val);
|
ret = opb_readb(aspeed, fsi_base + addr, val);
|
||||||
@@ -265,14 +269,14 @@ static int aspeed_master_read(struct fsi_master *master, int link,
|
|||||||
ret = opb_readl(aspeed, fsi_base + addr, val);
|
ret = opb_readl(aspeed, fsi_base + addr, val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = check_errors(aspeed, ret);
|
ret = check_errors(aspeed, ret);
|
||||||
if (ret)
|
done:
|
||||||
return ret;
|
mutex_unlock(&aspeed->lock);
|
||||||
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aspeed_master_write(struct fsi_master *master, int link,
|
static int aspeed_master_write(struct fsi_master *master, int link,
|
||||||
@@ -287,6 +291,8 @@ static int aspeed_master_write(struct fsi_master *master, int link,
|
|||||||
addr |= id << 21;
|
addr |= id << 21;
|
||||||
addr += link * FSI_HUB_LINK_SIZE;
|
addr += link * FSI_HUB_LINK_SIZE;
|
||||||
|
|
||||||
|
mutex_lock(&aspeed->lock);
|
||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
ret = opb_writeb(aspeed, fsi_base + addr, *(u8 *)val);
|
ret = opb_writeb(aspeed, fsi_base + addr, *(u8 *)val);
|
||||||
@@ -298,14 +304,14 @@ static int aspeed_master_write(struct fsi_master *master, int link,
|
|||||||
ret = opb_writel(aspeed, fsi_base + addr, *(__be32 *)val);
|
ret = opb_writel(aspeed, fsi_base + addr, *(__be32 *)val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = check_errors(aspeed, ret);
|
ret = check_errors(aspeed, ret);
|
||||||
if (ret)
|
done:
|
||||||
return ret;
|
mutex_unlock(&aspeed->lock);
|
||||||
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aspeed_master_link_enable(struct fsi_master *master, int link,
|
static int aspeed_master_link_enable(struct fsi_master *master, int link,
|
||||||
@@ -320,17 +326,21 @@ static int aspeed_master_link_enable(struct fsi_master *master, int link,
|
|||||||
|
|
||||||
reg = cpu_to_be32(0x80000000 >> bit);
|
reg = cpu_to_be32(0x80000000 >> bit);
|
||||||
|
|
||||||
if (!enable)
|
mutex_lock(&aspeed->lock);
|
||||||
return opb_writel(aspeed, ctrl_base + FSI_MCENP0 + (4 * idx),
|
|
||||||
reg);
|
if (!enable) {
|
||||||
|
ret = opb_writel(aspeed, ctrl_base + FSI_MCENP0 + (4 * idx), reg);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
ret = opb_writel(aspeed, ctrl_base + FSI_MSENP0 + (4 * idx), reg);
|
ret = opb_writel(aspeed, ctrl_base + FSI_MSENP0 + (4 * idx), reg);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
mdelay(FSI_LINK_ENABLE_SETUP_TIME);
|
mdelay(FSI_LINK_ENABLE_SETUP_TIME);
|
||||||
|
done:
|
||||||
return 0;
|
mutex_unlock(&aspeed->lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aspeed_master_term(struct fsi_master *master, int link, uint8_t id)
|
static int aspeed_master_term(struct fsi_master *master, int link, uint8_t id)
|
||||||
@@ -431,9 +441,11 @@ static ssize_t cfam_reset_store(struct device *dev, struct device_attribute *att
|
|||||||
{
|
{
|
||||||
struct fsi_master_aspeed *aspeed = dev_get_drvdata(dev);
|
struct fsi_master_aspeed *aspeed = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
mutex_lock(&aspeed->lock);
|
||||||
gpiod_set_value(aspeed->cfam_reset_gpio, 1);
|
gpiod_set_value(aspeed->cfam_reset_gpio, 1);
|
||||||
usleep_range(900, 1000);
|
usleep_range(900, 1000);
|
||||||
gpiod_set_value(aspeed->cfam_reset_gpio, 0);
|
gpiod_set_value(aspeed->cfam_reset_gpio, 0);
|
||||||
|
mutex_unlock(&aspeed->lock);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@@ -597,6 +609,7 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, aspeed);
|
dev_set_drvdata(&pdev->dev, aspeed);
|
||||||
|
|
||||||
|
mutex_init(&aspeed->lock);
|
||||||
aspeed_master_init(aspeed);
|
aspeed_master_init(aspeed);
|
||||||
|
|
||||||
rc = fsi_master_register(&aspeed->master);
|
rc = fsi_master_register(&aspeed->master);
|
||||||
|
Reference in New Issue
Block a user