diff options
Diffstat (limited to 'drivers/pinctrl/mediatek/pinctrl-mtk-common.c')
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 120 |
1 files changed, 103 insertions, 17 deletions
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index ad1ea1695b4a..7726c6caaf83 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/mfd/syscon.h> | 33 | #include <linux/mfd/syscon.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
36 | #include <linux/pm.h> | ||
36 | #include <dt-bindings/pinctrl/mt65xx.h> | 37 | #include <dt-bindings/pinctrl/mt65xx.h> |
37 | 38 | ||
38 | #include "../core.h" | 39 | #include "../core.h" |
@@ -702,7 +703,7 @@ static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev, | |||
702 | 703 | ||
703 | ret = mtk_pctrl_is_function_valid(pctl, g->pin, function); | 704 | ret = mtk_pctrl_is_function_valid(pctl, g->pin, function); |
704 | if (!ret) { | 705 | if (!ret) { |
705 | dev_err(pctl->dev, "invaild function %d on group %d .\n", | 706 | dev_err(pctl->dev, "invalid function %d on group %d .\n", |
706 | function, group); | 707 | function, group); |
707 | return -EINVAL; | 708 | return -EINVAL; |
708 | } | 709 | } |
@@ -1062,6 +1063,77 @@ static int mtk_eint_set_type(struct irq_data *d, | |||
1062 | return 0; | 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 | static void mtk_eint_ack(struct irq_data *d) | 1137 | static void mtk_eint_ack(struct irq_data *d) |
1066 | { | 1138 | { |
1067 | struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d); | 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 | static struct irq_chip mtk_pinctrl_irq_chip = { | 1149 | static struct irq_chip mtk_pinctrl_irq_chip = { |
1078 | .name = "mt-eint", | 1150 | .name = "mt-eint", |
1151 | .irq_disable = mtk_eint_mask, | ||
1079 | .irq_mask = mtk_eint_mask, | 1152 | .irq_mask = mtk_eint_mask, |
1080 | .irq_unmask = mtk_eint_unmask, | 1153 | .irq_unmask = mtk_eint_unmask, |
1081 | .irq_ack = mtk_eint_ack, | 1154 | .irq_ack = mtk_eint_ack, |
1082 | .irq_set_type = mtk_eint_set_type, | 1155 | .irq_set_type = mtk_eint_set_type, |
1156 | .irq_set_wake = mtk_eint_irq_set_wake, | ||
1083 | .irq_request_resources = mtk_pinctrl_irq_request_resources, | 1157 | .irq_request_resources = mtk_pinctrl_irq_request_resources, |
1084 | .irq_release_resources = mtk_pinctrl_irq_release_resources, | 1158 | .irq_release_resources = mtk_pinctrl_irq_release_resources, |
1085 | }; | 1159 | }; |
@@ -1118,8 +1192,8 @@ mtk_eint_debounce_process(struct mtk_pinctrl *pctl, int index) | |||
1118 | 1192 | ||
1119 | static void mtk_eint_irq_handler(unsigned irq, struct irq_desc *desc) | 1193 | static void mtk_eint_irq_handler(unsigned irq, struct irq_desc *desc) |
1120 | { | 1194 | { |
1121 | struct irq_chip *chip = irq_get_chip(irq); | 1195 | struct irq_chip *chip = irq_desc_get_chip(desc); |
1122 | struct mtk_pinctrl *pctl = irq_get_handler_data(irq); | 1196 | struct mtk_pinctrl *pctl = irq_desc_get_handler_data(desc); |
1123 | unsigned int status, eint_num; | 1197 | unsigned int status, eint_num; |
1124 | int offset, index, virq; | 1198 | int offset, index, virq; |
1125 | const struct mtk_eint_offsets *eint_offsets = | 1199 | const struct mtk_eint_offsets *eint_offsets = |
@@ -1202,12 +1276,6 @@ static int mtk_pctrl_build_state(struct platform_device *pdev) | |||
1202 | return 0; | 1276 | return 0; |
1203 | } | 1277 | } |
1204 | 1278 | ||
1205 | static struct pinctrl_desc mtk_pctrl_desc = { | ||
1206 | .confops = &mtk_pconf_ops, | ||
1207 | .pctlops = &mtk_pctrl_ops, | ||
1208 | .pmxops = &mtk_pmx_ops, | ||
1209 | }; | ||
1210 | |||
1211 | int mtk_pctrl_init(struct platform_device *pdev, | 1279 | int mtk_pctrl_init(struct platform_device *pdev, |
1212 | const struct mtk_pinctrl_devdata *data, | 1280 | const struct mtk_pinctrl_devdata *data, |
1213 | struct regmap *regmap) | 1281 | struct regmap *regmap) |
@@ -1217,7 +1285,7 @@ int mtk_pctrl_init(struct platform_device *pdev, | |||
1217 | struct device_node *np = pdev->dev.of_node, *node; | 1285 | struct device_node *np = pdev->dev.of_node, *node; |
1218 | struct property *prop; | 1286 | struct property *prop; |
1219 | struct resource *res; | 1287 | struct resource *res; |
1220 | int i, ret, irq; | 1288 | int i, ret, irq, ports_buf; |
1221 | 1289 | ||
1222 | pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); | 1290 | pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); |
1223 | if (!pctl) | 1291 | if (!pctl) |
@@ -1265,12 +1333,17 @@ int mtk_pctrl_init(struct platform_device *pdev, | |||
1265 | 1333 | ||
1266 | for (i = 0; i < pctl->devdata->npins; i++) | 1334 | for (i = 0; i < pctl->devdata->npins; i++) |
1267 | pins[i] = pctl->devdata->pins[i].pin; | 1335 | pins[i] = pctl->devdata->pins[i].pin; |
1268 | mtk_pctrl_desc.name = dev_name(&pdev->dev); | 1336 | |
1269 | mtk_pctrl_desc.owner = THIS_MODULE; | 1337 | pctl->pctl_desc.name = dev_name(&pdev->dev); |
1270 | mtk_pctrl_desc.pins = pins; | 1338 | pctl->pctl_desc.owner = THIS_MODULE; |
1271 | mtk_pctrl_desc.npins = pctl->devdata->npins; | 1339 | pctl->pctl_desc.pins = pins; |
1340 | pctl->pctl_desc.npins = pctl->devdata->npins; | ||
1341 | pctl->pctl_desc.confops = &mtk_pconf_ops; | ||
1342 | pctl->pctl_desc.pctlops = &mtk_pctrl_ops; | ||
1343 | pctl->pctl_desc.pmxops = &mtk_pmx_ops; | ||
1272 | pctl->dev = &pdev->dev; | 1344 | pctl->dev = &pdev->dev; |
1273 | pctl->pctl_dev = pinctrl_register(&mtk_pctrl_desc, &pdev->dev, pctl); | 1345 | |
1346 | pctl->pctl_dev = pinctrl_register(&pctl->pctl_desc, &pdev->dev, pctl); | ||
1274 | if (IS_ERR(pctl->pctl_dev)) { | 1347 | if (IS_ERR(pctl->pctl_dev)) { |
1275 | dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); | 1348 | dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); |
1276 | return PTR_ERR(pctl->pctl_dev); | 1349 | return PTR_ERR(pctl->pctl_dev); |
@@ -1319,6 +1392,21 @@ int mtk_pctrl_init(struct platform_device *pdev, | |||
1319 | goto chip_error; | 1392 | goto chip_error; |
1320 | } | 1393 | } |
1321 | 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 | |||
1322 | pctl->eint_dual_edges = devm_kcalloc(&pdev->dev, pctl->devdata->ap_num, | 1410 | pctl->eint_dual_edges = devm_kcalloc(&pdev->dev, pctl->devdata->ap_num, |
1323 | sizeof(int), GFP_KERNEL); | 1411 | sizeof(int), GFP_KERNEL); |
1324 | if (!pctl->eint_dual_edges) { | 1412 | if (!pctl->eint_dual_edges) { |
@@ -1348,11 +1436,9 @@ int mtk_pctrl_init(struct platform_device *pdev, | |||
1348 | irq_set_chip_and_handler(virq, &mtk_pinctrl_irq_chip, | 1436 | irq_set_chip_and_handler(virq, &mtk_pinctrl_irq_chip, |
1349 | handle_level_irq); | 1437 | handle_level_irq); |
1350 | irq_set_chip_data(virq, pctl); | 1438 | irq_set_chip_data(virq, pctl); |
1351 | set_irq_flags(virq, IRQF_VALID); | ||
1352 | }; | 1439 | }; |
1353 | 1440 | ||
1354 | irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl); | 1441 | irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl); |
1355 | set_irq_flags(irq, IRQF_VALID); | ||
1356 | return 0; | 1442 | return 0; |
1357 | 1443 | ||
1358 | chip_error: | 1444 | chip_error: |