aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/soc/mediatek/mtk-pmic-wrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/mediatek/mtk-pmic-wrap.c')
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c225
1 files changed, 97 insertions, 128 deletions
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index bf39a64f3ecc..d8cb0f833645 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -13,6 +13,9 @@
#include <linux/regmap.h>
#include <linux/reset.h>
+#define PWRAP_POLL_DELAY_US 10
+#define PWRAP_POLL_TIMEOUT_US 10000
+
#define PWRAP_MT8135_BRIDGE_IORD_ARB_EN 0x4
#define PWRAP_MT8135_BRIDGE_WACS3_EN 0x10
#define PWRAP_MT8135_BRIDGE_INIT_DONE3 0x14
@@ -1140,12 +1143,9 @@ enum pwrap_type {
};
struct pmic_wrapper;
-struct pwrap_slv_type {
- const u32 *dew_regs;
- enum pmic_type type;
+
+struct pwrap_slv_regops {
const struct regmap_config *regmap;
- /* Flags indicating the capability for the target slave */
- u32 caps;
/*
* pwrap operations are highly associated with the PMIC types,
* so the pointers added increases flexibility allowing determination
@@ -1155,6 +1155,14 @@ struct pwrap_slv_type {
int (*pwrap_write)(struct pmic_wrapper *wrp, u32 adr, u32 wdata);
};
+struct pwrap_slv_type {
+ const u32 *dew_regs;
+ enum pmic_type type;
+ const struct pwrap_slv_regops *regops;
+ /* Flags indicating the capability for the target slave */
+ u32 caps;
+};
+
struct pmic_wrapper {
struct device *dev;
void __iomem *base;
@@ -1241,27 +1249,14 @@ static bool pwrap_is_fsm_idle_and_sync_idle(struct pmic_wrapper *wrp)
(val & PWRAP_STATE_SYNC_IDLE0);
}
-static int pwrap_wait_for_state(struct pmic_wrapper *wrp,
- bool (*fp)(struct pmic_wrapper *))
-{
- unsigned long timeout;
-
- timeout = jiffies + usecs_to_jiffies(10000);
-
- do {
- if (time_after(jiffies, timeout))
- return fp(wrp) ? 0 : -ETIMEDOUT;
- if (fp(wrp))
- return 0;
- } while (1);
-}
-
static int pwrap_read16(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
{
+ bool tmp;
int ret;
u32 val;
- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+ ret = readx_poll_timeout(pwrap_is_fsm_idle, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret) {
pwrap_leave_fsm_vldclr(wrp);
return ret;
@@ -1273,7 +1268,8 @@ static int pwrap_read16(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
val = (adr >> 1) << 16;
pwrap_writel(wrp, val, PWRAP_WACS2_CMD);
- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr);
+ ret = readx_poll_timeout(pwrap_is_fsm_vldclr, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret)
return ret;
@@ -1290,11 +1286,14 @@ static int pwrap_read16(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
static int pwrap_read32(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
{
+ bool tmp;
int ret, msb;
*rdata = 0;
for (msb = 0; msb < 2; msb++) {
- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+ ret = readx_poll_timeout(pwrap_is_fsm_idle, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
+
if (ret) {
pwrap_leave_fsm_vldclr(wrp);
return ret;
@@ -1303,7 +1302,8 @@ static int pwrap_read32(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
pwrap_writel(wrp, ((msb << 30) | (adr << 16)),
PWRAP_WACS2_CMD);
- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr);
+ ret = readx_poll_timeout(pwrap_is_fsm_vldclr, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret)
return ret;
@@ -1318,14 +1318,16 @@ static int pwrap_read32(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
{
- return wrp->slave->pwrap_read(wrp, adr, rdata);
+ return wrp->slave->regops->pwrap_read(wrp, adr, rdata);
}
static int pwrap_write16(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
{
+ bool tmp;
int ret;
- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+ ret = readx_poll_timeout(pwrap_is_fsm_idle, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret) {
pwrap_leave_fsm_vldclr(wrp);
return ret;
@@ -1344,10 +1346,12 @@ static int pwrap_write16(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
static int pwrap_write32(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
{
+ bool tmp;
int ret, msb, rdata;
for (msb = 0; msb < 2; msb++) {
- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+ ret = readx_poll_timeout(pwrap_is_fsm_idle, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret) {
pwrap_leave_fsm_vldclr(wrp);
return ret;
@@ -1373,7 +1377,7 @@ static int pwrap_write32(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
{
- return wrp->slave->pwrap_write(wrp, adr, wdata);
+ return wrp->slave->regops->pwrap_write(wrp, adr, wdata);
}
static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata)
@@ -1388,6 +1392,7 @@ static int pwrap_regmap_write(void *context, u32 adr, u32 wdata)
static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
{
+ bool tmp;
int ret, i;
pwrap_writel(wrp, 0, PWRAP_HIPRIO_ARB_EN);
@@ -1407,7 +1412,8 @@ static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
pwrap_writel(wrp, wrp->master->spi_w | PWRAP_MAN_CMD_OP_OUTS,
PWRAP_MAN_CMD);
- ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle);
+ ret = readx_poll_timeout(pwrap_is_sync_idle, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret) {
dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
return ret;
@@ -1458,14 +1464,15 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
static int pwrap_init_dual_io(struct pmic_wrapper *wrp)
{
int ret;
+ bool tmp;
u32 rdata;
/* Enable dual IO mode */
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1);
/* Check IDLE & INIT_DONE in advance */
- ret = pwrap_wait_for_state(wrp,
- pwrap_is_fsm_idle_and_sync_idle);
+ ret = readx_poll_timeout(pwrap_is_fsm_idle_and_sync_idle, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret) {
dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
return ret;
@@ -1570,6 +1577,7 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
static int pwrap_init_cipher(struct pmic_wrapper *wrp)
{
int ret;
+ bool tmp;
u32 rdata = 0;
pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST);
@@ -1624,14 +1632,16 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
}
/* wait for cipher data ready@AP */
- ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready);
+ ret = readx_poll_timeout(pwrap_is_cipher_ready, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret) {
dev_err(wrp->dev, "cipher data ready@AP fail, ret=%d\n", ret);
return ret;
}
/* wait for cipher data ready@PMIC */
- ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready);
+ ret = readx_poll_timeout(pwrap_is_pmic_cipher_ready, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret) {
dev_err(wrp->dev,
"timeout waiting for cipher data ready@PMIC\n");
@@ -1640,7 +1650,8 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
/* wait for cipher mode idle */
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_MODE], 0x1);
- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+ ret = readx_poll_timeout(pwrap_is_fsm_idle_and_sync_idle, wrp, tmp, tmp,
+ PWRAP_POLL_DELAY_US, PWRAP_POLL_TIMEOUT_US);
if (ret) {
dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret);
return ret;
@@ -1885,99 +1896,82 @@ static const struct regmap_config pwrap_regmap_config32 = {
.max_register = 0xffff,
};
+static const struct pwrap_slv_regops pwrap_regops16 = {
+ .pwrap_read = pwrap_read16,
+ .pwrap_write = pwrap_write16,
+ .regmap = &pwrap_regmap_config16,
+};
+
+static const struct pwrap_slv_regops pwrap_regops32 = {
+ .pwrap_read = pwrap_read32,
+ .pwrap_write = pwrap_write32,
+ .regmap = &pwrap_regmap_config32,
+};
+
static const struct pwrap_slv_type pmic_mt6323 = {
.dew_regs = mt6323_regs,
.type = PMIC_MT6323,
- .regmap = &pwrap_regmap_config16,
+ .regops = &pwrap_regops16,
.caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO |
PWRAP_SLV_CAP_SECURITY,
- .pwrap_read = pwrap_read16,
- .pwrap_write = pwrap_write16,
};
static const struct pwrap_slv_type pmic_mt6351 = {
.dew_regs = mt6351_regs,
.type = PMIC_MT6351,
- .regmap = &pwrap_regmap_config16,
+ .regops = &pwrap_regops16,
.caps = 0,
- .pwrap_read = pwrap_read16,
- .pwrap_write = pwrap_write16,
};
static const struct pwrap_slv_type pmic_mt6357 = {
.dew_regs = mt6357_regs,
.type = PMIC_MT6357,
- .regmap = &pwrap_regmap_config16,
+ .regops = &pwrap_regops16,
.caps = 0,
- .pwrap_read = pwrap_read16,
- .pwrap_write = pwrap_write16,
};
static const struct pwrap_slv_type pmic_mt6358 = {
.dew_regs = mt6358_regs,
.type = PMIC_MT6358,
- .regmap = &pwrap_regmap_config16,
+ .regops = &pwrap_regops16,
.caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO,
- .pwrap_read = pwrap_read16,
- .pwrap_write = pwrap_write16,
};
static const struct pwrap_slv_type pmic_mt6359 = {
.dew_regs = mt6359_regs,
.type = PMIC_MT6359,
- .regmap = &pwrap_regmap_config16,
+ .regops = &pwrap_regops16,
.caps = PWRAP_SLV_CAP_DUALIO,
- .pwrap_read = pwrap_read16,
- .pwrap_write = pwrap_write16,
};
static const struct pwrap_slv_type pmic_mt6380 = {
.dew_regs = NULL,
.type = PMIC_MT6380,
- .regmap = &pwrap_regmap_config32,
+ .regops = &pwrap_regops32,
.caps = 0,
- .pwrap_read = pwrap_read32,
- .pwrap_write = pwrap_write32,
};
static const struct pwrap_slv_type pmic_mt6397 = {
.dew_regs = mt6397_regs,
.type = PMIC_MT6397,
- .regmap = &pwrap_regmap_config16,
+ .regops = &pwrap_regops16,
.caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO |
PWRAP_SLV_CAP_SECURITY,
- .pwrap_read = pwrap_read16,
- .pwrap_write = pwrap_write16,
};
static const struct of_device_id of_slave_match_tbl[] = {
- {
- .compatible = "mediatek,mt6323",
- .data = &pmic_mt6323,
- }, {
- .compatible = "mediatek,mt6351",
- .data = &pmic_mt6351,
- }, {
- .compatible = "mediatek,mt6357",
- .data = &pmic_mt6357,
- }, {
- .compatible = "mediatek,mt6358",
- .data = &pmic_mt6358,
- }, {
- .compatible = "mediatek,mt6359",
- .data = &pmic_mt6359,
- }, {
- /* The MT6380 PMIC only implements a regulator, so we bind it
- * directly instead of using a MFD.
- */
- .compatible = "mediatek,mt6380-regulator",
- .data = &pmic_mt6380,
- }, {
- .compatible = "mediatek,mt6397",
- .data = &pmic_mt6397,
- }, {
- /* sentinel */
- }
+ { .compatible = "mediatek,mt6323", .data = &pmic_mt6323 },
+ { .compatible = "mediatek,mt6351", .data = &pmic_mt6351 },
+ { .compatible = "mediatek,mt6357", .data = &pmic_mt6357 },
+ { .compatible = "mediatek,mt6358", .data = &pmic_mt6358 },
+ { .compatible = "mediatek,mt6359", .data = &pmic_mt6359 },
+
+ /* The MT6380 PMIC only implements a regulator, so we bind it
+ * directly instead of using a MFD.
+ */
+ { .compatible = "mediatek,mt6380-regulator", .data = &pmic_mt6380 },
+ { .compatible = "mediatek,mt6397", .data = &pmic_mt6397 },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_slave_match_tbl);
@@ -2136,45 +2130,19 @@ static struct pmic_wrapper_type pwrap_mt8186 = {
};
static const struct of_device_id of_pwrap_match_tbl[] = {
- {
- .compatible = "mediatek,mt2701-pwrap",
- .data = &pwrap_mt2701,
- }, {
- .compatible = "mediatek,mt6765-pwrap",
- .data = &pwrap_mt6765,
- }, {
- .compatible = "mediatek,mt6779-pwrap",
- .data = &pwrap_mt6779,
- }, {
- .compatible = "mediatek,mt6797-pwrap",
- .data = &pwrap_mt6797,
- }, {
- .compatible = "mediatek,mt6873-pwrap",
- .data = &pwrap_mt6873,
- }, {
- .compatible = "mediatek,mt7622-pwrap",
- .data = &pwrap_mt7622,
- }, {
- .compatible = "mediatek,mt8135-pwrap",
- .data = &pwrap_mt8135,
- }, {
- .compatible = "mediatek,mt8173-pwrap",
- .data = &pwrap_mt8173,
- }, {
- .compatible = "mediatek,mt8183-pwrap",
- .data = &pwrap_mt8183,
- }, {
- .compatible = "mediatek,mt8186-pwrap",
- .data = &pwrap_mt8186,
- }, {
- .compatible = "mediatek,mt8195-pwrap",
- .data = &pwrap_mt8195,
- }, {
- .compatible = "mediatek,mt8516-pwrap",
- .data = &pwrap_mt8516,
- }, {
- /* sentinel */
- }
+ { .compatible = "mediatek,mt2701-pwrap", .data = &pwrap_mt2701 },
+ { .compatible = "mediatek,mt6765-pwrap", .data = &pwrap_mt6765 },
+ { .compatible = "mediatek,mt6779-pwrap", .data = &pwrap_mt6779 },
+ { .compatible = "mediatek,mt6797-pwrap", .data = &pwrap_mt6797 },
+ { .compatible = "mediatek,mt6873-pwrap", .data = &pwrap_mt6873 },
+ { .compatible = "mediatek,mt7622-pwrap", .data = &pwrap_mt7622 },
+ { .compatible = "mediatek,mt8135-pwrap", .data = &pwrap_mt8135 },
+ { .compatible = "mediatek,mt8173-pwrap", .data = &pwrap_mt8173 },
+ { .compatible = "mediatek,mt8183-pwrap", .data = &pwrap_mt8183 },
+ { .compatible = "mediatek,mt8186-pwrap", .data = &pwrap_mt8186 },
+ { .compatible = "mediatek,mt8195-pwrap", .data = &pwrap_mt8195 },
+ { .compatible = "mediatek,mt8516-pwrap", .data = &pwrap_mt8516 },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl);
@@ -2185,7 +2153,6 @@ static int pwrap_probe(struct platform_device *pdev)
struct pmic_wrapper *wrp;
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_slave_id = NULL;
- struct resource *res;
if (np->child)
of_slave_id = of_match_node(of_slave_match_tbl, np->child);
@@ -2205,8 +2172,7 @@ static int pwrap_probe(struct platform_device *pdev)
wrp->slave = of_slave_id->data;
wrp->dev = &pdev->dev;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap");
- wrp->base = devm_ioremap_resource(wrp->dev, res);
+ wrp->base = devm_platform_ioremap_resource_byname(pdev, "pwrap");
if (IS_ERR(wrp->base))
return PTR_ERR(wrp->base);
@@ -2220,9 +2186,7 @@ static int pwrap_probe(struct platform_device *pdev)
}
if (HAS_CAP(wrp->master->caps, PWRAP_CAP_BRIDGE)) {
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "pwrap-bridge");
- wrp->bridge_base = devm_ioremap_resource(wrp->dev, res);
+ wrp->bridge_base = devm_platform_ioremap_resource_byname(pdev, "pwrap-bridge");
if (IS_ERR(wrp->bridge_base))
return PTR_ERR(wrp->bridge_base);
@@ -2315,13 +2279,18 @@ static int pwrap_probe(struct platform_device *pdev)
pwrap_writel(wrp, wrp->master->int1_en_all, PWRAP_INT1_EN);
irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
+ goto err_out2;
+ }
+
ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt,
IRQF_TRIGGER_HIGH,
"mt-pmic-pwrap", wrp);
if (ret)
goto err_out2;
- wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, wrp->slave->regmap);
+ wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, wrp->slave->regops->regmap);
if (IS_ERR(wrp->regmap)) {
ret = PTR_ERR(wrp->regmap);
goto err_out2;