diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 7da08f5c0..392688b7c 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #endif /* Meson I2C register map */ @@ -69,6 +71,11 @@ enum { STATE_WRITE, }; +struct meson_i2c_data { + bool tee; + u32 tee_reg; +}; + /** * struct meson_i2c - Meson I2C device private data * @@ -112,8 +119,20 @@ struct meson_i2c { int retain_fastmode; int irq; #endif + struct meson_i2c_data *data; }; +static void meson_i2c_writel(struct meson_i2c *i2c, u32 data, int reg) +{ + struct arm_smccc_res res; + + if (i2c->data->tee) + arm_smccc_smc(SECURE_PWM_I2C, SECID_I2C, 0, + i2c->data->tee_reg + reg, data, 0, 0, 0, &res); + else + writel(data, i2c->regs + reg); +} + static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask, u32 val) { @@ -122,7 +141,7 @@ static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask, data = readl(i2c->regs + reg); data &= ~mask; data |= val & mask; - writel(data, i2c->regs + reg); + meson_i2c_writel(i2c, data, reg); } static void meson_i2c_reset_tokens(struct meson_i2c *i2c) @@ -303,8 +322,8 @@ static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len) for (i = 4; i < min(8, len); i++) wdata1 |= *buf++ << ((i - 4) * 8); - writel(wdata0, i2c->regs + REG_TOK_WDATA0); - writel(wdata1, i2c->regs + REG_TOK_WDATA1); + meson_i2c_writel(i2c, wdata0, REG_TOK_WDATA0); + meson_i2c_writel(i2c, wdata1, REG_TOK_WDATA1); dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__, wdata0, wdata1, len); @@ -332,9 +351,8 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c) if (i2c->last && i2c->pos + i2c->count >= i2c->msg->len) meson_i2c_add_token(i2c, TOKEN_STOP); - - writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0); - writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1); + meson_i2c_writel(i2c, i2c->tokens[0], REG_TOK_LIST0); + meson_i2c_writel(i2c, i2c->tokens[1], REG_TOK_LIST1); } static irqreturn_t meson_i2c_irq(int irqno, void *dev_id) @@ -401,7 +419,7 @@ static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg) meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, GENMASK(7, 0), (unsigned int)((msg->addr << 1) & GENMASK(7, 0))); #else - writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR); + meson_i2c_writel(i2c, msg->addr << 1, REG_SLAVE_ADDR); #endif meson_i2c_add_token(i2c, TOKEN_START); meson_i2c_add_token(i2c, token); @@ -564,6 +582,7 @@ static int meson_i2c_probe(struct platform_device *pdev) if (fwnode_property_present(&np->fwnode, "retain-fast-mode")) i2c->retain_fastmode = 1; + i2c->data = (struct meson_i2c_data *)of_device_get_match_data(&pdev->dev); #endif i2c->dev = &pdev->dev; platform_set_drvdata(pdev, i2c); @@ -578,6 +597,8 @@ static int meson_i2c_probe(struct platform_device *pdev) } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); i2c->regs = devm_ioremap_resource(&pdev->dev, mem); + if (i2c->data->tee) + i2c->data->tee_reg = mem->start; if (IS_ERR(i2c->regs)) return PTR_ERR(i2c->regs); @@ -742,8 +763,22 @@ static const struct dev_pm_ops meson_i2c_pm_ops = { }; #endif +static struct meson_i2c_data i2c_tee_data = { + .tee = true, +}; + +static struct meson_i2c_data i2c_normal_data = { + .tee = false, +}; + static const struct of_device_id meson_i2c_match[] = { - { .compatible = "amlogic,meson-i2c" }, + { .compatible = "amlogic,meson-i2c", + .data = &i2c_normal_data + }, + { + .compatible = "amlogic,meson-tee-i2c", + .data = &i2c_tee_data + }, {}, };