33
33
#include <linux/mfd/syscon.h>
34
34
#include <linux/delay.h>
35
35
#include <linux/interrupt.h>
36
+ #include <linux/pm.h>
36
37
#include <dt-bindings/pinctrl/mt65xx.h>
37
38
38
39
#include "../core.h"
@@ -1062,6 +1063,77 @@ static int mtk_eint_set_type(struct irq_data *d,
1062
1063
return 0 ;
1063
1064
}
1064
1065
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
+
1065
1137
static void mtk_eint_ack (struct irq_data * d )
1066
1138
{
1067
1139
struct mtk_pinctrl * pctl = irq_data_get_irq_chip_data (d );
@@ -1076,10 +1148,12 @@ static void mtk_eint_ack(struct irq_data *d)
1076
1148
1077
1149
static struct irq_chip mtk_pinctrl_irq_chip = {
1078
1150
.name = "mt-eint" ,
1151
+ .irq_disable = mtk_eint_mask ,
1079
1152
.irq_mask = mtk_eint_mask ,
1080
1153
.irq_unmask = mtk_eint_unmask ,
1081
1154
.irq_ack = mtk_eint_ack ,
1082
1155
.irq_set_type = mtk_eint_set_type ,
1156
+ .irq_set_wake = mtk_eint_irq_set_wake ,
1083
1157
.irq_request_resources = mtk_pinctrl_irq_request_resources ,
1084
1158
.irq_release_resources = mtk_pinctrl_irq_release_resources ,
1085
1159
};
@@ -1211,7 +1285,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
1211
1285
struct device_node * np = pdev -> dev .of_node , * node ;
1212
1286
struct property * prop ;
1213
1287
struct resource * res ;
1214
- int i , ret , irq ;
1288
+ int i , ret , irq , ports_buf ;
1215
1289
1216
1290
pctl = devm_kzalloc (& pdev -> dev , sizeof (* pctl ), GFP_KERNEL );
1217
1291
if (!pctl )
@@ -1318,6 +1392,21 @@ int mtk_pctrl_init(struct platform_device *pdev,
1318
1392
goto chip_error ;
1319
1393
}
1320
1394
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
+
1321
1410
pctl -> eint_dual_edges = devm_kcalloc (& pdev -> dev , pctl -> devdata -> ap_num ,
1322
1411
sizeof (int ), GFP_KERNEL );
1323
1412
if (!pctl -> eint_dual_edges ) {
0 commit comments