Skip to content

Commit

Permalink
pinctrl: mediatek: add EINT support to MT7622 SoC
Browse files Browse the repository at this point in the history
Add EINT support to MT7622 SoC and the support is made as just an option
to MT7622 pinctrl.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
moore-bros authored and linusw committed May 24, 2018
1 parent e46df23 commit e6dabd3
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 1 deletion.
2 changes: 1 addition & 1 deletion drivers/pinctrl/mediatek/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ menu "MediaTek pinctrl drivers"

config EINT_MTK
bool "MediaTek External Interrupt Support"
depends on PINCTRL_MTK || COMPILE_TEST
depends on PINCTRL_MTK || PINCTRL_MT7622 || COMPILE_TEST
select IRQ_DOMAIN

config PINCTRL_MTK
Expand Down
143 changes: 143 additions & 0 deletions drivers/pinctrl/mediatek/pinctrl-mt7622.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
Expand All @@ -30,6 +31,7 @@
#include "../core.h"
#include "../pinconf.h"
#include "../pinmux.h"
#include "mtk-eint.h"

#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
Expand Down Expand Up @@ -123,6 +125,8 @@ struct mtk_pin_soc {
unsigned int ngrps;
const struct function_desc *funcs;
unsigned int nfuncs;
const struct mtk_eint_regs *eint_regs;
const struct mtk_eint_hw *eint_hw;
};

struct mtk_pinctrl {
Expand All @@ -131,6 +135,7 @@ struct mtk_pinctrl {
struct device *dev;
struct gpio_chip chip;
const struct mtk_pin_soc *soc;
struct mtk_eint *eint;
};

static const struct mtk_pin_field_calc mt7622_pin_mode_range[] = {
Expand Down Expand Up @@ -913,6 +918,13 @@ static const struct pin_config_item mtk_conf_items[] = {
};
#endif

static const struct mtk_eint_hw mt7622_eint_hw = {
.port_mask = 7,
.ports = 7,
.ap_num = ARRAY_SIZE(mt7622_pins),
.db_cnt = 20,
};

static const struct mtk_pin_soc mt7622_data = {
.reg_cal = mt7622_reg_cals,
.pins = mt7622_pins,
Expand All @@ -921,6 +933,7 @@ static const struct mtk_pin_soc mt7622_data = {
.ngrps = ARRAY_SIZE(mt7622_groups),
.funcs = mt7622_functions,
.nfuncs = ARRAY_SIZE(mt7622_functions),
.eint_hw = &mt7622_eint_hw,
};

static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val)
Expand Down Expand Up @@ -1441,6 +1454,32 @@ static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
return pinctrl_gpio_direction_output(chip->base + gpio);
}

static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
unsigned long eint_n;

eint_n = offset;

return mtk_eint_find_irq(hw->eint, eint_n);
}

static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
unsigned long eint_n;
u32 debounce;

if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;

debounce = pinconf_to_config_argument(config);
eint_n = offset;

return mtk_eint_set_debounce(hw->eint, eint_n, debounce);
}

static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
{
struct gpio_chip *chip = &hw->chip;
Expand All @@ -1454,6 +1493,8 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
chip->direction_output = mtk_gpio_direction_output;
chip->get = mtk_gpio_get;
chip->set = mtk_gpio_set;
chip->to_irq = mtk_gpio_to_irq,
chip->set_config = mtk_gpio_set_config,
chip->base = -1;
chip->ngpio = hw->soc->npins;
chip->of_node = np;
Expand Down Expand Up @@ -1514,6 +1555,103 @@ static int mtk_build_functions(struct mtk_pinctrl *hw)
return 0;
}

static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n,
unsigned int *gpio_n,
struct gpio_chip **gpio_chip)
{
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;

*gpio_chip = &hw->chip;
*gpio_n = eint_n;

return 0;
}

static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
{
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
struct gpio_chip *gpio_chip;
unsigned int gpio_n;
int err;

err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
if (err)
return err;

return mtk_gpio_get(gpio_chip, gpio_n);
}

static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
{
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
struct gpio_chip *gpio_chip;
unsigned int gpio_n;
int err;

err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
if (err)
return err;

err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_MODE,
MTK_GPIO_MODE);
if (err)
return err;

err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_DIR, MTK_INPUT);
if (err)
return err;

err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_SMT, MTK_ENABLE);
if (err)
return err;

return 0;
}

static const struct mtk_eint_xt mtk_eint_xt = {
.get_gpio_n = mtk_xt_get_gpio_n,
.get_gpio_state = mtk_xt_get_gpio_state,
.set_gpio_as_eint = mtk_xt_set_gpio_as_eint,
};

static int
mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res;

if (!IS_ENABLED(CONFIG_EINT_MTK))
return 0;

if (!of_property_read_bool(np, "interrupt-controller"))
return -ENODEV;

hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
if (!hw->eint)
return -ENOMEM;

res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eint");
if (!res) {
dev_err(&pdev->dev, "Unable to get eint resource\n");
return -ENODEV;
}

hw->eint->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hw->eint->base))
return PTR_ERR(hw->eint->base);

hw->eint->irq = irq_of_parse_and_map(np, 0);
if (!hw->eint->irq)
return -EINVAL;

hw->eint->dev = &pdev->dev;
hw->eint->hw = hw->soc->eint_hw;
hw->eint->pctl = hw;
hw->eint->gpio_xlate = &mtk_eint_xt;

return mtk_eint_do_init(hw->eint);
}

static const struct of_device_id mtk_pinctrl_of_match[] = {
{ .compatible = "mediatek,mt7622-pinctrl", .data = &mt7622_data},
{ }
Expand Down Expand Up @@ -1577,6 +1715,11 @@ static int mtk_pinctrl_probe(struct platform_device *pdev)
return err;
}

err = mtk_build_eint(hw, pdev);
if (err)
dev_warn(&pdev->dev,
"Failed to add EINT, but pinctrl still can work\n");

platform_set_drvdata(pdev, hw);

return 0;
Expand Down

0 comments on commit e6dabd3

Please sign in to comment.