mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
pinctrl: add pinctrl&gpio support for g12a
PD#156734: pinctrl: add pinctrl&gpio support for g12a
the new pin feature (drive-strength) is first introduced in Meson
Series SoC [G12A]. we can refer the following example to use:
mux {
groups = "uart_ao_tx_a", "uart_ao_rx_a";
function = "uart_ao_a";
drive-strength = <1>;
}
the value of drive-strength can be set to 0/1/2/3, the larger
the value, the faster the slew rate.
Change-Id: I22c6967aa1d5de1b3f6acb84cb18a79b05c0403b
Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
This commit is contained in:
@@ -13,6 +13,8 @@ Required properties for the root node:
|
||||
"amlogic,meson-axg-aobus-pinctrl"
|
||||
"amlogic,meson-txlx-periphs-pinctrl"
|
||||
"amlogic,meson-txlx-aobus-pinctrl"
|
||||
"amlogic,meson-g12a-periphs-pinctrl"
|
||||
"amlogic,meson-g12a-aobus-pinctrl"
|
||||
- reg: address and size of registers controlling irq functionality
|
||||
|
||||
=== GPIO sub-nodes ===
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
clock-names = "clk_uart";
|
||||
xtal_tick_en = <1>;
|
||||
fifosize = < 64 >;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&ao_uart_pins>;
|
||||
support-sysrq = <0>; /* 0 not support , 1 support */
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <dt-bindings/clock/amlogic,g12a-clkc.h>
|
||||
#include <dt-bindings/clock/amlogic,g12a-audio-clk.h>
|
||||
#include <dt-bindings/iio/adc/amlogic-saradc.h>
|
||||
#include <dt-bindings/gpio/meson-g12a-gpio.h>
|
||||
#include <dt-bindings/pwm/pwm.h>
|
||||
#include <dt-bindings/pwm/meson.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
@@ -198,6 +199,44 @@
|
||||
cpuinfo_cmd = <0x82000044>;
|
||||
};
|
||||
|
||||
pinctrl_aobus: pinctrl@ff800014{
|
||||
compatible = "amlogic,meson-g12a-aobus-pinctrl";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
gpio_ao: ao-bank@ff800014{
|
||||
reg = <0x0 0xff800014 0x0 0x8>,
|
||||
<0x0 0xff800024 0x0 0x14>,
|
||||
<0x0 0xff80001c 0x0 0x8>;
|
||||
reg-names = "mux","gpio", "drive-strength";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_periphs: pinctrl@ff634480{
|
||||
compatible = "amlogic,meson-g12a-periphs-pinctrl";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
gpio: banks@ff6346c0{
|
||||
reg = <0x0 0xff6346c0 0x0 0x40>,
|
||||
<0x0 0xff6344e8 0x0 0x18>,
|
||||
<0x0 0xff634520 0x0 0x18>,
|
||||
<0x0 0xff634440 0x0 0x4c>,
|
||||
<0x0 0xff634740 0x0 0x1c>;
|
||||
reg-names = "mux",
|
||||
"pull",
|
||||
"pull-enable",
|
||||
"gpio",
|
||||
"drive-strength";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <2>;
|
||||
@@ -268,3 +307,16 @@
|
||||
|
||||
};/* end of / */
|
||||
|
||||
&pinctrl_aobus {
|
||||
ao_uart_pins:ao_uart {
|
||||
mux {
|
||||
groups = "uart_ao_tx_a",
|
||||
"uart_ao_rx_a";
|
||||
function = "uart_ao_a";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
};
|
||||
|
||||
@@ -205,6 +205,7 @@ CONFIG_AMLOGIC_PINCTRL=y
|
||||
CONFIG_AMLOGIC_PINCTRL_MESON_GXL=y
|
||||
CONFIG_AMLOGIC_PINCTRL_MESON_AXG=y
|
||||
CONFIG_AMLOGIC_PINCTRL_MESON_TXLX=y
|
||||
CONFIG_AMLOGIC_PINCTRL_MESON_G12A=y
|
||||
CONFIG_AMLOGIC_USB=y
|
||||
CONFIG_AMLOGIC_USB_DWC_OTG_HCD=y
|
||||
CONFIG_AMLOGIC_USB_HOST_ELECT_TEST=y
|
||||
|
||||
@@ -197,6 +197,7 @@ CONFIG_AMLOGIC_PINCTRL=y
|
||||
CONFIG_AMLOGIC_PINCTRL_MESON_GXL=y
|
||||
CONFIG_AMLOGIC_PINCTRL_MESON_AXG=y
|
||||
CONFIG_AMLOGIC_PINCTRL_MESON_TXLX=y
|
||||
CONFIG_AMLOGIC_PINCTRL_MESON_G12A=y
|
||||
CONFIG_AMLOGIC_USB=y
|
||||
CONFIG_AMLOGIC_USB_DWC_OTG_HCD=y
|
||||
CONFIG_AMLOGIC_USB_HOST_ELECT_TEST=y
|
||||
|
||||
@@ -35,6 +35,16 @@ config AMLOGIC_PINCTRL_MESON_TXLX
|
||||
select AMLOGIC_PINCTRL_MESON8_PMX
|
||||
default n
|
||||
|
||||
config AMLOGIC_PINCTRL_MESON_G12A
|
||||
bool "Meson g12a SoC pinctrl driver"
|
||||
depends on ARM64
|
||||
select AMLOGIC_PINCTRL_MESON_AXG_PMX
|
||||
select AMLOGIC_PINCONF_MESON_G12A
|
||||
default n
|
||||
|
||||
config AMLOGIC_PINCONF_MESON_G12A
|
||||
bool
|
||||
|
||||
config AMLOGIC_PINCTRL_MESON8_PMX
|
||||
bool
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
#
|
||||
obj-$(CONFIG_AMLOGIC_PINCTRL) += pinctrl-meson.o
|
||||
obj-$(CONFIG_AMLOGIC_PINCTRL_MESON8_PMX) += pinctrl-meson8-pmx.o
|
||||
obj-$(CONFIG_AMLOGIC_PINCONF_MESON_G12A) += pinconf-meson-g12a.o
|
||||
obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o
|
||||
obj-$(CONFIG_AMLOGIC_PINCTRL_MESON8B) += pinctrl-meson8b.o
|
||||
obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
|
||||
obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
|
||||
obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_TXLX) += pinctrl-meson-txlx.o
|
||||
obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
|
||||
|
||||
190
drivers/amlogic/pinctrl/pinconf-meson-g12a.c
Normal file
190
drivers/amlogic/pinctrl/pinconf-meson-g12a.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* drivers/amlogic/pinctrl/pinconf-meson-g12a.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include "pinctrl-meson.h"
|
||||
#include "pinconf-meson-g12a.h"
|
||||
|
||||
static int meson_get_drive_bank(struct meson_pinctrl *pc, unsigned int pin,
|
||||
struct meson_drive_bank **bank)
|
||||
{
|
||||
int i;
|
||||
struct meson_drive_data *drive = pc->data->pcf_drv_data;
|
||||
|
||||
for (i = 0; i < drive->num_drive_banks; i++) {
|
||||
if (pin >= drive->drive_banks[i].first &&
|
||||
pin <= drive->drive_banks[i].last) {
|
||||
*bank = &drive->drive_banks[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void meson_drive_calc_reg_and_bit(struct meson_drive_bank *drive_bank,
|
||||
unsigned int pin, unsigned int *reg,
|
||||
unsigned int *bit)
|
||||
{
|
||||
struct meson_reg_desc *desc = &drive_bank->reg;
|
||||
int shift = pin - drive_bank->first;
|
||||
|
||||
*reg = (desc->reg + (desc->bit + (shift << 1)) / 32) * 4;
|
||||
*bit = (desc->bit + (shift << 1)) % 32;
|
||||
}
|
||||
|
||||
static int meson_pinconf_set_drive_strength(struct meson_pinctrl *pc,
|
||||
unsigned int pin, u16 arg)
|
||||
{
|
||||
struct meson_drive_bank *drive_bank;
|
||||
unsigned int reg, bit;
|
||||
int ret;
|
||||
|
||||
dev_dbg(pc->dev, "pin %u: set drive-strength\n", pin);
|
||||
|
||||
ret = meson_get_drive_bank(pc, pin, &drive_bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (arg >= 4) {
|
||||
dev_err(pc->dev,
|
||||
"pin %u: invalid drive-strength [0-3]: %d\n",
|
||||
pin, arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
meson_drive_calc_reg_and_bit(drive_bank, pin,
|
||||
®, &bit);
|
||||
|
||||
ret = regmap_update_bits(pc->reg_drive, reg,
|
||||
0x3 << bit, (arg & 0x3) << bit);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
|
||||
unsigned int pin, u16 *arg)
|
||||
{
|
||||
struct meson_drive_bank *drive_bank;
|
||||
unsigned int reg, bit;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = meson_get_drive_bank(pc, pin, &drive_bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
meson_drive_calc_reg_and_bit(drive_bank, pin, ®, &bit);
|
||||
|
||||
ret = regmap_read(pc->reg_drive, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*arg = (val >> bit) & 0x3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_g12a_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
|
||||
enum pin_config_param param;
|
||||
int i, ret;
|
||||
u16 arg;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
ret = meson_pinconf_set_pull(pc, pin, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
ret = meson_pinconf_set_drive_strength(pc, pin, arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_g12a_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;
|
||||
|
||||
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;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (meson_pinconf_get_drive_strength(pc, pin, &arg))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
dev_dbg(pc->dev, "pinconf for pin %u is %lu\n", pin, *config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_g12a_pinconf_group_set(struct pinctrl_dev *pcdev,
|
||||
unsigned int num_group, unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
|
||||
struct meson_pmx_group *group = &pc->data->groups[num_group];
|
||||
int i;
|
||||
|
||||
dev_dbg(pc->dev, "set pinconf for group %s\n", group->name);
|
||||
|
||||
for (i = 0; i < group->num_pins; i++) {
|
||||
meson_g12a_pinconf_set(pcdev, group->pins[i], configs,
|
||||
num_configs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct pinconf_ops meson_g12a_pinconf_ops = {
|
||||
.pin_config_get = meson_g12a_pinconf_get,
|
||||
.pin_config_set = meson_g12a_pinconf_set,
|
||||
.pin_config_group_set = meson_g12a_pinconf_group_set,
|
||||
.is_generic = true,
|
||||
};
|
||||
45
drivers/amlogic/pinctrl/pinconf-meson-g12a.h
Normal file
45
drivers/amlogic/pinctrl/pinconf-meson-g12a.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* drivers/amlogic/pinctrl/pinconf-meson-g12a.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PINCONF_MESON_G12A_H
|
||||
#define PINCONF_MESON_G12A_H
|
||||
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
|
||||
struct meson_drive_bank {
|
||||
const char *name;
|
||||
unsigned int first;
|
||||
unsigned int last;
|
||||
struct meson_reg_desc reg;
|
||||
};
|
||||
|
||||
struct meson_drive_data {
|
||||
struct meson_drive_bank *drive_banks;
|
||||
unsigned int num_drive_banks;
|
||||
};
|
||||
|
||||
#define BANK_DRIVE(n, f, l, r, o) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.first = f, \
|
||||
.last = l, \
|
||||
.reg = {r, o}, \
|
||||
}
|
||||
|
||||
extern const struct pinconf_ops meson_g12a_pinconf_ops;
|
||||
|
||||
#endif /*PINCONF_MESON_G12A_H*/
|
||||
1495
drivers/amlogic/pinctrl/pinctrl-meson-g12a.c
Normal file
1495
drivers/amlogic/pinctrl/pinctrl-meson-g12a.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -178,86 +178,97 @@ int meson_pmx_get_groups(struct pinctrl_dev *pcdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
int meson_pinconf_set_pull(struct meson_pinctrl *pc, unsigned int pin,
|
||||
enum pin_config_param param)
|
||||
{
|
||||
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
|
||||
struct meson_bank *bank;
|
||||
enum pin_config_param param;
|
||||
unsigned int reg, bit;
|
||||
int i, ret;
|
||||
u16 arg;
|
||||
int ret;
|
||||
|
||||
ret = meson_get_bank(pc, pin, &bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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,
|
||||
®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_pullen, reg,
|
||||
BIT(bit), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
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,
|
||||
®, &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, ®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_pull, reg,
|
||||
BIT(bit), BIT(bit));
|
||||
if (ret)
|
||||
return ret;
|
||||
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,
|
||||
®, &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, ®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_pull, reg,
|
||||
BIT(bit), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
dev_dbg(pc->dev, "pin %u: enable input\n", pin);
|
||||
|
||||
meson_calc_reg_and_bit(bank, pin, REG_DIR,
|
||||
®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_gpio, reg,
|
||||
BIT(bit), BIT(bit));
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
|
||||
enum pin_config_param param;
|
||||
int i, ret;
|
||||
u16 arg;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
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,
|
||||
®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_pullen, reg,
|
||||
BIT(bit), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
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,
|
||||
®, &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, ®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_pull, reg,
|
||||
BIT(bit), BIT(bit));
|
||||
if (ret)
|
||||
return ret;
|
||||
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,
|
||||
®, &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, ®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_pull, reg,
|
||||
BIT(bit), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
dev_dbg(pc->dev, "pin %u: enable input\n", pin);
|
||||
|
||||
meson_calc_reg_and_bit(bank, pin, REG_DIR,
|
||||
®, &bit);
|
||||
ret = regmap_update_bits(pc->reg_gpio, reg,
|
||||
BIT(bit), BIT(bit));
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
ret = meson_pinconf_set_pull(pc, pin, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
|
||||
int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin)
|
||||
{
|
||||
struct meson_bank *bank;
|
||||
unsigned int reg, bit, val;
|
||||
@@ -582,23 +593,44 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
|
||||
return PTR_ERR(pc->reg_mux);
|
||||
}
|
||||
|
||||
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_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_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_pull = meson_map_resource(pc, gpio_np, "pull");
|
||||
/* Use gpio region if pull one is not present */
|
||||
if (IS_ERR(pc->reg_pull)) {
|
||||
if (PTR_ERR(pc->reg_pull) == -ENOENT) {
|
||||
pc->reg_pull = pc->reg_gpio;
|
||||
} else {
|
||||
dev_err(pc->dev, "pull registers not found\n");
|
||||
return PTR_ERR(pc->reg_pull);
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
if (PTR_ERR(pc->reg_pullen) == -ENOENT)
|
||||
pc->reg_pullen = pc->reg_pull;
|
||||
else {
|
||||
dev_err(pc->dev, "pull-enable registers not found\n");
|
||||
return PTR_ERR(pc->reg_pullen);
|
||||
}
|
||||
}
|
||||
|
||||
pc->reg_drive = meson_map_resource(pc, gpio_np, "drive-strength");
|
||||
if (IS_ERR(pc->reg_drive)) {
|
||||
if (PTR_ERR(pc->reg_drive) == -ENOENT)
|
||||
pc->reg_drive = NULL;
|
||||
else {
|
||||
dev_err(pc->dev, "drive-strength registers not found\n");
|
||||
return PTR_ERR(pc->reg_drive);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -624,9 +656,13 @@ int meson_pinctrl_probe(struct platform_device *pdev)
|
||||
pc->desc.pctlops = &meson_pctrl_ops;
|
||||
pc->desc.pmxops = pc->data->pmx_ops;
|
||||
pc->desc.pins = pc->data->pins;
|
||||
pc->desc.confops = &meson_pinconf_ops;
|
||||
pc->desc.npins = pc->data->num_pins;
|
||||
|
||||
if (pc->data->pcf_ops)
|
||||
pc->desc.confops = pc->data->pcf_ops;
|
||||
else
|
||||
pc->desc.confops = &meson_pinconf_ops;
|
||||
|
||||
if (pc->data->init)
|
||||
pc->data->init(pc);
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
@@ -117,7 +119,9 @@ struct meson_pinctrl_data {
|
||||
unsigned int num_funcs;
|
||||
unsigned int num_banks;
|
||||
const struct pinmux_ops *pmx_ops;
|
||||
const struct pinconf_ops *pcf_ops;
|
||||
void *pmx_data;
|
||||
void *pcf_drv_data;
|
||||
};
|
||||
|
||||
struct meson_pinctrl {
|
||||
@@ -129,6 +133,7 @@ struct meson_pinctrl {
|
||||
struct regmap *reg_pullen;
|
||||
struct regmap *reg_pull;
|
||||
struct regmap *reg_gpio;
|
||||
struct regmap *reg_drive;
|
||||
struct gpio_chip chip;
|
||||
struct device_node *of_node;
|
||||
struct device_node *of_irq;
|
||||
@@ -171,3 +176,9 @@ extern int meson_pmx_get_groups(struct pinctrl_dev *pcdev,
|
||||
unsigned int selector,
|
||||
const char * const **groups,
|
||||
unsigned int * const num_groups);
|
||||
|
||||
/* Common pinconf functions */
|
||||
extern int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin);
|
||||
|
||||
extern int meson_pinconf_set_pull(struct meson_pinctrl *pc, unsigned int pin,
|
||||
enum pin_config_param param);
|
||||
|
||||
@@ -38,7 +38,12 @@ static const struct pin_config_item conf_items[] = {
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
|
||||
#ifdef CONFIG_AMLOGIC_MODIFY
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH,
|
||||
"output drive strength", NULL, true),
|
||||
#else
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA", true),
|
||||
#endif
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec", true),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_ENABLE, "input enabled", NULL, false),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL, false),
|
||||
|
||||
116
include/dt-bindings/gpio/meson-g12a-gpio.h
Normal file
116
include/dt-bindings/gpio/meson-g12a-gpio.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Amlogic, Inc. All rights reserved.
|
||||
* Author: Xingyu Chen <xingyu.chen@amlogic.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_MESON_G12A_GPIO_H
|
||||
#define _DT_BINDINGS_MESON_G12A_GPIO_H
|
||||
|
||||
/* First GPIO chip */
|
||||
#define GPIOAO_0 0
|
||||
#define GPIOAO_1 1
|
||||
#define GPIOAO_2 2
|
||||
#define GPIOAO_3 3
|
||||
#define GPIOAO_4 4
|
||||
#define GPIOAO_5 5
|
||||
#define GPIOAO_6 6
|
||||
#define GPIOAO_7 7
|
||||
#define GPIOAO_8 8
|
||||
#define GPIOAO_9 9
|
||||
#define GPIOAO_10 10
|
||||
#define GPIOAO_11 11
|
||||
#define GPIOE_0 12
|
||||
#define GPIOE_1 13
|
||||
#define GPIOE_2 14
|
||||
#define GPIO_TEST_N 15
|
||||
|
||||
/* Second GPIO chip */
|
||||
#define GPIOZ_0 0
|
||||
#define GPIOZ_1 1
|
||||
#define GPIOZ_2 2
|
||||
#define GPIOZ_3 3
|
||||
#define GPIOZ_4 4
|
||||
#define GPIOZ_5 5
|
||||
#define GPIOZ_6 6
|
||||
#define GPIOZ_7 7
|
||||
#define GPIOZ_8 8
|
||||
#define GPIOZ_9 9
|
||||
#define GPIOZ_10 10
|
||||
#define GPIOZ_11 11
|
||||
#define GPIOZ_12 12
|
||||
#define GPIOZ_13 13
|
||||
#define GPIOZ_14 14
|
||||
#define GPIOZ_15 15
|
||||
#define GPIOH_0 16
|
||||
#define GPIOH_1 17
|
||||
#define GPIOH_2 18
|
||||
#define GPIOH_3 19
|
||||
#define GPIOH_4 20
|
||||
#define GPIOH_5 21
|
||||
#define GPIOH_6 22
|
||||
#define GPIOH_7 23
|
||||
#define GPIOH_8 24
|
||||
#define BOOT_0 25
|
||||
#define BOOT_1 26
|
||||
#define BOOT_2 27
|
||||
#define BOOT_3 28
|
||||
#define BOOT_4 29
|
||||
#define BOOT_5 30
|
||||
#define BOOT_6 31
|
||||
#define BOOT_7 32
|
||||
#define BOOT_8 33
|
||||
#define BOOT_9 34
|
||||
#define BOOT_10 35
|
||||
#define BOOT_11 36
|
||||
#define BOOT_12 37
|
||||
#define BOOT_13 38
|
||||
#define BOOT_14 39
|
||||
#define BOOT_15 40
|
||||
#define GPIOC_0 41
|
||||
#define GPIOC_1 42
|
||||
#define GPIOC_2 43
|
||||
#define GPIOC_3 44
|
||||
#define GPIOC_4 45
|
||||
#define GPIOC_5 46
|
||||
#define GPIOC_6 47
|
||||
#define GPIOC_7 48
|
||||
#define GPIOA_0 49
|
||||
#define GPIOA_1 50
|
||||
#define GPIOA_2 51
|
||||
#define GPIOA_3 52
|
||||
#define GPIOA_4 53
|
||||
#define GPIOA_5 54
|
||||
#define GPIOA_6 55
|
||||
#define GPIOA_7 56
|
||||
#define GPIOA_8 57
|
||||
#define GPIOA_9 58
|
||||
#define GPIOA_10 59
|
||||
#define GPIOA_11 60
|
||||
#define GPIOA_12 61
|
||||
#define GPIOA_13 62
|
||||
#define GPIOA_14 63
|
||||
#define GPIOA_15 64
|
||||
#define GPIOX_0 65
|
||||
#define GPIOX_1 66
|
||||
#define GPIOX_2 67
|
||||
#define GPIOX_3 68
|
||||
#define GPIOX_4 69
|
||||
#define GPIOX_5 70
|
||||
#define GPIOX_6 71
|
||||
#define GPIOX_7 72
|
||||
#define GPIOX_8 73
|
||||
#define GPIOX_9 74
|
||||
#define GPIOX_10 75
|
||||
#define GPIOX_11 76
|
||||
#define GPIOX_12 77
|
||||
#define GPIOX_13 78
|
||||
#define GPIOX_14 79
|
||||
#define GPIOX_15 80
|
||||
#define GPIOX_16 81
|
||||
#define GPIOX_17 82
|
||||
#define GPIOX_18 83
|
||||
#define GPIOX_19 84
|
||||
|
||||
#endif /* _DT_BINDINGS_MESON_G12A_GPIO_H */
|
||||
Reference in New Issue
Block a user