diff options
Diffstat (limited to 'drivers/soc/mediatek/mtk-pmic-wrap.c')
-rw-r--r-- | drivers/soc/mediatek/mtk-pmic-wrap.c | 225 |
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; |