diff mbox series

[RFC] gpio-omap: handle bias flags

Message ID 20200709173007.GA739269@x1
State New
Headers show
Series [RFC] gpio-omap: handle bias flags | expand

Commit Message

Drew Fustini July 9, 2020, 5:30 p.m. UTC
Tony - what do you think of this approach?

I have added this in arch/arm/boot/dts/am335x-pocketbeagle.dts to
describe the pins which will be gpio lines accessed by userspace
through gpiod ioctl() calls:

&am33xx_pinmux {

	pinctrl-names = "default";
	pinctrl-0 =   < &gpio_pins >;

	gpio_pins: pinmux-gpio-pins {
		/* MUX_MODE7 is gpio mode */
		pinctrl-single,pins = <
			/* PIN 95 and PIN 94 */
			AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT, MUX_MODE7)
			AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE7)
			/* PIN 100 */
			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT, MUX_MODE7)
			/* PIN 18 */
			AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_INPUT, MUX_MODE7)
		>;
		pinctrl-single,bias-pullup   = < 8 16  8 24>;
		pinctrl-single,bias-pulldown = < 8  0  8 24>;
	};

The "pinctrl-single,bias-pullup" and "pinctrl-single,bias-pulldown"
pinconf properties are set for the gpio_pins pin group.  The input
value 0x8 causes both to be inactive but still added to the
PIN_MAP_TYPE_CONFIGS_GROUP pinctrl map.  This is necessary for
pcs_pinconf_set() to be able to be able to set the bias config.

For AM335x, the pin conf register has the format [0]:

bit	attribute      value
  6	slew           { 0: fast, 1: slow }
  5     rx_active      { 0: rx disable, 1: rx enabled }
  4     pu_typesel     { 0: pulldown select, 1: pullup select }
  3     puden          { 0: pud enable, 1: disabled }
  2     mode           3 bits to selec mode 0 to 7
  1     mode
  0     mode

Here is how I derived the values:

pinctrl-single,bias-pullup   = <[input] [enabled] [disable] [mask]>;
pinctrl-single,bias-pullup   = <     8        16        8      24 >;

          2^5    2^4    2^3    2^2    2^1    2^0  | 
         0x20   0x10   0x08   0x04   0x02   0x01  |
           32     16      8      4      2      1  | 
-------------------------------------------------------  
input       x      0      1     x      x      x   |   8 
enabled     x      1      0     x      x      x   |  16
disabled    x      0      1     x      x      x   |   8
mask        x      1      1     x      x      x   |  24


pinctrl-single,bias-pulldown = <[input] [enabled] [disable] [mask]>;
pinctrl-single,bias-pulldown = <     8         0        8      24 >;

          2^5    2^4    2^3    2^2    2^1    2^0  | 
         0x20   0x10   0x08   0x04   0x02   0x01  |
           32     16      8      4      2      1  | 
-------------------------------------------------------  
input       x      0      1     x      x      x   |   8 
enabled     x      0      0     x      x      x   |   0 
disabled    x      0      1     x      x      x   |   8
mask        x      1      1     x      x      x   |  24

The pinconf bias properties get applied to the pin group during boot
when pcs_pinconf_group_set() calls pcs_pinconf_set() for each pin. Here
is the output from function_graph tracer:

              pinconf_apply_setting() {
                pcs_pinconf_group_set() {
                  pinctrl_generic_get_group_pins();
                  pcs_pinconf_set() {
                    pcs_get_function() {
                      pinmux_generic_get_function();
                    }
                    pcs_readl();
                    pcs_writel();
                    pcs_readl();
                    pcs_writel();
                  }
                  pcs_pinconf_set() {
                    pcs_get_function() {
                      pinmux_generic_get_function();
                    }
                    pcs_readl();
                    pcs_writel();
                    pcs_readl();
                    pcs_writel();
                  }
                  pcs_pinconf_set() {
                    pcs_get_function() {
                      pinmux_generic_get_function();
                    }
                    pcs_readl();
                    pcs_writel();
                    pcs_readl();
                    pcs_writel();
                  }
                  pcs_pinconf_set() {
                    pcs_get_function() {
                      pinmux_generic_get_function();
                    }
                    pcs_readl();
                    pcs_writel();
                    pcs_readl();
                    pcs_writel();
                  }
                }
              }

After boot, I then use gpiomon utility with bias flags:

	gpiomon -B pull-up 3 14

gpiochip 3 line 14 maps to pin 100 which is AM335X_PIN_MCASP0_ACLKX at
offset 0x990.  For this to succeed, I modified omap_gpio_set_config() in
gpio_omap.c to handle PIN_CONFIG_BIAS_PULL_{UP,DOWN} by calling
gpiochip_generic_config().  Here is output of function_grapher tracer:

             gpio_ioctl() {
               gpiochip_get_desc();
               gpiod_request() {
                 gpiod_request_commit() {
                   gpiochip_line_is_valid();
                   omap_gpio_request() {
                     omap_gpio_runtime_resume() {
                       omap_gpio_unidle() {
                         omap_gpio_restore_context();
                       }
                     }
                     omap_enable_gpio_module();
                   }
                   gpiod_get_direction() {
                     gpiod_to_chip();
                     omap_gpio_get_direction();
                   }
                 }
               }
               gpiod_direction_input() {
                 omap_gpio_input() {
                   omap_set_gpio_direction();
                 }
                 gpio_set_bias() {
                   gpio_set_config() {
                     gpio_do_set_config() {
                       omap_gpio_set_config() {
                         gpiochip_generic_config() {
                           pinctrl_gpio_set_config() {
                             pinctrl_get_device_gpio_range() {
                               pinctrl_match_gpio_range();
                             }
                             pinconf_set_config() {
                               pcs_pinconf_set() {
                                 pcs_get_function() {
                                   pinmux_generic_get_function();
                                 }
                                 pcs_readl();
                                 pcs_pinconf_clear_bias.constprop.0();
                                 pcs_writel();

Thanks,
Drew

[0] http://www.ti.com/lit/ds/symlink/am3358.pdf
---
 drivers/gpio/gpio-omap.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index b8e2ecc3eade..a471a152f318 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -896,12 +896,25 @@  static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
 				unsigned long config)
 {
 	u32 debounce;
+	int ret;
 
-	if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
-		return -ENOTSUPP;
+	if ((pinconf_to_config_param(config) == PIN_CONFIG_BIAS_DISABLE) ||
+	    (pinconf_to_config_param(config) == PIN_CONFIG_BIAS_PULL_UP) ||
+	    (pinconf_to_config_param(config) == PIN_CONFIG_BIAS_PULL_DOWN))
+	{
+		ret = gpiochip_generic_config(chip, offset, config);
+	}
+	else if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE)
+	{
+		debounce = pinconf_to_config_argument(config);
+		ret = omap_gpio_debounce(chip, offset, debounce);
+	}
+	else
+	{
+		ret = -ENOTSUPP;
+	}
 
-	debounce = pinconf_to_config_argument(config);
-	return omap_gpio_debounce(chip, offset, debounce);
+	return ret;
 }
 
 static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)