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.c115
1 files changed, 61 insertions, 54 deletions
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 079f8ee8d353..18295b15ecd9 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -43,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>
@@ -56,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
*
@@ -66,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;
@@ -90,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)
@@ -147,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)
@@ -155,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,
@@ -167,13 +175,14 @@ 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_gpio_bit(struct meson_pinctrl *pc,
unsigned int pin,
unsigned int reg_type,
bool arg)
{
- struct meson_bank *bank;
+ const struct meson_bank *bank;
unsigned int reg, bit;
int ret;
@@ -190,7 +199,7 @@ static int meson_pinconf_get_gpio_bit(struct meson_pinctrl *pc,
unsigned int pin,
unsigned int reg_type)
{
- struct meson_bank *bank;
+ const struct meson_bank *bank;
unsigned int reg, bit, val;
int ret;
@@ -210,13 +219,13 @@ static int meson_pinconf_set_output(struct meson_pinctrl *pc,
unsigned int pin,
bool out)
{
- return meson_pinconf_set_gpio_bit(pc, pin, REG_DIR, !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, REG_DIR);
+ int ret = meson_pinconf_get_gpio_bit(pc, pin, MESON_REG_DIR);
if (ret < 0)
return ret;
@@ -228,13 +237,13 @@ static int meson_pinconf_set_drive(struct meson_pinctrl *pc,
unsigned int pin,
bool high)
{
- return meson_pinconf_set_gpio_bit(pc, pin, REG_OUT, 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, REG_OUT);
+ return meson_pinconf_get_gpio_bit(pc, pin, MESON_REG_OUT);
}
static int meson_pinconf_set_output_drive(struct meson_pinctrl *pc,
@@ -253,7 +262,7 @@ static int meson_pinconf_set_output_drive(struct meson_pinctrl *pc,
static int meson_pinconf_disable_bias(struct meson_pinctrl *pc,
unsigned int pin)
{
- struct meson_bank *bank;
+ const struct meson_bank *bank;
unsigned int reg, bit = 0;
int ret;
@@ -261,7 +270,7 @@ static int meson_pinconf_disable_bias(struct meson_pinctrl *pc,
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_update_bits(pc->reg_pullen, reg, BIT(bit), 0);
if (ret)
return ret;
@@ -272,7 +281,7 @@ static int meson_pinconf_disable_bias(struct meson_pinctrl *pc,
static int meson_pinconf_enable_bias(struct meson_pinctrl *pc, unsigned int pin,
bool pull_up)
{
- struct meson_bank *bank;
+ const struct meson_bank *bank;
unsigned int reg, bit, val = 0;
int ret;
@@ -280,7 +289,7 @@ static int meson_pinconf_enable_bias(struct meson_pinctrl *pc, unsigned int pin,
if (ret)
return ret;
- meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_PULL, &reg, &bit);
if (pull_up)
val = BIT(bit);
@@ -288,7 +297,7 @@ static int meson_pinconf_enable_bias(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_update_bits(pc->reg_pullen, reg, BIT(bit), BIT(bit));
if (ret)
return ret;
@@ -300,7 +309,7 @@ static int meson_pinconf_set_drive_strength(struct meson_pinctrl *pc,
unsigned int pin,
u16 drive_strength_ua)
{
- struct meson_bank *bank;
+ const struct meson_bank *bank;
unsigned int reg, bit, ds_val;
int ret;
@@ -313,8 +322,7 @@ static int meson_pinconf_set_drive_strength(struct meson_pinctrl *pc,
if (ret)
return ret;
- meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
- bit = bit << 1;
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_DS, &reg, &bit);
if (drive_strength_ua <= 500) {
ds_val = MESON_PINCONF_DRV_500UA;
@@ -352,7 +360,7 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
switch (param) {
case PIN_CONFIG_DRIVE_STRENGTH_UA:
case PIN_CONFIG_OUTPUT_ENABLE:
- case PIN_CONFIG_OUTPUT:
+ case PIN_CONFIG_LEVEL:
arg = pinconf_to_config_argument(configs[i]);
break;
@@ -376,7 +384,7 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
case PIN_CONFIG_OUTPUT_ENABLE:
ret = meson_pinconf_set_output(pc, pin, arg);
break;
- case PIN_CONFIG_OUTPUT:
+ case PIN_CONFIG_LEVEL:
ret = meson_pinconf_set_output_drive(pc, pin, arg);
break;
default:
@@ -392,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;
@@ -400,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)
@@ -409,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)
@@ -428,7 +436,7 @@ static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
unsigned int pin,
u16 *drive_strength_ua)
{
- struct meson_bank *bank;
+ const struct meson_bank *bank;
unsigned int reg, bit;
unsigned int val;
int ret;
@@ -440,8 +448,7 @@ static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
if (ret)
return ret;
- meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
- bit = bit << 1;
+ meson_calc_reg_and_bit(bank, pin, MESON_REG_DS, &reg, &bit);
ret = regmap_read(pc->reg_ds, reg, &val);
if (ret)
@@ -480,7 +487,7 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
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;
@@ -495,7 +502,7 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin,
return -EINVAL;
arg = 1;
break;
- case PIN_CONFIG_OUTPUT:
+ case PIN_CONFIG_LEVEL:
ret = meson_pinconf_get_output(pc, pin);
if (ret <= 0)
return -EINVAL;
@@ -522,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);
@@ -573,23 +580,23 @@ static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
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)
{
- meson_pinconf_set_drive(gpiochip_get_data(chip), gpio, value);
+ 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));
@@ -601,6 +608,7 @@ 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;
@@ -612,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) {
@@ -656,28 +662,23 @@ 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");
- of_node_put(np);
- 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_OR_NULL(pc->reg_mux)) {
@@ -720,6 +721,7 @@ int meson8_aobus_parse_dt_extra(struct meson_pinctrl *pc)
return 0;
}
+EXPORT_SYMBOL_GPL(meson8_aobus_parse_dt_extra);
int meson_a1_parse_dt_extra(struct meson_pinctrl *pc)
{
@@ -729,6 +731,7 @@ int meson_a1_parse_dt_extra(struct meson_pinctrl *pc)
return 0;
}
+EXPORT_SYMBOL_GPL(meson_a1_parse_dt_extra);
int meson_pinctrl_probe(struct platform_device *pdev)
{
@@ -743,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;
@@ -763,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");