summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/meson/pinctrl-meson.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/meson/pinctrl-meson.c')
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.c491
1 files changed, 360 insertions, 131 deletions
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index ea87d739f534..18295b15ecd9 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -1,14 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Pin controller and GPIO driver for Amlogic Meson SoCs
*
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@@ -31,6 +25,9 @@
* In some cases the register ranges for pull enable and pull
* direction are the same and thus there are only 3 register ranges.
*
+ * Since Meson G12A SoC, the ao register ranges for gpio, pull enable
+ * and pull direction are the same, so there are only 2 register ranges.
+ *
* For the pull and GPIO configuration every bank uses a contiguous
* set of bits in the register sets described above; the same register
* can be shared by more banks with different offsets.
@@ -46,12 +43,12 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
-#include <linux/of_device.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/seq_file.h>
@@ -59,6 +56,10 @@
#include "../pinctrl-utils.h"
#include "pinctrl-meson.h"
+static const unsigned int meson_bit_strides[] = {
+ 1, 1, 1, 1, 1, 2, 1
+};
+
/**
* meson_get_bank() - find the bank containing a given pin
*
@@ -69,7 +70,7 @@
* Return: 0 on success, a negative value on error
*/
static int meson_get_bank(struct meson_pinctrl *pc, unsigned int pin,
- struct meson_bank **bank)
+ const struct meson_bank **bank)
{
int i;
@@ -93,14 +94,16 @@ static int meson_get_bank(struct meson_pinctrl *pc, unsigned int pin,
* @reg: the computed register offset
* @bit: the computed bit
*/
-static void meson_calc_reg_and_bit(struct meson_bank *bank, unsigned int pin,
+static void meson_calc_reg_and_bit(const struct meson_bank *bank,
+ unsigned int pin,
enum meson_reg_type reg_type,
unsigned int *reg, unsigned int *bit)
{
- struct meson_reg_desc *desc = &bank->regs[reg_type];
+ const struct meson_reg_desc *desc = &bank->regs[reg_type];
- *reg = desc->reg * 4;
- *bit = desc->bit + pin - bank->first;
+ *bit = (desc->bit + pin - bank->first) * meson_bit_strides[reg_type];
+ *reg = (desc->reg + (*bit / 32)) * 4;
+ *bit &= 0x1f;
}
static int meson_get_groups_count(struct pinctrl_dev *pcdev)
@@ -150,6 +153,7 @@ int meson_pmx_get_funcs_count(struct pinctrl_dev *pcdev)
return pc->data->num_funcs;
}
+EXPORT_SYMBOL_GPL(meson_pmx_get_funcs_count);
const char *meson_pmx_get_func_name(struct pinctrl_dev *pcdev,
unsigned selector)
@@ -158,6 +162,7 @@ const char *meson_pmx_get_func_name(struct pinctrl_dev *pcdev,
return pc->data->funcs[selector].name;
}
+EXPORT_SYMBOL_GPL(meson_pmx_get_func_name);
int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector,
const char * const **groups,
@@ -170,69 +175,224 @@ int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector,
return 0;
}
+EXPORT_SYMBOL_GPL(meson_pmx_get_groups);
-static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
- unsigned long *configs, unsigned num_configs)
+static int meson_pinconf_set_gpio_bit(struct meson_pinctrl *pc,
+ unsigned int pin,
+ unsigned int reg_type,
+ bool arg)
{
- struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
- struct meson_bank *bank;
- enum pin_config_param param;
+ const struct meson_bank *bank;
unsigned int reg, bit;
- int i, ret;
+ int ret;
ret = meson_get_bank(pc, pin, &bank);
if (ret)
return ret;
+ meson_calc_reg_and_bit(bank, pin, reg_type, &reg, &bit);
+ return regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
+ arg ? BIT(bit) : 0);
+}
+
+static int meson_pinconf_get_gpio_bit(struct meson_pinctrl *pc,
+ unsigned int pin,
+ unsigned int reg_type)
+{
+ const struct meson_bank *bank;
+ unsigned int reg, bit, val;
+ int ret;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, reg_type, &reg, &bit);
+ ret = regmap_read(pc->reg_gpio, reg, &val);
+ if (ret)
+ return ret;
+
+ return BIT(bit) & val ? 1 : 0;
+}
+
+static int meson_pinconf_set_output(struct meson_pinctrl *pc,
+ unsigned int pin,
+ bool out)
+{
+ return meson_pinconf_set_gpio_bit(pc, pin, MESON_REG_DIR, !out);
+}
+
+static int meson_pinconf_get_output(struct meson_pinctrl *pc,
+ unsigned int pin)
+{
+ int ret = meson_pinconf_get_gpio_bit(pc, pin, MESON_REG_DIR);
+
+ if (ret < 0)
+ return ret;
+
+ return !ret;
+}
+
+static int meson_pinconf_set_drive(struct meson_pinctrl *pc,
+ unsigned int pin,
+ bool high)
+{
+ return meson_pinconf_set_gpio_bit(pc, pin, MESON_REG_OUT, high);
+}
+
+static int meson_pinconf_get_drive(struct meson_pinctrl *pc,
+ unsigned int pin)
+{
+ return meson_pinconf_get_gpio_bit(pc, pin, MESON_REG_OUT);
+}
+
+static int meson_pinconf_set_output_drive(struct meson_pinctrl *pc,
+ unsigned int pin,
+ bool high)
+{
+ int ret;
+
+ ret = meson_pinconf_set_output(pc, pin, true);
+ if (ret)
+ return ret;
+
+ return meson_pinconf_set_drive(pc, pin, high);
+}
+
+static int meson_pinconf_disable_bias(struct meson_pinctrl *pc,
+ unsigned int pin)
+{
+ const struct meson_bank *bank;
+ unsigned int reg, bit = 0;
+ int ret;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_PULLEN, &reg, &bit);
+ ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int meson_pinconf_enable_bias(struct meson_pinctrl *pc, unsigned int pin,
+ bool pull_up)
+{
+ const struct meson_bank *bank;
+ unsigned int reg, bit, val = 0;
+ int ret;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_PULL, &reg, &bit);
+ if (pull_up)
+ val = BIT(bit);
+
+ ret = regmap_update_bits(pc->reg_pull, reg, BIT(bit), val);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_PULLEN, &reg, &bit);
+ ret = regmap_update_bits(pc->reg_pullen, reg, BIT(bit), BIT(bit));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int meson_pinconf_set_drive_strength(struct meson_pinctrl *pc,
+ unsigned int pin,
+ u16 drive_strength_ua)
+{
+ const struct meson_bank *bank;
+ unsigned int reg, bit, ds_val;
+ int ret;
+
+ if (!pc->reg_ds) {
+ dev_err(pc->dev, "drive-strength not supported\n");
+ return -ENOTSUPP;
+ }
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_DS, &reg, &bit);
+
+ if (drive_strength_ua <= 500) {
+ ds_val = MESON_PINCONF_DRV_500UA;
+ } else if (drive_strength_ua <= 2500) {
+ ds_val = MESON_PINCONF_DRV_2500UA;
+ } else if (drive_strength_ua <= 3000) {
+ ds_val = MESON_PINCONF_DRV_3000UA;
+ } else if (drive_strength_ua <= 4000) {
+ ds_val = MESON_PINCONF_DRV_4000UA;
+ } else {
+ dev_warn_once(pc->dev,
+ "pin %u: invalid drive-strength : %d , default to 4mA\n",
+ pin, drive_strength_ua);
+ ds_val = MESON_PINCONF_DRV_4000UA;
+ }
+
+ ret = regmap_update_bits(pc->reg_ds, reg, 0x3 << bit, ds_val << bit);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
+ unsigned long *configs, unsigned num_configs)
+{
+ struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
+ enum pin_config_param param;
+ unsigned int arg = 0;
+ int i, ret;
+
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
switch (param) {
+ case PIN_CONFIG_DRIVE_STRENGTH_UA:
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ case PIN_CONFIG_LEVEL:
+ arg = pinconf_to_config_argument(configs[i]);
+ break;
+
+ default:
+ break;
+ }
+
+ switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- dev_dbg(pc->dev, "pin %u: disable bias\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg,
- &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), 0);
- if (ret)
- return ret;
+ ret = meson_pinconf_disable_bias(pc, pin);
break;
case PIN_CONFIG_BIAS_PULL_UP:
- dev_dbg(pc->dev, "pin %u: enable pull-up\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
- &reg, &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), BIT(bit));
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
- ret = regmap_update_bits(pc->reg_pull, reg,
- BIT(bit), BIT(bit));
- if (ret)
- return ret;
+ ret = meson_pinconf_enable_bias(pc, pin, true);
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- dev_dbg(pc->dev, "pin %u: enable pull-down\n", pin);
-
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
- &reg, &bit);
- ret = regmap_update_bits(pc->reg_pullen, reg,
- BIT(bit), BIT(bit));
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
- ret = regmap_update_bits(pc->reg_pull, reg,
- BIT(bit), 0);
- if (ret)
- return ret;
+ ret = meson_pinconf_enable_bias(pc, pin, false);
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH_UA:
+ ret = meson_pinconf_set_drive_strength(pc, pin, arg);
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ ret = meson_pinconf_set_output(pc, pin, arg);
+ break;
+ case PIN_CONFIG_LEVEL:
+ ret = meson_pinconf_set_output_drive(pc, pin, arg);
break;
default:
- return -ENOTSUPP;
+ ret = -ENOTSUPP;
}
+
+ if (ret)
+ return ret;
}
return 0;
@@ -240,7 +400,7 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
{
- struct meson_bank *bank;
+ const struct meson_bank *bank;
unsigned int reg, bit, val;
int ret, conf;
@@ -248,7 +408,7 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
if (ret)
return ret;
- meson_calc_reg_and_bit(bank, pin, REG_PULLEN, &reg, &bit);
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_PULLEN, &reg, &bit);
ret = regmap_read(pc->reg_pullen, reg, &val);
if (ret)
@@ -257,7 +417,7 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
if (!(val & BIT(bit))) {
conf = PIN_CONFIG_BIAS_DISABLE;
} else {
- meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_PULL, &reg, &bit);
ret = regmap_read(pc->reg_pull, reg, &val);
if (ret)
@@ -272,22 +432,88 @@ static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
return conf;
}
+static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
+ unsigned int pin,
+ u16 *drive_strength_ua)
+{
+ const struct meson_bank *bank;
+ unsigned int reg, bit;
+ unsigned int val;
+ int ret;
+
+ if (!pc->reg_ds)
+ return -ENOTSUPP;
+
+ ret = meson_get_bank(pc, pin, &bank);
+ if (ret)
+ return ret;
+
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_DS, &reg, &bit);
+
+ ret = regmap_read(pc->reg_ds, reg, &val);
+ if (ret)
+ return ret;
+
+ switch ((val >> bit) & 0x3) {
+ case MESON_PINCONF_DRV_500UA:
+ *drive_strength_ua = 500;
+ break;
+ case MESON_PINCONF_DRV_2500UA:
+ *drive_strength_ua = 2500;
+ break;
+ case MESON_PINCONF_DRV_3000UA:
+ *drive_strength_ua = 3000;
+ break;
+ case MESON_PINCONF_DRV_4000UA:
+ *drive_strength_ua = 4000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
unsigned long *config)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
enum pin_config_param param = pinconf_to_config_param(*config);
u16 arg;
+ int ret;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_PULL_UP:
if (meson_pinconf_get_pull(pc, pin) == param)
- arg = 1;
+ arg = 60000;
else
return -EINVAL;
break;
+ case PIN_CONFIG_DRIVE_STRENGTH_UA:
+ ret = meson_pinconf_get_drive_strength(pc, pin, &arg);
+ if (ret)
+ return ret;
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ ret = meson_pinconf_get_output(pc, pin);
+ if (ret <= 0)
+ return -EINVAL;
+ arg = 1;
+ break;
+ case PIN_CONFIG_LEVEL:
+ ret = meson_pinconf_get_output(pc, pin);
+ if (ret <= 0)
+ return -EINVAL;
+
+ ret = meson_pinconf_get_drive(pc, pin);
+ if (ret < 0)
+ return -EINVAL;
+
+ arg = ret;
+ break;
+
default:
return -ENOTSUPP;
}
@@ -303,7 +529,7 @@ static int meson_pinconf_group_set(struct pinctrl_dev *pcdev,
unsigned long *configs, unsigned num_configs)
{
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
- struct meson_pmx_group *group = &pc->data->groups[num_group];
+ const struct meson_pmx_group *group = &pc->data->groups[num_group];
int i;
dev_dbg(pc->dev, "set pinconf for group %s\n", group->name);
@@ -330,72 +556,47 @@ static const struct pinconf_ops meson_pinconf_ops = {
.is_generic = true,
};
-static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+static int meson_gpio_get_direction(struct gpio_chip *chip, unsigned gpio)
{
struct meson_pinctrl *pc = gpiochip_get_data(chip);
- unsigned int reg, bit;
- struct meson_bank *bank;
int ret;
- ret = meson_get_bank(pc, gpio, &bank);
- if (ret)
+ ret = meson_pinconf_get_output(pc, gpio);
+ if (ret < 0)
return ret;
- meson_calc_reg_and_bit(bank, gpio, REG_DIR, &reg, &bit);
+ return ret ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
+}
- return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), BIT(bit));
+static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ return meson_pinconf_set_output(gpiochip_get_data(chip), gpio, false);
}
static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
int value)
{
- struct meson_pinctrl *pc = gpiochip_get_data(chip);
- unsigned int reg, bit;
- struct meson_bank *bank;
- int ret;
-
- ret = meson_get_bank(pc, gpio, &bank);
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, gpio, REG_DIR, &reg, &bit);
- ret = regmap_update_bits(pc->reg_gpio, reg, BIT(bit), 0);
- if (ret)
- return ret;
-
- meson_calc_reg_and_bit(bank, gpio, REG_OUT, &reg, &bit);
- return regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
- value ? BIT(bit) : 0);
+ return meson_pinconf_set_output_drive(gpiochip_get_data(chip),
+ gpio, value);
}
-static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
+static int meson_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
{
- struct meson_pinctrl *pc = gpiochip_get_data(chip);
- unsigned int reg, bit;
- struct meson_bank *bank;
- int ret;
-
- ret = meson_get_bank(pc, gpio, &bank);
- if (ret)
- return;
-
- meson_calc_reg_and_bit(bank, gpio, REG_OUT, &reg, &bit);
- regmap_update_bits(pc->reg_gpio, reg, BIT(bit),
- value ? BIT(bit) : 0);
+ return meson_pinconf_set_drive(gpiochip_get_data(chip), gpio, value);
}
static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio)
{
struct meson_pinctrl *pc = gpiochip_get_data(chip);
+ const struct meson_bank *bank;
unsigned int reg, bit, val;
- struct meson_bank *bank;
int ret;
ret = meson_get_bank(pc, gpio, &bank);
if (ret)
return ret;
- meson_calc_reg_and_bit(bank, gpio, REG_IN, &reg, &bit);
+ meson_calc_reg_and_bit(bank, gpio, MESON_REG_IN, &reg, &bit);
regmap_read(pc->reg_gpio, reg, &val);
return !!(val & BIT(bit));
@@ -407,8 +608,11 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc)
pc->chip.label = pc->data->name;
pc->chip.parent = pc->dev;
+ pc->chip.fwnode = pc->fwnode;
pc->chip.request = gpiochip_generic_request;
pc->chip.free = gpiochip_generic_free;
+ pc->chip.set_config = gpiochip_generic_config;
+ pc->chip.get_direction = meson_gpio_get_direction;
pc->chip.direction_input = meson_gpio_direction_input;
pc->chip.direction_output = meson_gpio_direction_output;
pc->chip.get = meson_gpio_get;
@@ -416,8 +620,6 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc)
pc->chip.base = -1;
pc->chip.ngpio = pc->data->num_pins;
pc->chip.can_sleep = false;
- pc->chip.of_node = pc->of_node;
- pc->chip.of_gpio_n_cells = 2;
ret = gpiochip_add_data(&pc->chip, pc);
if (ret) {
@@ -444,7 +646,7 @@ static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
i = of_property_match_string(node, "reg-names", name);
if (of_address_to_resource(node, i, &res))
- return ERR_PTR(-ENOENT);
+ return NULL;
base = devm_ioremap_resource(pc->dev, &res);
if (IS_ERR(base))
@@ -460,54 +662,77 @@ static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
return devm_regmap_init_mmio(pc->dev, base, &meson_regmap_config);
}
-static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
- struct device_node *node)
+static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc)
{
- struct device_node *np, *gpio_np = NULL;
-
- for_each_child_of_node(node, np) {
- if (!of_find_property(np, "gpio-controller", NULL))
- continue;
- if (gpio_np) {
- dev_err(pc->dev, "multiple gpio nodes\n");
- return -EINVAL;
- }
- gpio_np = np;
- }
+ struct device_node *gpio_np;
+ unsigned int chips;
- if (!gpio_np) {
+ chips = gpiochip_node_count(pc->dev);
+ if (!chips) {
dev_err(pc->dev, "no gpio node found\n");
return -EINVAL;
}
+ if (chips > 1) {
+ dev_err(pc->dev, "multiple gpio nodes\n");
+ return -EINVAL;
+ }
- pc->of_node = gpio_np;
+ pc->fwnode = gpiochip_node_get_first(pc->dev);
+ gpio_np = to_of_node(pc->fwnode);
pc->reg_mux = meson_map_resource(pc, gpio_np, "mux");
- if (IS_ERR(pc->reg_mux)) {
+ if (IS_ERR_OR_NULL(pc->reg_mux)) {
dev_err(pc->dev, "mux registers not found\n");
- return PTR_ERR(pc->reg_mux);
+ return pc->reg_mux ? PTR_ERR(pc->reg_mux) : -ENOENT;
}
- pc->reg_pull = meson_map_resource(pc, gpio_np, "pull");
- if (IS_ERR(pc->reg_pull)) {
- dev_err(pc->dev, "pull registers not found\n");
- return PTR_ERR(pc->reg_pull);
+ pc->reg_gpio = meson_map_resource(pc, gpio_np, "gpio");
+ if (IS_ERR_OR_NULL(pc->reg_gpio)) {
+ dev_err(pc->dev, "gpio registers not found\n");
+ return pc->reg_gpio ? PTR_ERR(pc->reg_gpio) : -ENOENT;
}
+ pc->reg_pull = meson_map_resource(pc, gpio_np, "pull");
+ if (IS_ERR(pc->reg_pull))
+ pc->reg_pull = NULL;
+
pc->reg_pullen = meson_map_resource(pc, gpio_np, "pull-enable");
- /* Use pull region if pull-enable one is not present */
if (IS_ERR(pc->reg_pullen))
- pc->reg_pullen = pc->reg_pull;
+ pc->reg_pullen = NULL;
- pc->reg_gpio = meson_map_resource(pc, gpio_np, "gpio");
- if (IS_ERR(pc->reg_gpio)) {
- dev_err(pc->dev, "gpio registers not found\n");
- return PTR_ERR(pc->reg_gpio);
+ pc->reg_ds = meson_map_resource(pc, gpio_np, "ds");
+ if (IS_ERR(pc->reg_ds)) {
+ dev_dbg(pc->dev, "ds registers not found - skipping\n");
+ pc->reg_ds = NULL;
}
+ if (pc->data->parse_dt)
+ return pc->data->parse_dt(pc);
+
return 0;
}
+int meson8_aobus_parse_dt_extra(struct meson_pinctrl *pc)
+{
+ if (!pc->reg_pull)
+ return -EINVAL;
+
+ pc->reg_pullen = pc->reg_pull;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(meson8_aobus_parse_dt_extra);
+
+int meson_a1_parse_dt_extra(struct meson_pinctrl *pc)
+{
+ pc->reg_pull = pc->reg_gpio;
+ pc->reg_pullen = pc->reg_gpio;
+ pc->reg_ds = pc->reg_gpio;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(meson_a1_parse_dt_extra);
+
int meson_pinctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -521,7 +746,7 @@ int meson_pinctrl_probe(struct platform_device *pdev)
pc->dev = dev;
pc->data = (struct meson_pinctrl_data *) of_device_get_match_data(dev);
- ret = meson_pinctrl_parse_dt(pc, dev->of_node);
+ ret = meson_pinctrl_parse_dt(pc);
if (ret)
return ret;
@@ -541,3 +766,7 @@ int meson_pinctrl_probe(struct platform_device *pdev)
return meson_gpiolib_register(pc);
}
+EXPORT_SYMBOL_GPL(meson_pinctrl_probe);
+
+MODULE_DESCRIPTION("Amlogic Meson SoCs core pinctrl driver");
+MODULE_LICENSE("GPL v2");