summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/mediatek/pinctrl-mtk-common.c')
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c152
1 files changed, 95 insertions, 57 deletions
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 5f7c421ab6e7..d6a46fe0cda8 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -8,8 +8,6 @@
#include <linux/io.h>
#include <linux/gpio/driver.h>
#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/machine.h>
@@ -88,7 +86,7 @@ static int mtk_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
return 0;
}
-static void mtk_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static int mtk_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
unsigned int reg_addr;
unsigned int bit;
@@ -102,7 +100,7 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
else
reg_addr = CLR_ADDR(reg_addr, pctl);
- regmap_write(mtk_get_regmap(pctl, offset), reg_addr, bit);
+ return regmap_write(mtk_get_regmap(pctl, offset), reg_addr, bit);
}
static int mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
@@ -131,7 +129,7 @@ static int mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
*/
if (pctl->devdata->spec_ies_smt_set) {
return pctl->devdata->spec_ies_smt_set(mtk_get_regmap(pctl, pin),
- pin, pctl->devdata->port_align, value, arg);
+ pctl->devdata, pin, value, arg);
}
if (arg == PIN_CONFIG_INPUT_ENABLE)
@@ -151,10 +149,27 @@ static int mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
}
int mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
- const struct mtk_pin_ies_smt_set *ies_smt_infos, unsigned int info_num,
- unsigned int pin, unsigned char align, int value)
+ const struct mtk_pinctrl_devdata *devdata,
+ unsigned int pin, int value, enum pin_config_param arg)
{
- unsigned int i, reg_addr, bit;
+ const struct mtk_pin_ies_smt_set *ies_smt_infos = NULL;
+ unsigned int i, info_num, reg_addr, bit;
+
+ switch (arg) {
+ case PIN_CONFIG_INPUT_ENABLE:
+ ies_smt_infos = devdata->spec_ies;
+ info_num = devdata->n_spec_ies;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ ies_smt_infos = devdata->spec_smt;
+ info_num = devdata->n_spec_smt;
+ break;
+ default:
+ break;
+ }
+
+ if (!ies_smt_infos)
+ return -EINVAL;
for (i = 0; i < info_num; i++) {
if (pin >= ies_smt_infos[i].start &&
@@ -167,9 +182,9 @@ int mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
return -EINVAL;
if (value)
- reg_addr = ies_smt_infos[i].offset + align;
+ reg_addr = ies_smt_infos[i].offset + devdata->port_align;
else
- reg_addr = ies_smt_infos[i].offset + (align << 1);
+ reg_addr = ies_smt_infos[i].offset + (devdata->port_align << 1);
bit = BIT(ies_smt_infos[i].bit);
regmap_write(regmap, reg_addr, bit);
@@ -222,9 +237,8 @@ static int mtk_pconf_set_driving(struct mtk_pinctrl *pctl,
}
int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
- const struct mtk_pin_spec_pupd_set_samereg *pupd_infos,
- unsigned int info_num, unsigned int pin,
- unsigned char align, bool isup, unsigned int r1r0)
+ const struct mtk_pinctrl_devdata *devdata,
+ unsigned int pin, bool isup, unsigned int r1r0)
{
unsigned int i;
unsigned int reg_pupd, reg_set, reg_rst;
@@ -232,8 +246,11 @@ int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
const struct mtk_pin_spec_pupd_set_samereg *spec_pupd_pin;
bool find = false;
- for (i = 0; i < info_num; i++) {
- if (pin == pupd_infos[i].pin) {
+ if (!devdata->spec_pupd)
+ return -EINVAL;
+
+ for (i = 0; i < devdata->n_spec_pupd; i++) {
+ if (pin == devdata->spec_pupd[i].pin) {
find = true;
break;
}
@@ -242,9 +259,9 @@ int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
if (!find)
return -EINVAL;
- spec_pupd_pin = pupd_infos + i;
- reg_set = spec_pupd_pin->offset + align;
- reg_rst = spec_pupd_pin->offset + (align << 1);
+ spec_pupd_pin = devdata->spec_pupd + i;
+ reg_set = spec_pupd_pin->offset + devdata->port_align;
+ reg_rst = spec_pupd_pin->offset + (devdata->port_align << 1);
if (isup)
reg_pupd = reg_rst;
@@ -298,7 +315,8 @@ static int mtk_pconf_set_pull_select(struct mtk_pinctrl *pctl,
*/
r1r0 = enable ? arg : MTK_PUPD_SET_R1R0_00;
ret = pctl->devdata->spec_pull_set(mtk_get_regmap(pctl, pin),
- pin, pctl->devdata->port_align, isup, r1r0);
+ pctl->devdata, pin, isup,
+ r1r0);
if (!ret)
return 0;
}
@@ -310,6 +328,21 @@ static int mtk_pconf_set_pull_select(struct mtk_pinctrl *pctl,
return -EINVAL;
}
+ if (pctl->devdata->mt8365_set_clr_mode) {
+ bit = pin & pctl->devdata->mode_mask;
+ reg_pullen = mtk_get_port(pctl, pin) +
+ pctl->devdata->pullen_offset;
+ reg_pullsel = mtk_get_port(pctl, pin) +
+ pctl->devdata->pullsel_offset;
+ ret = pctl->devdata->mt8365_set_clr_mode(mtk_get_regmap(pctl, pin),
+ bit, reg_pullen, reg_pullsel,
+ enable, isup);
+ if (ret)
+ return -EINVAL;
+
+ return 0;
+ }
+
bit = BIT(pin & pctl->devdata->mode_mask);
if (enable)
reg_pullen = SET_ADDR(mtk_get_port(pctl, pin) +
@@ -351,7 +384,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev,
mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true);
ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param);
break;
- case PIN_CONFIG_OUTPUT:
+ case PIN_CONFIG_LEVEL:
mtk_gpio_set(pctl->chip, pin, arg);
ret = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
break;
@@ -588,7 +621,6 @@ static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned *num_maps)
{
- struct device_node *np;
unsigned reserved_maps;
int ret;
@@ -596,12 +628,11 @@ static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
*num_maps = 0;
reserved_maps = 0;
- for_each_child_of_node(np_config, np) {
+ for_each_child_of_node_scoped(np_config, np) {
ret = mtk_pctrl_dt_subnode_to_map(pctldev, np, map,
&reserved_maps, num_maps);
if (ret < 0) {
pinctrl_utils_free_map(pctldev, *map, *num_maps);
- of_node_put(np);
return ret;
}
}
@@ -775,17 +806,16 @@ static const struct pinmux_ops mtk_pmx_ops = {
.gpio_request_enable = mtk_pmx_gpio_request_enable,
};
-static int mtk_gpio_direction_input(struct gpio_chip *chip,
- unsigned offset)
-{
- return pinctrl_gpio_direction_input(chip->base + offset);
-}
-
static int mtk_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
- mtk_gpio_set(chip, offset, value);
- return pinctrl_gpio_direction_output(chip->base + offset);
+ int ret;
+
+ ret = mtk_gpio_set(chip, offset, value);
+ if (ret)
+ return ret;
+
+ return pinctrl_gpio_direction_output(chip, offset);
}
static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
@@ -865,13 +895,12 @@ static const struct gpio_chip mtk_gpio_chip = {
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get_direction = mtk_gpio_get_direction,
- .direction_input = mtk_gpio_direction_input,
+ .direction_input = pinctrl_gpio_direction_input,
.direction_output = mtk_gpio_direction_output,
.get = mtk_gpio_get,
.set = mtk_gpio_set,
.to_irq = mtk_gpio_to_irq,
.set_config = mtk_gpio_set_config,
- .of_gpio_n_cells = 2,
};
static int mtk_eint_suspend(struct device *device)
@@ -888,9 +917,8 @@ static int mtk_eint_resume(struct device *device)
return mtk_eint_do_resume(pctl->eint);
}
-const struct dev_pm_ops mtk_eint_pm_ops = {
- .suspend_noirq = mtk_eint_suspend,
- .resume_noirq = mtk_eint_resume,
+EXPORT_GPL_DEV_SLEEP_PM_OPS(mtk_eint_pm_ops) = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_eint_suspend, mtk_eint_resume)
};
static int mtk_pctrl_build_state(struct platform_device *pdev)
@@ -992,9 +1020,15 @@ static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev)
if (!pctl->eint)
return -ENOMEM;
- pctl->eint->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(pctl->eint->base))
- return PTR_ERR(pctl->eint->base);
+ pctl->eint->nbase = 1;
+ /* mtk-eint expects an array */
+ pctl->eint->base = devm_kzalloc(pctl->dev, sizeof(pctl->eint->base), GFP_KERNEL);
+ if (!pctl->eint->base)
+ return -ENOMEM;
+
+ pctl->eint->base[0] = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pctl->eint->base[0]))
+ return PTR_ERR(pctl->eint->base[0]);
pctl->eint->irq = irq_of_parse_and_map(np, 0);
if (!pctl->eint->irq)
@@ -1010,17 +1044,18 @@ static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev)
pctl->eint->pctl = pctl;
pctl->eint->gpio_xlate = &mtk_eint_xt;
- return mtk_eint_do_init(pctl->eint);
+ return mtk_eint_do_init(pctl->eint, NULL);
}
+/* This is used as a common probe function */
int mtk_pctrl_init(struct platform_device *pdev,
const struct mtk_pinctrl_devdata *data,
struct regmap *regmap)
{
+ struct device *dev = &pdev->dev;
struct pinctrl_pin_desc *pins;
struct mtk_pinctrl *pctl;
struct device_node *np = pdev->dev.of_node, *node;
- struct property *prop;
int ret, i;
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
@@ -1029,38 +1064,31 @@ int mtk_pctrl_init(struct platform_device *pdev,
platform_set_drvdata(pdev, pctl);
- prop = of_find_property(np, "pins-are-numbered", NULL);
- if (!prop) {
- dev_err(&pdev->dev, "only support pins-are-numbered format\n");
- return -EINVAL;
- }
-
node = of_parse_phandle(np, "mediatek,pctl-regmap", 0);
if (node) {
pctl->regmap1 = syscon_node_to_regmap(node);
+ of_node_put(node);
if (IS_ERR(pctl->regmap1))
return PTR_ERR(pctl->regmap1);
} else if (regmap) {
pctl->regmap1 = regmap;
} else {
- dev_err(&pdev->dev, "Pinctrl node has not register regmap.\n");
- return -EINVAL;
+ return dev_err_probe(dev, -EINVAL, "Cannot find pinctrl regmap.\n");
}
/* Only 8135 has two base addr, other SoCs have only one. */
node = of_parse_phandle(np, "mediatek,pctl-regmap", 1);
if (node) {
pctl->regmap2 = syscon_node_to_regmap(node);
+ of_node_put(node);
if (IS_ERR(pctl->regmap2))
return PTR_ERR(pctl->regmap2);
}
pctl->devdata = data;
ret = mtk_pctrl_build_state(pdev);
- if (ret) {
- dev_err(&pdev->dev, "build state failed: %d\n", ret);
- return -EINVAL;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "build state failed\n");
pins = devm_kcalloc(&pdev->dev, pctl->devdata->npins, sizeof(*pins),
GFP_KERNEL);
@@ -1081,10 +1109,9 @@ int mtk_pctrl_init(struct platform_device *pdev,
pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc,
pctl);
- if (IS_ERR(pctl->pctl_dev)) {
- dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
- return PTR_ERR(pctl->pctl_dev);
- }
+ if (IS_ERR(pctl->pctl_dev))
+ return dev_err_probe(dev, PTR_ERR(pctl->pctl_dev),
+ "Couldn't register pinctrl driver\n");
pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
if (!pctl->chip)
@@ -1118,3 +1145,14 @@ chip_error:
gpiochip_remove(pctl->chip);
return ret;
}
+
+int mtk_pctrl_common_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct mtk_pinctrl_devdata *data = device_get_match_data(dev);
+
+ if (!data)
+ return -ENODEV;
+
+ return mtk_pctrl_init(pdev, data, NULL);
+}