Skip to content

Commit 58a5e1b

Browse files
maoguangmenglinusw
authored andcommitted
pinctrl: mediatek: Implement wake handler and suspend resume
This patch implement irq_set_wake to get who is wakeup source and setup on suspend resume. Signed-off-by: Maoguang Meng <[email protected]> Reviewed-by: Daniel Kurtz <[email protected]> Acked-by: Yingjoe Chen <[email protected]> Acked-by: Hongzhou Yang <[email protected]> Signed-off-by: Linus Walleij <[email protected]>
1 parent d48c2c0 commit 58a5e1b

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

drivers/pinctrl/mediatek/pinctrl-mt8173.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ static struct platform_driver mtk_pinctrl_driver = {
385385
.driver = {
386386
.name = "mediatek-mt8173-pinctrl",
387387
.of_match_table = mt8173_pctrl_match,
388+
.pm = &mtk_eint_pm_ops,
388389
},
389390
};
390391

drivers/pinctrl/mediatek/pinctrl-mtk-common.c

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <linux/mfd/syscon.h>
3434
#include <linux/delay.h>
3535
#include <linux/interrupt.h>
36+
#include <linux/pm.h>
3637
#include <dt-bindings/pinctrl/mt65xx.h>
3738

3839
#include "../core.h"
@@ -1062,6 +1063,77 @@ static int mtk_eint_set_type(struct irq_data *d,
10621063
return 0;
10631064
}
10641065

1066+
static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
1067+
{
1068+
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1069+
int shift = d->hwirq & 0x1f;
1070+
int reg = d->hwirq >> 5;
1071+
1072+
if (on)
1073+
pctl->wake_mask[reg] |= BIT(shift);
1074+
else
1075+
pctl->wake_mask[reg] &= ~BIT(shift);
1076+
1077+
return 0;
1078+
}
1079+
1080+
static void mtk_eint_chip_write_mask(const struct mtk_eint_offsets *chip,
1081+
void __iomem *eint_reg_base, u32 *buf)
1082+
{
1083+
int port;
1084+
void __iomem *reg;
1085+
1086+
for (port = 0; port < chip->ports; port++) {
1087+
reg = eint_reg_base + (port << 2);
1088+
writel_relaxed(~buf[port], reg + chip->mask_set);
1089+
writel_relaxed(buf[port], reg + chip->mask_clr);
1090+
}
1091+
}
1092+
1093+
static void mtk_eint_chip_read_mask(const struct mtk_eint_offsets *chip,
1094+
void __iomem *eint_reg_base, u32 *buf)
1095+
{
1096+
int port;
1097+
void __iomem *reg;
1098+
1099+
for (port = 0; port < chip->ports; port++) {
1100+
reg = eint_reg_base + chip->mask + (port << 2);
1101+
buf[port] = ~readl_relaxed(reg);
1102+
/* Mask is 0 when irq is enabled, and 1 when disabled. */
1103+
}
1104+
}
1105+
1106+
static int mtk_eint_suspend(struct device *device)
1107+
{
1108+
void __iomem *reg;
1109+
struct mtk_pinctrl *pctl = dev_get_drvdata(device);
1110+
const struct mtk_eint_offsets *eint_offsets =
1111+
&pctl->devdata->eint_offsets;
1112+
1113+
reg = pctl->eint_reg_base;
1114+
mtk_eint_chip_read_mask(eint_offsets, reg, pctl->cur_mask);
1115+
mtk_eint_chip_write_mask(eint_offsets, reg, pctl->wake_mask);
1116+
1117+
return 0;
1118+
}
1119+
1120+
static int mtk_eint_resume(struct device *device)
1121+
{
1122+
struct mtk_pinctrl *pctl = dev_get_drvdata(device);
1123+
const struct mtk_eint_offsets *eint_offsets =
1124+
&pctl->devdata->eint_offsets;
1125+
1126+
mtk_eint_chip_write_mask(eint_offsets,
1127+
pctl->eint_reg_base, pctl->cur_mask);
1128+
1129+
return 0;
1130+
}
1131+
1132+
const struct dev_pm_ops mtk_eint_pm_ops = {
1133+
.suspend = mtk_eint_suspend,
1134+
.resume = mtk_eint_resume,
1135+
};
1136+
10651137
static void mtk_eint_ack(struct irq_data *d)
10661138
{
10671139
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
@@ -1076,10 +1148,12 @@ static void mtk_eint_ack(struct irq_data *d)
10761148

10771149
static struct irq_chip mtk_pinctrl_irq_chip = {
10781150
.name = "mt-eint",
1151+
.irq_disable = mtk_eint_mask,
10791152
.irq_mask = mtk_eint_mask,
10801153
.irq_unmask = mtk_eint_unmask,
10811154
.irq_ack = mtk_eint_ack,
10821155
.irq_set_type = mtk_eint_set_type,
1156+
.irq_set_wake = mtk_eint_irq_set_wake,
10831157
.irq_request_resources = mtk_pinctrl_irq_request_resources,
10841158
.irq_release_resources = mtk_pinctrl_irq_release_resources,
10851159
};
@@ -1211,7 +1285,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
12111285
struct device_node *np = pdev->dev.of_node, *node;
12121286
struct property *prop;
12131287
struct resource *res;
1214-
int i, ret, irq;
1288+
int i, ret, irq, ports_buf;
12151289

12161290
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
12171291
if (!pctl)
@@ -1318,6 +1392,21 @@ int mtk_pctrl_init(struct platform_device *pdev,
13181392
goto chip_error;
13191393
}
13201394

1395+
ports_buf = pctl->devdata->eint_offsets.ports;
1396+
pctl->wake_mask = devm_kcalloc(&pdev->dev, ports_buf,
1397+
sizeof(*pctl->wake_mask), GFP_KERNEL);
1398+
if (!pctl->wake_mask) {
1399+
ret = -ENOMEM;
1400+
goto chip_error;
1401+
}
1402+
1403+
pctl->cur_mask = devm_kcalloc(&pdev->dev, ports_buf,
1404+
sizeof(*pctl->cur_mask), GFP_KERNEL);
1405+
if (!pctl->cur_mask) {
1406+
ret = -ENOMEM;
1407+
goto chip_error;
1408+
}
1409+
13211410
pctl->eint_dual_edges = devm_kcalloc(&pdev->dev, pctl->devdata->ap_num,
13221411
sizeof(int), GFP_KERNEL);
13231412
if (!pctl->eint_dual_edges) {

drivers/pinctrl/mediatek/pinctrl-mtk-common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ struct mtk_pinctrl {
267267
void __iomem *eint_reg_base;
268268
struct irq_domain *domain;
269269
int *eint_dual_edges;
270+
u32 *wake_mask;
271+
u32 *cur_mask;
270272
};
271273

272274
int mtk_pctrl_init(struct platform_device *pdev,
@@ -282,4 +284,6 @@ int mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
282284
const struct mtk_pin_ies_smt_set *ies_smt_infos, unsigned int info_num,
283285
unsigned int pin, unsigned char align, int value);
284286

287+
extern const struct dev_pm_ops mtk_eint_pm_ops;
288+
285289
#endif /* __PINCTRL_MTK_COMMON_H */

0 commit comments

Comments
 (0)