mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
Two fixes for the testunit and and a fixup for the code reorganization
of the previous wmt-driver -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmaADYQACgkQFA3kzBSg KbYLHg//Zcm15ojDvBkvGCHnlien/ZwaVQnTmM1zuo8SziwlnNVBST9ib7wz0Mfr SACAs3kGaNw5nSA/ryVxYw5s03YyWoqcwwgnB3rY+JX1lOsOxBv0Jzjh1SumwQHC RGimQv7nU8Ype8HEcy6cy2WKBSH0gEDiHwUfraxDpRBejQTJqREtJGyMXQzNFzEr QM1q6AuXSnhq75t3cpcN3d2xCnmnv6UbFEsxbYB+TWg8XVJkYwcc/hbGLz3wz3kz G/eLgerPaDXDr372LPsTKyaKb07vrk3gCyqCpYFAV3FYtCHHSlaNFnrdJBZtZA+4 1k7QmDDlfoV+Or64oDdfgAhUhvZNqpwSmIlJs7SiNH/1xIqt9RDni3XOomCgi32l IWiYN6XDVJxV81AyObYdI6qFLEgPja7MQCXFe3U06J//hxTuiBRcPnuDoakZVkgr hMrEQKxlwkcQCBoZYIUjgFxEtRStXxp4d15TbjVNa4pLQmBstb7Ax8RHXNgbLQWn 3sIpoutSr1qMBKvb8SFKCZxTfjzScLwMDn+NIS04XmlAt8YZ5m8XwRkx5j/d1wUD N0x7+wvP/O04Z4XfT3V46VD2Yp+bd6xrLx0LJx6W4f1hZCXUj3vaTL/ykFV5Sf6u m07j+zzASprZ7NysGWhPYhn7J3Wxc2ng0ogjYQcP5Pt+saI62S4= =pKpi -----END PGP SIGNATURE----- Merge tag 'i2c-for-6.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux Pull i2c fixes from Wolfram Sang: "Two fixes for the testunit and and a fixup for the code reorganization of the previous wmt-driver" * tag 'i2c-for-6.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: testunit: discard write requests while old command is running i2c: testunit: don't erase registers after STOP i2c: viai2c: turn common code into a proper module
This commit is contained in:
commit
ebe70b3ace
@ -29,8 +29,7 @@ obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
|
||||
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
|
||||
obj-$(CONFIG_I2C_VIA) += i2c-via.o
|
||||
obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
|
||||
i2c-zhaoxin-objs := i2c-viai2c-zhaoxin.o i2c-viai2c-common.o
|
||||
obj-$(CONFIG_I2C_ZHAOXIN) += i2c-zhaoxin.o
|
||||
obj-$(CONFIG_I2C_ZHAOXIN) += i2c-viai2c-zhaoxin.o i2c-viai2c-common.o
|
||||
|
||||
# Mac SMBus host controller drivers
|
||||
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
|
||||
@ -120,8 +119,7 @@ obj-$(CONFIG_I2C_TEGRA_BPMP) += i2c-tegra-bpmp.o
|
||||
obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
|
||||
obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o
|
||||
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
|
||||
i2c-wmt-objs := i2c-viai2c-wmt.o i2c-viai2c-common.o
|
||||
obj-$(CONFIG_I2C_WMT) += i2c-wmt.o
|
||||
obj-$(CONFIG_I2C_WMT) += i2c-viai2c-wmt.o i2c-viai2c-common.o
|
||||
i2c-octeon-objs := i2c-octeon-core.o i2c-octeon-platdrv.o
|
||||
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
|
||||
i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o
|
||||
|
@ -17,6 +17,7 @@ int viai2c_wait_bus_not_busy(struct viai2c *i2c)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viai2c_wait_bus_not_busy);
|
||||
|
||||
static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, int last)
|
||||
{
|
||||
@ -121,6 +122,7 @@ int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
|
||||
return (ret < 0) ? ret : i;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viai2c_xfer);
|
||||
|
||||
/*
|
||||
* Main process of the byte mode xfer
|
||||
@ -130,7 +132,7 @@ int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
* 0: there is still data that needs to be transferred
|
||||
* -EIO: error occurred
|
||||
*/
|
||||
static int viai2c_irq_xfer(struct viai2c *i2c)
|
||||
int viai2c_irq_xfer(struct viai2c *i2c)
|
||||
{
|
||||
u16 val;
|
||||
struct i2c_msg *msg = i2c->msg;
|
||||
@ -171,51 +173,11 @@ static int viai2c_irq_xfer(struct viai2c *i2c)
|
||||
|
||||
return i2c->xfered_len == msg->len;
|
||||
}
|
||||
|
||||
int __weak viai2c_fifo_irq_xfer(struct viai2c *i2c, bool irq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t viai2c_isr(int irq, void *data)
|
||||
{
|
||||
struct viai2c *i2c = data;
|
||||
u8 status;
|
||||
|
||||
/* save the status and write-clear it */
|
||||
status = readw(i2c->base + VIAI2C_REG_ISR);
|
||||
if (!status && i2c->platform == VIAI2C_PLAT_ZHAOXIN)
|
||||
return IRQ_NONE;
|
||||
|
||||
writew(status, i2c->base + VIAI2C_REG_ISR);
|
||||
|
||||
i2c->ret = 0;
|
||||
if (status & VIAI2C_ISR_NACK_ADDR)
|
||||
i2c->ret = -EIO;
|
||||
|
||||
if (i2c->platform == VIAI2C_PLAT_WMT && (status & VIAI2C_ISR_SCL_TIMEOUT))
|
||||
i2c->ret = -ETIMEDOUT;
|
||||
|
||||
if (!i2c->ret) {
|
||||
if (i2c->mode == VIAI2C_BYTE_MODE)
|
||||
i2c->ret = viai2c_irq_xfer(i2c);
|
||||
else
|
||||
i2c->ret = viai2c_fifo_irq_xfer(i2c, true);
|
||||
}
|
||||
|
||||
/* All the data has been successfully transferred or error occurred */
|
||||
if (i2c->ret)
|
||||
complete(&i2c->complete);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viai2c_irq_xfer);
|
||||
|
||||
int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat)
|
||||
{
|
||||
int err;
|
||||
int irq_flags;
|
||||
struct viai2c *i2c;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
|
||||
if (!i2c)
|
||||
@ -225,28 +187,8 @@ int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat)
|
||||
if (IS_ERR(i2c->base))
|
||||
return PTR_ERR(i2c->base);
|
||||
|
||||
if (plat == VIAI2C_PLAT_WMT) {
|
||||
irq_flags = 0;
|
||||
i2c->irq = irq_of_parse_and_map(np, 0);
|
||||
if (!i2c->irq)
|
||||
return -EINVAL;
|
||||
} else if (plat == VIAI2C_PLAT_ZHAOXIN) {
|
||||
irq_flags = IRQF_SHARED;
|
||||
i2c->irq = platform_get_irq(pdev, 0);
|
||||
if (i2c->irq < 0)
|
||||
return i2c->irq;
|
||||
} else {
|
||||
return dev_err_probe(&pdev->dev, -EINVAL, "wrong platform type\n");
|
||||
}
|
||||
|
||||
i2c->platform = plat;
|
||||
|
||||
err = devm_request_irq(&pdev->dev, i2c->irq, viai2c_isr,
|
||||
irq_flags, pdev->name, i2c);
|
||||
if (err)
|
||||
return dev_err_probe(&pdev->dev, err,
|
||||
"failed to request irq %i\n", i2c->irq);
|
||||
|
||||
i2c->dev = &pdev->dev;
|
||||
init_completion(&i2c->complete);
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
@ -254,3 +196,8 @@ int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat)
|
||||
*pi2c = i2c;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(viai2c_init);
|
||||
|
||||
MODULE_DESCRIPTION("Via/Wondermedia/Zhaoxin I2C master-mode bus adapter");
|
||||
MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -80,6 +80,6 @@ struct viai2c {
|
||||
int viai2c_wait_bus_not_busy(struct viai2c *i2c);
|
||||
int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num);
|
||||
int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat);
|
||||
int viai2c_fifo_irq_xfer(struct viai2c *i2c, bool irq);
|
||||
int viai2c_irq_xfer(struct viai2c *i2c);
|
||||
|
||||
#endif
|
||||
|
@ -72,6 +72,32 @@ static int wmt_i2c_reset_hardware(struct viai2c *i2c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t wmt_i2c_isr(int irq, void *data)
|
||||
{
|
||||
struct viai2c *i2c = data;
|
||||
u8 status;
|
||||
|
||||
/* save the status and write-clear it */
|
||||
status = readw(i2c->base + VIAI2C_REG_ISR);
|
||||
writew(status, i2c->base + VIAI2C_REG_ISR);
|
||||
|
||||
i2c->ret = 0;
|
||||
if (status & VIAI2C_ISR_NACK_ADDR)
|
||||
i2c->ret = -EIO;
|
||||
|
||||
if (status & VIAI2C_ISR_SCL_TIMEOUT)
|
||||
i2c->ret = -ETIMEDOUT;
|
||||
|
||||
if (!i2c->ret)
|
||||
i2c->ret = viai2c_irq_xfer(i2c);
|
||||
|
||||
/* All the data has been successfully transferred or error occurred */
|
||||
if (i2c->ret)
|
||||
complete(&i2c->complete);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int wmt_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
@ -84,6 +110,16 @@ static int wmt_i2c_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
i2c->irq = platform_get_irq(pdev, 0);
|
||||
if (i2c->irq < 0)
|
||||
return i2c->irq;
|
||||
|
||||
err = devm_request_irq(&pdev->dev, i2c->irq, wmt_i2c_isr,
|
||||
0, pdev->name, i2c);
|
||||
if (err)
|
||||
return dev_err_probe(&pdev->dev, err,
|
||||
"failed to request irq %i\n", i2c->irq);
|
||||
|
||||
i2c->clk = of_clk_get(np, 0);
|
||||
if (IS_ERR(i2c->clk)) {
|
||||
dev_err(&pdev->dev, "unable to request clock\n");
|
||||
|
@ -49,8 +49,7 @@ struct viai2c_zhaoxin {
|
||||
u16 xfer_len;
|
||||
};
|
||||
|
||||
/* 'irq == true' means in interrupt context */
|
||||
int viai2c_fifo_irq_xfer(struct viai2c *i2c, bool irq)
|
||||
static int viai2c_fifo_xfer(struct viai2c *i2c)
|
||||
{
|
||||
u16 i;
|
||||
u8 tmp;
|
||||
@ -59,17 +58,6 @@ int viai2c_fifo_irq_xfer(struct viai2c *i2c, bool irq)
|
||||
bool read = !!(msg->flags & I2C_M_RD);
|
||||
struct viai2c_zhaoxin *priv = i2c->pltfm_priv;
|
||||
|
||||
if (irq) {
|
||||
/* get the received data */
|
||||
if (read)
|
||||
for (i = 0; i < priv->xfer_len; i++)
|
||||
msg->buf[i2c->xfered_len + i] = ioread8(base + ZXI2C_REG_HRDR);
|
||||
|
||||
i2c->xfered_len += priv->xfer_len;
|
||||
if (i2c->xfered_len == msg->len)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* reset fifo buffer */
|
||||
tmp = ioread8(base + ZXI2C_REG_HCR);
|
||||
iowrite8(tmp | ZXI2C_HCR_RST_FIFO, base + ZXI2C_REG_HCR);
|
||||
@ -92,18 +80,59 @@ int viai2c_fifo_irq_xfer(struct viai2c *i2c, bool irq)
|
||||
iowrite8(tmp, base + VIAI2C_REG_CR);
|
||||
}
|
||||
|
||||
if (irq) {
|
||||
/* continue transmission */
|
||||
tmp = ioread8(base + VIAI2C_REG_CR);
|
||||
iowrite8(tmp |= VIAI2C_CR_CPU_RDY, base + VIAI2C_REG_CR);
|
||||
} else {
|
||||
u16 tcr_val = i2c->tcr;
|
||||
u16 tcr_val = i2c->tcr;
|
||||
|
||||
/* start transmission */
|
||||
tcr_val |= read ? VIAI2C_TCR_READ : 0;
|
||||
writew(tcr_val | msg->addr, base + VIAI2C_REG_TCR);
|
||||
/* start transmission */
|
||||
tcr_val |= read ? VIAI2C_TCR_READ : 0;
|
||||
writew(tcr_val | msg->addr, base + VIAI2C_REG_TCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int viai2c_fifo_irq_xfer(struct viai2c *i2c)
|
||||
{
|
||||
u16 i;
|
||||
u8 tmp;
|
||||
struct i2c_msg *msg = i2c->msg;
|
||||
void __iomem *base = i2c->base;
|
||||
bool read = !!(msg->flags & I2C_M_RD);
|
||||
struct viai2c_zhaoxin *priv = i2c->pltfm_priv;
|
||||
|
||||
/* get the received data */
|
||||
if (read)
|
||||
for (i = 0; i < priv->xfer_len; i++)
|
||||
msg->buf[i2c->xfered_len + i] = ioread8(base + ZXI2C_REG_HRDR);
|
||||
|
||||
i2c->xfered_len += priv->xfer_len;
|
||||
if (i2c->xfered_len == msg->len)
|
||||
return 1;
|
||||
|
||||
/* reset fifo buffer */
|
||||
tmp = ioread8(base + ZXI2C_REG_HCR);
|
||||
iowrite8(tmp | ZXI2C_HCR_RST_FIFO, base + ZXI2C_REG_HCR);
|
||||
|
||||
/* set xfer len */
|
||||
priv->xfer_len = min_t(u16, msg->len - i2c->xfered_len, ZXI2C_FIFO_SIZE);
|
||||
if (read) {
|
||||
iowrite8(priv->xfer_len - 1, base + ZXI2C_REG_HRLR);
|
||||
} else {
|
||||
iowrite8(priv->xfer_len - 1, base + ZXI2C_REG_HTLR);
|
||||
/* set write data */
|
||||
for (i = 0; i < priv->xfer_len; i++)
|
||||
iowrite8(msg->buf[i2c->xfered_len + i], base + ZXI2C_REG_HTDR);
|
||||
}
|
||||
|
||||
/* prepare to stop transmission */
|
||||
if (priv->hrv && msg->len == (i2c->xfered_len + priv->xfer_len)) {
|
||||
tmp = ioread8(base + VIAI2C_REG_CR);
|
||||
tmp |= read ? VIAI2C_CR_RX_END : VIAI2C_CR_TX_END;
|
||||
iowrite8(tmp, base + VIAI2C_REG_CR);
|
||||
}
|
||||
|
||||
/* continue transmission */
|
||||
tmp = ioread8(base + VIAI2C_REG_CR);
|
||||
iowrite8(tmp |= VIAI2C_CR_CPU_RDY, base + VIAI2C_REG_CR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -135,7 +164,7 @@ static int zxi2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int
|
||||
priv->xfer_len = 0;
|
||||
i2c->xfered_len = 0;
|
||||
|
||||
viai2c_fifo_irq_xfer(i2c, 0);
|
||||
viai2c_fifo_xfer(i2c);
|
||||
|
||||
if (!wait_for_completion_timeout(&i2c->complete, VIAI2C_TIMEOUT))
|
||||
return -ETIMEDOUT;
|
||||
@ -228,6 +257,36 @@ static void zxi2c_get_bus_speed(struct viai2c *i2c)
|
||||
dev_info(i2c->dev, "speed mode is %s\n", i2c_freq_mode_string(params[0]));
|
||||
}
|
||||
|
||||
static irqreturn_t zxi2c_isr(int irq, void *data)
|
||||
{
|
||||
struct viai2c *i2c = data;
|
||||
u8 status;
|
||||
|
||||
/* save the status and write-clear it */
|
||||
status = readw(i2c->base + VIAI2C_REG_ISR);
|
||||
if (!status)
|
||||
return IRQ_NONE;
|
||||
|
||||
writew(status, i2c->base + VIAI2C_REG_ISR);
|
||||
|
||||
i2c->ret = 0;
|
||||
if (status & VIAI2C_ISR_NACK_ADDR)
|
||||
i2c->ret = -EIO;
|
||||
|
||||
if (!i2c->ret) {
|
||||
if (i2c->mode == VIAI2C_BYTE_MODE)
|
||||
i2c->ret = viai2c_irq_xfer(i2c);
|
||||
else
|
||||
i2c->ret = viai2c_fifo_irq_xfer(i2c);
|
||||
}
|
||||
|
||||
/* All the data has been successfully transferred or error occurred */
|
||||
if (i2c->ret)
|
||||
complete(&i2c->complete);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int zxi2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
int error;
|
||||
@ -239,6 +298,16 @@ static int zxi2c_probe(struct platform_device *pdev)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
i2c->irq = platform_get_irq(pdev, 0);
|
||||
if (i2c->irq < 0)
|
||||
return i2c->irq;
|
||||
|
||||
error = devm_request_irq(&pdev->dev, i2c->irq, zxi2c_isr,
|
||||
IRQF_SHARED, pdev->name, i2c);
|
||||
if (error)
|
||||
return dev_err_probe(&pdev->dev, error,
|
||||
"failed to request irq %i\n", i2c->irq);
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
@ -118,9 +118,12 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
|
||||
queue_delayed_work(system_long_wq, &tu->worker,
|
||||
msecs_to_jiffies(10 * tu->regs[TU_REG_DELAY]));
|
||||
}
|
||||
fallthrough;
|
||||
break;
|
||||
|
||||
case I2C_SLAVE_WRITE_REQUESTED:
|
||||
if (test_bit(TU_FLAG_IN_PROCESS, &tu->flags))
|
||||
return -EBUSY;
|
||||
|
||||
memset(tu->regs, 0, TU_NUM_REGS);
|
||||
tu->reg_idx = 0;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user