Browse Source

Merge tag 'pinctrl-v4.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

Pull pin control updates from Linus Walleij:
 "This kernel cycle was quite calm when it comes to pin control and
  there is really just one major change, and that is the introduction of
  devm_pinctrl_register() managed resources.

  Apart from that linear development, details below.

  Core changes:

   - Add the devm_pinctrl_register() API and switch all applicable
     drivers to use it, saving lots of lines of code all over the place.

  New drivers:

   - driver for the Broadcom NS2 SoC

   - subdriver for the PXA25x SoCs

   - subdriver for the AMLogic Meson GXBB SoC

  Driver improvements:

   - the Intel Baytrail driver now properly supports pin control

   - Nomadik, Rockchip, Broadcom BCM2835 support the .get_direction()
     callback in the GPIO portions

   - continued development and stabilization of several SH-PFC SoC
     subdrivers: r8a7795, r8a7790, r8a7794 etc"

* tag 'pinctrl-v4.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (85 commits)
  Revert "pinctrl: tegra: avoid parked_reg and parked_bank"
  pinctrl: meson: Fix eth_tx_en bit index
  pinctrl: tegra: avoid parked_reg and parked_bank
  pinctrl: tegra: Correctly check the supported configuration
  pinctrl: amlogic: Add support for Amlogic Meson GXBB SoC
  pinctrl: rockchip: fix pull setting error for rk3399
  pinctrl: stm32: Implement .pin_config_dbg_show()
  pinctrl: nomadik: hide nmk_gpio_get_mode when unused
  pinctrl: ns2: rename pinctrl_utils_dt_free_map
  pinctrl: at91: Merge clk_prepare and clk_enable into clk_prepare_enable
  pinctrl: at91: Make at91_gpio_template const
  pinctrl: baytrail: fix some error handling in debugfs
  pinctrl: ns2: add pinmux driver support for Broadcom NS2 SoC
  pinctrl: sirf/atlas7: trivial fix of spelling mistake on flagged
  pinctrl: sh-pfc: Kill unused variable in sh_pfc_remove()
  pinctrl: nomadik: implement .get_direction()
  pinctrl: nomadik: use BIT() with offsets consequently
  pinctrl: exynos5440: Use off-stack memory for pinctrl_gpio_range
  pinctrl: zynq: Use devm_pinctrl_register() for pinctrl registration
  pinctrl: u300: Use devm_pinctrl_register() for pinctrl registration
  ...
Linus Torvalds 9 years ago
parent
commit
a37571a29e
100 changed files with 4548 additions and 812 deletions
  1. 2 2
      Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
  2. 2 0
      Documentation/driver-model/devres.txt
  3. 13 0
      drivers/pinctrl/bcm/Kconfig
  4. 1 0
      drivers/pinctrl/bcm/Makefile
  5. 2 4
      drivers/pinctrl/bcm/pinctrl-bcm281xx.c
  6. 14 2
      drivers/pinctrl/bcm/pinctrl-bcm2835.c
  7. 2 2
      drivers/pinctrl/bcm/pinctrl-cygnus-mux.c
  8. 3 11
      drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
  9. 1117 0
      drivers/pinctrl/bcm/pinctrl-ns2-mux.c
  10. 2 2
      drivers/pinctrl/bcm/pinctrl-nsp-gpio.c
  11. 3 2
      drivers/pinctrl/berlin/berlin.c
  12. 63 0
      drivers/pinctrl/core.c
  13. 1 10
      drivers/pinctrl/freescale/pinctrl-imx.c
  14. 0 1
      drivers/pinctrl/freescale/pinctrl-imx.h
  15. 1 10
      drivers/pinctrl/freescale/pinctrl-imx1-core.c
  16. 0 1
      drivers/pinctrl/freescale/pinctrl-imx1.c
  17. 0 1
      drivers/pinctrl/freescale/pinctrl-imx1.h
  18. 0 1
      drivers/pinctrl/freescale/pinctrl-imx21.c
  19. 0 1
      drivers/pinctrl/freescale/pinctrl-imx25.c
  20. 0 1
      drivers/pinctrl/freescale/pinctrl-imx27.c
  21. 0 1
      drivers/pinctrl/freescale/pinctrl-imx35.c
  22. 0 1
      drivers/pinctrl/freescale/pinctrl-imx50.c
  23. 0 1
      drivers/pinctrl/freescale/pinctrl-imx51.c
  24. 0 1
      drivers/pinctrl/freescale/pinctrl-imx53.c
  25. 0 1
      drivers/pinctrl/freescale/pinctrl-imx6dl.c
  26. 0 1
      drivers/pinctrl/freescale/pinctrl-imx6q.c
  27. 0 1
      drivers/pinctrl/freescale/pinctrl-imx6sl.c
  28. 0 1
      drivers/pinctrl/freescale/pinctrl-imx6sx.c
  29. 0 1
      drivers/pinctrl/freescale/pinctrl-imx6ul.c
  30. 0 1
      drivers/pinctrl/freescale/pinctrl-imx7d.c
  31. 0 1
      drivers/pinctrl/freescale/pinctrl-vf610.c
  32. 3 0
      drivers/pinctrl/intel/Kconfig
  33. 1451 256
      drivers/pinctrl/intel/pinctrl-baytrail.c
  34. 3 5
      drivers/pinctrl/intel/pinctrl-cherryview.c
  35. 3 5
      drivers/pinctrl/intel/pinctrl-intel.c
  36. 8 13
      drivers/pinctrl/mediatek/pinctrl-mtk-common.c
  37. 1 1
      drivers/pinctrl/meson/Makefile
  38. 432 0
      drivers/pinctrl/meson/pinctrl-meson-gxbb.c
  39. 10 2
      drivers/pinctrl/meson/pinctrl-meson.c
  40. 2 0
      drivers/pinctrl/meson/pinctrl-meson.h
  41. 1 1
      drivers/pinctrl/meson/pinctrl-meson8b.c
  42. 0 6
      drivers/pinctrl/mvebu/pinctrl-armada-370.c
  43. 0 6
      drivers/pinctrl/mvebu/pinctrl-armada-375.c
  44. 0 6
      drivers/pinctrl/mvebu/pinctrl-armada-38x.c
  45. 0 6
      drivers/pinctrl/mvebu/pinctrl-armada-39x.c
  46. 0 6
      drivers/pinctrl/mvebu/pinctrl-armada-xp.c
  47. 1 4
      drivers/pinctrl/mvebu/pinctrl-dove.c
  48. 0 6
      drivers/pinctrl/mvebu/pinctrl-kirkwood.c
  49. 1 8
      drivers/pinctrl/mvebu/pinctrl-mvebu.c
  50. 0 1
      drivers/pinctrl/mvebu/pinctrl-mvebu.h
  51. 0 6
      drivers/pinctrl/mvebu/pinctrl-orion.c
  52. 4 3
      drivers/pinctrl/nomadik/pinctrl-abx500.c
  53. 78 90
      drivers/pinctrl/nomadik/pinctrl-nomadik.c
  54. 1 1
      drivers/pinctrl/pinconf-generic.c
  55. 2 11
      drivers/pinctrl/pinctrl-adi2.c
  56. 5 7
      drivers/pinctrl/pinctrl-amd.c
  57. 4 7
      drivers/pinctrl/pinctrl-as3722.c
  58. 15 15
      drivers/pinctrl/pinctrl-at91-pio4.c
  59. 6 22
      drivers/pinctrl/pinctrl-at91.c
  60. 4 11
      drivers/pinctrl/pinctrl-digicolor.c
  61. 1 1
      drivers/pinctrl/pinctrl-lantiq.c
  62. 2 3
      drivers/pinctrl/pinctrl-lpc18xx.c
  63. 3 11
      drivers/pinctrl/pinctrl-palmas.c
  64. 3 2
      drivers/pinctrl/pinctrl-pic32.c
  65. 3 3
      drivers/pinctrl/pinctrl-pistachio.c
  66. 139 53
      drivers/pinctrl/pinctrl-rockchip.c
  67. 1 1
      drivers/pinctrl/pinctrl-st.c
  68. 2 3
      drivers/pinctrl/pinctrl-tb10x.c
  69. 2 11
      drivers/pinctrl/pinctrl-tz1090-pdc.c
  70. 2 11
      drivers/pinctrl/pinctrl-tz1090.c
  71. 1 11
      drivers/pinctrl/pinctrl-u300.c
  72. 2 2
      drivers/pinctrl/pinctrl-utils.c
  73. 1 1
      drivers/pinctrl/pinctrl-utils.h
  74. 2 12
      drivers/pinctrl/pinctrl-zynq.c
  75. 9 1
      drivers/pinctrl/pxa/Kconfig
  76. 1 0
      drivers/pinctrl/pxa/Makefile
  77. 274 0
      drivers/pinctrl/pxa/pinctrl-pxa25x.c
  78. 2 2
      drivers/pinctrl/pxa/pinctrl-pxa2xx.c
  79. 4 6
      drivers/pinctrl/qcom/pinctrl-msm.c
  80. 3 6
      drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
  81. 3 6
      drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
  82. 3 8
      drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
  83. 3 8
      drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
  84. 9 8
      drivers/pinctrl/samsung/pinctrl-exynos5440.c
  85. 2 1
      drivers/pinctrl/samsung/pinctrl-samsung.c
  86. 16 4
      drivers/pinctrl/sh-pfc/core.c
  87. 3 2
      drivers/pinctrl/sh-pfc/core.h
  88. 53 1
      drivers/pinctrl/sh-pfc/pfc-r8a7790.c
  89. 217 0
      drivers/pinctrl/sh-pfc/pfc-r8a7794.c
  90. 210 8
      drivers/pinctrl/sh-pfc/pfc-r8a7795.c
  91. 112 12
      drivers/pinctrl/sh-pfc/pinctrl.c
  92. 18 1
      drivers/pinctrl/sh-pfc/sh_pfc.h
  93. 1 10
      drivers/pinctrl/spear/pinctrl-spear.c
  94. 0 1
      drivers/pinctrl/spear/pinctrl-spear.h
  95. 0 6
      drivers/pinctrl/spear/pinctrl-spear1310.c
  96. 0 6
      drivers/pinctrl/spear/pinctrl-spear1340.c
  97. 0 6
      drivers/pinctrl/spear/pinctrl-spear300.c
  98. 0 6
      drivers/pinctrl/spear/pinctrl-spear310.c
  99. 0 6
      drivers/pinctrl/spear/pinctrl-spear320.c
  100. 180 5
      drivers/pinctrl/stm32/pinctrl-stm32.c

+ 2 - 2
Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt

@@ -72,8 +72,8 @@ Pin Configuration Node Properties:
 
 
 The pin configuration parameters use the generic pinconf bindings defined in
 The pin configuration parameters use the generic pinconf bindings defined in
 pinctrl-bindings.txt in this directory. The supported parameters are
 pinctrl-bindings.txt in this directory. The supported parameters are
-bias-disable, bias-pull-up, bias-pull-down and power-source. For pins that
-have a configurable I/O voltage, the power-source value should be the
+bias-disable, bias-pull-up, bias-pull-down, drive strength and power-source. For
+pins that have a configurable I/O voltage, the power-source value should be the
 nominal I/O voltage in millivolts.
 nominal I/O voltage in millivolts.
 
 
 
 

+ 2 - 0
Documentation/driver-model/devres.txt

@@ -328,6 +328,8 @@ PHY
 PINCTRL
 PINCTRL
   devm_pinctrl_get()
   devm_pinctrl_get()
   devm_pinctrl_put()
   devm_pinctrl_put()
+  devm_pinctrl_register()
+  devm_pinctrl_unregister()
 
 
 PWM
 PWM
   devm_pwm_get()
   devm_pwm_get()

+ 13 - 0
drivers/pinctrl/bcm/Kconfig

@@ -86,3 +86,16 @@ config PINCTRL_NSP_GPIO
 	  The ChipcommonA GPIO controller support basic PINCONF functions such
 	  The ChipcommonA GPIO controller support basic PINCONF functions such
 	  as bias pull up, pull down, and drive strength configurations, when
 	  as bias pull up, pull down, and drive strength configurations, when
 	  these pins are muxed to GPIO.
 	  these pins are muxed to GPIO.
+
+config PINCTRL_NS2_MUX
+	bool "Broadcom Northstar2 pinmux driver"
+	depends on OF
+	depends on ARCH_BCM_IPROC || COMPILE_TEST
+	select PINMUX
+	select GENERIC_PINCONF
+	default ARM64 && ARCH_BCM_IPROC
+	help
+	  Say yes here to enable the Broadcom NS2 MUX driver.
+
+	  The Broadcom Northstar2 IOMUX driver supports group based IOMUX
+	  configuration.

+ 1 - 0
drivers/pinctrl/bcm/Makefile

@@ -5,3 +5,4 @@ obj-$(CONFIG_PINCTRL_BCM2835)		+= pinctrl-bcm2835.o
 obj-$(CONFIG_PINCTRL_IPROC_GPIO)	+= pinctrl-iproc-gpio.o
 obj-$(CONFIG_PINCTRL_IPROC_GPIO)	+= pinctrl-iproc-gpio.o
 obj-$(CONFIG_PINCTRL_CYGNUS_MUX)	+= pinctrl-cygnus-mux.o
 obj-$(CONFIG_PINCTRL_CYGNUS_MUX)	+= pinctrl-cygnus-mux.o
 obj-$(CONFIG_PINCTRL_NSP_GPIO)		+= pinctrl-nsp-gpio.o
 obj-$(CONFIG_PINCTRL_NSP_GPIO)		+= pinctrl-nsp-gpio.o
+obj-$(CONFIG_PINCTRL_NS2_MUX)		+= pinctrl-ns2-mux.o

+ 2 - 4
drivers/pinctrl/bcm/pinctrl-bcm281xx.c

@@ -1024,7 +1024,7 @@ static struct pinctrl_ops bcm281xx_pinctrl_ops = {
 	.get_group_pins = bcm281xx_pinctrl_get_group_pins,
 	.get_group_pins = bcm281xx_pinctrl_get_group_pins,
 	.pin_dbg_show = bcm281xx_pinctrl_pin_dbg_show,
 	.pin_dbg_show = bcm281xx_pinctrl_pin_dbg_show,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
 static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
@@ -1422,9 +1422,7 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 	bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins;
 	bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins;
 	bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins;
 	bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins;
 
 
-	pctl = pinctrl_register(&bcm281xx_pinctrl_desc,
-				&pdev->dev,
-				pdata);
+	pctl = devm_pinctrl_register(&pdev->dev, &bcm281xx_pinctrl_desc, pdata);
 	if (IS_ERR(pctl)) {
 	if (IS_ERR(pctl)) {
 		dev_err(&pdev->dev, "Failed to register pinctrl\n");
 		dev_err(&pdev->dev, "Failed to register pinctrl\n");
 		return PTR_ERR(pctl);
 		return PTR_ERR(pctl);

+ 14 - 2
drivers/pinctrl/bcm/pinctrl-bcm2835.c

@@ -342,6 +342,18 @@ static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset)
 	return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
 	return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
 }
 }
 
 
+static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
+
+	/* Alternative function doesn't clearly provide a direction */
+	if (fsel > BCM2835_FSEL_GPIO_OUT)
+		return -EINVAL;
+
+	return (fsel == BCM2835_FSEL_GPIO_IN);
+}
+
 static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 {
 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
@@ -370,6 +382,7 @@ static struct gpio_chip bcm2835_gpio_chip = {
 	.free = gpiochip_generic_free,
 	.free = gpiochip_generic_free,
 	.direction_input = bcm2835_gpio_direction_input,
 	.direction_input = bcm2835_gpio_direction_input,
 	.direction_output = bcm2835_gpio_direction_output,
 	.direction_output = bcm2835_gpio_direction_output,
+	.get_direction = bcm2835_gpio_get_direction,
 	.get = bcm2835_gpio_get,
 	.get = bcm2835_gpio_get,
 	.set = bcm2835_gpio_set,
 	.set = bcm2835_gpio_set,
 	.to_irq = bcm2835_gpio_to_irq,
 	.to_irq = bcm2835_gpio_to_irq,
@@ -1027,7 +1040,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
 		return err;
 		return err;
 	}
 	}
 
 
-	pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc);
+	pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
 	if (IS_ERR(pc->pctl_dev)) {
 	if (IS_ERR(pc->pctl_dev)) {
 		gpiochip_remove(&pc->gpio_chip);
 		gpiochip_remove(&pc->gpio_chip);
 		return PTR_ERR(pc->pctl_dev);
 		return PTR_ERR(pc->pctl_dev);
@@ -1045,7 +1058,6 @@ static int bcm2835_pinctrl_remove(struct platform_device *pdev)
 {
 {
 	struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev);
 	struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev);
 
 
-	pinctrl_unregister(pc->pctl_dev);
 	gpiochip_remove(&pc->gpio_chip);
 	gpiochip_remove(&pc->gpio_chip);
 
 
 	return 0;
 	return 0;

+ 2 - 2
drivers/pinctrl/bcm/pinctrl-cygnus-mux.c

@@ -737,7 +737,7 @@ static const struct pinctrl_ops cygnus_pinctrl_ops = {
 	.get_group_pins = cygnus_get_group_pins,
 	.get_group_pins = cygnus_get_group_pins,
 	.pin_dbg_show = cygnus_pin_dbg_show,
 	.pin_dbg_show = cygnus_pin_dbg_show,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int cygnus_get_functions_count(struct pinctrl_dev *pctrl_dev)
 static int cygnus_get_functions_count(struct pinctrl_dev *pctrl_dev)
@@ -987,7 +987,7 @@ static int cygnus_pinmux_probe(struct platform_device *pdev)
 	cygnus_pinctrl_desc.pins = pins;
 	cygnus_pinctrl_desc.pins = pins;
 	cygnus_pinctrl_desc.npins = num_pins;
 	cygnus_pinctrl_desc.npins = num_pins;
 
 
-	pinctrl->pctl = pinctrl_register(&cygnus_pinctrl_desc, &pdev->dev,
+	pinctrl->pctl = devm_pinctrl_register(&pdev->dev, &cygnus_pinctrl_desc,
 			pinctrl);
 			pinctrl);
 	if (IS_ERR(pinctrl->pctl)) {
 	if (IS_ERR(pinctrl->pctl)) {
 		dev_err(&pdev->dev, "unable to register Cygnus IOMUX pinctrl\n");
 		dev_err(&pdev->dev, "unable to register Cygnus IOMUX pinctrl\n");

+ 3 - 11
drivers/pinctrl/bcm/pinctrl-iproc-gpio.c

@@ -379,7 +379,7 @@ static const struct pinctrl_ops iproc_pctrl_ops = {
 	.get_groups_count = iproc_get_groups_count,
 	.get_groups_count = iproc_get_groups_count,
 	.get_group_name = iproc_get_group_name,
 	.get_group_name = iproc_get_group_name,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio,
 static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio,
@@ -623,7 +623,7 @@ static int iproc_gpio_register_pinconf(struct iproc_gpio *chip)
 	pctldesc->npins = gc->ngpio;
 	pctldesc->npins = gc->ngpio;
 	pctldesc->confops = &iproc_pconf_ops;
 	pctldesc->confops = &iproc_pconf_ops;
 
 
-	chip->pctl = pinctrl_register(pctldesc, chip->dev, chip);
+	chip->pctl = devm_pinctrl_register(chip->dev, pctldesc, chip);
 	if (IS_ERR(chip->pctl)) {
 	if (IS_ERR(chip->pctl)) {
 		dev_err(chip->dev, "unable to register pinctrl device\n");
 		dev_err(chip->dev, "unable to register pinctrl device\n");
 		return PTR_ERR(chip->pctl);
 		return PTR_ERR(chip->pctl);
@@ -632,11 +632,6 @@ static int iproc_gpio_register_pinconf(struct iproc_gpio *chip)
 	return 0;
 	return 0;
 }
 }
 
 
-static void iproc_gpio_unregister_pinconf(struct iproc_gpio *chip)
-{
-	pinctrl_unregister(chip->pctl);
-}
-
 static const struct of_device_id iproc_gpio_of_match[] = {
 static const struct of_device_id iproc_gpio_of_match[] = {
 	{ .compatible = "brcm,cygnus-ccm-gpio" },
 	{ .compatible = "brcm,cygnus-ccm-gpio" },
 	{ .compatible = "brcm,cygnus-asiu-gpio" },
 	{ .compatible = "brcm,cygnus-asiu-gpio" },
@@ -720,7 +715,7 @@ static int iproc_gpio_probe(struct platform_device *pdev)
 					   handle_simple_irq, IRQ_TYPE_NONE);
 					   handle_simple_irq, IRQ_TYPE_NONE);
 		if (ret) {
 		if (ret) {
 			dev_err(dev, "no GPIO irqchip\n");
 			dev_err(dev, "no GPIO irqchip\n");
-			goto err_unregister_pinconf;
+			goto err_rm_gpiochip;
 		}
 		}
 
 
 		gpiochip_set_chained_irqchip(gc, &iproc_gpio_irq_chip, irq,
 		gpiochip_set_chained_irqchip(gc, &iproc_gpio_irq_chip, irq,
@@ -729,9 +724,6 @@ static int iproc_gpio_probe(struct platform_device *pdev)
 
 
 	return 0;
 	return 0;
 
 
-err_unregister_pinconf:
-	iproc_gpio_unregister_pinconf(chip);
-
 err_rm_gpiochip:
 err_rm_gpiochip:
 	gpiochip_remove(gc);
 	gpiochip_remove(gc);
 
 

+ 1117 - 0
drivers/pinctrl/bcm/pinctrl-ns2-mux.c

@@ -0,0 +1,1117 @@
+/* Copyright (C) 2016 Broadcom Corporation
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This file contains the Northstar2 IOMUX driver that supports group
+ * based PINMUX configuration. The PWM is functional only when the
+ * corresponding mfio pin group is selected as gpio.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#define NS2_NUM_IOMUX			19
+#define NS2_NUM_PWM_MUX			4
+
+#define NS2_PIN_MUX_BASE0		0x00
+#define NS2_PIN_MUX_BASE1		0x01
+#define NS2_PIN_CONF_BASE		0x02
+#define NS2_MUX_PAD_FUNC1_OFFSET	0x04
+
+#define NS2_PIN_SRC_MASK		0x01
+#define NS2_PIN_PULL_MASK		0x03
+#define NS2_PIN_DRIVE_STRENGTH_MASK	0x07
+
+#define NS2_PIN_PULL_UP			0x01
+#define NS2_PIN_PULL_DOWN		0x02
+
+#define NS2_PIN_INPUT_EN_MASK		0x01
+
+/*
+ * Northstar2 IOMUX register description
+ *
+ * @base: base address number
+ * @offset: register offset for mux configuration of a group
+ * @shift: bit shift for mux configuration of a group
+ * @mask: mask bits
+ * @alt: alternate function to set to
+ */
+struct ns2_mux {
+	unsigned int base;
+	unsigned int offset;
+	unsigned int shift;
+	unsigned int mask;
+	unsigned int alt;
+};
+
+/*
+ * Keep track of Northstar2 IOMUX configuration and prevent double
+ * configuration
+ *
+ * @ns2_mux: Northstar2 IOMUX register description
+ * @is_configured: flag to indicate whether a mux setting has already
+ * been configured
+ */
+struct ns2_mux_log {
+	struct ns2_mux mux;
+	bool is_configured;
+};
+
+/*
+ * Group based IOMUX configuration
+ *
+ * @name: name of the group
+ * @pins: array of pins used by this group
+ * @num_pins: total number of pins used by this group
+ * @mux: Northstar2 group based IOMUX configuration
+ */
+struct ns2_pin_group {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned int num_pins;
+	const struct ns2_mux mux;
+};
+
+/*
+ * Northstar2 mux function and supported pin groups
+ *
+ * @name: name of the function
+ * @groups: array of groups that can be supported by this function
+ * @num_groups: total number of groups that can be supported by function
+ */
+struct ns2_pin_function {
+	const char *name;
+	const char * const *groups;
+	const unsigned int num_groups;
+};
+
+/*
+ * Northstar2 IOMUX pinctrl core
+ *
+ * @pctl: pointer to pinctrl_dev
+ * @dev: pointer to device
+ * @base0: first IOMUX register base
+ * @base1: second IOMUX register base
+ * @pinconf_base: configuration register base
+ * @groups: pointer to array of groups
+ * @num_groups: total number of groups
+ * @functions: pointer to array of functions
+ * @num_functions: total number of functions
+ * @mux_log: pointer to the array of mux logs
+ * @lock: lock to protect register access
+ */
+struct ns2_pinctrl {
+	struct pinctrl_dev *pctl;
+	struct device *dev;
+	void __iomem *base0;
+	void __iomem *base1;
+	void __iomem *pinconf_base;
+
+	const struct ns2_pin_group *groups;
+	unsigned int num_groups;
+
+	const struct ns2_pin_function *functions;
+	unsigned int num_functions;
+
+	struct ns2_mux_log *mux_log;
+
+	spinlock_t lock;
+};
+
+/*
+ * Pin configuration info
+ *
+ * @base: base address number
+ * @offset: register offset from base
+ * @src_shift: slew rate control bit shift in the register
+ * @input_en: input enable control bit shift
+ * @pull_shift: pull-up/pull-down control bit shift in the register
+ * @drive_shift: drive strength control bit shift in the register
+ */
+struct ns2_pinconf {
+	unsigned int base;
+	unsigned int offset;
+	unsigned int src_shift;
+	unsigned int input_en;
+	unsigned int pull_shift;
+	unsigned int drive_shift;
+};
+
+/*
+ * Description of a pin in Northstar2
+ *
+ * @pin: pin number
+ * @name: pin name
+ * @pin_conf: pin configuration structure
+ */
+struct ns2_pin {
+	unsigned int pin;
+	char *name;
+	struct ns2_pinconf pin_conf;
+};
+
+#define NS2_PIN_DESC(p, n, b, o, s, i, pu, d)	\
+{						\
+	.pin = p,				\
+	.name = n,				\
+	.pin_conf = {				\
+		.base = b,			\
+		.offset = o,			\
+		.src_shift = s,			\
+		.input_en = i,			\
+		.pull_shift = pu,		\
+		.drive_shift = d,		\
+	}					\
+}
+
+/*
+ * List of pins in Northstar2
+ */
+static struct ns2_pin ns2_pins[] = {
+	NS2_PIN_DESC(0, "mfio_0", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(1, "mfio_1", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(2, "mfio_2", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(3, "mfio_3", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(4, "mfio_4", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(5, "mfio_5", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(6, "mfio_6", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(7, "mfio_7", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(8, "mfio_8", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(9, "mfio_9", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(10, "mfio_10", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(11, "mfio_11", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(12, "mfio_12", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(13, "mfio_13", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(14, "mfio_14", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(15, "mfio_15", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(16, "mfio_16", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(17, "mfio_17", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(18, "mfio_18", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(19, "mfio_19", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(20, "mfio_20", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(21, "mfio_21", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(22, "mfio_22", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(23, "mfio_23", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(24, "mfio_24", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(25, "mfio_25", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(26, "mfio_26", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(27, "mfio_27", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(28, "mfio_28", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(29, "mfio_29", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(30, "mfio_30", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(31, "mfio_31", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(32, "mfio_32", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(33, "mfio_33", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(34, "mfio_34", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(35, "mfio_35", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(36, "mfio_36", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(37, "mfio_37", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(38, "mfio_38", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(39, "mfio_39", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(40, "mfio_40", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(41, "mfio_41", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(42, "mfio_42", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(43, "mfio_43", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(44, "mfio_44", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(45, "mfio_45", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(46, "mfio_46", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(47, "mfio_47", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(48, "mfio_48", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(49, "mfio_49", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(50, "mfio_50", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(51, "mfio_51", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(52, "mfio_52", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(53, "mfio_53", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(54, "mfio_54", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(55, "mfio_55", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(56, "mfio_56", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(57, "mfio_57", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(58, "mfio_58", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(59, "mfio_59", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(60, "mfio_60", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(61, "mfio_61", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(62, "mfio_62", -1, 0, 0, 0, 0, 0),
+	NS2_PIN_DESC(63, "qspi_wp", 2, 0x0, 31, 30, 27, 24),
+	NS2_PIN_DESC(64, "qspi_hold", 2, 0x0, 23, 22, 19, 16),
+	NS2_PIN_DESC(65, "qspi_cs", 2, 0x0, 15, 14, 11, 8),
+	NS2_PIN_DESC(66, "qspi_sck", 2, 0x0, 7, 6, 3, 0),
+	NS2_PIN_DESC(67, "uart3_sin", 2, 0x04, 31, 30, 27, 24),
+	NS2_PIN_DESC(68, "uart3_sout", 2, 0x04, 23, 22, 19, 16),
+	NS2_PIN_DESC(69, "qspi_mosi", 2, 0x04, 15, 14, 11, 8),
+	NS2_PIN_DESC(70, "qspi_miso", 2, 0x04, 7, 6, 3, 0),
+	NS2_PIN_DESC(71, "spi0_fss", 2, 0x08, 31, 30, 27, 24),
+	NS2_PIN_DESC(72, "spi0_rxd", 2, 0x08, 23, 22, 19, 16),
+	NS2_PIN_DESC(73, "spi0_txd", 2, 0x08, 15, 14, 11, 8),
+	NS2_PIN_DESC(74, "spi0_sck", 2, 0x08, 7, 6, 3, 0),
+	NS2_PIN_DESC(75, "spi1_fss", 2, 0x0c, 31, 30, 27, 24),
+	NS2_PIN_DESC(76, "spi1_rxd", 2, 0x0c, 23, 22, 19, 16),
+	NS2_PIN_DESC(77, "spi1_txd", 2, 0x0c, 15, 14, 11, 8),
+	NS2_PIN_DESC(78, "spi1_sck", 2, 0x0c, 7, 6, 3, 0),
+	NS2_PIN_DESC(79, "sdio0_data7", 2, 0x10, 31, 30, 27, 24),
+	NS2_PIN_DESC(80, "sdio0_emmc_rst", 2, 0x10, 23, 22, 19, 16),
+	NS2_PIN_DESC(81, "sdio0_led_on", 2, 0x10, 15, 14, 11, 8),
+	NS2_PIN_DESC(82, "sdio0_wp", 2, 0x10, 7, 6, 3, 0),
+	NS2_PIN_DESC(83, "sdio0_data3", 2, 0x14, 31, 30, 27, 24),
+	NS2_PIN_DESC(84, "sdio0_data4", 2, 0x14, 23, 22, 19, 16),
+	NS2_PIN_DESC(85, "sdio0_data5", 2, 0x14, 15, 14, 11, 8),
+	NS2_PIN_DESC(86, "sdio0_data6", 2, 0x14, 7, 6, 3, 0),
+	NS2_PIN_DESC(87, "sdio0_cmd", 2, 0x18, 31, 30, 27, 24),
+	NS2_PIN_DESC(88, "sdio0_data0", 2, 0x18, 23, 22, 19, 16),
+	NS2_PIN_DESC(89, "sdio0_data1", 2, 0x18, 15, 14, 11, 8),
+	NS2_PIN_DESC(90, "sdio0_data2", 2, 0x18, 7, 6, 3, 0),
+	NS2_PIN_DESC(91, "sdio1_led_on", 2, 0x1c, 31, 30, 27, 24),
+	NS2_PIN_DESC(92, "sdio1_wp", 2, 0x1c, 23, 22, 19, 16),
+	NS2_PIN_DESC(93, "sdio0_cd_l", 2, 0x1c, 15, 14, 11, 8),
+	NS2_PIN_DESC(94, "sdio0_clk", 2, 0x1c, 7, 6, 3, 0),
+	NS2_PIN_DESC(95, "sdio1_data5", 2, 0x20, 31, 30, 27, 24),
+	NS2_PIN_DESC(96, "sdio1_data6", 2, 0x20, 23, 22, 19, 16),
+	NS2_PIN_DESC(97, "sdio1_data7", 2, 0x20, 15, 14, 11, 8),
+	NS2_PIN_DESC(98, "sdio1_emmc_rst", 2, 0x20, 7, 6, 3, 0),
+	NS2_PIN_DESC(99, "sdio1_data1", 2, 0x24, 31, 30, 27, 24),
+	NS2_PIN_DESC(100, "sdio1_data2", 2, 0x24, 23, 22, 19, 16),
+	NS2_PIN_DESC(101, "sdio1_data3", 2, 0x24, 15, 14, 11, 8),
+	NS2_PIN_DESC(102, "sdio1_data4", 2, 0x24, 7, 6, 3, 0),
+	NS2_PIN_DESC(103, "sdio1_cd_l", 2, 0x28, 31, 30, 27, 24),
+	NS2_PIN_DESC(104, "sdio1_clk", 2, 0x28, 23, 22, 19, 16),
+	NS2_PIN_DESC(105, "sdio1_cmd", 2, 0x28, 15, 14, 11, 8),
+	NS2_PIN_DESC(106, "sdio1_data0", 2, 0x28, 7, 6, 3, 0),
+	NS2_PIN_DESC(107, "ext_mdio_0", 2, 0x2c, 15, 14, 11, 8),
+	NS2_PIN_DESC(108, "ext_mdc_0", 2, 0x2c, 7, 6, 3, 0),
+	NS2_PIN_DESC(109, "usb3_p1_vbus_ppc", 2, 0x34, 31, 30, 27, 24),
+	NS2_PIN_DESC(110, "usb3_p1_overcurrent", 2, 0x34, 23, 22, 19, 16),
+	NS2_PIN_DESC(111, "usb3_p0_vbus_ppc", 2, 0x34, 15, 14, 11, 8),
+	NS2_PIN_DESC(112, "usb3_p0_overcurrent", 2, 0x34, 7, 6, 3, 0),
+	NS2_PIN_DESC(113, "usb2_presence_indication", 2, 0x38, 31, 30, 27, 24),
+	NS2_PIN_DESC(114, "usb2_vbus_present", 2, 0x38, 23, 22, 19, 16),
+	NS2_PIN_DESC(115, "usb2_vbus_ppc", 2, 0x38, 15, 14, 11, 8),
+	NS2_PIN_DESC(116, "usb2_overcurrent", 2, 0x38, 7, 6, 3, 0),
+	NS2_PIN_DESC(117, "sata_led1", 2, 0x3c, 15, 14, 11, 8),
+	NS2_PIN_DESC(118, "sata_led0", 2, 0x3c, 7, 6, 3, 0),
+};
+
+/*
+ * List of groups of pins
+ */
+
+static const unsigned int nand_pins[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+	11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
+static const unsigned int nor_data_pins[] =  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+	10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
+
+static const unsigned int gpio_0_1_pins[] = {24, 25};
+static const unsigned int pwm_0_pins[] = {24};
+static const unsigned int pwm_1_pins[] = {25};
+
+static const unsigned int uart1_ext_clk_pins[] = {26};
+static const unsigned int nor_adv_pins[] = {26};
+
+static const unsigned int gpio_2_5_pins[] = {27, 28, 29, 30};
+static const unsigned int pcie_ab1_clk_wak_pins[] = {27, 28, 29, 30};
+static const unsigned int nor_addr_0_3_pins[] = {27, 28, 29, 30};
+static const unsigned int pwm_2_pins[] = {27};
+static const unsigned int pwm_3_pins[] = {28};
+
+static const unsigned int gpio_6_7_pins[] = {31, 32};
+static const unsigned int pcie_a3_clk_wak_pins[] = {31, 32};
+static const unsigned int nor_addr_4_5_pins[] = {31, 32};
+
+static const unsigned int gpio_8_9_pins[] = {33, 34};
+static const unsigned int pcie_b3_clk_wak_pins[] = {33, 34};
+static const unsigned int nor_addr_6_7_pins[] = {33, 34};
+
+static const unsigned int gpio_10_11_pins[] = {35, 36};
+static const unsigned int pcie_b2_clk_wak_pins[] = {35, 36};
+static const unsigned int nor_addr_8_9_pins[] = {35, 36};
+
+static const unsigned int gpio_12_13_pins[] = {37, 38};
+static const unsigned int pcie_a2_clk_wak_pins[] = {37, 38};
+static const unsigned int nor_addr_10_11_pins[] = {37, 38};
+
+static const unsigned int gpio_14_17_pins[] = {39, 40, 41, 42};
+static const unsigned int uart0_modem_pins[] = {39, 40, 41, 42};
+static const unsigned int nor_addr_12_15_pins[] = {39, 40, 41, 42};
+
+static const unsigned int gpio_18_19_pins[] = {43, 44};
+static const unsigned int uart0_rts_cts_pins[] = {43, 44};
+
+static const unsigned int gpio_20_21_pins[] = {45, 46};
+static const unsigned int uart0_in_out_pins[] = {45, 46};
+
+static const unsigned int gpio_22_23_pins[] = {47, 48};
+static const unsigned int uart1_dcd_dsr_pins[] = {47, 48};
+
+static const unsigned int gpio_24_25_pins[] = {49, 50};
+static const unsigned int uart1_ri_dtr_pins[] = {49, 50};
+
+static const unsigned int gpio_26_27_pins[] = {51, 52};
+static const unsigned int uart1_rts_cts_pins[] = {51, 52};
+
+static const unsigned int gpio_28_29_pins[] = {53, 54};
+static const unsigned int uart1_in_out_pins[] = {53, 54};
+
+static const unsigned int gpio_30_31_pins[] = {55, 56};
+static const unsigned int uart2_rts_cts_pins[] = {55, 56};
+
+#define NS2_PIN_GROUP(group_name, ba, off, sh, ma, al)	\
+{							\
+	.name = __stringify(group_name) "_grp",		\
+	.pins = group_name ## _pins,			\
+	.num_pins = ARRAY_SIZE(group_name ## _pins),	\
+	.mux = {					\
+		.base = ba,				\
+		.offset = off,				\
+		.shift = sh,				\
+		.mask = ma,				\
+		.alt = al,				\
+	}						\
+}
+
+/*
+ * List of Northstar2 pin groups
+ */
+static const struct ns2_pin_group ns2_pin_groups[] = {
+	NS2_PIN_GROUP(nand, 0, 0, 31, 1, 0),
+	NS2_PIN_GROUP(nor_data, 0, 0, 31, 1, 1),
+	NS2_PIN_GROUP(gpio_0_1, 0, 0, 31, 1, 0),
+
+	NS2_PIN_GROUP(uart1_ext_clk, 0, 4, 30, 3, 1),
+	NS2_PIN_GROUP(nor_adv, 0, 4, 30, 3, 2),
+
+	NS2_PIN_GROUP(gpio_2_5,	0, 4, 28, 3, 0),
+	NS2_PIN_GROUP(pcie_ab1_clk_wak, 0, 4, 28, 3, 1),
+	NS2_PIN_GROUP(nor_addr_0_3, 0, 4, 28, 3, 2),
+
+	NS2_PIN_GROUP(gpio_6_7, 0, 4, 26, 3, 0),
+	NS2_PIN_GROUP(pcie_a3_clk_wak, 0, 4, 26, 3, 1),
+	NS2_PIN_GROUP(nor_addr_4_5, 0, 4, 26, 3, 2),
+
+	NS2_PIN_GROUP(gpio_8_9, 0, 4, 24, 3, 0),
+	NS2_PIN_GROUP(pcie_b3_clk_wak, 0, 4, 24, 3, 1),
+	NS2_PIN_GROUP(nor_addr_6_7, 0, 4, 24, 3, 2),
+
+	NS2_PIN_GROUP(gpio_10_11, 0, 4, 22, 3, 0),
+	NS2_PIN_GROUP(pcie_b2_clk_wak, 0, 4, 22, 3, 1),
+	NS2_PIN_GROUP(nor_addr_8_9, 0, 4, 22, 3, 2),
+
+	NS2_PIN_GROUP(gpio_12_13, 0, 4, 20, 3, 0),
+	NS2_PIN_GROUP(pcie_a2_clk_wak, 0, 4, 20, 3, 1),
+	NS2_PIN_GROUP(nor_addr_10_11, 0, 4, 20, 3, 2),
+
+	NS2_PIN_GROUP(gpio_14_17, 0, 4, 18, 3, 0),
+	NS2_PIN_GROUP(uart0_modem, 0, 4, 18, 3, 1),
+	NS2_PIN_GROUP(nor_addr_12_15, 0, 4, 18, 3, 2),
+
+	NS2_PIN_GROUP(gpio_18_19, 0, 4, 16, 3, 0),
+	NS2_PIN_GROUP(uart0_rts_cts, 0, 4, 16, 3, 1),
+
+	NS2_PIN_GROUP(gpio_20_21, 0, 4, 14, 3, 0),
+	NS2_PIN_GROUP(uart0_in_out, 0, 4, 14, 3, 1),
+
+	NS2_PIN_GROUP(gpio_22_23, 0, 4, 12, 3, 0),
+	NS2_PIN_GROUP(uart1_dcd_dsr, 0, 4, 12, 3, 1),
+
+	NS2_PIN_GROUP(gpio_24_25, 0, 4, 10, 3, 0),
+	NS2_PIN_GROUP(uart1_ri_dtr, 0, 4, 10, 3, 1),
+
+	NS2_PIN_GROUP(gpio_26_27, 0, 4, 8, 3, 0),
+	NS2_PIN_GROUP(uart1_rts_cts, 0, 4, 8, 3, 1),
+
+	NS2_PIN_GROUP(gpio_28_29, 0, 4, 6, 3, 0),
+	NS2_PIN_GROUP(uart1_in_out, 0, 4, 6, 3, 1),
+
+	NS2_PIN_GROUP(gpio_30_31, 0, 4, 4, 3, 0),
+	NS2_PIN_GROUP(uart2_rts_cts, 0, 4, 4, 3, 1),
+
+	NS2_PIN_GROUP(pwm_0, 1, 0, 0, 1, 1),
+	NS2_PIN_GROUP(pwm_1, 1, 0, 1, 1, 1),
+	NS2_PIN_GROUP(pwm_2, 1, 0, 2, 1, 1),
+	NS2_PIN_GROUP(pwm_3, 1, 0, 3, 1, 1),
+};
+
+/*
+ * List of groups supported by functions
+ */
+
+static const char * const nand_grps[] = {"nand_grp"};
+
+static const char * const nor_grps[] = {"nor_data_grp", "nor_adv_grp",
+	"nor_addr_0_3_grp", "nor_addr_4_5_grp",	"nor_addr_6_7_grp",
+	"nor_addr_8_9_grp", "nor_addr_10_11_grp", "nor_addr_12_15_grp"};
+
+static const char * const gpio_grps[] = {"gpio_0_1_grp", "gpio_2_5_grp",
+	"gpio_6_7_grp",	"gpio_8_9_grp",	"gpio_10_11_grp", "gpio_12_13_grp",
+	"gpio_14_17_grp", "gpio_18_19_grp", "gpio_20_21_grp", "gpio_22_23_grp",
+	"gpio_24_25_grp", "gpio_26_27_grp", "gpio_28_29_grp",
+	"gpio_30_31_grp"};
+
+static const char * const pcie_grps[] = {"pcie_ab1_clk_wak_grp",
+	"pcie_a3_clk_wak_grp", "pcie_b3_clk_wak_grp", "pcie_b2_clk_wak_grp",
+	"pcie_a2_clk_wak_grp"};
+
+static const char * const uart0_grps[] = {"uart0_modem_grp",
+	"uart0_rts_cts_grp", "uart0_in_out_grp"};
+
+static const char * const uart1_grps[] = {"uart1_ext_clk_grp",
+	"uart1_dcd_dsr_grp", "uart1_ri_dtr_grp", "uart1_rts_cts_grp",
+	"uart1_in_out_grp"};
+
+static const char * const uart2_grps[] = {"uart2_rts_cts_grp"};
+
+static const char * const pwm_grps[] = {"pwm_0_grp", "pwm_1_grp",
+	"pwm_2_grp", "pwm_3_grp"};
+
+#define NS2_PIN_FUNCTION(func)				\
+{							\
+	.name = #func,					\
+	.groups = func ## _grps,			\
+	.num_groups = ARRAY_SIZE(func ## _grps),	\
+}
+
+/*
+ * List of supported functions
+ */
+static const struct ns2_pin_function ns2_pin_functions[] = {
+	NS2_PIN_FUNCTION(nand),
+	NS2_PIN_FUNCTION(nor),
+	NS2_PIN_FUNCTION(gpio),
+	NS2_PIN_FUNCTION(pcie),
+	NS2_PIN_FUNCTION(uart0),
+	NS2_PIN_FUNCTION(uart1),
+	NS2_PIN_FUNCTION(uart2),
+	NS2_PIN_FUNCTION(pwm),
+};
+
+static int ns2_get_groups_count(struct pinctrl_dev *pctrl_dev)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+	return pinctrl->num_groups;
+}
+
+static const char *ns2_get_group_name(struct pinctrl_dev *pctrl_dev,
+				      unsigned int selector)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+	return pinctrl->groups[selector].name;
+}
+
+static int ns2_get_group_pins(struct pinctrl_dev *pctrl_dev,
+			      unsigned int selector, const unsigned int **pins,
+			      unsigned int *num_pins)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+	*pins = pinctrl->groups[selector].pins;
+	*num_pins = pinctrl->groups[selector].num_pins;
+
+	return 0;
+}
+
+static void ns2_pin_dbg_show(struct pinctrl_dev *pctrl_dev,
+			     struct seq_file *s, unsigned int offset)
+{
+	seq_printf(s, " %s", dev_name(pctrl_dev->dev));
+}
+
+static struct pinctrl_ops ns2_pinctrl_ops = {
+	.get_groups_count = ns2_get_groups_count,
+	.get_group_name = ns2_get_group_name,
+	.get_group_pins = ns2_get_group_pins,
+	.pin_dbg_show = ns2_pin_dbg_show,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+	.dt_free_map = pinctrl_utils_free_map,
+};
+
+static int ns2_get_functions_count(struct pinctrl_dev *pctrl_dev)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+	return pinctrl->num_functions;
+}
+
+static const char *ns2_get_function_name(struct pinctrl_dev *pctrl_dev,
+					 unsigned int selector)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+	return pinctrl->functions[selector].name;
+}
+
+static int ns2_get_function_groups(struct pinctrl_dev *pctrl_dev,
+				   unsigned int selector,
+				   const char * const **groups,
+				   unsigned int * const num_groups)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+
+	*groups = pinctrl->functions[selector].groups;
+	*num_groups = pinctrl->functions[selector].num_groups;
+
+	return 0;
+}
+
+static int ns2_pinmux_set(struct ns2_pinctrl *pinctrl,
+			  const struct ns2_pin_function *func,
+			  const struct ns2_pin_group *grp,
+			  struct ns2_mux_log *mux_log)
+{
+	const struct ns2_mux *mux = &grp->mux;
+	int i;
+	u32 val, mask;
+	unsigned long flags;
+	void __iomem *base_address;
+
+	for (i = 0; i < NS2_NUM_IOMUX; i++) {
+		if ((mux->shift != mux_log[i].mux.shift) ||
+			(mux->base != mux_log[i].mux.base) ||
+			(mux->offset != mux_log[i].mux.offset))
+			continue;
+
+		/* if this is a new configuration, just do it! */
+		if (!mux_log[i].is_configured)
+			break;
+
+		/*
+		 * IOMUX has been configured previously and one is trying to
+		 * configure it to a different function
+		 */
+		if (mux_log[i].mux.alt != mux->alt) {
+			dev_err(pinctrl->dev,
+				"double configuration error detected!\n");
+			dev_err(pinctrl->dev, "func:%s grp:%s\n",
+				func->name, grp->name);
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+	if (i == NS2_NUM_IOMUX)
+		return -EINVAL;
+
+	mask = mux->mask;
+	mux_log[i].mux.alt = mux->alt;
+	mux_log[i].is_configured = true;
+
+	switch (mux->base) {
+	case NS2_PIN_MUX_BASE0:
+		base_address = pinctrl->base0;
+		break;
+
+	case NS2_PIN_MUX_BASE1:
+		base_address = pinctrl->base1;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	val = readl(base_address + grp->mux.offset);
+	val &= ~(mask << grp->mux.shift);
+	val |= grp->mux.alt << grp->mux.shift;
+	writel(val, (base_address + grp->mux.offset));
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+	return 0;
+}
+
+static int ns2_pinmux_enable(struct pinctrl_dev *pctrl_dev,
+			     unsigned int func_select, unsigned int grp_select)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+	const struct ns2_pin_function *func;
+	const struct ns2_pin_group *grp;
+
+	if (grp_select > pinctrl->num_groups ||
+		func_select > pinctrl->num_functions)
+		return -EINVAL;
+
+	func = &pinctrl->functions[func_select];
+	grp = &pinctrl->groups[grp_select];
+
+	dev_dbg(pctrl_dev->dev, "func:%u name:%s grp:%u name:%s\n",
+		func_select, func->name, grp_select, grp->name);
+
+	dev_dbg(pctrl_dev->dev, "offset:0x%08x shift:%u alt:%u\n",
+		grp->mux.offset, grp->mux.shift, grp->mux.alt);
+
+	return ns2_pinmux_set(pinctrl, func, grp, pinctrl->mux_log);
+}
+
+static int ns2_pin_set_enable(struct pinctrl_dev *pctrldev, unsigned int pin,
+			    u16 enable)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	unsigned long flags;
+	u32 val;
+	void __iomem *base_address;
+
+	base_address = pinctrl->pinconf_base;
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	val = readl(base_address + pin_data->pin_conf.offset);
+	val &= ~(NS2_PIN_SRC_MASK << pin_data->pin_conf.input_en);
+
+	if (!enable)
+		val |= NS2_PIN_INPUT_EN_MASK << pin_data->pin_conf.input_en;
+
+	writel(val, (base_address + pin_data->pin_conf.offset));
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+	dev_dbg(pctrldev->dev, "pin:%u set enable:%d\n", pin, enable);
+	return 0;
+}
+
+static int ns2_pin_get_enable(struct pinctrl_dev *pctrldev, unsigned int pin)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	unsigned long flags;
+	int enable;
+
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	enable = readl(pinctrl->pinconf_base + pin_data->pin_conf.offset);
+	enable = (enable >> pin_data->pin_conf.input_en) &
+			NS2_PIN_INPUT_EN_MASK;
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+	if (!enable)
+		enable = NS2_PIN_INPUT_EN_MASK;
+	else
+		enable = 0;
+
+	dev_dbg(pctrldev->dev, "pin:%u get disable:%d\n", pin, enable);
+	return enable;
+}
+
+static int ns2_pin_set_slew(struct pinctrl_dev *pctrldev, unsigned int pin,
+			    u16 slew)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	unsigned long flags;
+	u32 val;
+	void __iomem *base_address;
+
+	base_address = pinctrl->pinconf_base;
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	val = readl(base_address + pin_data->pin_conf.offset);
+	val &= ~(NS2_PIN_SRC_MASK << pin_data->pin_conf.src_shift);
+
+	if (slew)
+		val |= NS2_PIN_SRC_MASK << pin_data->pin_conf.src_shift;
+
+	writel(val, (base_address + pin_data->pin_conf.offset));
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+	dev_dbg(pctrldev->dev, "pin:%u set slew:%d\n", pin, slew);
+	return 0;
+}
+
+static int ns2_pin_get_slew(struct pinctrl_dev *pctrldev, unsigned int pin,
+			    u16 *slew)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	val = readl(pinctrl->pinconf_base + pin_data->pin_conf.offset);
+	*slew = (val >> pin_data->pin_conf.src_shift) & NS2_PIN_SRC_MASK;
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+	dev_dbg(pctrldev->dev, "pin:%u get slew:%d\n", pin, *slew);
+	return 0;
+}
+
+static int ns2_pin_set_pull(struct pinctrl_dev *pctrldev, unsigned int pin,
+			    bool pull_up, bool pull_down)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	unsigned long flags;
+	u32 val;
+	void __iomem *base_address;
+
+	base_address = pinctrl->pinconf_base;
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	val = readl(base_address + pin_data->pin_conf.offset);
+	val &= ~(NS2_PIN_PULL_MASK << pin_data->pin_conf.pull_shift);
+
+	if (pull_up == true)
+		val |= NS2_PIN_PULL_UP << pin_data->pin_conf.pull_shift;
+	if (pull_down == true)
+		val |= NS2_PIN_PULL_DOWN << pin_data->pin_conf.pull_shift;
+	writel(val, (base_address + pin_data->pin_conf.offset));
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+	dev_dbg(pctrldev->dev, "pin:%u set pullup:%d pulldown: %d\n",
+		pin, pull_up, pull_down);
+	return 0;
+}
+
+static void ns2_pin_get_pull(struct pinctrl_dev *pctrldev,
+			     unsigned int pin, bool *pull_up,
+			     bool *pull_down)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	val = readl(pinctrl->pinconf_base + pin_data->pin_conf.offset);
+	val = (val >> pin_data->pin_conf.pull_shift) & NS2_PIN_PULL_MASK;
+	*pull_up = false;
+	*pull_down = false;
+
+	if (val == NS2_PIN_PULL_UP)
+		*pull_up = true;
+
+	if (val == NS2_PIN_PULL_DOWN)
+		*pull_down = true;
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+}
+
+static int ns2_pin_set_strength(struct pinctrl_dev *pctrldev, unsigned int pin,
+				u16 strength)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	u32 val;
+	unsigned long flags;
+	void __iomem *base_address;
+
+	/* make sure drive strength is supported */
+	if (strength < 2 || strength > 16 || (strength % 2))
+		return -ENOTSUPP;
+
+	base_address = pinctrl->pinconf_base;
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	val = readl(base_address + pin_data->pin_conf.offset);
+	val &= ~(NS2_PIN_DRIVE_STRENGTH_MASK << pin_data->pin_conf.drive_shift);
+	val |= ((strength / 2) - 1) << pin_data->pin_conf.drive_shift;
+	writel(val, (base_address + pin_data->pin_conf.offset));
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+	dev_dbg(pctrldev->dev, "pin:%u set drive strength:%d mA\n",
+		pin, strength);
+	return 0;
+}
+
+static int ns2_pin_get_strength(struct pinctrl_dev *pctrldev, unsigned int pin,
+				 u16 *strength)
+{
+	struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pinctrl->lock, flags);
+	val = readl(pinctrl->pinconf_base + pin_data->pin_conf.offset);
+	*strength = (val >> pin_data->pin_conf.drive_shift) &
+					NS2_PIN_DRIVE_STRENGTH_MASK;
+	*strength = (*strength + 1) * 2;
+	spin_unlock_irqrestore(&pinctrl->lock, flags);
+
+	dev_dbg(pctrldev->dev, "pin:%u get drive strength:%d mA\n",
+		pin, *strength);
+	return 0;
+}
+
+static int ns2_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
+			      unsigned long *config)
+{
+	struct ns2_pin *pin_data = pctldev->desc->pins[pin].drv_data;
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	bool pull_up, pull_down;
+	u16 arg = 0;
+	int ret;
+
+	if (pin_data->pin_conf.base == -1)
+		return -ENOTSUPP;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		ns2_pin_get_pull(pctldev, pin, &pull_up, &pull_down);
+		if ((pull_up == false) && (pull_down == false))
+			return 0;
+		else
+			return -EINVAL;
+
+	case PIN_CONFIG_BIAS_PULL_UP:
+		ns2_pin_get_pull(pctldev, pin, &pull_up, &pull_down);
+		if (pull_up)
+			return 0;
+		else
+			return -EINVAL;
+
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		ns2_pin_get_pull(pctldev, pin, &pull_up, &pull_down);
+		if (pull_down)
+			return 0;
+		else
+			return -EINVAL;
+
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		ret = ns2_pin_get_strength(pctldev, pin, &arg);
+		if (ret)
+			return ret;
+		*config = pinconf_to_config_packed(param, arg);
+		return 0;
+
+	case PIN_CONFIG_SLEW_RATE:
+		ret = ns2_pin_get_slew(pctldev, pin, &arg);
+		if (ret)
+			return ret;
+		*config = pinconf_to_config_packed(param, arg);
+		return 0;
+
+	case PIN_CONFIG_INPUT_ENABLE:
+		ret = ns2_pin_get_enable(pctldev, pin);
+		if (ret)
+			return 0;
+		else
+			return -EINVAL;
+
+	default:
+		return -ENOTSUPP;
+	}
+}
+
+static int ns2_pin_config_set(struct pinctrl_dev *pctrldev, unsigned int pin,
+			      unsigned long *configs, unsigned int num_configs)
+{
+	struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
+	enum pin_config_param param;
+	unsigned int i;
+	u16 arg;
+	int ret = -ENOTSUPP;
+
+	if (pin_data->pin_conf.base == -1)
+		return -ENOTSUPP;
+
+	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:
+			ret = ns2_pin_set_pull(pctrldev, pin, false, false);
+			if (ret < 0)
+				goto out;
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_UP:
+			ret = ns2_pin_set_pull(pctrldev, pin, true, false);
+			if (ret < 0)
+				goto out;
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			ret = ns2_pin_set_pull(pctrldev, pin, false, true);
+			if (ret < 0)
+				goto out;
+			break;
+
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			ret = ns2_pin_set_strength(pctrldev, pin, arg);
+			if (ret < 0)
+				goto out;
+			break;
+
+		case PIN_CONFIG_SLEW_RATE:
+			ret = ns2_pin_set_slew(pctrldev, pin, arg);
+			if (ret < 0)
+				goto out;
+			break;
+
+		case PIN_CONFIG_INPUT_ENABLE:
+			ret = ns2_pin_set_enable(pctrldev, pin, arg);
+			if (ret < 0)
+				goto out;
+			break;
+
+		default:
+			dev_err(pctrldev->dev, "invalid configuration\n");
+			return -ENOTSUPP;
+		}
+	}
+out:
+	return ret;
+}
+static struct pinmux_ops ns2_pinmux_ops = {
+	.get_functions_count = ns2_get_functions_count,
+	.get_function_name = ns2_get_function_name,
+	.get_function_groups = ns2_get_function_groups,
+	.set_mux = ns2_pinmux_enable,
+};
+
+static const struct pinconf_ops ns2_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_get = ns2_pin_config_get,
+	.pin_config_set = ns2_pin_config_set,
+};
+
+static struct pinctrl_desc ns2_pinctrl_desc = {
+	.name = "ns2-pinmux",
+	.pctlops = &ns2_pinctrl_ops,
+	.pmxops = &ns2_pinmux_ops,
+	.confops = &ns2_pinconf_ops,
+};
+
+static int ns2_mux_log_init(struct ns2_pinctrl *pinctrl)
+{
+	struct ns2_mux_log *log;
+	unsigned int i;
+
+	pinctrl->mux_log = devm_kcalloc(pinctrl->dev, NS2_NUM_IOMUX,
+					sizeof(struct ns2_mux_log),
+					GFP_KERNEL);
+	if (!pinctrl->mux_log)
+		return -ENOMEM;
+
+	for (i = 0; i < NS2_NUM_IOMUX; i++)
+		pinctrl->mux_log[i].is_configured = false;
+	/* Group 0 uses bit 31 in the IOMUX_PAD_FUNCTION_0 register */
+	log = &pinctrl->mux_log[0];
+	log->mux.base = NS2_PIN_MUX_BASE0;
+	log->mux.offset = 0;
+	log->mux.shift = 31;
+	log->mux.alt = 0;
+
+	/*
+	 * Groups 1 through 14 use two bits each in the
+	 * IOMUX_PAD_FUNCTION_1 register starting with
+	 * bit position 30.
+	 */
+	for (i = 1; i < (NS2_NUM_IOMUX - NS2_NUM_PWM_MUX); i++) {
+		log = &pinctrl->mux_log[i];
+		log->mux.base = NS2_PIN_MUX_BASE0;
+		log->mux.offset = NS2_MUX_PAD_FUNC1_OFFSET;
+		log->mux.shift = 32 - (i * 2);
+		log->mux.alt = 0;
+	}
+
+	/*
+	 * Groups 15 through 18 use one bit each in the
+	 * AUX_SEL register.
+	 */
+	for (i = 0; i < NS2_NUM_PWM_MUX; i++) {
+		log = &pinctrl->mux_log[(NS2_NUM_IOMUX - NS2_NUM_PWM_MUX) + i];
+		log->mux.base = NS2_PIN_MUX_BASE1;
+		log->mux.offset = 0;
+		log->mux.shift = i;
+		log->mux.alt =  0;
+	}
+	return 0;
+}
+
+static int ns2_pinmux_probe(struct platform_device *pdev)
+{
+	struct ns2_pinctrl *pinctrl;
+	struct resource *res;
+	int i, ret;
+	struct pinctrl_pin_desc *pins;
+	unsigned int num_pins = ARRAY_SIZE(ns2_pins);
+
+	pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL);
+	if (!pinctrl)
+		return -ENOMEM;
+
+	pinctrl->dev = &pdev->dev;
+	platform_set_drvdata(pdev, pinctrl);
+	spin_lock_init(&pinctrl->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pinctrl->base0 = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pinctrl->base0)) {
+		dev_err(&pdev->dev, "unable to map I/O space\n");
+		return PTR_ERR(pinctrl->base0);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	pinctrl->base1 = devm_ioremap_nocache(&pdev->dev, res->start,
+					resource_size(res));
+	if (!pinctrl->base1) {
+		dev_err(&pdev->dev, "unable to map I/O space\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	pinctrl->pinconf_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pinctrl->pinconf_base)) {
+		dev_err(&pdev->dev, "unable to map I/O space\n");
+		return PTR_ERR(pinctrl->pinconf_base);
+	}
+
+	ret = ns2_mux_log_init(pinctrl);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to initialize IOMUX log\n");
+		return ret;
+	}
+
+	pins = devm_kcalloc(&pdev->dev, num_pins, sizeof(*pins), GFP_KERNEL);
+	if (!pins)
+		return -ENOMEM;
+
+	for (i = 0; i < num_pins; i++) {
+		pins[i].number = ns2_pins[i].pin;
+		pins[i].name = ns2_pins[i].name;
+		pins[i].drv_data = &ns2_pins[i];
+	}
+
+	pinctrl->groups = ns2_pin_groups;
+	pinctrl->num_groups = ARRAY_SIZE(ns2_pin_groups);
+	pinctrl->functions = ns2_pin_functions;
+	pinctrl->num_functions = ARRAY_SIZE(ns2_pin_functions);
+	ns2_pinctrl_desc.pins = pins;
+	ns2_pinctrl_desc.npins = num_pins;
+
+	pinctrl->pctl = pinctrl_register(&ns2_pinctrl_desc, &pdev->dev,
+			pinctrl);
+	if (!pinctrl->pctl) {
+		dev_err(&pdev->dev, "unable to register IOMUX pinctrl\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id ns2_pinmux_of_match[] = {
+	{.compatible = "brcm,ns2-pinmux"},
+	{ }
+};
+
+static struct platform_driver ns2_pinmux_driver = {
+	.driver = {
+		.name = "ns2-pinmux",
+		.of_match_table = ns2_pinmux_of_match,
+	},
+	.probe = ns2_pinmux_probe,
+};
+
+static int __init ns2_pinmux_init(void)
+{
+	return platform_driver_register(&ns2_pinmux_driver);
+}
+arch_initcall(ns2_pinmux_init);

+ 2 - 2
drivers/pinctrl/bcm/pinctrl-nsp-gpio.c

@@ -363,7 +363,7 @@ static const struct pinctrl_ops nsp_pctrl_ops = {
 	.get_groups_count = nsp_get_groups_count,
 	.get_groups_count = nsp_get_groups_count,
 	.get_group_name = nsp_get_group_name,
 	.get_group_name = nsp_get_group_name,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u16 slew)
 static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u16 slew)
@@ -609,7 +609,7 @@ static int nsp_gpio_register_pinconf(struct nsp_gpio *chip)
 	pctldesc->npins = gc->ngpio;
 	pctldesc->npins = gc->ngpio;
 	pctldesc->confops = &nsp_pconf_ops;
 	pctldesc->confops = &nsp_pconf_ops;
 
 
-	chip->pctl = pinctrl_register(pctldesc, chip->dev, chip);
+	chip->pctl = devm_pinctrl_register(chip->dev, pctldesc, chip);
 	if (IS_ERR(chip->pctl)) {
 	if (IS_ERR(chip->pctl)) {
 		dev_err(chip->dev, "unable to register pinctrl device\n");
 		dev_err(chip->dev, "unable to register pinctrl device\n");
 		return PTR_ERR(chip->pctl);
 		return PTR_ERR(chip->pctl);

+ 3 - 2
drivers/pinctrl/berlin/berlin.c

@@ -104,7 +104,7 @@ static const struct pinctrl_ops berlin_pinctrl_ops = {
 	.get_groups_count	= &berlin_pinctrl_get_group_count,
 	.get_groups_count	= &berlin_pinctrl_get_group_count,
 	.get_group_name		= &berlin_pinctrl_get_group_name,
 	.get_group_name		= &berlin_pinctrl_get_group_name,
 	.dt_node_to_map		= &berlin_pinctrl_dt_node_to_map,
 	.dt_node_to_map		= &berlin_pinctrl_dt_node_to_map,
-	.dt_free_map		= &pinctrl_utils_dt_free_map,
+	.dt_free_map		= &pinctrl_utils_free_map,
 };
 };
 
 
 static int berlin_pinmux_get_functions_count(struct pinctrl_dev *pctrl_dev)
 static int berlin_pinmux_get_functions_count(struct pinctrl_dev *pctrl_dev)
@@ -316,7 +316,8 @@ int berlin_pinctrl_probe_regmap(struct platform_device *pdev,
 		return ret;
 		return ret;
 	}
 	}
 
 
-	pctrl->pctrl_dev = pinctrl_register(&berlin_pctrl_desc, dev, pctrl);
+	pctrl->pctrl_dev = devm_pinctrl_register(dev, &berlin_pctrl_desc,
+						 pctrl);
 	if (IS_ERR(pctrl->pctrl_dev)) {
 	if (IS_ERR(pctrl->pctrl_dev)) {
 		dev_err(dev, "failed to register pinctrl driver\n");
 		dev_err(dev, "failed to register pinctrl driver\n");
 		return PTR_ERR(pctrl->pctrl_dev);
 		return PTR_ERR(pctrl->pctrl_dev);

+ 63 - 0
drivers/pinctrl/core.c

@@ -1872,6 +1872,69 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
 }
 }
 EXPORT_SYMBOL_GPL(pinctrl_unregister);
 EXPORT_SYMBOL_GPL(pinctrl_unregister);
 
 
+static void devm_pinctrl_dev_release(struct device *dev, void *res)
+{
+	struct pinctrl_dev *pctldev = *(struct pinctrl_dev **)res;
+
+	pinctrl_unregister(pctldev);
+}
+
+static int devm_pinctrl_dev_match(struct device *dev, void *res, void *data)
+{
+	struct pctldev **r = res;
+
+	if (WARN_ON(!r || !*r))
+		return 0;
+
+	return *r == data;
+}
+
+/**
+ * devm_pinctrl_register() - Resource managed version of pinctrl_register().
+ * @dev: parent device for this pin controller
+ * @pctldesc: descriptor for this pin controller
+ * @driver_data: private pin controller data for this pin controller
+ *
+ * Returns an error pointer if pincontrol register failed. Otherwise
+ * it returns valid pinctrl handle.
+ *
+ * The pinctrl device will be automatically released when the device is unbound.
+ */
+struct pinctrl_dev *devm_pinctrl_register(struct device *dev,
+					  struct pinctrl_desc *pctldesc,
+					  void *driver_data)
+{
+	struct pinctrl_dev **ptr, *pctldev;
+
+	ptr = devres_alloc(devm_pinctrl_dev_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	pctldev = pinctrl_register(pctldesc, dev, driver_data);
+	if (IS_ERR(pctldev)) {
+		devres_free(ptr);
+		return pctldev;
+	}
+
+	*ptr = pctldev;
+	devres_add(dev, ptr);
+
+	return pctldev;
+}
+EXPORT_SYMBOL_GPL(devm_pinctrl_register);
+
+/**
+ * devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister().
+ * @dev: device for which which resource was allocated
+ * @pctldev: the pinctrl device to unregister.
+ */
+void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev)
+{
+	WARN_ON(devres_release(dev, devm_pinctrl_dev_release,
+			       devm_pinctrl_dev_match, pctldev));
+}
+EXPORT_SYMBOL_GPL(devm_pinctrl_unregister);
+
 static int __init pinctrl_init(void)
 static int __init pinctrl_init(void)
 {
 {
 	pr_info("initialized pinctrl subsystem\n");
 	pr_info("initialized pinctrl subsystem\n");

+ 1 - 10
drivers/pinctrl/freescale/pinctrl-imx.c

@@ -789,7 +789,7 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 	ipctl->info = info;
 	ipctl->info = info;
 	ipctl->dev = info->dev;
 	ipctl->dev = info->dev;
 	platform_set_drvdata(pdev, ipctl);
 	platform_set_drvdata(pdev, ipctl);
-	ipctl->pctl = pinctrl_register(&imx_pinctrl_desc, &pdev->dev, ipctl);
+	ipctl->pctl = devm_pinctrl_register(&pdev->dev, &imx_pinctrl_desc, ipctl);
 	if (IS_ERR(ipctl->pctl)) {
 	if (IS_ERR(ipctl->pctl)) {
 		dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
 		dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
 		return PTR_ERR(ipctl->pctl);
 		return PTR_ERR(ipctl->pctl);
@@ -799,12 +799,3 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 
 
 	return 0;
 	return 0;
 }
 }
-
-int imx_pinctrl_remove(struct platform_device *pdev)
-{
-	struct imx_pinctrl *ipctl = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(ipctl->pctl);
-
-	return 0;
-}

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx.h

@@ -99,5 +99,4 @@ struct imx_pinctrl_soc_info {
 
 
 int imx_pinctrl_probe(struct platform_device *pdev,
 int imx_pinctrl_probe(struct platform_device *pdev,
 			struct imx_pinctrl_soc_info *info);
 			struct imx_pinctrl_soc_info *info);
-int imx_pinctrl_remove(struct platform_device *pdev);
 #endif /* __DRIVERS_PINCTRL_IMX_H */
 #endif /* __DRIVERS_PINCTRL_IMX_H */

+ 1 - 10
drivers/pinctrl/freescale/pinctrl-imx1-core.c

@@ -635,7 +635,7 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev,
 	ipctl->info = info;
 	ipctl->info = info;
 	ipctl->dev = info->dev;
 	ipctl->dev = info->dev;
 	platform_set_drvdata(pdev, ipctl);
 	platform_set_drvdata(pdev, ipctl);
-	ipctl->pctl = pinctrl_register(pctl_desc, &pdev->dev, ipctl);
+	ipctl->pctl = devm_pinctrl_register(&pdev->dev, pctl_desc, ipctl);
 	if (IS_ERR(ipctl->pctl)) {
 	if (IS_ERR(ipctl->pctl)) {
 		dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
 		dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
 		return PTR_ERR(ipctl->pctl);
 		return PTR_ERR(ipctl->pctl);
@@ -652,12 +652,3 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev,
 
 
 	return 0;
 	return 0;
 }
 }
-
-int imx1_pinctrl_core_remove(struct platform_device *pdev)
-{
-	struct imx1_pinctrl *ipctl = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(ipctl->pctl);
-
-	return 0;
-}

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx1.c

@@ -269,7 +269,6 @@ static struct platform_driver imx1_pinctrl_driver = {
 		.name		= "imx1-pinctrl",
 		.name		= "imx1-pinctrl",
 		.of_match_table	= imx1_pinctrl_of_match,
 		.of_match_table	= imx1_pinctrl_of_match,
 	},
 	},
-	.remove	= imx1_pinctrl_core_remove,
 };
 };
 module_platform_driver_probe(imx1_pinctrl_driver, imx1_pinctrl_probe);
 module_platform_driver_probe(imx1_pinctrl_driver, imx1_pinctrl_probe);
 
 

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx1.h

@@ -69,5 +69,4 @@ struct imx1_pinctrl_soc_info {
 
 
 int imx1_pinctrl_core_probe(struct platform_device *pdev,
 int imx1_pinctrl_core_probe(struct platform_device *pdev,
 			struct imx1_pinctrl_soc_info *info);
 			struct imx1_pinctrl_soc_info *info);
-int imx1_pinctrl_core_remove(struct platform_device *pdev);
 #endif /* __DRIVERS_PINCTRL_IMX1_H */
 #endif /* __DRIVERS_PINCTRL_IMX1_H */

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx21.c

@@ -332,7 +332,6 @@ static struct platform_driver imx21_pinctrl_driver = {
 		.name		= "imx21-pinctrl",
 		.name		= "imx21-pinctrl",
 		.of_match_table	= imx21_pinctrl_of_match,
 		.of_match_table	= imx21_pinctrl_of_match,
 	},
 	},
-	.remove	= imx1_pinctrl_core_remove,
 };
 };
 module_platform_driver_probe(imx21_pinctrl_driver, imx21_pinctrl_probe);
 module_platform_driver_probe(imx21_pinctrl_driver, imx21_pinctrl_probe);
 
 

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx25.c

@@ -331,7 +331,6 @@ static struct platform_driver imx25_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx25_pinctrl_of_match),
 		.of_match_table = of_match_ptr(imx25_pinctrl_of_match),
 	},
 	},
 	.probe = imx25_pinctrl_probe,
 	.probe = imx25_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx25_pinctrl_init(void)
 static int __init imx25_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx27.c

@@ -405,7 +405,6 @@ static struct platform_driver imx27_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx27_pinctrl_of_match),
 		.of_match_table = of_match_ptr(imx27_pinctrl_of_match),
 	},
 	},
 	.probe = imx27_pinctrl_probe,
 	.probe = imx27_pinctrl_probe,
-	.remove = imx1_pinctrl_core_remove,
 };
 };
 
 
 static int __init imx27_pinctrl_init(void)
 static int __init imx27_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx35.c

@@ -1021,7 +1021,6 @@ static struct platform_driver imx35_pinctrl_driver = {
 		.of_match_table = imx35_pinctrl_of_match,
 		.of_match_table = imx35_pinctrl_of_match,
 	},
 	},
 	.probe = imx35_pinctrl_probe,
 	.probe = imx35_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx35_pinctrl_init(void)
 static int __init imx35_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx50.c

@@ -408,7 +408,6 @@ static struct platform_driver imx50_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx50_pinctrl_of_match),
 		.of_match_table = of_match_ptr(imx50_pinctrl_of_match),
 	},
 	},
 	.probe = imx50_pinctrl_probe,
 	.probe = imx50_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx50_pinctrl_init(void)
 static int __init imx50_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx51.c

@@ -784,7 +784,6 @@ static struct platform_driver imx51_pinctrl_driver = {
 		.of_match_table = imx51_pinctrl_of_match,
 		.of_match_table = imx51_pinctrl_of_match,
 	},
 	},
 	.probe = imx51_pinctrl_probe,
 	.probe = imx51_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx51_pinctrl_init(void)
 static int __init imx51_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx53.c

@@ -471,7 +471,6 @@ static struct platform_driver imx53_pinctrl_driver = {
 		.of_match_table = imx53_pinctrl_of_match,
 		.of_match_table = imx53_pinctrl_of_match,
 	},
 	},
 	.probe = imx53_pinctrl_probe,
 	.probe = imx53_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx53_pinctrl_init(void)
 static int __init imx53_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx6dl.c

@@ -477,7 +477,6 @@ static struct platform_driver imx6dl_pinctrl_driver = {
 		.of_match_table = imx6dl_pinctrl_of_match,
 		.of_match_table = imx6dl_pinctrl_of_match,
 	},
 	},
 	.probe = imx6dl_pinctrl_probe,
 	.probe = imx6dl_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx6dl_pinctrl_init(void)
 static int __init imx6dl_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx6q.c

@@ -483,7 +483,6 @@ static struct platform_driver imx6q_pinctrl_driver = {
 		.of_match_table = imx6q_pinctrl_of_match,
 		.of_match_table = imx6q_pinctrl_of_match,
 	},
 	},
 	.probe = imx6q_pinctrl_probe,
 	.probe = imx6q_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx6q_pinctrl_init(void)
 static int __init imx6q_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx6sl.c

@@ -384,7 +384,6 @@ static struct platform_driver imx6sl_pinctrl_driver = {
 		.of_match_table = imx6sl_pinctrl_of_match,
 		.of_match_table = imx6sl_pinctrl_of_match,
 	},
 	},
 	.probe = imx6sl_pinctrl_probe,
 	.probe = imx6sl_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx6sl_pinctrl_init(void)
 static int __init imx6sl_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx6sx.c

@@ -387,7 +387,6 @@ static struct platform_driver imx6sx_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx6sx_pinctrl_of_match),
 		.of_match_table = of_match_ptr(imx6sx_pinctrl_of_match),
 	},
 	},
 	.probe = imx6sx_pinctrl_probe,
 	.probe = imx6sx_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx6sx_pinctrl_init(void)
 static int __init imx6sx_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx6ul.c

@@ -303,7 +303,6 @@ static struct platform_driver imx6ul_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx6ul_pinctrl_of_match),
 		.of_match_table = of_match_ptr(imx6ul_pinctrl_of_match),
 	},
 	},
 	.probe = imx6ul_pinctrl_probe,
 	.probe = imx6ul_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx6ul_pinctrl_init(void)
 static int __init imx6ul_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-imx7d.c

@@ -395,7 +395,6 @@ static struct platform_driver imx7d_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx7d_pinctrl_of_match),
 		.of_match_table = of_match_ptr(imx7d_pinctrl_of_match),
 	},
 	},
 	.probe = imx7d_pinctrl_probe,
 	.probe = imx7d_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init imx7d_pinctrl_init(void)
 static int __init imx7d_pinctrl_init(void)

+ 0 - 1
drivers/pinctrl/freescale/pinctrl-vf610.c

@@ -318,7 +318,6 @@ static struct platform_driver vf610_pinctrl_driver = {
 		.of_match_table = vf610_pinctrl_of_match,
 		.of_match_table = vf610_pinctrl_of_match,
 	},
 	},
 	.probe = vf610_pinctrl_probe,
 	.probe = vf610_pinctrl_probe,
-	.remove = imx_pinctrl_remove,
 };
 };
 
 
 static int __init vf610_pinctrl_init(void)
 static int __init vf610_pinctrl_init(void)

+ 3 - 0
drivers/pinctrl/intel/Kconfig

@@ -6,6 +6,9 @@ config PINCTRL_BAYTRAIL
 	bool "Intel Baytrail GPIO pin control"
 	bool "Intel Baytrail GPIO pin control"
 	depends on GPIOLIB && ACPI
 	depends on GPIOLIB && ACPI
 	select GPIOLIB_IRQCHIP
 	select GPIOLIB_IRQCHIP
+	select PINMUX
+	select PINCONF
+	select GENERIC_PINCONF
 	help
 	help
 	  driver for memory mapped GPIO functionality on Intel Baytrail
 	  driver for memory mapped GPIO functionality on Intel Baytrail
 	  platforms. Supports 3 banks with 102, 28 and 44 gpios.
 	  platforms. Supports 3 banks with 102, 28 and 44 gpios.

+ 1451 - 256
drivers/pinctrl/intel/pinctrl-baytrail.c

@@ -20,6 +20,7 @@
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 #include <linux/gpio/driver.h>
 #include <linux/gpio/driver.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
@@ -27,6 +28,9 @@
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
 
 
 /* memory mapped register offsets */
 /* memory mapped register offsets */
 #define BYT_CONF0_REG		0x000
 #define BYT_CONF0_REG		0x000
@@ -34,6 +38,7 @@
 #define BYT_VAL_REG		0x008
 #define BYT_VAL_REG		0x008
 #define BYT_DFT_REG		0x00c
 #define BYT_DFT_REG		0x00c
 #define BYT_INT_STAT_REG	0x800
 #define BYT_INT_STAT_REG	0x800
+#define BYT_DEBOUNCE_REG	0x9d0
 
 
 /* BYT_CONF0_REG register bits */
 /* BYT_CONF0_REG register bits */
 #define BYT_IODEN		BIT(31)
 #define BYT_IODEN		BIT(31)
@@ -41,6 +46,7 @@
 #define BYT_TRIG_NEG		BIT(26)
 #define BYT_TRIG_NEG		BIT(26)
 #define BYT_TRIG_POS		BIT(25)
 #define BYT_TRIG_POS		BIT(25)
 #define BYT_TRIG_LVL		BIT(24)
 #define BYT_TRIG_LVL		BIT(24)
+#define BYT_DEBOUNCE_EN		BIT(20)
 #define BYT_PULL_STR_SHIFT	9
 #define BYT_PULL_STR_SHIFT	9
 #define BYT_PULL_STR_MASK	(3 << BYT_PULL_STR_SHIFT)
 #define BYT_PULL_STR_MASK	(3 << BYT_PULL_STR_SHIFT)
 #define BYT_PULL_STR_2K		(0 << BYT_PULL_STR_SHIFT)
 #define BYT_PULL_STR_2K		(0 << BYT_PULL_STR_SHIFT)
@@ -65,6 +71,16 @@
 				 BYT_PIN_MUX)
 				 BYT_PIN_MUX)
 #define BYT_VAL_RESTORE_MASK	(BYT_DIR_MASK | BYT_LEVEL)
 #define BYT_VAL_RESTORE_MASK	(BYT_DIR_MASK | BYT_LEVEL)
 
 
+/* BYT_DEBOUNCE_REG bits */
+#define BYT_DEBOUNCE_PULSE_MASK		0x7
+#define BYT_DEBOUNCE_PULSE_375US	1
+#define BYT_DEBOUNCE_PULSE_750US	2
+#define BYT_DEBOUNCE_PULSE_1500US	3
+#define BYT_DEBOUNCE_PULSE_3MS		4
+#define BYT_DEBOUNCE_PULSE_6MS		5
+#define BYT_DEBOUNCE_PULSE_12MS		6
+#define BYT_DEBOUNCE_PULSE_24MS		7
+
 #define BYT_NGPIO_SCORE		102
 #define BYT_NGPIO_SCORE		102
 #define BYT_NGPIO_NCORE		28
 #define BYT_NGPIO_NCORE		28
 #define BYT_NGPIO_SUS		44
 #define BYT_NGPIO_SUS		44
@@ -74,18 +90,227 @@
 #define BYT_SUS_ACPI_UID	"3"
 #define BYT_SUS_ACPI_UID	"3"
 
 
 /*
 /*
- * Baytrail gpio controller consist of three separate sub-controllers called
- * SCORE, NCORE and SUS. The sub-controllers are identified by their acpi UID.
- *
- * GPIO numbering is _not_ ordered meaning that gpio # 0 in ACPI namespace does
- * _not_ correspond to the first gpio register at controller's gpio base.
- * There is no logic or pattern in mapping gpio numbers to registers (pads) so
- * each sub-controller needs to have its own mapping table
+ * This is the function value most pins have for GPIO muxing. If the value
+ * differs from the default one, it must be explicitly mentioned. Otherwise, the
+ * pin control implementation will set the muxing value to default GPIO if it
+ * does not find a match for the requested function.
  */
  */
+#define BYT_DEFAULT_GPIO_MUX	0
+
+struct byt_gpio_pin_context {
+	u32 conf0;
+	u32 val;
+};
+
+struct byt_simple_func_mux {
+	const char *name;
+	unsigned short func;
+};
+
+struct byt_mixed_func_mux {
+	const char *name;
+	const unsigned short *func_values;
+};
+
+struct byt_pingroup {
+	const char *name;
+	const unsigned int *pins;
+	size_t npins;
+	unsigned short has_simple_funcs;
+	union {
+		const struct byt_simple_func_mux *simple_funcs;
+		const struct byt_mixed_func_mux *mixed_funcs;
+	};
+	size_t nfuncs;
+};
+
+struct byt_function {
+	const char *name;
+	const char * const *groups;
+	size_t ngroups;
+};
+
+struct byt_community {
+	unsigned int pin_base;
+	size_t npins;
+	const unsigned int *pad_map;
+	void __iomem *reg_base;
+};
+
+#define SIMPLE_FUNC(n, f)	\
+	{			\
+		.name	= (n),	\
+		.func	= (f),	\
+	}
+#define MIXED_FUNC(n, f)		\
+	{				\
+		.name		= (n),	\
+		.func_values	= (f),	\
+	}
+
+#define PIN_GROUP_SIMPLE(n, p, f)				\
+	{							\
+		.name			= (n),			\
+		.pins			= (p),			\
+		.npins			= ARRAY_SIZE((p)),	\
+		.has_simple_funcs	= 1,		\
+		.simple_funcs		= (f),			\
+		.nfuncs			= ARRAY_SIZE((f)),	\
+	}
+#define PIN_GROUP_MIXED(n, p, f)				\
+	{							\
+		.name			= (n),			\
+		.pins			= (p),			\
+		.npins			= ARRAY_SIZE((p)),	\
+		.has_simple_funcs	= 0,			\
+		.mixed_funcs		= (f),			\
+		.nfuncs			= ARRAY_SIZE((f)),	\
+	}
+
+#define FUNCTION(n, g)					\
+	{						\
+		.name		= (n),			\
+		.groups		= (g),			\
+		.ngroups	= ARRAY_SIZE((g)),	\
+	}
 
 
-/* score_pins[gpio_nr] = pad_nr */
+#define COMMUNITY(p, n, map)		\
+	{				\
+		.pin_base	= (p),	\
+		.npins		= (n),	\
+		.pad_map	= (map),\
+	}
 
 
-static unsigned const score_pins[BYT_NGPIO_SCORE] = {
+struct byt_pinctrl_soc_data {
+	const char *uid;
+	const struct pinctrl_pin_desc *pins;
+	size_t npins;
+	const struct byt_pingroup *groups;
+	size_t ngroups;
+	const struct byt_function *functions;
+	size_t nfunctions;
+	const struct byt_community *communities;
+	size_t ncommunities;
+};
+
+struct byt_gpio {
+	struct gpio_chip chip;
+	struct platform_device *pdev;
+	struct pinctrl_dev *pctl_dev;
+	struct pinctrl_desc pctl_desc;
+	raw_spinlock_t lock;
+	const struct byt_pinctrl_soc_data *soc_data;
+	struct byt_community *communities_copy;
+	struct byt_gpio_pin_context *saved_context;
+};
+
+/* SCORE pins, aka GPIOC_<pin_no> or GPIO_S0_SC[<pin_no>] */
+static const struct pinctrl_pin_desc byt_score_pins[] = {
+	PINCTRL_PIN(0, "SATA_GP0"),
+	PINCTRL_PIN(1, "SATA_GP1"),
+	PINCTRL_PIN(2, "SATA_LED#"),
+	PINCTRL_PIN(3, "PCIE_CLKREQ0"),
+	PINCTRL_PIN(4, "PCIE_CLKREQ1"),
+	PINCTRL_PIN(5, "PCIE_CLKREQ2"),
+	PINCTRL_PIN(6, "PCIE_CLKREQ3"),
+	PINCTRL_PIN(7, "SD3_WP"),
+	PINCTRL_PIN(8, "HDA_RST"),
+	PINCTRL_PIN(9, "HDA_SYNC"),
+	PINCTRL_PIN(10, "HDA_CLK"),
+	PINCTRL_PIN(11, "HDA_SDO"),
+	PINCTRL_PIN(12, "HDA_SDI0"),
+	PINCTRL_PIN(13, "HDA_SDI1"),
+	PINCTRL_PIN(14, "GPIO_S0_SC14"),
+	PINCTRL_PIN(15, "GPIO_S0_SC15"),
+	PINCTRL_PIN(16, "MMC1_CLK"),
+	PINCTRL_PIN(17, "MMC1_D0"),
+	PINCTRL_PIN(18, "MMC1_D1"),
+	PINCTRL_PIN(19, "MMC1_D2"),
+	PINCTRL_PIN(20, "MMC1_D3"),
+	PINCTRL_PIN(21, "MMC1_D4"),
+	PINCTRL_PIN(22, "MMC1_D5"),
+	PINCTRL_PIN(23, "MMC1_D6"),
+	PINCTRL_PIN(24, "MMC1_D7"),
+	PINCTRL_PIN(25, "MMC1_CMD"),
+	PINCTRL_PIN(26, "MMC1_RST"),
+	PINCTRL_PIN(27, "SD2_CLK"),
+	PINCTRL_PIN(28, "SD2_D0"),
+	PINCTRL_PIN(29, "SD2_D1"),
+	PINCTRL_PIN(30, "SD2_D2"),
+	PINCTRL_PIN(31, "SD2_D3_CD"),
+	PINCTRL_PIN(32, "SD2_CMD"),
+	PINCTRL_PIN(33, "SD3_CLK"),
+	PINCTRL_PIN(34, "SD3_D0"),
+	PINCTRL_PIN(35, "SD3_D1"),
+	PINCTRL_PIN(36, "SD3_D2"),
+	PINCTRL_PIN(37, "SD3_D3"),
+	PINCTRL_PIN(38, "SD3_CD"),
+	PINCTRL_PIN(39, "SD3_CMD"),
+	PINCTRL_PIN(40, "SD3_1P8EN"),
+	PINCTRL_PIN(41, "SD3_PWREN#"),
+	PINCTRL_PIN(42, "ILB_LPC_AD0"),
+	PINCTRL_PIN(43, "ILB_LPC_AD1"),
+	PINCTRL_PIN(44, "ILB_LPC_AD2"),
+	PINCTRL_PIN(45, "ILB_LPC_AD3"),
+	PINCTRL_PIN(46, "ILB_LPC_FRAME"),
+	PINCTRL_PIN(47, "ILB_LPC_CLK0"),
+	PINCTRL_PIN(48, "ILB_LPC_CLK1"),
+	PINCTRL_PIN(49, "ILB_LPC_CLKRUN"),
+	PINCTRL_PIN(50, "ILB_LPC_SERIRQ"),
+	PINCTRL_PIN(51, "PCU_SMB_DATA"),
+	PINCTRL_PIN(52, "PCU_SMB_CLK"),
+	PINCTRL_PIN(53, "PCU_SMB_ALERT"),
+	PINCTRL_PIN(54, "ILB_8254_SPKR"),
+	PINCTRL_PIN(55, "GPIO_S0_SC55"),
+	PINCTRL_PIN(56, "GPIO_S0_SC56"),
+	PINCTRL_PIN(57, "GPIO_S0_SC57"),
+	PINCTRL_PIN(58, "GPIO_S0_SC58"),
+	PINCTRL_PIN(59, "GPIO_S0_SC59"),
+	PINCTRL_PIN(60, "GPIO_S0_SC60"),
+	PINCTRL_PIN(61, "GPIO_S0_SC61"),
+	PINCTRL_PIN(62, "LPE_I2S2_CLK"),
+	PINCTRL_PIN(63, "LPE_I2S2_FRM"),
+	PINCTRL_PIN(64, "LPE_I2S2_DATAIN"),
+	PINCTRL_PIN(65, "LPE_I2S2_DATAOUT"),
+	PINCTRL_PIN(66, "SIO_SPI_CS"),
+	PINCTRL_PIN(67, "SIO_SPI_MISO"),
+	PINCTRL_PIN(68, "SIO_SPI_MOSI"),
+	PINCTRL_PIN(69, "SIO_SPI_CLK"),
+	PINCTRL_PIN(70, "SIO_UART1_RXD"),
+	PINCTRL_PIN(71, "SIO_UART1_TXD"),
+	PINCTRL_PIN(72, "SIO_UART1_RTS"),
+	PINCTRL_PIN(73, "SIO_UART1_CTS"),
+	PINCTRL_PIN(74, "SIO_UART2_RXD"),
+	PINCTRL_PIN(75, "SIO_UART2_TXD"),
+	PINCTRL_PIN(76, "SIO_UART2_RTS"),
+	PINCTRL_PIN(77, "SIO_UART2_CTS"),
+	PINCTRL_PIN(78, "SIO_I2C0_DATA"),
+	PINCTRL_PIN(79, "SIO_I2C0_CLK"),
+	PINCTRL_PIN(80, "SIO_I2C1_DATA"),
+	PINCTRL_PIN(81, "SIO_I2C1_CLK"),
+	PINCTRL_PIN(82, "SIO_I2C2_DATA"),
+	PINCTRL_PIN(83, "SIO_I2C2_CLK"),
+	PINCTRL_PIN(84, "SIO_I2C3_DATA"),
+	PINCTRL_PIN(85, "SIO_I2C3_CLK"),
+	PINCTRL_PIN(86, "SIO_I2C4_DATA"),
+	PINCTRL_PIN(87, "SIO_I2C4_CLK"),
+	PINCTRL_PIN(88, "SIO_I2C5_DATA"),
+	PINCTRL_PIN(89, "SIO_I2C5_CLK"),
+	PINCTRL_PIN(90, "SIO_I2C6_DATA"),
+	PINCTRL_PIN(91, "SIO_I2C6_CLK"),
+	PINCTRL_PIN(92, "GPIO_S0_SC92"),
+	PINCTRL_PIN(93, "GPIO_S0_SC93"),
+	PINCTRL_PIN(94, "SIO_PWM0"),
+	PINCTRL_PIN(95, "SIO_PWM1"),
+	PINCTRL_PIN(96, "PMC_PLT_CLK0"),
+	PINCTRL_PIN(97, "PMC_PLT_CLK1"),
+	PINCTRL_PIN(98, "PMC_PLT_CLK2"),
+	PINCTRL_PIN(99, "PMC_PLT_CLK3"),
+	PINCTRL_PIN(100, "PMC_PLT_CLK4"),
+	PINCTRL_PIN(101, "PMC_PLT_CLK5"),
+};
+
+static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
 	36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
 	36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
 	54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
 	54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
@@ -99,13 +324,263 @@ static unsigned const score_pins[BYT_NGPIO_SCORE] = {
 	97, 100,
 	97, 100,
 };
 };
 
 
-static unsigned const ncore_pins[BYT_NGPIO_NCORE] = {
-	19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
-	14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
-	3, 6, 10, 13, 2, 5, 9, 7,
+/* SCORE groups */
+static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
+static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
+static const struct byt_simple_func_mux byt_score_uart_mux[] = {
+	SIMPLE_FUNC("uart", 1),
+};
+
+static const unsigned int byt_score_pwm0_pins[] = { 94 };
+static const unsigned int byt_score_pwm1_pins[] = { 95 };
+static const struct byt_simple_func_mux byt_score_pwm_mux[] = {
+	SIMPLE_FUNC("pwm", 1),
 };
 };
 
 
-static unsigned const sus_pins[BYT_NGPIO_SUS] = {
+static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 };
+static const struct byt_simple_func_mux byt_score_spi_mux[] = {
+	SIMPLE_FUNC("spi", 1),
+};
+
+static const unsigned int byt_score_i2c5_pins[] = { 88, 89 };
+static const unsigned int byt_score_i2c6_pins[] = { 90, 91 };
+static const unsigned int byt_score_i2c4_pins[] = { 86, 87 };
+static const unsigned int byt_score_i2c3_pins[] = { 84, 85 };
+static const unsigned int byt_score_i2c2_pins[] = { 82, 83 };
+static const unsigned int byt_score_i2c1_pins[] = { 80, 81 };
+static const unsigned int byt_score_i2c0_pins[] = { 78, 79 };
+static const struct byt_simple_func_mux byt_score_i2c_mux[] = {
+	SIMPLE_FUNC("i2c", 1),
+};
+
+static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 };
+static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 };
+static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 };
+static const struct byt_simple_func_mux byt_score_ssp_mux[] = {
+	SIMPLE_FUNC("ssp", 1),
+};
+
+static const unsigned int byt_score_sdcard_pins[] = {
+	7, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+};
+static const unsigned short byt_score_sdcard_mux_values[] = {
+	2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+static const struct byt_mixed_func_mux byt_score_sdcard_mux[] = {
+	MIXED_FUNC("sdcard", byt_score_sdcard_mux_values),
+};
+
+static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 };
+static const struct byt_simple_func_mux byt_score_sdio_mux[] = {
+	SIMPLE_FUNC("sdio", 1),
+};
+
+static const unsigned int byt_score_emmc_pins[] = {
+	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+};
+static const struct byt_simple_func_mux byt_score_emmc_mux[] = {
+	SIMPLE_FUNC("emmc", 1),
+};
+
+static const unsigned int byt_score_ilb_lpc_pins[] = {
+	42, 43, 44, 45, 46, 47, 48, 49, 50,
+};
+static const struct byt_simple_func_mux byt_score_lpc_mux[] = {
+	SIMPLE_FUNC("lpc", 1),
+};
+
+static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 };
+static const struct byt_simple_func_mux byt_score_sata_mux[] = {
+	SIMPLE_FUNC("sata", 1),
+};
+
+static const unsigned int byt_score_plt_clk0_pins[] = { 96 };
+static const unsigned int byt_score_plt_clk1_pins[] = { 97 };
+static const unsigned int byt_score_plt_clk2_pins[] = { 98 };
+static const unsigned int byt_score_plt_clk4_pins[] = { 99 };
+static const unsigned int byt_score_plt_clk5_pins[] = { 100 };
+static const unsigned int byt_score_plt_clk3_pins[] = { 101 };
+static const struct byt_simple_func_mux byt_score_plt_clk_mux[] = {
+	SIMPLE_FUNC("plt_clk", 1),
+};
+
+static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
+static const struct byt_simple_func_mux byt_score_smbus_mux[] = {
+	SIMPLE_FUNC("smbus", 1),
+};
+
+static const struct byt_pingroup byt_score_groups[] = {
+	PIN_GROUP_SIMPLE("uart1_grp",
+			 byt_score_uart1_pins, byt_score_uart_mux),
+	PIN_GROUP_SIMPLE("uart2_grp",
+			 byt_score_uart2_pins, byt_score_uart_mux),
+	PIN_GROUP_SIMPLE("pwm0_grp",
+			 byt_score_pwm0_pins, byt_score_pwm_mux),
+	PIN_GROUP_SIMPLE("pwm1_grp",
+			 byt_score_pwm1_pins, byt_score_pwm_mux),
+	PIN_GROUP_SIMPLE("ssp2_grp",
+			 byt_score_ssp2_pins, byt_score_pwm_mux),
+	PIN_GROUP_SIMPLE("sio_spi_grp",
+			 byt_score_sio_spi_pins, byt_score_spi_mux),
+	PIN_GROUP_SIMPLE("i2c5_grp",
+			 byt_score_i2c5_pins, byt_score_i2c_mux),
+	PIN_GROUP_SIMPLE("i2c6_grp",
+			 byt_score_i2c6_pins, byt_score_i2c_mux),
+	PIN_GROUP_SIMPLE("i2c4_grp",
+			 byt_score_i2c4_pins, byt_score_i2c_mux),
+	PIN_GROUP_SIMPLE("i2c3_grp",
+			 byt_score_i2c3_pins, byt_score_i2c_mux),
+	PIN_GROUP_SIMPLE("i2c2_grp",
+			 byt_score_i2c2_pins, byt_score_i2c_mux),
+	PIN_GROUP_SIMPLE("i2c1_grp",
+			 byt_score_i2c1_pins, byt_score_i2c_mux),
+	PIN_GROUP_SIMPLE("i2c0_grp",
+			 byt_score_i2c0_pins, byt_score_i2c_mux),
+	PIN_GROUP_SIMPLE("ssp0_grp",
+			 byt_score_ssp0_pins, byt_score_ssp_mux),
+	PIN_GROUP_SIMPLE("ssp1_grp",
+			 byt_score_ssp1_pins, byt_score_ssp_mux),
+	PIN_GROUP_MIXED("sdcard_grp",
+			byt_score_sdcard_pins, byt_score_sdcard_mux),
+	PIN_GROUP_SIMPLE("sdio_grp",
+			 byt_score_sdio_pins, byt_score_sdio_mux),
+	PIN_GROUP_SIMPLE("emmc_grp",
+			 byt_score_emmc_pins, byt_score_emmc_mux),
+	PIN_GROUP_SIMPLE("lpc_grp",
+			 byt_score_ilb_lpc_pins, byt_score_lpc_mux),
+	PIN_GROUP_SIMPLE("sata_grp",
+			 byt_score_sata_pins, byt_score_sata_mux),
+	PIN_GROUP_SIMPLE("plt_clk0_grp",
+			 byt_score_plt_clk0_pins, byt_score_plt_clk_mux),
+	PIN_GROUP_SIMPLE("plt_clk1_grp",
+			 byt_score_plt_clk1_pins, byt_score_plt_clk_mux),
+	PIN_GROUP_SIMPLE("plt_clk2_grp",
+			 byt_score_plt_clk2_pins, byt_score_plt_clk_mux),
+	PIN_GROUP_SIMPLE("plt_clk3_grp",
+			 byt_score_plt_clk3_pins, byt_score_plt_clk_mux),
+	PIN_GROUP_SIMPLE("plt_clk4_grp",
+			 byt_score_plt_clk4_pins, byt_score_plt_clk_mux),
+	PIN_GROUP_SIMPLE("plt_clk5_grp",
+			 byt_score_plt_clk5_pins, byt_score_plt_clk_mux),
+	PIN_GROUP_SIMPLE("smbus_grp",
+			 byt_score_smbus_pins, byt_score_smbus_mux),
+};
+
+static const char * const byt_score_uart_groups[] = {
+	"uart1_grp", "uart2_grp",
+};
+static const char * const byt_score_pwm_groups[] = {
+	"pwm0_grp", "pwm1_grp",
+};
+static const char * const byt_score_ssp_groups[] = {
+	"ssp0_grp", "ssp1_grp", "ssp2_grp",
+};
+static const char * const byt_score_spi_groups[] = { "sio_spi_grp" };
+static const char * const byt_score_i2c_groups[] = {
+	"i2c0_grp", "i2c1_grp", "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp",
+	"i2c6_grp",
+};
+static const char * const byt_score_sdcard_groups[] = { "sdcard_grp" };
+static const char * const byt_score_sdio_groups[] = { "sdio_grp" };
+static const char * const byt_score_emmc_groups[] = { "emmc_grp" };
+static const char * const byt_score_lpc_groups[] = { "lpc_grp" };
+static const char * const byt_score_sata_groups[] = { "sata_grp" };
+static const char * const byt_score_plt_clk_groups[] = {
+	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
+	"plt_clk4_grp", "plt_clk5_grp",
+};
+static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
+static const char * const byt_score_gpio_groups[] = {
+	"uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp",
+	"ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp",
+	"i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp",
+	"sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
+	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
+	"plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
+
+};
+
+static const struct byt_function byt_score_functions[] = {
+	FUNCTION("uart", byt_score_uart_groups),
+	FUNCTION("pwm", byt_score_pwm_groups),
+	FUNCTION("ssp", byt_score_ssp_groups),
+	FUNCTION("spi", byt_score_spi_groups),
+	FUNCTION("i2c", byt_score_i2c_groups),
+	FUNCTION("sdcard", byt_score_sdcard_groups),
+	FUNCTION("sdio", byt_score_sdio_groups),
+	FUNCTION("emmc", byt_score_emmc_groups),
+	FUNCTION("lpc", byt_score_lpc_groups),
+	FUNCTION("sata", byt_score_sata_groups),
+	FUNCTION("plt_clk", byt_score_plt_clk_groups),
+	FUNCTION("smbus", byt_score_smbus_groups),
+	FUNCTION("gpio", byt_score_gpio_groups),
+};
+
+static const struct byt_community byt_score_communities[] = {
+	COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map),
+};
+
+static const struct byt_pinctrl_soc_data byt_score_soc_data = {
+	.uid		= BYT_SCORE_ACPI_UID,
+	.pins		= byt_score_pins,
+	.npins		= ARRAY_SIZE(byt_score_pins),
+	.groups		= byt_score_groups,
+	.ngroups	= ARRAY_SIZE(byt_score_groups),
+	.functions	= byt_score_functions,
+	.nfunctions	= ARRAY_SIZE(byt_score_functions),
+	.communities	= byt_score_communities,
+	.ncommunities	= ARRAY_SIZE(byt_score_communities),
+};
+
+/* SUS pins, aka GPIOS_<pin_no> or GPIO_S5[<pin_no>]  */
+static const struct pinctrl_pin_desc byt_sus_pins[] = {
+	PINCTRL_PIN(0, "GPIO_S50"),
+	PINCTRL_PIN(1, "GPIO_S51"),
+	PINCTRL_PIN(2, "GPIO_S52"),
+	PINCTRL_PIN(3, "GPIO_S53"),
+	PINCTRL_PIN(4, "GPIO_S54"),
+	PINCTRL_PIN(5, "GPIO_S55"),
+	PINCTRL_PIN(6, "GPIO_S56"),
+	PINCTRL_PIN(7, "GPIO_S57"),
+	PINCTRL_PIN(8, "GPIO_S58"),
+	PINCTRL_PIN(9, "GPIO_S59"),
+	PINCTRL_PIN(10, "GPIO_S510"),
+	PINCTRL_PIN(11, "PMC_SUSPWRDNACK"),
+	PINCTRL_PIN(12, "PMC_SUSCLK0"),
+	PINCTRL_PIN(13, "GPIO_S513"),
+	PINCTRL_PIN(14, "USB_ULPI_RST"),
+	PINCTRL_PIN(15, "PMC_WAKE_PCIE0#"),
+	PINCTRL_PIN(16, "PMC_PWRBTN"),
+	PINCTRL_PIN(17, "GPIO_S517"),
+	PINCTRL_PIN(18, "PMC_SUS_STAT"),
+	PINCTRL_PIN(19, "USB_OC0"),
+	PINCTRL_PIN(20, "USB_OC1"),
+	PINCTRL_PIN(21, "PCU_SPI_CS1"),
+	PINCTRL_PIN(22, "GPIO_S522"),
+	PINCTRL_PIN(23, "GPIO_S523"),
+	PINCTRL_PIN(24, "GPIO_S524"),
+	PINCTRL_PIN(25, "GPIO_S525"),
+	PINCTRL_PIN(26, "GPIO_S526"),
+	PINCTRL_PIN(27, "GPIO_S527"),
+	PINCTRL_PIN(28, "GPIO_S528"),
+	PINCTRL_PIN(29, "GPIO_S529"),
+	PINCTRL_PIN(30, "GPIO_S530"),
+	PINCTRL_PIN(31, "USB_ULPI_CLK"),
+	PINCTRL_PIN(32, "USB_ULPI_DATA0"),
+	PINCTRL_PIN(33, "USB_ULPI_DATA1"),
+	PINCTRL_PIN(34, "USB_ULPI_DATA2"),
+	PINCTRL_PIN(35, "USB_ULPI_DATA3"),
+	PINCTRL_PIN(36, "USB_ULPI_DATA4"),
+	PINCTRL_PIN(37, "USB_ULPI_DATA5"),
+	PINCTRL_PIN(38, "USB_ULPI_DATA6"),
+	PINCTRL_PIN(39, "USB_ULPI_DATA7"),
+	PINCTRL_PIN(40, "USB_ULPI_DIR"),
+	PINCTRL_PIN(41, "USB_ULPI_NXT"),
+	PINCTRL_PIN(42, "USB_ULPI_STP"),
+	PINCTRL_PIN(43, "USB_ULPI_REFCLK"),
+};
+
+static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = {
 	29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
 	29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
 	18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
 	18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
 	0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
 	0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
@@ -113,86 +588,373 @@ static unsigned const sus_pins[BYT_NGPIO_SUS] = {
 	52, 53, 59, 40,
 	52, 53, 59, 40,
 };
 };
 
 
-static struct pinctrl_gpio_range byt_ranges[] = {
-	{
-		.name = BYT_SCORE_ACPI_UID, /* match with acpi _UID in probe */
-		.npins = BYT_NGPIO_SCORE,
-		.pins = score_pins,
-	},
-	{
-		.name = BYT_NCORE_ACPI_UID,
-		.npins = BYT_NGPIO_NCORE,
-		.pins = ncore_pins,
-	},
-	{
-		.name = BYT_SUS_ACPI_UID,
-		.npins = BYT_NGPIO_SUS,
-		.pins = sus_pins,
-	},
-	{
-	},
+static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 };
+static const struct byt_simple_func_mux byt_sus_usb_oc_mux[] = {
+	SIMPLE_FUNC("usb", 0),
+	SIMPLE_FUNC("gpio", 1),
 };
 };
 
 
-struct byt_gpio_pin_context {
-	u32 conf0;
-	u32 val;
+static const unsigned int byt_sus_usb_ulpi_pins[] = {
+	14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+};
+static const unsigned short byt_sus_usb_ulpi_mode_values[] = {
+	2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+static const unsigned short byt_sus_usb_ulpi_gpio_mode_values[] = {
+	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const struct byt_mixed_func_mux byt_sus_usb_ulpi_mux[] = {
+	MIXED_FUNC("usb", byt_sus_usb_ulpi_mode_values),
+	MIXED_FUNC("gpio", byt_sus_usb_ulpi_gpio_mode_values),
 };
 };
 
 
-struct byt_gpio {
-	struct gpio_chip		chip;
-	struct platform_device		*pdev;
-	raw_spinlock_t			lock;
-	void __iomem			*reg_base;
-	struct pinctrl_gpio_range	*range;
-	struct byt_gpio_pin_context	*saved_context;
+static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
+static const struct byt_simple_func_mux byt_sus_pcu_spi_mux[] = {
+	SIMPLE_FUNC("spi", 0),
+	SIMPLE_FUNC("gpio", 1),
+};
+
+static const struct byt_pingroup byt_sus_groups[] = {
+	PIN_GROUP_SIMPLE("usb_oc_grp",
+			byt_sus_usb_over_current_pins, byt_sus_usb_oc_mux),
+	PIN_GROUP_MIXED("usb_ulpi_grp",
+			byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mux),
+	PIN_GROUP_SIMPLE("pcu_spi_grp",
+			byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mux),
+};
+
+static const char * const byt_sus_usb_groups[] = {
+	"usb_oc_grp", "usb_ulpi_grp",
+};
+static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
+static const char * const byt_sus_gpio_groups[] = {
+	"usb_oc_grp", "usb_ulpi_grp", "pcu_spi_grp",
+};
+
+static const struct byt_function byt_sus_functions[] = {
+	FUNCTION("usb", byt_sus_usb_groups),
+	FUNCTION("spi", byt_sus_spi_groups),
+	FUNCTION("gpio", byt_sus_gpio_groups),
+};
+
+static const struct byt_community byt_sus_communities[] = {
+	COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map),
+};
+
+static const struct byt_pinctrl_soc_data byt_sus_soc_data = {
+	.uid		= BYT_SUS_ACPI_UID,
+	.pins		= byt_sus_pins,
+	.npins		= ARRAY_SIZE(byt_sus_pins),
+	.groups		= byt_sus_groups,
+	.ngroups	= ARRAY_SIZE(byt_sus_groups),
+	.functions	= byt_sus_functions,
+	.nfunctions	= ARRAY_SIZE(byt_sus_functions),
+	.communities	= byt_sus_communities,
+	.ncommunities	= ARRAY_SIZE(byt_sus_communities),
+};
+
+static const struct pinctrl_pin_desc byt_ncore_pins[] = {
+	PINCTRL_PIN(0, "GPIO_NCORE0"),
+	PINCTRL_PIN(1, "GPIO_NCORE1"),
+	PINCTRL_PIN(2, "GPIO_NCORE2"),
+	PINCTRL_PIN(3, "GPIO_NCORE3"),
+	PINCTRL_PIN(4, "GPIO_NCORE4"),
+	PINCTRL_PIN(5, "GPIO_NCORE5"),
+	PINCTRL_PIN(6, "GPIO_NCORE6"),
+	PINCTRL_PIN(7, "GPIO_NCORE7"),
+	PINCTRL_PIN(8, "GPIO_NCORE8"),
+	PINCTRL_PIN(9, "GPIO_NCORE9"),
+	PINCTRL_PIN(10, "GPIO_NCORE10"),
+	PINCTRL_PIN(11, "GPIO_NCORE11"),
+	PINCTRL_PIN(12, "GPIO_NCORE12"),
+	PINCTRL_PIN(13, "GPIO_NCORE13"),
+	PINCTRL_PIN(14, "GPIO_NCORE14"),
+	PINCTRL_PIN(15, "GPIO_NCORE15"),
+	PINCTRL_PIN(16, "GPIO_NCORE16"),
+	PINCTRL_PIN(17, "GPIO_NCORE17"),
+	PINCTRL_PIN(18, "GPIO_NCORE18"),
+	PINCTRL_PIN(19, "GPIO_NCORE19"),
+	PINCTRL_PIN(20, "GPIO_NCORE20"),
+	PINCTRL_PIN(21, "GPIO_NCORE21"),
+	PINCTRL_PIN(22, "GPIO_NCORE22"),
+	PINCTRL_PIN(23, "GPIO_NCORE23"),
+	PINCTRL_PIN(24, "GPIO_NCORE24"),
+	PINCTRL_PIN(25, "GPIO_NCORE25"),
+	PINCTRL_PIN(26, "GPIO_NCORE26"),
+	PINCTRL_PIN(27, "GPIO_NCORE27"),
+};
+
+static unsigned const byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
+	19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
+	14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
+	3, 6, 10, 13, 2, 5, 9, 7,
+};
+
+static const struct byt_community byt_ncore_communities[] = {
+	COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map),
+};
+
+static const struct byt_pinctrl_soc_data byt_ncore_soc_data = {
+	.uid		= BYT_NCORE_ACPI_UID,
+	.pins		= byt_ncore_pins,
+	.npins		= ARRAY_SIZE(byt_ncore_pins),
+	.communities	= byt_ncore_communities,
+	.ncommunities	= ARRAY_SIZE(byt_ncore_communities),
+};
+
+static const struct byt_pinctrl_soc_data *byt_soc_data[] = {
+	&byt_score_soc_data,
+	&byt_sus_soc_data,
+	&byt_ncore_soc_data,
+	NULL,
 };
 };
 
 
-static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
-				 int reg)
+static struct byt_community *byt_get_community(struct byt_gpio *vg,
+					       unsigned int pin)
 {
 {
-	struct byt_gpio *vg = gpiochip_get_data(chip);
-	u32 reg_offset;
+	struct byt_community *comm;
+	int i;
 
 
+	for (i = 0; i < vg->soc_data->ncommunities; i++) {
+		comm = vg->communities_copy + i;
+		if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base)
+			return comm;
+	}
+
+	return NULL;
+}
+
+static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset,
+				  int reg)
+{
+	struct byt_community *comm = byt_get_community(vg, offset);
+	u32 reg_offset = 0;
+
+	if (!comm)
+		return NULL;
+
+	offset -= comm->pin_base;
 	if (reg == BYT_INT_STAT_REG)
 	if (reg == BYT_INT_STAT_REG)
 		reg_offset = (offset / 32) * 4;
 		reg_offset = (offset / 32) * 4;
 	else
 	else
-		reg_offset = vg->range->pins[offset] * 16;
+		reg_offset = comm->pad_map[offset] * 16;
 
 
-	return vg->reg_base + reg_offset + reg;
+	return comm->reg_base + reg_offset + reg;
 }
 }
 
 
-static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned offset)
+static int byt_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
+
+	return vg->soc_data->ngroups;
+}
+
+static const char *byt_get_group_name(struct pinctrl_dev *pctldev,
+				      unsigned int selector)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
+
+	return vg->soc_data->groups[selector].name;
+}
+
+static int byt_get_group_pins(struct pinctrl_dev *pctldev,
+			      unsigned int selector,
+			      const unsigned int **pins,
+			      unsigned int *num_pins)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins		= vg->soc_data->groups[selector].pins;
+	*num_pins	= vg->soc_data->groups[selector].npins;
+
+	return 0;
+}
+
+static const struct pinctrl_ops byt_pinctrl_ops = {
+	.get_groups_count	= byt_get_groups_count,
+	.get_group_name		= byt_get_group_name,
+	.get_group_pins		= byt_get_group_pins,
+};
+
+static int byt_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
+
+	return vg->soc_data->nfunctions;
+}
+
+static const char *byt_get_function_name(struct pinctrl_dev *pctldev,
+					 unsigned int selector)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
+
+	return vg->soc_data->functions[selector].name;
+}
+
+static int byt_get_function_groups(struct pinctrl_dev *pctldev,
+				   unsigned int selector,
+				   const char * const **groups,
+				   unsigned int *num_groups)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups		= vg->soc_data->functions[selector].groups;
+	*num_groups	= vg->soc_data->functions[selector].ngroups;
+
+	return 0;
+}
+
+static int byt_get_group_simple_mux(const struct byt_pingroup group,
+				    const char *func_name,
+				    unsigned short *func)
+{
+	int i;
+
+	for (i = 0; i < group.nfuncs; i++) {
+		if (!strcmp(group.simple_funcs[i].name, func_name)) {
+			*func = group.simple_funcs[i].func;
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int byt_get_group_mixed_mux(const struct byt_pingroup group,
+				   const char *func_name,
+				   const unsigned short **func)
+{
+	int i;
+
+	for (i = 0; i < group.nfuncs; i++) {
+		if (!strcmp(group.mixed_funcs[i].name, func_name)) {
+			*func = group.mixed_funcs[i].func_values;
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static void byt_set_group_simple_mux(struct byt_gpio *vg,
+				     const struct byt_pingroup group,
+				     unsigned short func)
 {
 {
-	void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
 	unsigned long flags;
 	unsigned long flags;
-	u32 value;
+	int i;
 
 
 	raw_spin_lock_irqsave(&vg->lock, flags);
 	raw_spin_lock_irqsave(&vg->lock, flags);
-	value = readl(reg);
-	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
-	writel(value, reg);
+
+	for (i = 0; i < group.npins; i++) {
+		void __iomem *padcfg0;
+		u32 value;
+
+		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
+		if (!padcfg0) {
+			dev_warn(&vg->pdev->dev,
+				 "Group %s, pin %i not muxed (no padcfg0)\n",
+				 group.name, i);
+			continue;
+		}
+
+		value = readl(padcfg0);
+		value &= ~BYT_PIN_MUX;
+		value |= func;
+		writel(value, padcfg0);
+	}
+
+	raw_spin_unlock_irqrestore(&vg->lock, flags);
+}
+
+static void byt_set_group_mixed_mux(struct byt_gpio *vg,
+				    const struct byt_pingroup group,
+				    const unsigned short *func)
+{
+	unsigned long flags;
+	int i;
+
+	raw_spin_lock_irqsave(&vg->lock, flags);
+
+	for (i = 0; i < group.npins; i++) {
+		void __iomem *padcfg0;
+		u32 value;
+
+		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
+		if (!padcfg0) {
+			dev_warn(&vg->pdev->dev,
+				 "Group %s, pin %i not muxed (no padcfg0)\n",
+				 group.name, i);
+			continue;
+		}
+
+		value = readl(padcfg0);
+		value &= ~BYT_PIN_MUX;
+		value |= func[i];
+		writel(value, padcfg0);
+	}
+
 	raw_spin_unlock_irqrestore(&vg->lock, flags);
 	raw_spin_unlock_irqrestore(&vg->lock, flags);
 }
 }
 
 
+static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
+		       unsigned int group_selector)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
+	const struct byt_function func = vg->soc_data->functions[func_selector];
+	const struct byt_pingroup group = vg->soc_data->groups[group_selector];
+	const unsigned short *mixed_func;
+	unsigned short simple_func;
+	int ret = 1;
+
+	if (group.has_simple_funcs)
+		ret = byt_get_group_simple_mux(group, func.name, &simple_func);
+	else
+		ret = byt_get_group_mixed_mux(group, func.name, &mixed_func);
+
+	if (ret)
+		byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
+	else if (group.has_simple_funcs)
+		byt_set_group_simple_mux(vg, group, simple_func);
+	else
+		byt_set_group_mixed_mux(vg, group, mixed_func);
+
+	return 0;
+}
+
 static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
 static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
 {
 {
 	/* SCORE pin 92-93 */
 	/* SCORE pin 92-93 */
-	if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
-		offset >= 92 && offset <= 93)
+	if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
+	    offset >= 92 && offset <= 93)
 		return 1;
 		return 1;
 
 
 	/* SUS pin 11-21 */
 	/* SUS pin 11-21 */
-	if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
-		offset >= 11 && offset <= 21)
+	if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) &&
+	    offset >= 11 && offset <= 21)
 		return 1;
 		return 1;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
+static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
 {
 {
-	struct byt_gpio *vg = gpiochip_get_data(chip);
-	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
+	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&vg->lock, flags);
+	value = readl(reg);
+	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+	writel(value, reg);
+	raw_spin_unlock_irqrestore(&vg->lock, flags);
+}
+
+static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
+				   struct pinctrl_gpio_range *range,
+				   unsigned int offset)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
+	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
 	u32 value, gpio_mux;
 	u32 value, gpio_mux;
 	unsigned long flags;
 	unsigned long flags;
 
 
@@ -225,53 +987,318 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
 	return 0;
 	return 0;
 }
 }
 
 
-static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
+static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
+				  struct pinctrl_gpio_range *range,
+				  unsigned int offset)
 {
 {
-	struct byt_gpio *vg = gpiochip_get_data(chip);
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
+
+	byt_gpio_clear_triggering(vg, offset);
+	pm_runtime_put(&vg->pdev->dev);
+}
+
+static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+				  struct pinctrl_gpio_range *range,
+				  unsigned int offset,
+				  bool input)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
+	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&vg->lock, flags);
+
+	value = readl(val_reg);
+	value &= ~BYT_DIR_MASK;
+	if (input)
+		value |= BYT_OUTPUT_EN;
+	else
+		/*
+		 * Before making any direction modifications, do a check if gpio
+		 * is set for direct IRQ.  On baytrail, setting GPIO to output
+		 * does not make sense, so let's at least warn the caller before
+		 * they shoot themselves in the foot.
+		 */
+		WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
+		     "Potential Error: Setting GPIO with direct_irq_en to output");
+	writel(value, val_reg);
+
+	raw_spin_unlock_irqrestore(&vg->lock, flags);
+
+	return 0;
+}
+
+static const struct pinmux_ops byt_pinmux_ops = {
+	.get_functions_count	= byt_get_functions_count,
+	.get_function_name	= byt_get_function_name,
+	.get_function_groups	= byt_get_function_groups,
+	.set_mux		= byt_set_mux,
+	.gpio_request_enable	= byt_gpio_request_enable,
+	.gpio_disable_free	= byt_gpio_disable_free,
+	.gpio_set_direction	= byt_gpio_set_direction,
+};
+
+static void byt_get_pull_strength(u32 reg, u16 *strength)
+{
+	switch (reg & BYT_PULL_STR_MASK) {
+	case BYT_PULL_STR_2K:
+		*strength = 2000;
+		break;
+	case BYT_PULL_STR_10K:
+		*strength = 10000;
+		break;
+	case BYT_PULL_STR_20K:
+		*strength = 20000;
+		break;
+	case BYT_PULL_STR_40K:
+		*strength = 40000;
+		break;
+	}
+}
+
+static int byt_set_pull_strength(u32 *reg, u16 strength)
+{
+	*reg &= ~BYT_PULL_STR_MASK;
+
+	switch (strength) {
+	case 2000:
+		*reg |= BYT_PULL_STR_2K;
+		break;
+	case 10000:
+		*reg |= BYT_PULL_STR_10K;
+		break;
+	case 20000:
+		*reg |= BYT_PULL_STR_20K;
+		break;
+	case 40000:
+		*reg |= BYT_PULL_STR_40K;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
+			      unsigned long *config)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+	unsigned long flags;
+	u32 conf, pull, val, debounce;
+	u16 arg = 0;
+
+	raw_spin_lock_irqsave(&vg->lock, flags);
+	conf = readl(conf_reg);
+	pull = conf & BYT_PULL_ASSIGN_MASK;
+	val = readl(val_reg);
+	raw_spin_unlock_irqrestore(&vg->lock, flags);
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		if (pull)
+			return -EINVAL;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		/* Pull assignment is only applicable in input mode */
+		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_DOWN)
+			return -EINVAL;
+
+		byt_get_pull_strength(conf, &arg);
+
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		/* Pull assignment is only applicable in input mode */
+		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_UP)
+			return -EINVAL;
+
+		byt_get_pull_strength(conf, &arg);
+
+		break;
+	case PIN_CONFIG_INPUT_DEBOUNCE:
+		if (!(conf & BYT_DEBOUNCE_EN))
+			return -EINVAL;
+
+		raw_spin_lock_irqsave(&vg->lock, flags);
+		debounce = readl(byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG));
+		raw_spin_unlock_irqrestore(&vg->lock, flags);
+
+		switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
+		case BYT_DEBOUNCE_PULSE_375US:
+			arg = 375;
+			break;
+		case BYT_DEBOUNCE_PULSE_750US:
+			arg = 750;
+			break;
+		case BYT_DEBOUNCE_PULSE_1500US:
+			arg = 1500;
+			break;
+		case BYT_DEBOUNCE_PULSE_3MS:
+			arg = 3000;
+			break;
+		case BYT_DEBOUNCE_PULSE_6MS:
+			arg = 6000;
+			break;
+		case BYT_DEBOUNCE_PULSE_12MS:
+			arg = 12000;
+			break;
+		case BYT_DEBOUNCE_PULSE_24MS:
+			arg = 24000;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+
+	return 0;
+}
+
+static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
+			      unsigned int offset,
+			      unsigned long *configs,
+			      unsigned int num_configs)
+{
+	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
+	unsigned int param, arg;
+	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+	unsigned long flags;
+	u32 conf, val, debounce;
+	int i, ret = 0;
+
+	raw_spin_lock_irqsave(&vg->lock, flags);
+
+	conf = readl(conf_reg);
+	val = readl(val_reg);
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
 
 
-	byt_gpio_clear_triggering(vg, offset);
-	pm_runtime_put(&vg->pdev->dev);
-}
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			conf &= ~BYT_PULL_ASSIGN_MASK;
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			/* Set default strength value in case none is given */
+			if (arg == 1)
+				arg = 2000;
+
+			/*
+			 * Pull assignment is only applicable in input mode. If
+			 * chip is not in input mode, set it and warn about it.
+			 */
+			if (val & BYT_INPUT_EN) {
+				val &= ~BYT_INPUT_EN;
+				writel(val, val_reg);
+				dev_warn(&vg->pdev->dev,
+					 "pin %u forcibly set to input mode\n",
+					 offset);
+			}
 
 
-static int byt_irq_type(struct irq_data *d, unsigned type)
-{
-	struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
-	u32 offset = irqd_to_hwirq(d);
-	u32 value;
-	unsigned long flags;
-	void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+			conf &= ~BYT_PULL_ASSIGN_MASK;
+			conf |= BYT_PULL_ASSIGN_DOWN;
+			ret = byt_set_pull_strength(&conf, arg);
 
 
-	if (offset >= vg->chip.ngpio)
-		return -EINVAL;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			/* Set default strength value in case none is given */
+			if (arg == 1)
+				arg = 2000;
+
+			/*
+			 * Pull assignment is only applicable in input mode. If
+			 * chip is not in input mode, set it and warn about it.
+			 */
+			if (val & BYT_INPUT_EN) {
+				val &= ~BYT_INPUT_EN;
+				writel(val, val_reg);
+				dev_warn(&vg->pdev->dev,
+					 "pin %u forcibly set to input mode\n",
+					 offset);
+			}
 
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
-	value = readl(reg);
+			conf &= ~BYT_PULL_ASSIGN_MASK;
+			conf |= BYT_PULL_ASSIGN_UP;
+			ret = byt_set_pull_strength(&conf, arg);
 
 
-	WARN(value & BYT_DIRECT_IRQ_EN,
-		"Bad pad config for io mode, force direct_irq_en bit clearing");
+			break;
+		case PIN_CONFIG_INPUT_DEBOUNCE:
+			debounce = readl(byt_gpio_reg(vg, offset,
+						      BYT_DEBOUNCE_REG));
+			conf &= ~BYT_DEBOUNCE_PULSE_MASK;
+
+			switch (arg) {
+			case 375:
+				conf |= BYT_DEBOUNCE_PULSE_375US;
+				break;
+			case 750:
+				conf |= BYT_DEBOUNCE_PULSE_750US;
+				break;
+			case 1500:
+				conf |= BYT_DEBOUNCE_PULSE_1500US;
+				break;
+			case 3000:
+				conf |= BYT_DEBOUNCE_PULSE_3MS;
+				break;
+			case 6000:
+				conf |= BYT_DEBOUNCE_PULSE_6MS;
+				break;
+			case 12000:
+				conf |= BYT_DEBOUNCE_PULSE_12MS;
+				break;
+			case 24000:
+				conf |= BYT_DEBOUNCE_PULSE_24MS;
+				break;
+			default:
+				ret = -EINVAL;
+			}
 
 
-	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
-	 * are used to indicate high and low level triggering
-	 */
-	value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
-		   BYT_TRIG_LVL);
+			break;
+		default:
+			ret = -ENOTSUPP;
+		}
 
 
-	writel(value, reg);
+		if (ret)
+			break;
+	}
 
 
-	if (type & IRQ_TYPE_EDGE_BOTH)
-		irq_set_handler_locked(d, handle_edge_irq);
-	else if (type & IRQ_TYPE_LEVEL_MASK)
-		irq_set_handler_locked(d, handle_level_irq);
+	if (!ret)
+		writel(conf, conf_reg);
 
 
 	raw_spin_unlock_irqrestore(&vg->lock, flags);
 	raw_spin_unlock_irqrestore(&vg->lock, flags);
 
 
-	return 0;
+	return ret;
 }
 }
 
 
+static const struct pinconf_ops byt_pinconf_ops = {
+	.is_generic	= true,
+	.pin_config_get	= byt_pin_config_get,
+	.pin_config_set	= byt_pin_config_set,
+};
+
+static const struct pinctrl_desc byt_pinctrl_desc = {
+	.pctlops	= &byt_pinctrl_ops,
+	.pmxops		= &byt_pinmux_ops,
+	.confops	= &byt_pinconf_ops,
+	.owner		= THIS_MODULE,
+};
+
 static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
 static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 {
-	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
 	struct byt_gpio *vg = gpiochip_get_data(chip);
 	struct byt_gpio *vg = gpiochip_get_data(chip);
+	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
 	unsigned long flags;
 	unsigned long flags;
 	u32 val;
 	u32 val;
 
 
@@ -285,69 +1312,58 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
 static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 {
 	struct byt_gpio *vg = gpiochip_get_data(chip);
 	struct byt_gpio *vg = gpiochip_get_data(chip);
-	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
+	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
 	unsigned long flags;
 	unsigned long flags;
 	u32 old_val;
 	u32 old_val;
 
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	if (!reg)
+		return;
 
 
+	raw_spin_lock_irqsave(&vg->lock, flags);
 	old_val = readl(reg);
 	old_val = readl(reg);
-
 	if (value)
 	if (value)
 		writel(old_val | BYT_LEVEL, reg);
 		writel(old_val | BYT_LEVEL, reg);
 	else
 	else
 		writel(old_val & ~BYT_LEVEL, reg);
 		writel(old_val & ~BYT_LEVEL, reg);
-
 	raw_spin_unlock_irqrestore(&vg->lock, flags);
 	raw_spin_unlock_irqrestore(&vg->lock, flags);
 }
 }
 
 
-static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
 {
 {
 	struct byt_gpio *vg = gpiochip_get_data(chip);
 	struct byt_gpio *vg = gpiochip_get_data(chip);
-	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
+	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
 	unsigned long flags;
 	unsigned long flags;
 	u32 value;
 	u32 value;
 
 
+	if (!reg)
+		return -EINVAL;
+
 	raw_spin_lock_irqsave(&vg->lock, flags);
 	raw_spin_lock_irqsave(&vg->lock, flags);
+	value = readl(reg);
+	raw_spin_unlock_irqrestore(&vg->lock, flags);
 
 
-	value = readl(reg) | BYT_DIR_MASK;
-	value &= ~BYT_INPUT_EN;		/* active low */
-	writel(value, reg);
+	if (!(value & BYT_OUTPUT_EN))
+		return GPIOF_DIR_OUT;
+	if (!(value & BYT_INPUT_EN))
+		return GPIOF_DIR_IN;
 
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	return -EINVAL;
+}
 
 
-	return 0;
+static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+	return pinctrl_gpio_direction_input(chip->base + offset);
 }
 }
 
 
 static int byt_gpio_direction_output(struct gpio_chip *chip,
 static int byt_gpio_direction_output(struct gpio_chip *chip,
-				     unsigned gpio, int value)
+				     unsigned int offset, int value)
 {
 {
-	struct byt_gpio *vg = gpiochip_get_data(chip);
-	void __iomem *conf_reg = byt_gpio_reg(chip, gpio, BYT_CONF0_REG);
-	void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
-	unsigned long flags;
-	u32 reg_val;
-
-	raw_spin_lock_irqsave(&vg->lock, flags);
-
-	/*
-	 * Before making any direction modifications, do a check if gpio
-	 * is set for direct IRQ.  On baytrail, setting GPIO to output does
-	 * not make sense, so let's at least warn the caller before they shoot
-	 * themselves in the foot.
-	 */
-	WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
-		"Potential Error: Setting GPIO with direct_irq_en to output");
-
-	reg_val = readl(reg) | BYT_DIR_MASK;
-	reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN);
+	int ret = pinctrl_gpio_direction_output(chip->base + offset);
 
 
-	if (value)
-		writel(reg_val | BYT_LEVEL, reg);
-	else
-		writel(reg_val & ~BYT_LEVEL, reg);
+	if (ret)
+		return ret;
 
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	byt_gpio_set(chip, offset, value);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -356,20 +1372,45 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
 {
 	struct byt_gpio *vg = gpiochip_get_data(chip);
 	struct byt_gpio *vg = gpiochip_get_data(chip);
 	int i;
 	int i;
-	u32 conf0, val, offs;
+	u32 conf0, val;
 
 
-	for (i = 0; i < vg->chip.ngpio; i++) {
+	for (i = 0; i < vg->soc_data->npins; i++) {
+		const struct byt_community *comm;
 		const char *pull_str = NULL;
 		const char *pull_str = NULL;
 		const char *pull = NULL;
 		const char *pull = NULL;
+		void __iomem *reg;
 		unsigned long flags;
 		unsigned long flags;
 		const char *label;
 		const char *label;
-		offs = vg->range->pins[i] * 16;
+		unsigned int pin;
 
 
 		raw_spin_lock_irqsave(&vg->lock, flags);
 		raw_spin_lock_irqsave(&vg->lock, flags);
-		conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
-		val = readl(vg->reg_base + offs + BYT_VAL_REG);
+		pin = vg->soc_data->pins[i].number;
+		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
+		if (!reg) {
+			seq_printf(s,
+				   "Could not retrieve pin %i conf0 reg\n",
+				   pin);
+			raw_spin_unlock_irqrestore(&vg->lock, flags);
+			continue;
+		}
+		conf0 = readl(reg);
+
+		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
+		if (!reg) {
+			seq_printf(s,
+				   "Could not retrieve pin %i val reg\n", pin);
+			raw_spin_unlock_irqrestore(&vg->lock, flags);
+			continue;
+		}
+		val = readl(reg);
 		raw_spin_unlock_irqrestore(&vg->lock, flags);
 		raw_spin_unlock_irqrestore(&vg->lock, flags);
 
 
+		comm = byt_get_community(vg, pin);
+		if (!comm) {
+			seq_printf(s,
+				   "Could not get community for pin %i\n", pin);
+			continue;
+		}
 		label = gpiochip_is_requested(chip, i);
 		label = gpiochip_is_requested(chip, i);
 		if (!label)
 		if (!label)
 			label = "Unrequested";
 			label = "Unrequested";
@@ -400,12 +1441,12 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 
 
 		seq_printf(s,
 		seq_printf(s,
 			   " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
 			   " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
-			   i,
+			   pin,
 			   label,
 			   label,
 			   val & BYT_INPUT_EN ? "  " : "in",
 			   val & BYT_INPUT_EN ? "  " : "in",
 			   val & BYT_OUTPUT_EN ? "   " : "out",
 			   val & BYT_OUTPUT_EN ? "   " : "out",
 			   val & BYT_LEVEL ? "hi" : "lo",
 			   val & BYT_LEVEL ? "hi" : "lo",
-			   vg->range->pins[i], offs,
+			   comm->pad_map[i], comm->pad_map[i] * 32,
 			   conf0 & 0x7,
 			   conf0 & 0x7,
 			   conf0 & BYT_TRIG_NEG ? " fall" : "     ",
 			   conf0 & BYT_TRIG_NEG ? " fall" : "     ",
 			   conf0 & BYT_TRIG_POS ? " rise" : "     ",
 			   conf0 & BYT_TRIG_POS ? " rise" : "     ",
@@ -423,27 +1464,17 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	}
 	}
 }
 }
 
 
-static void byt_gpio_irq_handler(struct irq_desc *desc)
-{
-	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct byt_gpio *vg = gpiochip_get_data(irq_desc_get_handler_data(desc));
-	struct irq_chip *chip = irq_data_get_irq_chip(data);
-	u32 base, pin;
-	void __iomem *reg;
-	unsigned long pending;
-	unsigned virq;
-
-	/* check from GPIO controller which pin triggered the interrupt */
-	for (base = 0; base < vg->chip.ngpio; base += 32) {
-		reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
-		pending = readl(reg);
-		for_each_set_bit(pin, &pending, 32) {
-			virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
-			generic_handle_irq(virq);
-		}
-	}
-	chip->irq_eoi(data);
-}
+static const struct gpio_chip byt_gpio_chip = {
+	.owner			= THIS_MODULE,
+	.request		= gpiochip_generic_request,
+	.free			= gpiochip_generic_free,
+	.get_direction		= byt_gpio_get_direction,
+	.direction_input	= byt_gpio_direction_input,
+	.direction_output	= byt_gpio_direction_output,
+	.get			= byt_gpio_get,
+	.set			= byt_gpio_set,
+	.dbg_show		= byt_gpio_dbg_show,
+};
 
 
 static void byt_irq_ack(struct irq_data *d)
 static void byt_irq_ack(struct irq_data *d)
 {
 {
@@ -452,12 +1483,23 @@ static void byt_irq_ack(struct irq_data *d)
 	unsigned offset = irqd_to_hwirq(d);
 	unsigned offset = irqd_to_hwirq(d);
 	void __iomem *reg;
 	void __iomem *reg;
 
 
+	reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG);
+	if (!reg)
+		return;
+
 	raw_spin_lock(&vg->lock);
 	raw_spin_lock(&vg->lock);
-	reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
 	writel(BIT(offset % 32), reg);
 	writel(BIT(offset % 32), reg);
 	raw_spin_unlock(&vg->lock);
 	raw_spin_unlock(&vg->lock);
 }
 }
 
 
+static void byt_irq_mask(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct byt_gpio *vg = gpiochip_get_data(gc);
+
+	byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
+}
+
 static void byt_irq_unmask(struct irq_data *d)
 static void byt_irq_unmask(struct irq_data *d)
 {
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -467,7 +1509,9 @@ static void byt_irq_unmask(struct irq_data *d)
 	void __iomem *reg;
 	void __iomem *reg;
 	u32 value;
 	u32 value;
 
 
-	reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+	reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+	if (!reg)
+		return;
 
 
 	raw_spin_lock_irqsave(&vg->lock, flags);
 	raw_spin_lock_irqsave(&vg->lock, flags);
 	value = readl(reg);
 	value = readl(reg);
@@ -493,23 +1537,81 @@ static void byt_irq_unmask(struct irq_data *d)
 	raw_spin_unlock_irqrestore(&vg->lock, flags);
 	raw_spin_unlock_irqrestore(&vg->lock, flags);
 }
 }
 
 
-static void byt_irq_mask(struct irq_data *d)
+static int byt_irq_type(struct irq_data *d, unsigned int type)
 {
 {
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct byt_gpio *vg = gpiochip_get_data(gc);
+	struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	u32 offset = irqd_to_hwirq(d);
+	u32 value;
+	unsigned long flags;
+	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
 
 
-	byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
+	if (!reg || offset >= vg->chip.ngpio)
+		return -EINVAL;
+
+	raw_spin_lock_irqsave(&vg->lock, flags);
+	value = readl(reg);
+
+	WARN(value & BYT_DIRECT_IRQ_EN,
+	     "Bad pad config for io mode, force direct_irq_en bit clearing");
+
+	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
+	 * are used to indicate high and low level triggering
+	 */
+	value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
+		   BYT_TRIG_LVL);
+
+	writel(value, reg);
+
+	if (type & IRQ_TYPE_EDGE_BOTH)
+		irq_set_handler_locked(d, handle_edge_irq);
+	else if (type & IRQ_TYPE_LEVEL_MASK)
+		irq_set_handler_locked(d, handle_level_irq);
+
+	raw_spin_unlock_irqrestore(&vg->lock, flags);
+
+	return 0;
 }
 }
 
 
 static struct irq_chip byt_irqchip = {
 static struct irq_chip byt_irqchip = {
-	.name = "BYT-GPIO",
-	.irq_ack = byt_irq_ack,
-	.irq_mask = byt_irq_mask,
-	.irq_unmask = byt_irq_unmask,
-	.irq_set_type = byt_irq_type,
-	.flags = IRQCHIP_SKIP_SET_WAKE,
+	.name		= "BYT-GPIO",
+	.irq_ack	= byt_irq_ack,
+	.irq_mask	= byt_irq_mask,
+	.irq_unmask	= byt_irq_unmask,
+	.irq_set_type	= byt_irq_type,
+	.flags		= IRQCHIP_SKIP_SET_WAKE,
 };
 };
 
 
+static void byt_gpio_irq_handler(struct irq_desc *desc)
+{
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct byt_gpio *vg = gpiochip_get_data(
+				irq_desc_get_handler_data(desc));
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+	u32 base, pin;
+	void __iomem *reg;
+	unsigned long pending;
+	unsigned int virq;
+
+	/* check from GPIO controller which pin triggered the interrupt */
+	for (base = 0; base < vg->chip.ngpio; base += 32) {
+		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
+
+		if (!reg) {
+			dev_warn(&vg->pdev->dev,
+				 "Pin %i: could not retrieve interrupt status register\n",
+				 base);
+			continue;
+		}
+
+		pending = readl(reg);
+		for_each_set_bit(pin, &pending, 32) {
+			virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
+			generic_handle_irq(virq);
+		}
+	}
+	chip->irq_eoi(data);
+}
+
 static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 {
 {
 	void __iomem *reg;
 	void __iomem *reg;
@@ -521,8 +1623,18 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 	 * do not use direct IRQ mode. This will prevent spurious
 	 * do not use direct IRQ mode. This will prevent spurious
 	 * interrupts from misconfigured pins.
 	 * interrupts from misconfigured pins.
 	 */
 	 */
-	for (i = 0; i < vg->chip.ngpio; i++) {
-		value = readl(byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG));
+	for (i = 0; i < vg->soc_data->npins; i++) {
+		unsigned int pin = vg->soc_data->pins[i].number;
+
+		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
+		if (!reg) {
+			dev_warn(&vg->pdev->dev,
+				 "Pin %i: could not retrieve conf0 register\n",
+				 i);
+			continue;
+		}
+
+		value = readl(reg);
 		if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) &&
 		if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) &&
 		    !(value & BYT_DIRECT_IRQ_EN)) {
 		    !(value & BYT_DIRECT_IRQ_EN)) {
 			byt_gpio_clear_triggering(vg, i);
 			byt_gpio_clear_triggering(vg, i);
@@ -531,8 +1643,16 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 	}
 	}
 
 
 	/* clear interrupt status trigger registers */
 	/* clear interrupt status trigger registers */
-	for (base = 0; base < vg->chip.ngpio; base += 32) {
-		reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
+	for (base = 0; base < vg->soc_data->npins; base += 32) {
+		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
+
+		if (!reg) {
+			dev_warn(&vg->pdev->dev,
+				 "Pin %i: could not retrieve irq status reg\n",
+				 base);
+			continue;
+		}
+
 		writel(0xffffffff, reg);
 		writel(0xffffffff, reg);
 		/* make sure trigger bits are cleared, if not then a pin
 		/* make sure trigger bits are cleared, if not then a pin
 		   might be misconfigured in bios */
 		   might be misconfigured in bios */
@@ -543,82 +1663,47 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 	}
 	}
 }
 }
 
 
-static int byt_gpio_probe(struct platform_device *pdev)
+static int byt_gpio_probe(struct byt_gpio *vg)
 {
 {
-	struct byt_gpio *vg;
 	struct gpio_chip *gc;
 	struct gpio_chip *gc;
-	struct resource *mem_rc, *irq_rc;
-	struct device *dev = &pdev->dev;
-	struct acpi_device *acpi_dev;
-	struct pinctrl_gpio_range *range;
-	acpi_handle handle = ACPI_HANDLE(dev);
+	struct resource *irq_rc;
 	int ret;
 	int ret;
 
 
-	if (acpi_bus_get_device(handle, &acpi_dev))
-		return -ENODEV;
-
-	vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL);
-	if (!vg) {
-		dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n");
-		return -ENOMEM;
-	}
-
-	for (range = byt_ranges; range->name; range++) {
-		if (!strcmp(acpi_dev->pnp.unique_id, range->name)) {
-			vg->chip.ngpio = range->npins;
-			vg->range = range;
-			break;
-		}
-	}
-
-	if (!vg->chip.ngpio || !vg->range)
-		return -ENODEV;
-
-	vg->pdev = pdev;
-	platform_set_drvdata(pdev, vg);
-
-	mem_rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	vg->reg_base = devm_ioremap_resource(dev, mem_rc);
-	if (IS_ERR(vg->reg_base))
-		return PTR_ERR(vg->reg_base);
-
-	raw_spin_lock_init(&vg->lock);
-
-	gc = &vg->chip;
-	gc->label = dev_name(&pdev->dev);
-	gc->owner = THIS_MODULE;
-	gc->request = byt_gpio_request;
-	gc->free = byt_gpio_free;
-	gc->direction_input = byt_gpio_direction_input;
-	gc->direction_output = byt_gpio_direction_output;
-	gc->get = byt_gpio_get;
-	gc->set = byt_gpio_set;
-	gc->dbg_show = byt_gpio_dbg_show;
-	gc->base = -1;
-	gc->can_sleep = false;
-	gc->parent = dev;
+	/* Set up gpio chip */
+	vg->chip	= byt_gpio_chip;
+	gc		= &vg->chip;
+	gc->label	= dev_name(&vg->pdev->dev);
+	gc->base	= -1;
+	gc->can_sleep	= false;
+	gc->parent	= &vg->pdev->dev;
+	gc->ngpio	= vg->soc_data->npins;
 
 
 #ifdef CONFIG_PM_SLEEP
 #ifdef CONFIG_PM_SLEEP
-	vg->saved_context = devm_kcalloc(&pdev->dev, gc->ngpio,
+	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
 				       sizeof(*vg->saved_context), GFP_KERNEL);
 				       sizeof(*vg->saved_context), GFP_KERNEL);
 #endif
 #endif
-
 	ret = gpiochip_add_data(gc, vg);
 	ret = gpiochip_add_data(gc, vg);
 	if (ret) {
 	if (ret) {
-		dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
+		dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
+	ret = gpiochip_add_pin_range(&vg->chip, dev_name(&vg->pdev->dev),
+				     0, 0, vg->soc_data->npins);
+	if (ret) {
+		dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
+		goto fail;
+	}
+
 	/* set up interrupts  */
 	/* set up interrupts  */
-	irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0);
 	if (irq_rc && irq_rc->start) {
 	if (irq_rc && irq_rc->start) {
 		byt_gpio_irq_init_hw(vg);
 		byt_gpio_irq_init_hw(vg);
 		ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
 		ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
 					   handle_simple_irq, IRQ_TYPE_NONE);
 					   handle_simple_irq, IRQ_TYPE_NONE);
 		if (ret) {
 		if (ret) {
-			dev_err(dev, "failed to add irqchip\n");
-			gpiochip_remove(gc);
-			return ret;
+			dev_err(&vg->pdev->dev, "failed to add irqchip\n");
+			goto fail;
 		}
 		}
 
 
 		gpiochip_set_chained_irqchip(gc, &byt_irqchip,
 		gpiochip_set_chained_irqchip(gc, &byt_irqchip,
@@ -626,7 +1711,120 @@ static int byt_gpio_probe(struct platform_device *pdev)
 					     byt_gpio_irq_handler);
 					     byt_gpio_irq_handler);
 	}
 	}
 
 
-	pm_runtime_enable(dev);
+	return ret;
+
+fail:
+	gpiochip_remove(&vg->chip);
+
+	return ret;
+}
+
+static int byt_set_soc_data(struct byt_gpio *vg,
+			    const struct byt_pinctrl_soc_data *soc_data)
+{
+	int i;
+
+	vg->soc_data = soc_data;
+	vg->communities_copy = devm_kcalloc(&vg->pdev->dev,
+					    soc_data->ncommunities,
+					    sizeof(*vg->communities_copy),
+					    GFP_KERNEL);
+	if (!vg->communities_copy)
+		return -ENOMEM;
+
+	for (i = 0; i < soc_data->ncommunities; i++) {
+		struct byt_community *comm = vg->communities_copy + i;
+		struct resource *mem_rc;
+
+		*comm = vg->soc_data->communities[i];
+
+		mem_rc = platform_get_resource(vg->pdev, IORESOURCE_MEM, 0);
+		comm->reg_base = devm_ioremap_resource(&vg->pdev->dev, mem_rc);
+		if (IS_ERR(comm->reg_base))
+			return PTR_ERR(comm->reg_base);
+	}
+
+	return 0;
+}
+
+static const struct acpi_device_id byt_gpio_acpi_match[] = {
+	{ "INT33B2", (kernel_ulong_t)byt_soc_data },
+	{ "INT33FC", (kernel_ulong_t)byt_soc_data },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
+
+static int byt_pinctrl_probe(struct platform_device *pdev)
+{
+	const struct byt_pinctrl_soc_data *soc_data = NULL;
+	const struct byt_pinctrl_soc_data **soc_table;
+	const struct acpi_device_id *acpi_id;
+	struct acpi_device *acpi_dev;
+	struct byt_gpio *vg;
+	int i, ret;
+
+	acpi_dev = ACPI_COMPANION(&pdev->dev);
+	if (!acpi_dev)
+		return -ENODEV;
+
+	acpi_id = acpi_match_device(byt_gpio_acpi_match, &pdev->dev);
+	if (!acpi_id)
+		return -ENODEV;
+
+	soc_table = (const struct byt_pinctrl_soc_data **)acpi_id->driver_data;
+
+	for (i = 0; soc_table[i]; i++) {
+		if (!strcmp(acpi_dev->pnp.unique_id, soc_table[i]->uid)) {
+			soc_data = soc_table[i];
+			break;
+		}
+	}
+
+	if (!soc_data)
+		return -ENODEV;
+
+	vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL);
+	if (!vg)
+		return -ENOMEM;
+
+	vg->pdev = pdev;
+	ret = byt_set_soc_data(vg, soc_data);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to set soc data\n");
+		return ret;
+	}
+
+	vg->pctl_desc		= byt_pinctrl_desc;
+	vg->pctl_desc.name	= dev_name(&pdev->dev);
+	vg->pctl_desc.pins	= vg->soc_data->pins;
+	vg->pctl_desc.npins	= vg->soc_data->npins;
+
+	vg->pctl_dev = pinctrl_register(&vg->pctl_desc, &pdev->dev, vg);
+	if (IS_ERR(vg->pctl_dev)) {
+		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
+		return PTR_ERR(vg->pctl_dev);
+	}
+
+	ret = byt_gpio_probe(vg);
+	if (ret) {
+		pinctrl_unregister(vg->pctl_dev);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, vg);
+	raw_spin_lock_init(&vg->lock);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static int byt_pinctrl_remove(struct platform_device *pdev)
+{
+	struct byt_gpio *vg = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+	gpiochip_remove(&vg->chip);
+	pinctrl_unregister(vg->pctl_dev);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -638,15 +1836,22 @@ static int byt_gpio_suspend(struct device *dev)
 	struct byt_gpio *vg = platform_get_drvdata(pdev);
 	struct byt_gpio *vg = platform_get_drvdata(pdev);
 	int i;
 	int i;
 
 
-	for (i = 0; i < vg->chip.ngpio; i++) {
+	for (i = 0; i < vg->soc_data->npins; i++) {
 		void __iomem *reg;
 		void __iomem *reg;
 		u32 value;
 		u32 value;
-
-		reg = byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG);
+		unsigned int pin = vg->soc_data->pins[i].number;
+
+		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
+		if (!reg) {
+			dev_warn(&vg->pdev->dev,
+				 "Pin %i: could not retrieve conf0 register\n",
+				 i);
+			continue;
+		}
 		value = readl(reg) & BYT_CONF0_RESTORE_MASK;
 		value = readl(reg) & BYT_CONF0_RESTORE_MASK;
 		vg->saved_context[i].conf0 = value;
 		vg->saved_context[i].conf0 = value;
 
 
-		reg = byt_gpio_reg(&vg->chip, i, BYT_VAL_REG);
+		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
 		value = readl(reg) & BYT_VAL_RESTORE_MASK;
 		value = readl(reg) & BYT_VAL_RESTORE_MASK;
 		vg->saved_context[i].val = value;
 		vg->saved_context[i].val = value;
 	}
 	}
@@ -660,11 +1865,18 @@ static int byt_gpio_resume(struct device *dev)
 	struct byt_gpio *vg = platform_get_drvdata(pdev);
 	struct byt_gpio *vg = platform_get_drvdata(pdev);
 	int i;
 	int i;
 
 
-	for (i = 0; i < vg->chip.ngpio; i++) {
+	for (i = 0; i < vg->soc_data->npins; i++) {
 		void __iomem *reg;
 		void __iomem *reg;
 		u32 value;
 		u32 value;
-
-		reg = byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG);
+		unsigned int pin = vg->soc_data->pins[i].number;
+
+		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
+		if (!reg) {
+			dev_warn(&vg->pdev->dev,
+				 "Pin %i: could not retrieve conf0 register\n",
+				 i);
+			continue;
+		}
 		value = readl(reg);
 		value = readl(reg);
 		if ((value & BYT_CONF0_RESTORE_MASK) !=
 		if ((value & BYT_CONF0_RESTORE_MASK) !=
 		     vg->saved_context[i].conf0) {
 		     vg->saved_context[i].conf0) {
@@ -674,7 +1886,7 @@ static int byt_gpio_resume(struct device *dev)
 			dev_info(dev, "restored pin %d conf0 %#08x", i, value);
 			dev_info(dev, "restored pin %d conf0 %#08x", i, value);
 		}
 		}
 
 
-		reg = byt_gpio_reg(&vg->chip, i, BYT_VAL_REG);
+		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
 		value = readl(reg);
 		value = readl(reg);
 		if ((value & BYT_VAL_RESTORE_MASK) !=
 		if ((value & BYT_VAL_RESTORE_MASK) !=
 		     vg->saved_context[i].val) {
 		     vg->saved_context[i].val) {
@@ -712,26 +1924,9 @@ static const struct dev_pm_ops byt_gpio_pm_ops = {
 			   NULL)
 			   NULL)
 };
 };
 
 
-static const struct acpi_device_id byt_gpio_acpi_match[] = {
-	{ "INT33B2", 0 },
-	{ "INT33FC", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
-
-static int byt_gpio_remove(struct platform_device *pdev)
-{
-	struct byt_gpio *vg = platform_get_drvdata(pdev);
-
-	pm_runtime_disable(&pdev->dev);
-	gpiochip_remove(&vg->chip);
-
-	return 0;
-}
-
 static struct platform_driver byt_gpio_driver = {
 static struct platform_driver byt_gpio_driver = {
-	.probe          = byt_gpio_probe,
-	.remove         = byt_gpio_remove,
+	.probe          = byt_pinctrl_probe,
+	.remove         = byt_pinctrl_remove,
 	.driver         = {
 	.driver         = {
 		.name   = "byt_gpio",
 		.name   = "byt_gpio",
 		.pm	= &byt_gpio_pm_ops,
 		.pm	= &byt_gpio_pm_ops,

+ 3 - 5
drivers/pinctrl/intel/pinctrl-cherryview.c

@@ -1526,17 +1526,16 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
 	pctrl->pctldesc.pins = pctrl->community->pins;
 	pctrl->pctldesc.pins = pctrl->community->pins;
 	pctrl->pctldesc.npins = pctrl->community->npins;
 	pctrl->pctldesc.npins = pctrl->community->npins;
 
 
-	pctrl->pctldev = pinctrl_register(&pctrl->pctldesc, &pdev->dev, pctrl);
+	pctrl->pctldev = devm_pinctrl_register(&pdev->dev, &pctrl->pctldesc,
+					       pctrl);
 	if (IS_ERR(pctrl->pctldev)) {
 	if (IS_ERR(pctrl->pctldev)) {
 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
 		return PTR_ERR(pctrl->pctldev);
 		return PTR_ERR(pctrl->pctldev);
 	}
 	}
 
 
 	ret = chv_gpio_probe(pctrl, irq);
 	ret = chv_gpio_probe(pctrl, irq);
-	if (ret) {
-		pinctrl_unregister(pctrl->pctldev);
+	if (ret)
 		return ret;
 		return ret;
-	}
 
 
 	platform_set_drvdata(pdev, pctrl);
 	platform_set_drvdata(pdev, pctrl);
 
 
@@ -1548,7 +1547,6 @@ static int chv_pinctrl_remove(struct platform_device *pdev)
 	struct chv_pinctrl *pctrl = platform_get_drvdata(pdev);
 	struct chv_pinctrl *pctrl = platform_get_drvdata(pdev);
 
 
 	gpiochip_remove(&pctrl->chip);
 	gpiochip_remove(&pctrl->chip);
-	pinctrl_unregister(pctrl->pctldev);
 
 
 	return 0;
 	return 0;
 }
 }

+ 3 - 5
drivers/pinctrl/intel/pinctrl-intel.c

@@ -1045,17 +1045,16 @@ int intel_pinctrl_probe(struct platform_device *pdev,
 	pctrl->pctldesc.pins = pctrl->soc->pins;
 	pctrl->pctldesc.pins = pctrl->soc->pins;
 	pctrl->pctldesc.npins = pctrl->soc->npins;
 	pctrl->pctldesc.npins = pctrl->soc->npins;
 
 
-	pctrl->pctldev = pinctrl_register(&pctrl->pctldesc, &pdev->dev, pctrl);
+	pctrl->pctldev = devm_pinctrl_register(&pdev->dev, &pctrl->pctldesc,
+					       pctrl);
 	if (IS_ERR(pctrl->pctldev)) {
 	if (IS_ERR(pctrl->pctldev)) {
 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
 		return PTR_ERR(pctrl->pctldev);
 		return PTR_ERR(pctrl->pctldev);
 	}
 	}
 
 
 	ret = intel_gpio_probe(pctrl, irq);
 	ret = intel_gpio_probe(pctrl, irq);
-	if (ret) {
-		pinctrl_unregister(pctrl->pctldev);
+	if (ret)
 		return ret;
 		return ret;
-	}
 
 
 	platform_set_drvdata(pdev, pctrl);
 	platform_set_drvdata(pdev, pctrl);
 
 
@@ -1068,7 +1067,6 @@ int intel_pinctrl_remove(struct platform_device *pdev)
 	struct intel_pinctrl *pctrl = platform_get_drvdata(pdev);
 	struct intel_pinctrl *pctrl = platform_get_drvdata(pdev);
 
 
 	gpiochip_remove(&pctrl->chip);
 	gpiochip_remove(&pctrl->chip);
-	pinctrl_unregister(pctrl->pctldev);
 
 
 	return 0;
 	return 0;
 }
 }

+ 8 - 13
drivers/pinctrl/mediatek/pinctrl-mtk-common.c

@@ -605,7 +605,7 @@ static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 		ret = mtk_pctrl_dt_subnode_to_map(pctldev, np, map,
 		ret = mtk_pctrl_dt_subnode_to_map(pctldev, np, map,
 				&reserved_maps, num_maps);
 				&reserved_maps, num_maps);
 		if (ret < 0) {
 		if (ret < 0) {
-			pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+			pinctrl_utils_free_map(pctldev, *map, *num_maps);
 			of_node_put(np);
 			of_node_put(np);
 			return ret;
 			return ret;
 		}
 		}
@@ -644,7 +644,7 @@ static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
 
 
 static const struct pinctrl_ops mtk_pctrl_ops = {
 static const struct pinctrl_ops mtk_pctrl_ops = {
 	.dt_node_to_map		= mtk_pctrl_dt_node_to_map,
 	.dt_node_to_map		= mtk_pctrl_dt_node_to_map,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 	.get_groups_count	= mtk_pctrl_get_groups_count,
 	.get_groups_count	= mtk_pctrl_get_groups_count,
 	.get_group_name		= mtk_pctrl_get_group_name,
 	.get_group_name		= mtk_pctrl_get_group_name,
 	.get_group_pins		= mtk_pctrl_get_group_pins,
 	.get_group_pins		= mtk_pctrl_get_group_pins,
@@ -1396,17 +1396,16 @@ int mtk_pctrl_init(struct platform_device *pdev,
 	pctl->pctl_desc.pmxops = &mtk_pmx_ops;
 	pctl->pctl_desc.pmxops = &mtk_pmx_ops;
 	pctl->dev = &pdev->dev;
 	pctl->dev = &pdev->dev;
 
 
-	pctl->pctl_dev = pinctrl_register(&pctl->pctl_desc, &pdev->dev, pctl);
+	pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc,
+					       pctl);
 	if (IS_ERR(pctl->pctl_dev)) {
 	if (IS_ERR(pctl->pctl_dev)) {
 		dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
 		return PTR_ERR(pctl->pctl_dev);
 		return PTR_ERR(pctl->pctl_dev);
 	}
 	}
 
 
 	pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
 	pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
-	if (!pctl->chip) {
-		ret = -ENOMEM;
-		goto pctrl_error;
-	}
+	if (!pctl->chip)
+		return -ENOMEM;
 
 
 	*pctl->chip = mtk_gpio_chip;
 	*pctl->chip = mtk_gpio_chip;
 	pctl->chip->ngpio = pctl->devdata->npins;
 	pctl->chip->ngpio = pctl->devdata->npins;
@@ -1415,10 +1414,8 @@ int mtk_pctrl_init(struct platform_device *pdev,
 	pctl->chip->base = -1;
 	pctl->chip->base = -1;
 
 
 	ret = gpiochip_add_data(pctl->chip, pctl);
 	ret = gpiochip_add_data(pctl->chip, pctl);
-	if (ret) {
-		ret = -EINVAL;
-		goto pctrl_error;
-	}
+	if (ret)
+		return -EINVAL;
 
 
 	/* Register the GPIO to pin mappings. */
 	/* Register the GPIO to pin mappings. */
 	ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
 	ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
@@ -1496,8 +1493,6 @@ int mtk_pctrl_init(struct platform_device *pdev,
 
 
 chip_error:
 chip_error:
 	gpiochip_remove(pctl->chip);
 	gpiochip_remove(pctl->chip);
-pctrl_error:
-	pinctrl_unregister(pctl->pctl_dev);
 	return ret;
 	return ret;
 }
 }
 
 

+ 1 - 1
drivers/pinctrl/meson/Makefile

@@ -1,2 +1,2 @@
-obj-y	+= pinctrl-meson8.o pinctrl-meson8b.o
+obj-y	+= pinctrl-meson8.o pinctrl-meson8b.o pinctrl-meson-gxbb.o
 obj-y	+= pinctrl-meson.o
 obj-y	+= pinctrl-meson.o

+ 432 - 0
drivers/pinctrl/meson/pinctrl-meson-gxbb.c

@@ -0,0 +1,432 @@
+/*
+ * Pin controller and GPIO driver for Amlogic Meson GXBB.
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.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/>.
+ */
+
+#include <dt-bindings/gpio/meson-gxbb-gpio.h>
+#include "pinctrl-meson.h"
+
+#define EE_OFF	14
+
+static const struct pinctrl_pin_desc meson_gxbb_periphs_pins[] = {
+	MESON_PIN(GPIOZ_0, EE_OFF),
+	MESON_PIN(GPIOZ_1, EE_OFF),
+	MESON_PIN(GPIOZ_2, EE_OFF),
+	MESON_PIN(GPIOZ_3, EE_OFF),
+	MESON_PIN(GPIOZ_4, EE_OFF),
+	MESON_PIN(GPIOZ_5, EE_OFF),
+	MESON_PIN(GPIOZ_6, EE_OFF),
+	MESON_PIN(GPIOZ_7, EE_OFF),
+	MESON_PIN(GPIOZ_8, EE_OFF),
+	MESON_PIN(GPIOZ_9, EE_OFF),
+	MESON_PIN(GPIOZ_10, EE_OFF),
+	MESON_PIN(GPIOZ_11, EE_OFF),
+	MESON_PIN(GPIOZ_12, EE_OFF),
+	MESON_PIN(GPIOZ_13, EE_OFF),
+	MESON_PIN(GPIOZ_14, EE_OFF),
+	MESON_PIN(GPIOZ_15, EE_OFF),
+
+	MESON_PIN(GPIOH_0, EE_OFF),
+	MESON_PIN(GPIOH_1, EE_OFF),
+	MESON_PIN(GPIOH_2, EE_OFF),
+	MESON_PIN(GPIOH_3, EE_OFF),
+
+	MESON_PIN(BOOT_0, EE_OFF),
+	MESON_PIN(BOOT_1, EE_OFF),
+	MESON_PIN(BOOT_2, EE_OFF),
+	MESON_PIN(BOOT_3, EE_OFF),
+	MESON_PIN(BOOT_4, EE_OFF),
+	MESON_PIN(BOOT_5, EE_OFF),
+	MESON_PIN(BOOT_6, EE_OFF),
+	MESON_PIN(BOOT_7, EE_OFF),
+	MESON_PIN(BOOT_8, EE_OFF),
+	MESON_PIN(BOOT_9, EE_OFF),
+	MESON_PIN(BOOT_10, EE_OFF),
+	MESON_PIN(BOOT_11, EE_OFF),
+	MESON_PIN(BOOT_12, EE_OFF),
+	MESON_PIN(BOOT_13, EE_OFF),
+	MESON_PIN(BOOT_14, EE_OFF),
+	MESON_PIN(BOOT_15, EE_OFF),
+	MESON_PIN(BOOT_16, EE_OFF),
+	MESON_PIN(BOOT_17, EE_OFF),
+
+	MESON_PIN(CARD_0, EE_OFF),
+	MESON_PIN(CARD_1, EE_OFF),
+	MESON_PIN(CARD_2, EE_OFF),
+	MESON_PIN(CARD_3, EE_OFF),
+	MESON_PIN(CARD_4, EE_OFF),
+	MESON_PIN(CARD_5, EE_OFF),
+	MESON_PIN(CARD_6, EE_OFF),
+
+	MESON_PIN(GPIODV_0, EE_OFF),
+	MESON_PIN(GPIODV_1, EE_OFF),
+	MESON_PIN(GPIODV_2, EE_OFF),
+	MESON_PIN(GPIODV_3, EE_OFF),
+	MESON_PIN(GPIODV_4, EE_OFF),
+	MESON_PIN(GPIODV_5, EE_OFF),
+	MESON_PIN(GPIODV_6, EE_OFF),
+	MESON_PIN(GPIODV_7, EE_OFF),
+	MESON_PIN(GPIODV_8, EE_OFF),
+	MESON_PIN(GPIODV_9, EE_OFF),
+	MESON_PIN(GPIODV_10, EE_OFF),
+	MESON_PIN(GPIODV_11, EE_OFF),
+	MESON_PIN(GPIODV_12, EE_OFF),
+	MESON_PIN(GPIODV_13, EE_OFF),
+	MESON_PIN(GPIODV_14, EE_OFF),
+	MESON_PIN(GPIODV_15, EE_OFF),
+	MESON_PIN(GPIODV_16, EE_OFF),
+	MESON_PIN(GPIODV_17, EE_OFF),
+	MESON_PIN(GPIODV_19, EE_OFF),
+	MESON_PIN(GPIODV_20, EE_OFF),
+	MESON_PIN(GPIODV_21, EE_OFF),
+	MESON_PIN(GPIODV_22, EE_OFF),
+	MESON_PIN(GPIODV_23, EE_OFF),
+	MESON_PIN(GPIODV_24, EE_OFF),
+	MESON_PIN(GPIODV_25, EE_OFF),
+	MESON_PIN(GPIODV_26, EE_OFF),
+	MESON_PIN(GPIODV_27, EE_OFF),
+	MESON_PIN(GPIODV_28, EE_OFF),
+	MESON_PIN(GPIODV_29, EE_OFF),
+
+	MESON_PIN(GPIOY_0, EE_OFF),
+	MESON_PIN(GPIOY_1, EE_OFF),
+	MESON_PIN(GPIOY_2, EE_OFF),
+	MESON_PIN(GPIOY_3, EE_OFF),
+	MESON_PIN(GPIOY_4, EE_OFF),
+	MESON_PIN(GPIOY_5, EE_OFF),
+	MESON_PIN(GPIOY_6, EE_OFF),
+	MESON_PIN(GPIOY_7, EE_OFF),
+	MESON_PIN(GPIOY_8, EE_OFF),
+	MESON_PIN(GPIOY_9, EE_OFF),
+	MESON_PIN(GPIOY_10, EE_OFF),
+	MESON_PIN(GPIOY_11, EE_OFF),
+	MESON_PIN(GPIOY_12, EE_OFF),
+	MESON_PIN(GPIOY_13, EE_OFF),
+	MESON_PIN(GPIOY_14, EE_OFF),
+	MESON_PIN(GPIOY_15, EE_OFF),
+	MESON_PIN(GPIOY_16, EE_OFF),
+
+	MESON_PIN(GPIOX_0, EE_OFF),
+	MESON_PIN(GPIOX_1, EE_OFF),
+	MESON_PIN(GPIOX_2, EE_OFF),
+	MESON_PIN(GPIOX_3, EE_OFF),
+	MESON_PIN(GPIOX_4, EE_OFF),
+	MESON_PIN(GPIOX_5, EE_OFF),
+	MESON_PIN(GPIOX_6, EE_OFF),
+	MESON_PIN(GPIOX_7, EE_OFF),
+	MESON_PIN(GPIOX_8, EE_OFF),
+	MESON_PIN(GPIOX_9, EE_OFF),
+	MESON_PIN(GPIOX_10, EE_OFF),
+	MESON_PIN(GPIOX_11, EE_OFF),
+	MESON_PIN(GPIOX_12, EE_OFF),
+	MESON_PIN(GPIOX_13, EE_OFF),
+	MESON_PIN(GPIOX_14, EE_OFF),
+	MESON_PIN(GPIOX_15, EE_OFF),
+	MESON_PIN(GPIOX_16, EE_OFF),
+	MESON_PIN(GPIOX_17, EE_OFF),
+	MESON_PIN(GPIOX_18, EE_OFF),
+	MESON_PIN(GPIOX_19, EE_OFF),
+	MESON_PIN(GPIOX_20, EE_OFF),
+	MESON_PIN(GPIOX_21, EE_OFF),
+	MESON_PIN(GPIOX_22, EE_OFF),
+
+	MESON_PIN(GPIOCLK_0, EE_OFF),
+	MESON_PIN(GPIOCLK_1, EE_OFF),
+	MESON_PIN(GPIOCLK_2, EE_OFF),
+	MESON_PIN(GPIOCLK_3, EE_OFF),
+
+	MESON_PIN(GPIO_TEST_N, EE_OFF),
+};
+
+static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
+	MESON_PIN(GPIOAO_0, 0),
+	MESON_PIN(GPIOAO_1, 0),
+	MESON_PIN(GPIOAO_2, 0),
+	MESON_PIN(GPIOAO_3, 0),
+	MESON_PIN(GPIOAO_4, 0),
+	MESON_PIN(GPIOAO_5, 0),
+	MESON_PIN(GPIOAO_6, 0),
+	MESON_PIN(GPIOAO_7, 0),
+	MESON_PIN(GPIOAO_8, 0),
+	MESON_PIN(GPIOAO_9, 0),
+	MESON_PIN(GPIOAO_10, 0),
+	MESON_PIN(GPIOAO_11, 0),
+	MESON_PIN(GPIOAO_12, 0),
+	MESON_PIN(GPIOAO_13, 0),
+};
+
+static const unsigned int uart_tx_ao_a_pins[]	= { PIN(GPIOAO_0, 0) };
+static const unsigned int uart_rx_ao_a_pins[]	= { PIN(GPIOAO_1, 0) };
+static const unsigned int uart_cts_ao_a_pins[]	= { PIN(GPIOAO_2, 0) };
+static const unsigned int uart_rts_ao_a_pins[]	= { PIN(GPIOAO_3, 0) };
+
+static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
+	GPIO_GROUP(GPIOZ_0, EE_OFF),
+	GPIO_GROUP(GPIOZ_1, EE_OFF),
+	GPIO_GROUP(GPIOZ_2, EE_OFF),
+	GPIO_GROUP(GPIOZ_3, EE_OFF),
+	GPIO_GROUP(GPIOZ_4, EE_OFF),
+	GPIO_GROUP(GPIOZ_5, EE_OFF),
+	GPIO_GROUP(GPIOZ_6, EE_OFF),
+	GPIO_GROUP(GPIOZ_7, EE_OFF),
+	GPIO_GROUP(GPIOZ_8, EE_OFF),
+	GPIO_GROUP(GPIOZ_9, EE_OFF),
+	GPIO_GROUP(GPIOZ_10, EE_OFF),
+	GPIO_GROUP(GPIOZ_11, EE_OFF),
+	GPIO_GROUP(GPIOZ_12, EE_OFF),
+	GPIO_GROUP(GPIOZ_13, EE_OFF),
+	GPIO_GROUP(GPIOZ_14, EE_OFF),
+	GPIO_GROUP(GPIOZ_15, EE_OFF),
+
+	GPIO_GROUP(GPIOH_0, EE_OFF),
+	GPIO_GROUP(GPIOH_1, EE_OFF),
+	GPIO_GROUP(GPIOH_2, EE_OFF),
+	GPIO_GROUP(GPIOH_3, EE_OFF),
+
+	GPIO_GROUP(BOOT_0, EE_OFF),
+	GPIO_GROUP(BOOT_1, EE_OFF),
+	GPIO_GROUP(BOOT_2, EE_OFF),
+	GPIO_GROUP(BOOT_3, EE_OFF),
+	GPIO_GROUP(BOOT_4, EE_OFF),
+	GPIO_GROUP(BOOT_5, EE_OFF),
+	GPIO_GROUP(BOOT_6, EE_OFF),
+	GPIO_GROUP(BOOT_7, EE_OFF),
+	GPIO_GROUP(BOOT_8, EE_OFF),
+	GPIO_GROUP(BOOT_9, EE_OFF),
+	GPIO_GROUP(BOOT_10, EE_OFF),
+	GPIO_GROUP(BOOT_11, EE_OFF),
+	GPIO_GROUP(BOOT_12, EE_OFF),
+	GPIO_GROUP(BOOT_13, EE_OFF),
+	GPIO_GROUP(BOOT_14, EE_OFF),
+	GPIO_GROUP(BOOT_15, EE_OFF),
+	GPIO_GROUP(BOOT_16, EE_OFF),
+	GPIO_GROUP(BOOT_17, EE_OFF),
+
+	GPIO_GROUP(CARD_0, EE_OFF),
+	GPIO_GROUP(CARD_1, EE_OFF),
+	GPIO_GROUP(CARD_2, EE_OFF),
+	GPIO_GROUP(CARD_3, EE_OFF),
+	GPIO_GROUP(CARD_4, EE_OFF),
+	GPIO_GROUP(CARD_5, EE_OFF),
+	GPIO_GROUP(CARD_6, EE_OFF),
+
+	GPIO_GROUP(GPIODV_0, EE_OFF),
+	GPIO_GROUP(GPIODV_1, EE_OFF),
+	GPIO_GROUP(GPIODV_2, EE_OFF),
+	GPIO_GROUP(GPIODV_3, EE_OFF),
+	GPIO_GROUP(GPIODV_4, EE_OFF),
+	GPIO_GROUP(GPIODV_5, EE_OFF),
+	GPIO_GROUP(GPIODV_6, EE_OFF),
+	GPIO_GROUP(GPIODV_7, EE_OFF),
+	GPIO_GROUP(GPIODV_8, EE_OFF),
+	GPIO_GROUP(GPIODV_9, EE_OFF),
+	GPIO_GROUP(GPIODV_10, EE_OFF),
+	GPIO_GROUP(GPIODV_11, EE_OFF),
+	GPIO_GROUP(GPIODV_12, EE_OFF),
+	GPIO_GROUP(GPIODV_13, EE_OFF),
+	GPIO_GROUP(GPIODV_14, EE_OFF),
+	GPIO_GROUP(GPIODV_15, EE_OFF),
+	GPIO_GROUP(GPIODV_16, EE_OFF),
+	GPIO_GROUP(GPIODV_17, EE_OFF),
+	GPIO_GROUP(GPIODV_19, EE_OFF),
+	GPIO_GROUP(GPIODV_20, EE_OFF),
+	GPIO_GROUP(GPIODV_21, EE_OFF),
+	GPIO_GROUP(GPIODV_22, EE_OFF),
+	GPIO_GROUP(GPIODV_23, EE_OFF),
+	GPIO_GROUP(GPIODV_24, EE_OFF),
+	GPIO_GROUP(GPIODV_25, EE_OFF),
+	GPIO_GROUP(GPIODV_26, EE_OFF),
+	GPIO_GROUP(GPIODV_27, EE_OFF),
+	GPIO_GROUP(GPIODV_28, EE_OFF),
+	GPIO_GROUP(GPIODV_29, EE_OFF),
+
+	GPIO_GROUP(GPIOY_0, EE_OFF),
+	GPIO_GROUP(GPIOY_1, EE_OFF),
+	GPIO_GROUP(GPIOY_2, EE_OFF),
+	GPIO_GROUP(GPIOY_3, EE_OFF),
+	GPIO_GROUP(GPIOY_4, EE_OFF),
+	GPIO_GROUP(GPIOY_5, EE_OFF),
+	GPIO_GROUP(GPIOY_6, EE_OFF),
+	GPIO_GROUP(GPIOY_7, EE_OFF),
+	GPIO_GROUP(GPIOY_8, EE_OFF),
+	GPIO_GROUP(GPIOY_9, EE_OFF),
+	GPIO_GROUP(GPIOY_10, EE_OFF),
+	GPIO_GROUP(GPIOY_11, EE_OFF),
+	GPIO_GROUP(GPIOY_12, EE_OFF),
+	GPIO_GROUP(GPIOY_13, EE_OFF),
+	GPIO_GROUP(GPIOY_14, EE_OFF),
+	GPIO_GROUP(GPIOY_15, EE_OFF),
+	GPIO_GROUP(GPIOY_16, EE_OFF),
+
+	GPIO_GROUP(GPIOX_0, EE_OFF),
+	GPIO_GROUP(GPIOX_1, EE_OFF),
+	GPIO_GROUP(GPIOX_2, EE_OFF),
+	GPIO_GROUP(GPIOX_3, EE_OFF),
+	GPIO_GROUP(GPIOX_4, EE_OFF),
+	GPIO_GROUP(GPIOX_5, EE_OFF),
+	GPIO_GROUP(GPIOX_6, EE_OFF),
+	GPIO_GROUP(GPIOX_7, EE_OFF),
+	GPIO_GROUP(GPIOX_8, EE_OFF),
+	GPIO_GROUP(GPIOX_9, EE_OFF),
+	GPIO_GROUP(GPIOX_10, EE_OFF),
+	GPIO_GROUP(GPIOX_11, EE_OFF),
+	GPIO_GROUP(GPIOX_12, EE_OFF),
+	GPIO_GROUP(GPIOX_13, EE_OFF),
+	GPIO_GROUP(GPIOX_14, EE_OFF),
+	GPIO_GROUP(GPIOX_15, EE_OFF),
+	GPIO_GROUP(GPIOX_16, EE_OFF),
+	GPIO_GROUP(GPIOX_17, EE_OFF),
+	GPIO_GROUP(GPIOX_18, EE_OFF),
+	GPIO_GROUP(GPIOX_19, EE_OFF),
+	GPIO_GROUP(GPIOX_20, EE_OFF),
+	GPIO_GROUP(GPIOX_21, EE_OFF),
+	GPIO_GROUP(GPIOX_22, EE_OFF),
+
+	GPIO_GROUP(GPIOCLK_0, EE_OFF),
+	GPIO_GROUP(GPIOCLK_1, EE_OFF),
+	GPIO_GROUP(GPIOCLK_2, EE_OFF),
+	GPIO_GROUP(GPIOCLK_3, EE_OFF),
+
+	GPIO_GROUP(GPIO_TEST_N, EE_OFF),
+};
+
+static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
+	GPIO_GROUP(GPIOAO_0, 0),
+	GPIO_GROUP(GPIOAO_1, 0),
+	GPIO_GROUP(GPIOAO_2, 0),
+	GPIO_GROUP(GPIOAO_3, 0),
+	GPIO_GROUP(GPIOAO_4, 0),
+	GPIO_GROUP(GPIOAO_5, 0),
+	GPIO_GROUP(GPIOAO_6, 0),
+	GPIO_GROUP(GPIOAO_7, 0),
+	GPIO_GROUP(GPIOAO_8, 0),
+	GPIO_GROUP(GPIOAO_9, 0),
+	GPIO_GROUP(GPIOAO_10, 0),
+	GPIO_GROUP(GPIOAO_11, 0),
+	GPIO_GROUP(GPIOAO_12, 0),
+	GPIO_GROUP(GPIOAO_13, 0),
+
+	/* bank AO */
+	GROUP(uart_tx_ao_a,	0,	12),
+	GROUP(uart_rx_ao_a,	0,	11),
+	GROUP(uart_cts_ao_a,	0,	10),
+	GROUP(uart_rts_ao_a,	0,	9),
+};
+
+static const char * const gpio_periphs_groups[] = {
+	"GPIOZ_0", "GPIOZ_1", "GPIOZ_2", "GPIOZ_3", "GPIOZ_4",
+	"GPIOZ_5", "GPIOZ_6", "GPIOZ_7", "GPIOZ_8", "GPIOZ_9",
+	"GPIOZ_10", "GPIOZ_11", "GPIOZ_12", "GPIOZ_13", "GPIOZ_14",
+	"GPIOZ_15",
+
+	"GPIOH_0", "GPIOH_1", "GPIOH_2", "GPIOH_3",
+
+	"BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4",
+	"BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9",
+	"BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14",
+	"BOOT_15", "BOOT_16", "BOOT_17",
+
+	"CARD_0", "CARD_1", "CARD_2", "CARD_3", "CARD_4",
+	"CARD_5", "CARD_6",
+
+	"GPIODV_0", "GPIODV_1", "GPIODV_2", "GPIODV_3", "GPIODV_4",
+	"GPIODV_5", "GPIODV_6", "GPIODV_7", "GPIODV_8", "GPIODV_9",
+	"GPIODV_10", "GPIODV_11", "GPIODV_12", "GPIODV_13", "GPIODV_14",
+	"GPIODV_15", "GPIODV_16", "GPIODV_17", "GPIODV_18", "GPIODV_19",
+	"GPIODV_20", "GPIODV_21", "GPIODV_22", "GPIODV_23", "GPIODV_24",
+	"GPIODV_25", "GPIODV_26", "GPIODV_27", "GPIODV_28", "GPIODV_29",
+
+	"GPIOY_0", "GPIOY_1", "GPIOY_2", "GPIOY_3", "GPIOY_4",
+	"GPIOY_5", "GPIOY_6", "GPIOY_7", "GPIOY_8", "GPIOY_9",
+	"GPIOY_10", "GPIOY_11", "GPIOY_12", "GPIOY_13", "GPIOY_14",
+	"GPIOY_15", "GPIOY_16",
+
+	"GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
+	"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
+	"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
+	"GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18", "GPIOX_19",
+	"GPIOX_20", "GPIOX_21", "GPIOX_22",
+
+	"GPIO_TEST_N",
+};
+
+static const char * const gpio_aobus_groups[] = {
+	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
+	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
+	"GPIOAO_10", "GPIOAO_11", "GPIOAO_12", "GPIOAO_13",
+};
+
+static const char * const uart_ao_groups[] = {
+	"uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a"
+};
+
+static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
+	FUNCTION(gpio_periphs),
+};
+
+static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
+	FUNCTION(gpio_aobus),
+	FUNCTION(uart_ao),
+};
+
+static struct meson_bank meson_gxbb_periphs_banks[] = {
+	/*   name    first                      last                    pullen  pull    dir     out     in  */
+	BANK("X",    PIN(GPIOX_0, EE_OFF),	PIN(GPIOX_22, EE_OFF),  4,  0,  4,  0,  12, 0,  13, 0,  14, 0),
+	BANK("Y",    PIN(GPIOY_0, EE_OFF),	PIN(GPIOY_16, EE_OFF),  1,  0,  1,  0,  3,  0,  4,  0,  5,  0),
+	BANK("DV",   PIN(GPIODV_0, EE_OFF),	PIN(GPIODV_29, EE_OFF), 0,  0,  0,  0,  0,  0,  1,  0,  2,  0),
+	BANK("H",    PIN(GPIOH_0, EE_OFF),	PIN(GPIOH_3, EE_OFF),   1, 20,  1, 20,  3, 20,  4, 20,  5, 20),
+	BANK("Z",    PIN(GPIOZ_0, EE_OFF),	PIN(GPIOZ_15, EE_OFF),  3,  0,  3,  0,  9,  0,  10, 0, 11,  0),
+	BANK("CARD", PIN(CARD_0, EE_OFF),	PIN(CARD_6, EE_OFF),    2, 20,  2, 20,  6, 20,  7, 20,  8, 20),
+	BANK("BOOT", PIN(BOOT_0, EE_OFF),	PIN(BOOT_17, EE_OFF),   2,  0,  2,  0,  6,  0,  7,  0,  8,  0),
+	BANK("CLK",  PIN(GPIOCLK_0, EE_OFF),	PIN(GPIOCLK_3, EE_OFF), 3, 28,  3, 28,  9, 28, 10, 28, 11, 28),
+};
+
+static struct meson_bank meson_gxbb_aobus_banks[] = {
+	/*   name    first              last               pullen  pull    dir     out     in  */
+	BANK("AO",   PIN(GPIOAO_0, 0),  PIN(GPIOAO_13, 0), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+};
+
+static struct meson_domain_data meson_gxbb_periphs_domain_data = {
+	.name		= "periphs-banks",
+	.banks		= meson_gxbb_periphs_banks,
+	.num_banks	= ARRAY_SIZE(meson_gxbb_periphs_banks),
+	.pin_base	= 14,
+	.num_pins	= 120,
+};
+
+static struct meson_domain_data meson_gxbb_aobus_domain_data = {
+	.name		= "aobus-banks",
+	.banks		= meson_gxbb_aobus_banks,
+	.num_banks	= ARRAY_SIZE(meson_gxbb_aobus_banks),
+	.pin_base	= 0,
+	.num_pins	= 14,
+};
+
+struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
+	.pins		= meson_gxbb_periphs_pins,
+	.groups		= meson_gxbb_periphs_groups,
+	.funcs		= meson_gxbb_periphs_functions,
+	.domain_data	= &meson_gxbb_periphs_domain_data,
+	.num_pins	= ARRAY_SIZE(meson_gxbb_periphs_pins),
+	.num_groups	= ARRAY_SIZE(meson_gxbb_periphs_groups),
+	.num_funcs	= ARRAY_SIZE(meson_gxbb_periphs_functions),
+};
+
+struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data = {
+	.pins		= meson_gxbb_aobus_pins,
+	.groups		= meson_gxbb_aobus_groups,
+	.funcs		= meson_gxbb_aobus_functions,
+	.domain_data	= &meson_gxbb_aobus_domain_data,
+	.num_pins	= ARRAY_SIZE(meson_gxbb_aobus_pins),
+	.num_groups	= ARRAY_SIZE(meson_gxbb_aobus_groups),
+	.num_funcs	= ARRAY_SIZE(meson_gxbb_aobus_functions),
+};

+ 10 - 2
drivers/pinctrl/meson/pinctrl-meson.c

@@ -171,7 +171,7 @@ static const struct pinctrl_ops meson_pctrl_ops = {
 	.get_group_name		= meson_get_group_name,
 	.get_group_name		= meson_get_group_name,
 	.get_group_pins		= meson_get_group_pins,
 	.get_group_pins		= meson_get_group_pins,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_all,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_all,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 	.pin_dbg_show		= meson_pin_dbg_show,
 	.pin_dbg_show		= meson_pin_dbg_show,
 };
 };
 
 
@@ -549,6 +549,14 @@ static const struct of_device_id meson_pinctrl_dt_match[] = {
 		.compatible = "amlogic,meson8b-aobus-pinctrl",
 		.compatible = "amlogic,meson8b-aobus-pinctrl",
 		.data = &meson8b_aobus_pinctrl_data,
 		.data = &meson8b_aobus_pinctrl_data,
 	},
 	},
+	{
+		.compatible = "amlogic,meson-gxbb-periphs-pinctrl",
+		.data = &meson_gxbb_periphs_pinctrl_data,
+	},
+	{
+		.compatible = "amlogic,meson-gxbb-aobus-pinctrl",
+		.data = &meson_gxbb_aobus_pinctrl_data,
+	},
 	{ },
 	{ },
 };
 };
 
 
@@ -713,7 +721,7 @@ static int meson_pinctrl_probe(struct platform_device *pdev)
 	pc->desc.pins		= pc->data->pins;
 	pc->desc.pins		= pc->data->pins;
 	pc->desc.npins		= pc->data->num_pins;
 	pc->desc.npins		= pc->data->num_pins;
 
 
-	pc->pcdev = pinctrl_register(&pc->desc, pc->dev, pc);
+	pc->pcdev = devm_pinctrl_register(pc->dev, &pc->desc, pc);
 	if (IS_ERR(pc->pcdev)) {
 	if (IS_ERR(pc->pcdev)) {
 		dev_err(pc->dev, "can't register pinctrl device");
 		dev_err(pc->dev, "can't register pinctrl device");
 		return PTR_ERR(pc->pcdev);
 		return PTR_ERR(pc->pcdev);

+ 2 - 0
drivers/pinctrl/meson/pinctrl-meson.h

@@ -199,3 +199,5 @@ extern struct meson_pinctrl_data meson8_cbus_pinctrl_data;
 extern struct meson_pinctrl_data meson8_aobus_pinctrl_data;
 extern struct meson_pinctrl_data meson8_aobus_pinctrl_data;
 extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data;
 extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data;
 extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data;
 extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data;
+extern struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data;
+extern struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data;

+ 1 - 1
drivers/pinctrl/meson/pinctrl-meson8b.c

@@ -564,7 +564,7 @@ static struct meson_pmx_group meson8b_cbus_groups[] = {
 	GROUP(eth_rx_clk,	6,	3),
 	GROUP(eth_rx_clk,	6,	3),
 	GROUP(eth_txd0_1,	6,	4),
 	GROUP(eth_txd0_1,	6,	4),
 	GROUP(eth_txd1_1,	6,	5),
 	GROUP(eth_txd1_1,	6,	5),
-	GROUP(eth_tx_en,	6,	0),
+	GROUP(eth_tx_en,	6,	6),
 	GROUP(eth_ref_clk,	6,	8),
 	GROUP(eth_ref_clk,	6,	8),
 	GROUP(eth_mdc,		6,	9),
 	GROUP(eth_mdc,		6,	9),
 	GROUP(eth_mdio_en,	6,	10),
 	GROUP(eth_mdio_en,	6,	10),

+ 0 - 6
drivers/pinctrl/mvebu/pinctrl-armada-370.c

@@ -417,18 +417,12 @@ static int armada_370_pinctrl_probe(struct platform_device *pdev)
 	return mvebu_pinctrl_probe(pdev);
 	return mvebu_pinctrl_probe(pdev);
 }
 }
 
 
-static int armada_370_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
 static struct platform_driver armada_370_pinctrl_driver = {
 static struct platform_driver armada_370_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = "armada-370-pinctrl",
 		.name = "armada-370-pinctrl",
 		.of_match_table = armada_370_pinctrl_of_match,
 		.of_match_table = armada_370_pinctrl_of_match,
 	},
 	},
 	.probe = armada_370_pinctrl_probe,
 	.probe = armada_370_pinctrl_probe,
-	.remove = armada_370_pinctrl_remove,
 };
 };
 
 
 module_platform_driver(armada_370_pinctrl_driver);
 module_platform_driver(armada_370_pinctrl_driver);

+ 0 - 6
drivers/pinctrl/mvebu/pinctrl-armada-375.c

@@ -435,18 +435,12 @@ static int armada_375_pinctrl_probe(struct platform_device *pdev)
 	return mvebu_pinctrl_probe(pdev);
 	return mvebu_pinctrl_probe(pdev);
 }
 }
 
 
-static int armada_375_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
 static struct platform_driver armada_375_pinctrl_driver = {
 static struct platform_driver armada_375_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = "armada-375-pinctrl",
 		.name = "armada-375-pinctrl",
 		.of_match_table = of_match_ptr(armada_375_pinctrl_of_match),
 		.of_match_table = of_match_ptr(armada_375_pinctrl_of_match),
 	},
 	},
 	.probe = armada_375_pinctrl_probe,
 	.probe = armada_375_pinctrl_probe,
-	.remove = armada_375_pinctrl_remove,
 };
 };
 
 
 module_platform_driver(armada_375_pinctrl_driver);
 module_platform_driver(armada_375_pinctrl_driver);

+ 0 - 6
drivers/pinctrl/mvebu/pinctrl-armada-38x.c

@@ -446,18 +446,12 @@ static int armada_38x_pinctrl_probe(struct platform_device *pdev)
 	return mvebu_pinctrl_probe(pdev);
 	return mvebu_pinctrl_probe(pdev);
 }
 }
 
 
-static int armada_38x_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
 static struct platform_driver armada_38x_pinctrl_driver = {
 static struct platform_driver armada_38x_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = "armada-38x-pinctrl",
 		.name = "armada-38x-pinctrl",
 		.of_match_table = of_match_ptr(armada_38x_pinctrl_of_match),
 		.of_match_table = of_match_ptr(armada_38x_pinctrl_of_match),
 	},
 	},
 	.probe = armada_38x_pinctrl_probe,
 	.probe = armada_38x_pinctrl_probe,
-	.remove = armada_38x_pinctrl_remove,
 };
 };
 
 
 module_platform_driver(armada_38x_pinctrl_driver);
 module_platform_driver(armada_38x_pinctrl_driver);

+ 0 - 6
drivers/pinctrl/mvebu/pinctrl-armada-39x.c

@@ -428,18 +428,12 @@ static int armada_39x_pinctrl_probe(struct platform_device *pdev)
 	return mvebu_pinctrl_probe(pdev);
 	return mvebu_pinctrl_probe(pdev);
 }
 }
 
 
-static int armada_39x_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
 static struct platform_driver armada_39x_pinctrl_driver = {
 static struct platform_driver armada_39x_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = "armada-39x-pinctrl",
 		.name = "armada-39x-pinctrl",
 		.of_match_table = of_match_ptr(armada_39x_pinctrl_of_match),
 		.of_match_table = of_match_ptr(armada_39x_pinctrl_of_match),
 	},
 	},
 	.probe = armada_39x_pinctrl_probe,
 	.probe = armada_39x_pinctrl_probe,
-	.remove = armada_39x_pinctrl_remove,
 };
 };
 
 
 module_platform_driver(armada_39x_pinctrl_driver);
 module_platform_driver(armada_39x_pinctrl_driver);

+ 0 - 6
drivers/pinctrl/mvebu/pinctrl-armada-xp.c

@@ -502,18 +502,12 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
 	return mvebu_pinctrl_probe(pdev);
 	return mvebu_pinctrl_probe(pdev);
 }
 }
 
 
-static int armada_xp_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
 static struct platform_driver armada_xp_pinctrl_driver = {
 static struct platform_driver armada_xp_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = "armada-xp-pinctrl",
 		.name = "armada-xp-pinctrl",
 		.of_match_table = armada_xp_pinctrl_of_match,
 		.of_match_table = armada_xp_pinctrl_of_match,
 	},
 	},
 	.probe = armada_xp_pinctrl_probe,
 	.probe = armada_xp_pinctrl_probe,
-	.remove = armada_xp_pinctrl_remove,
 	.suspend = armada_xp_pinctrl_suspend,
 	.suspend = armada_xp_pinctrl_suspend,
 	.resume = armada_xp_pinctrl_resume,
 	.resume = armada_xp_pinctrl_resume,
 };
 };

+ 1 - 4
drivers/pinctrl/mvebu/pinctrl-dove.c

@@ -840,12 +840,9 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
 
 
 static int dove_pinctrl_remove(struct platform_device *pdev)
 static int dove_pinctrl_remove(struct platform_device *pdev)
 {
 {
-	int ret;
-
-	ret = mvebu_pinctrl_remove(pdev);
 	if (!IS_ERR(clk))
 	if (!IS_ERR(clk))
 		clk_disable_unprepare(clk);
 		clk_disable_unprepare(clk);
-	return ret;
+	return 0;
 }
 }
 
 
 static struct platform_driver dove_pinctrl_driver = {
 static struct platform_driver dove_pinctrl_driver = {

+ 0 - 6
drivers/pinctrl/mvebu/pinctrl-kirkwood.c

@@ -481,18 +481,12 @@ static int kirkwood_pinctrl_probe(struct platform_device *pdev)
 	return mvebu_pinctrl_probe(pdev);
 	return mvebu_pinctrl_probe(pdev);
 }
 }
 
 
-static int kirkwood_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
 static struct platform_driver kirkwood_pinctrl_driver = {
 static struct platform_driver kirkwood_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = "kirkwood-pinctrl",
 		.name = "kirkwood-pinctrl",
 		.of_match_table = kirkwood_pinctrl_of_match,
 		.of_match_table = kirkwood_pinctrl_of_match,
 	},
 	},
 	.probe = kirkwood_pinctrl_probe,
 	.probe = kirkwood_pinctrl_probe,
-	.remove = kirkwood_pinctrl_remove,
 };
 };
 
 
 module_platform_driver(kirkwood_pinctrl_driver);
 module_platform_driver(kirkwood_pinctrl_driver);

+ 1 - 8
drivers/pinctrl/mvebu/pinctrl-mvebu.c

@@ -711,7 +711,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 		return ret;
 		return ret;
 	}
 	}
 
 
-	pctl->pctldev = pinctrl_register(&pctl->desc, &pdev->dev, pctl);
+	pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pctl->desc, pctl);
 	if (IS_ERR(pctl->pctldev)) {
 	if (IS_ERR(pctl->pctldev)) {
 		dev_err(&pdev->dev, "unable to register pinctrl driver\n");
 		dev_err(&pdev->dev, "unable to register pinctrl driver\n");
 		return PTR_ERR(pctl->pctldev);
 		return PTR_ERR(pctl->pctldev);
@@ -725,10 +725,3 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 
 
 	return 0;
 	return 0;
 }
 }
-
-int mvebu_pinctrl_remove(struct platform_device *pdev)
-{
-	struct mvebu_pinctrl *pctl = platform_get_drvdata(pdev);
-	pinctrl_unregister(pctl->pctldev);
-	return 0;
-}

+ 0 - 1
drivers/pinctrl/mvebu/pinctrl-mvebu.h

@@ -202,6 +202,5 @@ static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid,
 }
 }
 
 
 int mvebu_pinctrl_probe(struct platform_device *pdev);
 int mvebu_pinctrl_probe(struct platform_device *pdev);
-int mvebu_pinctrl_remove(struct platform_device *pdev);
 
 
 #endif
 #endif

+ 0 - 6
drivers/pinctrl/mvebu/pinctrl-orion.c

@@ -239,18 +239,12 @@ static int orion_pinctrl_probe(struct platform_device *pdev)
 	return mvebu_pinctrl_probe(pdev);
 	return mvebu_pinctrl_probe(pdev);
 }
 }
 
 
-static int orion_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
 static struct platform_driver orion_pinctrl_driver = {
 static struct platform_driver orion_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = "orion-pinctrl",
 		.name = "orion-pinctrl",
 		.of_match_table = of_match_ptr(orion_pinctrl_of_match),
 		.of_match_table = of_match_ptr(orion_pinctrl_of_match),
 	},
 	},
 	.probe = orion_pinctrl_probe,
 	.probe = orion_pinctrl_probe,
-	.remove = orion_pinctrl_remove,
 };
 };
 
 
 module_platform_driver(orion_pinctrl_driver);
 module_platform_driver(orion_pinctrl_driver);

+ 4 - 3
drivers/pinctrl/nomadik/pinctrl-abx500.c

@@ -937,7 +937,7 @@ static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev,
 		ret = abx500_dt_subnode_to_map(pctldev, np, map,
 		ret = abx500_dt_subnode_to_map(pctldev, np, map,
 				&reserved_maps, num_maps);
 				&reserved_maps, num_maps);
 		if (ret < 0) {
 		if (ret < 0) {
-			pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+			pinctrl_utils_free_map(pctldev, *map, *num_maps);
 			return ret;
 			return ret;
 		}
 		}
 	}
 	}
@@ -951,7 +951,7 @@ static const struct pinctrl_ops abx500_pinctrl_ops = {
 	.get_group_pins = abx500_get_group_pins,
 	.get_group_pins = abx500_get_group_pins,
 	.pin_dbg_show = abx500_pin_dbg_show,
 	.pin_dbg_show = abx500_pin_dbg_show,
 	.dt_node_to_map = abx500_dt_node_to_map,
 	.dt_node_to_map = abx500_dt_node_to_map,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
 static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
@@ -1212,7 +1212,8 @@ static int abx500_gpio_probe(struct platform_device *pdev)
 
 
 	abx500_pinctrl_desc.pins = pct->soc->pins;
 	abx500_pinctrl_desc.pins = pct->soc->pins;
 	abx500_pinctrl_desc.npins = pct->soc->npins;
 	abx500_pinctrl_desc.npins = pct->soc->npins;
-	pct->pctldev = pinctrl_register(&abx500_pinctrl_desc, &pdev->dev, pct);
+	pct->pctldev = devm_pinctrl_register(&pdev->dev, &abx500_pinctrl_desc,
+					     pct);
 	if (IS_ERR(pct->pctldev)) {
 	if (IS_ERR(pct->pctldev)) {
 		dev_err(&pdev->dev,
 		dev_err(&pdev->dev,
 			"could not register abx500 pinctrl driver\n");
 			"could not register abx500 pinctrl driver\n");

+ 78 - 90
drivers/pinctrl/nomadik/pinctrl-nomadik.c

@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
 #include <linux/of_address.h>
+#include <linux/bitops.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/pinctrl/pinmux.h>
@@ -292,15 +293,14 @@ static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
 static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
 				unsigned offset, int gpio_mode)
 				unsigned offset, int gpio_mode)
 {
 {
-	u32 bit = 1 << offset;
 	u32 afunc, bfunc;
 	u32 afunc, bfunc;
 
 
-	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit;
-	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit;
+	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~BIT(offset);
+	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~BIT(offset);
 	if (gpio_mode & NMK_GPIO_ALT_A)
 	if (gpio_mode & NMK_GPIO_ALT_A)
-		afunc |= bit;
+		afunc |= BIT(offset);
 	if (gpio_mode & NMK_GPIO_ALT_B)
 	if (gpio_mode & NMK_GPIO_ALT_B)
-		bfunc |= bit;
+		bfunc |= BIT(offset);
 	writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA);
 	writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA);
 	writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB);
 	writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB);
 }
 }
@@ -308,55 +308,52 @@ static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip,
 				unsigned offset, enum nmk_gpio_slpm mode)
 				unsigned offset, enum nmk_gpio_slpm mode)
 {
 {
-	u32 bit = 1 << offset;
 	u32 slpm;
 	u32 slpm;
 
 
 	slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
 	slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
 	if (mode == NMK_GPIO_SLPM_NOCHANGE)
 	if (mode == NMK_GPIO_SLPM_NOCHANGE)
-		slpm |= bit;
+		slpm |= BIT(offset);
 	else
 	else
-		slpm &= ~bit;
+		slpm &= ~BIT(offset);
 	writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC);
 	writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC);
 }
 }
 
 
 static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
 				unsigned offset, enum nmk_gpio_pull pull)
 				unsigned offset, enum nmk_gpio_pull pull)
 {
 {
-	u32 bit = 1 << offset;
 	u32 pdis;
 	u32 pdis;
 
 
 	pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
 	pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
 	if (pull == NMK_GPIO_PULL_NONE) {
 	if (pull == NMK_GPIO_PULL_NONE) {
-		pdis |= bit;
-		nmk_chip->pull_up &= ~bit;
+		pdis |= BIT(offset);
+		nmk_chip->pull_up &= ~BIT(offset);
 	} else {
 	} else {
-		pdis &= ~bit;
+		pdis &= ~BIT(offset);
 	}
 	}
 
 
 	writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS);
 	writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS);
 
 
 	if (pull == NMK_GPIO_PULL_UP) {
 	if (pull == NMK_GPIO_PULL_UP) {
-		nmk_chip->pull_up |= bit;
-		writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
+		nmk_chip->pull_up |= BIT(offset);
+		writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATS);
 	} else if (pull == NMK_GPIO_PULL_DOWN) {
 	} else if (pull == NMK_GPIO_PULL_DOWN) {
-		nmk_chip->pull_up &= ~bit;
-		writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
+		nmk_chip->pull_up &= ~BIT(offset);
+		writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATC);
 	}
 	}
 }
 }
 
 
 static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip,
 				  unsigned offset, bool lowemi)
 				  unsigned offset, bool lowemi)
 {
 {
-	u32 bit = BIT(offset);
-	bool enabled = nmk_chip->lowemi & bit;
+	bool enabled = nmk_chip->lowemi & BIT(offset);
 
 
 	if (lowemi == enabled)
 	if (lowemi == enabled)
 		return;
 		return;
 
 
 	if (lowemi)
 	if (lowemi)
-		nmk_chip->lowemi |= bit;
+		nmk_chip->lowemi |= BIT(offset);
 	else
 	else
-		nmk_chip->lowemi &= ~bit;
+		nmk_chip->lowemi &= ~BIT(offset);
 
 
 	writel_relaxed(nmk_chip->lowemi,
 	writel_relaxed(nmk_chip->lowemi,
 		       nmk_chip->addr + NMK_GPIO_LOWEMI);
 		       nmk_chip->addr + NMK_GPIO_LOWEMI);
@@ -365,22 +362,22 @@ static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
 				  unsigned offset)
 				  unsigned offset)
 {
 {
-	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+	writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRC);
 }
 }
 
 
 static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
 				  unsigned offset, int val)
 				  unsigned offset, int val)
 {
 {
 	if (val)
 	if (val)
-		writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
+		writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATS);
 	else
 	else
-		writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
+		writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATC);
 }
 }
 
 
 static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
 				  unsigned offset, int val)
 				  unsigned offset, int val)
 {
 {
-	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
+	writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRS);
 	__nmk_gpio_set_output(nmk_chip, offset, val);
 	__nmk_gpio_set_output(nmk_chip, offset, val);
 }
 }
 
 
@@ -614,34 +611,7 @@ static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev,
 	return NMK_GPIO_ALT_C;
 	return NMK_GPIO_ALT_C;
 }
 }
 
 
-int nmk_gpio_get_mode(int gpio)
-{
-	struct nmk_gpio_chip *nmk_chip;
-	u32 afunc, bfunc, bit;
-
-	nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP];
-	if (!nmk_chip)
-		return -EINVAL;
-
-	bit = 1 << (gpio % NMK_GPIO_PER_CHIP);
-
-	clk_enable(nmk_chip->clk);
-
-	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
-	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
-
-	clk_disable(nmk_chip->clk);
-
-	return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
-}
-EXPORT_SYMBOL(nmk_gpio_get_mode);
-
-
 /* IRQ functions */
 /* IRQ functions */
-static inline int nmk_gpio_get_bitmask(int gpio)
-{
-	return 1 << (gpio % NMK_GPIO_PER_CHIP);
-}
 
 
 static void nmk_gpio_irq_ack(struct irq_data *d)
 static void nmk_gpio_irq_ack(struct irq_data *d)
 {
 {
@@ -649,7 +619,7 @@ static void nmk_gpio_irq_ack(struct irq_data *d)
 	struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
 	struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
 
 
 	clk_enable(nmk_chip->clk);
 	clk_enable(nmk_chip->clk);
-	writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC);
+	writel(BIT(d->hwirq), nmk_chip->addr + NMK_GPIO_IC);
 	clk_disable(nmk_chip->clk);
 	clk_disable(nmk_chip->clk);
 }
 }
 
 
@@ -659,10 +629,9 @@ enum nmk_gpio_irq_type {
 };
 };
 
 
 static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
-				  int gpio, enum nmk_gpio_irq_type which,
+				  int offset, enum nmk_gpio_irq_type which,
 				  bool enable)
 				  bool enable)
 {
 {
-	u32 bitmask = nmk_gpio_get_bitmask(gpio);
 	u32 *rimscval;
 	u32 *rimscval;
 	u32 *fimscval;
 	u32 *fimscval;
 	u32 rimscreg;
 	u32 rimscreg;
@@ -681,24 +650,24 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
 	}
 	}
 
 
 	/* we must individually set/clear the two edges */
 	/* we must individually set/clear the two edges */
-	if (nmk_chip->edge_rising & bitmask) {
+	if (nmk_chip->edge_rising & BIT(offset)) {
 		if (enable)
 		if (enable)
-			*rimscval |= bitmask;
+			*rimscval |= BIT(offset);
 		else
 		else
-			*rimscval &= ~bitmask;
+			*rimscval &= ~BIT(offset);
 		writel(*rimscval, nmk_chip->addr + rimscreg);
 		writel(*rimscval, nmk_chip->addr + rimscreg);
 	}
 	}
-	if (nmk_chip->edge_falling & bitmask) {
+	if (nmk_chip->edge_falling & BIT(offset)) {
 		if (enable)
 		if (enable)
-			*fimscval |= bitmask;
+			*fimscval |= BIT(offset);
 		else
 		else
-			*fimscval &= ~bitmask;
+			*fimscval &= ~BIT(offset);
 		writel(*fimscval, nmk_chip->addr + fimscreg);
 		writel(*fimscval, nmk_chip->addr + fimscreg);
 	}
 	}
 }
 }
 
 
 static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
 static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
-				int gpio, bool on)
+				int offset, bool on)
 {
 {
 	/*
 	/*
 	 * Ensure WAKEUP_ENABLE is on.  No need to disable it if wakeup is
 	 * Ensure WAKEUP_ENABLE is on.  No need to disable it if wakeup is
@@ -706,21 +675,19 @@ static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
 	 * wakeup is anyhow controlled by the RIMSC and FIMSC registers.
 	 * wakeup is anyhow controlled by the RIMSC and FIMSC registers.
 	 */
 	 */
 	if (nmk_chip->sleepmode && on) {
 	if (nmk_chip->sleepmode && on) {
-		__nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP,
+		__nmk_gpio_set_slpm(nmk_chip, offset,
 				    NMK_GPIO_SLPM_WAKEUP_ENABLE);
 				    NMK_GPIO_SLPM_WAKEUP_ENABLE);
 	}
 	}
 
 
-	__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
+	__nmk_gpio_irq_modify(nmk_chip, offset, WAKE, on);
 }
 }
 
 
 static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
 static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
 {
 {
 	struct nmk_gpio_chip *nmk_chip;
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
 	unsigned long flags;
-	u32 bitmask;
 
 
 	nmk_chip = irq_data_get_irq_chip_data(d);
 	nmk_chip = irq_data_get_irq_chip_data(d);
-	bitmask = nmk_gpio_get_bitmask(d->hwirq);
 	if (!nmk_chip)
 	if (!nmk_chip)
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -730,7 +697,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
 
 
 	__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable);
 	__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable);
 
 
-	if (!(nmk_chip->real_wake & bitmask))
+	if (!(nmk_chip->real_wake & BIT(d->hwirq)))
 		__nmk_gpio_set_wake(nmk_chip, d->hwirq, enable);
 		__nmk_gpio_set_wake(nmk_chip, d->hwirq, enable);
 
 
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock(&nmk_chip->lock);
@@ -754,12 +721,10 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 {
 	struct nmk_gpio_chip *nmk_chip;
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
 	unsigned long flags;
-	u32 bitmask;
 
 
 	nmk_chip = irq_data_get_irq_chip_data(d);
 	nmk_chip = irq_data_get_irq_chip_data(d);
 	if (!nmk_chip)
 	if (!nmk_chip)
 		return -EINVAL;
 		return -EINVAL;
-	bitmask = nmk_gpio_get_bitmask(d->hwirq);
 
 
 	clk_enable(nmk_chip->clk);
 	clk_enable(nmk_chip->clk);
 	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
 	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
@@ -769,9 +734,9 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 		__nmk_gpio_set_wake(nmk_chip, d->hwirq, on);
 		__nmk_gpio_set_wake(nmk_chip, d->hwirq, on);
 
 
 	if (on)
 	if (on)
-		nmk_chip->real_wake |= bitmask;
+		nmk_chip->real_wake |= BIT(d->hwirq);
 	else
 	else
-		nmk_chip->real_wake &= ~bitmask;
+		nmk_chip->real_wake &= ~BIT(d->hwirq);
 
 
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock(&nmk_chip->lock);
 	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
 	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
@@ -786,10 +751,8 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 	bool wake = irqd_is_wakeup_set(d);
 	bool wake = irqd_is_wakeup_set(d);
 	struct nmk_gpio_chip *nmk_chip;
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
 	unsigned long flags;
-	u32 bitmask;
 
 
 	nmk_chip = irq_data_get_irq_chip_data(d);
 	nmk_chip = irq_data_get_irq_chip_data(d);
-	bitmask = nmk_gpio_get_bitmask(d->hwirq);
 	if (!nmk_chip)
 	if (!nmk_chip)
 		return -EINVAL;
 		return -EINVAL;
 	if (type & IRQ_TYPE_LEVEL_HIGH)
 	if (type & IRQ_TYPE_LEVEL_HIGH)
@@ -806,13 +769,13 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 	if (enabled || wake)
 	if (enabled || wake)
 		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false);
 		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false);
 
 
-	nmk_chip->edge_rising &= ~bitmask;
+	nmk_chip->edge_rising &= ~BIT(d->hwirq);
 	if (type & IRQ_TYPE_EDGE_RISING)
 	if (type & IRQ_TYPE_EDGE_RISING)
-		nmk_chip->edge_rising |= bitmask;
+		nmk_chip->edge_rising |= BIT(d->hwirq);
 
 
-	nmk_chip->edge_falling &= ~bitmask;
+	nmk_chip->edge_falling &= ~BIT(d->hwirq);
 	if (type & IRQ_TYPE_EDGE_FALLING)
 	if (type & IRQ_TYPE_EDGE_FALLING)
-		nmk_chip->edge_falling |= bitmask;
+		nmk_chip->edge_falling |= BIT(d->hwirq);
 
 
 	if (enabled)
 	if (enabled)
 		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true);
 		__nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true);
@@ -884,13 +847,27 @@ static void nmk_gpio_latent_irq_handler(struct irq_desc *desc)
 
 
 /* I/O Functions */
 /* I/O Functions */
 
 
+static int nmk_gpio_get_dir(struct gpio_chip *chip, unsigned offset)
+{
+	struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
+	int dir;
+
+	clk_enable(nmk_chip->clk);
+
+	dir = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
+
+	clk_disable(nmk_chip->clk);
+
+	return dir;
+}
+
 static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
 static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
 {
 {
 	struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
 	struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
 
 
 	clk_enable(nmk_chip->clk);
 	clk_enable(nmk_chip->clk);
 
 
-	writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+	writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRC);
 
 
 	clk_disable(nmk_chip->clk);
 	clk_disable(nmk_chip->clk);
 
 
@@ -900,12 +877,11 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
 static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
 static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
 {
 {
 	struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
 	struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
-	u32 bit = 1 << offset;
 	int value;
 	int value;
 
 
 	clk_enable(nmk_chip->clk);
 	clk_enable(nmk_chip->clk);
 
 
-	value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+	value = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset));
 
 
 	clk_disable(nmk_chip->clk);
 	clk_disable(nmk_chip->clk);
 
 
@@ -939,6 +915,19 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
 }
 }
 
 
 #ifdef CONFIG_DEBUG_FS
 #ifdef CONFIG_DEBUG_FS
+static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
+{
+	u32 afunc, bfunc;
+
+	clk_enable(nmk_chip->clk);
+
+	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & BIT(offset);
+	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & BIT(offset);
+
+	clk_disable(nmk_chip->clk);
+
+	return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
+}
 
 
 #include <linux/seq_file.h>
 #include <linux/seq_file.h>
 
 
@@ -952,7 +941,6 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
 	bool is_out;
 	bool is_out;
 	bool data_out;
 	bool data_out;
 	bool pull;
 	bool pull;
-	u32 bit = 1 << offset;
 	const char *modes[] = {
 	const char *modes[] = {
 		[NMK_GPIO_ALT_GPIO]	= "gpio",
 		[NMK_GPIO_ALT_GPIO]	= "gpio",
 		[NMK_GPIO_ALT_A]	= "altA",
 		[NMK_GPIO_ALT_A]	= "altA",
@@ -970,10 +958,10 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
 	};
 	};
 
 
 	clk_enable(nmk_chip->clk);
 	clk_enable(nmk_chip->clk);
-	is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit);
-	pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
-	data_out = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & bit);
-	mode = nmk_gpio_get_mode(gpio);
+	is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
+	pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & BIT(offset));
+	data_out = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset));
+	mode = nmk_gpio_get_mode(nmk_chip, offset);
 	if ((mode == NMK_GPIO_ALT_C) && pctldev)
 	if ((mode == NMK_GPIO_ALT_C) && pctldev)
 		mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
 		mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
 
 
@@ -1007,11 +995,10 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
 		 */
 		 */
 		if (irq > 0 && desc && desc->action) {
 		if (irq > 0 && desc && desc->action) {
 			char *trigger;
 			char *trigger;
-			u32 bitmask = nmk_gpio_get_bitmask(gpio);
 
 
-			if (nmk_chip->edge_rising & bitmask)
+			if (nmk_chip->edge_rising & BIT(offset))
 				trigger = "edge-rising";
 				trigger = "edge-rising";
-			else if (nmk_chip->edge_falling & bitmask)
+			else if (nmk_chip->edge_falling & BIT(offset))
 				trigger = "edge-falling";
 				trigger = "edge-falling";
 			else
 			else
 				trigger = "edge-undefined";
 				trigger = "edge-undefined";
@@ -1246,6 +1233,7 @@ static int nmk_gpio_probe(struct platform_device *dev)
 	chip = &nmk_chip->chip;
 	chip = &nmk_chip->chip;
 	chip->request = gpiochip_generic_request;
 	chip->request = gpiochip_generic_request;
 	chip->free = gpiochip_generic_free;
 	chip->free = gpiochip_generic_free;
+	chip->get_direction = nmk_gpio_get_dir;
 	chip->direction_input = nmk_gpio_make_input;
 	chip->direction_input = nmk_gpio_make_input;
 	chip->get = nmk_gpio_get_input;
 	chip->get = nmk_gpio_get_input;
 	chip->direction_output = nmk_gpio_make_output;
 	chip->direction_output = nmk_gpio_make_output;
@@ -1612,7 +1600,7 @@ static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 		ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map,
 		ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map,
 				&reserved_maps, num_maps);
 				&reserved_maps, num_maps);
 		if (ret < 0) {
 		if (ret < 0) {
-			pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+			pinctrl_utils_free_map(pctldev, *map, *num_maps);
 			return ret;
 			return ret;
 		}
 		}
 	}
 	}
@@ -1626,7 +1614,7 @@ static const struct pinctrl_ops nmk_pinctrl_ops = {
 	.get_group_pins = nmk_get_group_pins,
 	.get_group_pins = nmk_get_group_pins,
 	.pin_dbg_show = nmk_pin_dbg_show,
 	.pin_dbg_show = nmk_pin_dbg_show,
 	.dt_node_to_map = nmk_pinctrl_dt_node_to_map,
 	.dt_node_to_map = nmk_pinctrl_dt_node_to_map,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
 static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
@@ -2044,7 +2032,7 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
 	nmk_pinctrl_desc.npins = npct->soc->npins;
 	nmk_pinctrl_desc.npins = npct->soc->npins;
 	npct->dev = &pdev->dev;
 	npct->dev = &pdev->dev;
 
 
-	npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct);
+	npct->pctl = devm_pinctrl_register(&pdev->dev, &nmk_pinctrl_desc, npct);
 	if (IS_ERR(npct->pctl)) {
 	if (IS_ERR(npct->pctl)) {
 		dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n");
 		dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n");
 		return PTR_ERR(npct->pctl);
 		return PTR_ERR(npct->pctl);

+ 1 - 1
drivers/pinctrl/pinconf-generic.c

@@ -386,7 +386,7 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
 	return 0;
 	return 0;
 
 
 exit:
 exit:
-	pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+	pinctrl_utils_free_map(pctldev, *map, *num_maps);
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map);
 EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map);

+ 2 - 11
drivers/pinctrl/pinctrl-adi2.c

@@ -1058,7 +1058,8 @@ static int adi_pinctrl_probe(struct platform_device *pdev)
 	adi_pinmux_desc.npins = pinctrl->soc->npins;
 	adi_pinmux_desc.npins = pinctrl->soc->npins;
 
 
 	/* Now register the pin controller and all pins it handles */
 	/* Now register the pin controller and all pins it handles */
-	pinctrl->pctl = pinctrl_register(&adi_pinmux_desc, &pdev->dev, pinctrl);
+	pinctrl->pctl = devm_pinctrl_register(&pdev->dev, &adi_pinmux_desc,
+					      pinctrl);
 	if (IS_ERR(pinctrl->pctl)) {
 	if (IS_ERR(pinctrl->pctl)) {
 		dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n");
 		dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n");
 		return PTR_ERR(pinctrl->pctl);
 		return PTR_ERR(pinctrl->pctl);
@@ -1069,18 +1070,8 @@ static int adi_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int adi_pinctrl_remove(struct platform_device *pdev)
-{
-	struct adi_pinctrl *pinctrl = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(pinctrl->pctl);
-
-	return 0;
-}
-
 static struct platform_driver adi_pinctrl_driver = {
 static struct platform_driver adi_pinctrl_driver = {
 	.probe		= adi_pinctrl_probe,
 	.probe		= adi_pinctrl_probe,
-	.remove		= adi_pinctrl_remove,
 	.driver		= {
 	.driver		= {
 		.name	= DRIVER_NAME,
 		.name	= DRIVER_NAME,
 	},
 	},

+ 5 - 7
drivers/pinctrl/pinctrl-amd.c

@@ -580,7 +580,7 @@ static const struct pinctrl_ops amd_pinctrl_ops = {
 	.get_group_pins		= amd_get_group_pins,
 	.get_group_pins		= amd_get_group_pins,
 #ifdef CONFIG_OF
 #ifdef CONFIG_OF
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 #endif
 #endif
 };
 };
 
 
@@ -783,8 +783,8 @@ static int amd_gpio_probe(struct platform_device *pdev)
 	gpio_dev->ngroups = ARRAY_SIZE(kerncz_groups);
 	gpio_dev->ngroups = ARRAY_SIZE(kerncz_groups);
 
 
 	amd_pinctrl_desc.name = dev_name(&pdev->dev);
 	amd_pinctrl_desc.name = dev_name(&pdev->dev);
-	gpio_dev->pctrl = pinctrl_register(&amd_pinctrl_desc,
-					&pdev->dev, gpio_dev);
+	gpio_dev->pctrl = devm_pinctrl_register(&pdev->dev, &amd_pinctrl_desc,
+						gpio_dev);
 	if (IS_ERR(gpio_dev->pctrl)) {
 	if (IS_ERR(gpio_dev->pctrl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		return PTR_ERR(gpio_dev->pctrl);
 		return PTR_ERR(gpio_dev->pctrl);
@@ -792,7 +792,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
 
 
 	ret = gpiochip_add_data(&gpio_dev->gc, gpio_dev);
 	ret = gpiochip_add_data(&gpio_dev->gc, gpio_dev);
 	if (ret)
 	if (ret)
-		goto out1;
+		return ret;
 
 
 	ret = gpiochip_add_pin_range(&gpio_dev->gc, dev_name(&pdev->dev),
 	ret = gpiochip_add_pin_range(&gpio_dev->gc, dev_name(&pdev->dev),
 				0, 0, TOTAL_NUMBER_OF_PINS);
 				0, 0, TOTAL_NUMBER_OF_PINS);
@@ -825,8 +825,6 @@ static int amd_gpio_probe(struct platform_device *pdev)
 out2:
 out2:
 	gpiochip_remove(&gpio_dev->gc);
 	gpiochip_remove(&gpio_dev->gc);
 
 
-out1:
-	pinctrl_unregister(gpio_dev->pctrl);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -837,13 +835,13 @@ static int amd_gpio_remove(struct platform_device *pdev)
 	gpio_dev = platform_get_drvdata(pdev);
 	gpio_dev = platform_get_drvdata(pdev);
 
 
 	gpiochip_remove(&gpio_dev->gc);
 	gpiochip_remove(&gpio_dev->gc);
-	pinctrl_unregister(gpio_dev->pctrl);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
 static const struct acpi_device_id amd_gpio_acpi_match[] = {
 static const struct acpi_device_id amd_gpio_acpi_match[] = {
 	{ "AMD0030", 0 },
 	{ "AMD0030", 0 },
+	{ "AMDI0030", 0},
 	{ },
 	{ },
 };
 };
 MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match);
 MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match);

+ 4 - 7
drivers/pinctrl/pinctrl-as3722.c

@@ -201,7 +201,7 @@ static const struct pinctrl_ops as3722_pinctrl_ops = {
 	.get_group_name = as3722_pinctrl_get_group_name,
 	.get_group_name = as3722_pinctrl_get_group_name,
 	.get_group_pins = as3722_pinctrl_get_group_pins,
 	.get_group_pins = as3722_pinctrl_get_group_pins,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int as3722_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
 static int as3722_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
@@ -569,8 +569,8 @@ static int as3722_pinctrl_probe(struct platform_device *pdev)
 	as3722_pinctrl_desc.name = dev_name(&pdev->dev);
 	as3722_pinctrl_desc.name = dev_name(&pdev->dev);
 	as3722_pinctrl_desc.pins = as3722_pins_desc;
 	as3722_pinctrl_desc.pins = as3722_pins_desc;
 	as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc);
 	as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc);
-	as_pci->pctl = pinctrl_register(&as3722_pinctrl_desc,
-					&pdev->dev, as_pci);
+	as_pci->pctl = devm_pinctrl_register(&pdev->dev, &as3722_pinctrl_desc,
+					     as_pci);
 	if (IS_ERR(as_pci->pctl)) {
 	if (IS_ERR(as_pci->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		return PTR_ERR(as_pci->pctl);
 		return PTR_ERR(as_pci->pctl);
@@ -582,7 +582,7 @@ static int as3722_pinctrl_probe(struct platform_device *pdev)
 	ret = gpiochip_add_data(&as_pci->gpio_chip, as_pci);
 	ret = gpiochip_add_data(&as_pci->gpio_chip, as_pci);
 	if (ret < 0) {
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Couldn't register gpiochip, %d\n", ret);
 		dev_err(&pdev->dev, "Couldn't register gpiochip, %d\n", ret);
-		goto fail_chip_add;
+		return ret;
 	}
 	}
 
 
 	ret = gpiochip_add_pin_range(&as_pci->gpio_chip, dev_name(&pdev->dev),
 	ret = gpiochip_add_pin_range(&as_pci->gpio_chip, dev_name(&pdev->dev),
@@ -596,8 +596,6 @@ static int as3722_pinctrl_probe(struct platform_device *pdev)
 
 
 fail_range_add:
 fail_range_add:
 	gpiochip_remove(&as_pci->gpio_chip);
 	gpiochip_remove(&as_pci->gpio_chip);
-fail_chip_add:
-	pinctrl_unregister(as_pci->pctl);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -606,7 +604,6 @@ static int as3722_pinctrl_remove(struct platform_device *pdev)
 	struct as3722_pctrl_info *as_pci = platform_get_drvdata(pdev);
 	struct as3722_pctrl_info *as_pci = platform_get_drvdata(pdev);
 
 
 	gpiochip_remove(&as_pci->gpio_chip);
 	gpiochip_remove(&as_pci->gpio_chip);
-	pinctrl_unregister(as_pci->pctl);
 	return 0;
 	return 0;
 }
 }
 
 

+ 15 - 15
drivers/pinctrl/pinctrl-at91-pio4.c

@@ -579,7 +579,7 @@ static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
 	}
 	}
 
 
 	if (ret < 0) {
 	if (ret < 0) {
-		pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+		pinctrl_utils_free_map(pctldev, *map, *num_maps);
 		dev_err(pctldev->dev, "can't create maps for node %s\n",
 		dev_err(pctldev->dev, "can't create maps for node %s\n",
 			np_config->full_name);
 			np_config->full_name);
 	}
 	}
@@ -592,7 +592,7 @@ static const struct pinctrl_ops atmel_pctlops = {
 	.get_group_name		= atmel_pctl_get_group_name,
 	.get_group_name		= atmel_pctl_get_group_name,
 	.get_group_pins		= atmel_pctl_get_group_pins,
 	.get_group_pins		= atmel_pctl_get_group_pins,
 	.dt_node_to_map		= atmel_pctl_dt_node_to_map,
 	.dt_node_to_map		= atmel_pctl_dt_node_to_map,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 };
 };
 
 
 static int atmel_pmx_get_functions_count(struct pinctrl_dev *pctldev)
 static int atmel_pmx_get_functions_count(struct pinctrl_dev *pctldev)
@@ -1036,18 +1036,19 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
 		goto clk_prepare_enable_error;
 		goto clk_prepare_enable_error;
 	}
 	}
 
 
-	atmel_pioctrl->pinctrl_dev = pinctrl_register(&atmel_pinctrl_desc,
-						      &pdev->dev,
-						      atmel_pioctrl);
-	if (!atmel_pioctrl->pinctrl_dev) {
+	atmel_pioctrl->pinctrl_dev = devm_pinctrl_register(&pdev->dev,
+							   &atmel_pinctrl_desc,
+							   atmel_pioctrl);
+	if (IS_ERR(atmel_pioctrl->pinctrl_dev)) {
+		ret = PTR_ERR(atmel_pioctrl->pinctrl_dev);
 		dev_err(dev, "pinctrl registration failed\n");
 		dev_err(dev, "pinctrl registration failed\n");
-		goto pinctrl_register_error;
+		goto clk_unprep;
 	}
 	}
 
 
 	ret = gpiochip_add_data(atmel_pioctrl->gpio_chip, atmel_pioctrl);
 	ret = gpiochip_add_data(atmel_pioctrl->gpio_chip, atmel_pioctrl);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "failed to add gpiochip\n");
 		dev_err(dev, "failed to add gpiochip\n");
-		goto gpiochip_add_error;
+		goto clk_unprep;
 	}
 	}
 
 
 	ret = gpiochip_add_pin_range(atmel_pioctrl->gpio_chip, dev_name(dev),
 	ret = gpiochip_add_pin_range(atmel_pioctrl->gpio_chip, dev_name(dev),
@@ -1061,15 +1062,15 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
 
 
 	return 0;
 	return 0;
 
 
-clk_prepare_enable_error:
-	irq_domain_remove(atmel_pioctrl->irq_domain);
-pinctrl_register_error:
-	clk_disable_unprepare(atmel_pioctrl->clk);
-gpiochip_add_error:
-	pinctrl_unregister(atmel_pioctrl->pinctrl_dev);
 gpiochip_add_pin_range_error:
 gpiochip_add_pin_range_error:
 	gpiochip_remove(atmel_pioctrl->gpio_chip);
 	gpiochip_remove(atmel_pioctrl->gpio_chip);
 
 
+clk_unprep:
+	clk_disable_unprepare(atmel_pioctrl->clk);
+
+clk_prepare_enable_error:
+	irq_domain_remove(atmel_pioctrl->irq_domain);
+
 	return ret;
 	return ret;
 }
 }
 
 
@@ -1079,7 +1080,6 @@ int atmel_pinctrl_remove(struct platform_device *pdev)
 
 
 	irq_domain_remove(atmel_pioctrl->irq_domain);
 	irq_domain_remove(atmel_pioctrl->irq_domain);
 	clk_disable_unprepare(atmel_pioctrl->clk);
 	clk_disable_unprepare(atmel_pioctrl->clk);
-	pinctrl_unregister(atmel_pioctrl->pinctrl_dev);
 	gpiochip_remove(atmel_pioctrl->gpio_chip);
 	gpiochip_remove(atmel_pioctrl->gpio_chip);
 
 
 	return 0;
 	return 0;

+ 6 - 22
drivers/pinctrl/pinctrl-at91.c

@@ -1252,7 +1252,8 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	platform_set_drvdata(pdev, info);
 	platform_set_drvdata(pdev, info);
-	info->pctl = pinctrl_register(&at91_pinctrl_desc, &pdev->dev, info);
+	info->pctl = devm_pinctrl_register(&pdev->dev, &at91_pinctrl_desc,
+					   info);
 
 
 	if (IS_ERR(info->pctl)) {
 	if (IS_ERR(info->pctl)) {
 		dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n");
 		dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n");
@@ -1269,15 +1270,6 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int at91_pinctrl_remove(struct platform_device *pdev)
-{
-	struct at91_pinctrl *info = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(info->pctl);
-
-	return 0;
-}
-
 static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
 static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
 {
 {
 	struct at91_gpio_chip *at91_gpio = gpiochip_get_data(chip);
 	struct at91_gpio_chip *at91_gpio = gpiochip_get_data(chip);
@@ -1660,7 +1652,7 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev,
 }
 }
 
 
 /* This structure is replicated for each GPIO block allocated at probe time */
 /* This structure is replicated for each GPIO block allocated at probe time */
-static struct gpio_chip at91_gpio_template = {
+static const struct gpio_chip at91_gpio_template = {
 	.request		= gpiochip_generic_request,
 	.request		= gpiochip_generic_request,
 	.free			= gpiochip_generic_free,
 	.free			= gpiochip_generic_free,
 	.get_direction		= at91_gpio_get_direction,
 	.get_direction		= at91_gpio_get_direction,
@@ -1730,14 +1722,9 @@ static int at91_gpio_probe(struct platform_device *pdev)
 		goto err;
 		goto err;
 	}
 	}
 
 
-	ret = clk_prepare(at91_chip->clock);
-	if (ret)
-		goto clk_prepare_err;
-
-	/* enable PIO controller's clock */
-	ret = clk_enable(at91_chip->clock);
+	ret = clk_prepare_enable(at91_chip->clock);
 	if (ret) {
 	if (ret) {
-		dev_err(&pdev->dev, "failed to enable clock, ignoring.\n");
+		dev_err(&pdev->dev, "failed to prepare and enable clock, ignoring.\n");
 		goto clk_enable_err;
 		goto clk_enable_err;
 	}
 	}
 
 
@@ -1797,10 +1784,8 @@ static int at91_gpio_probe(struct platform_device *pdev)
 irq_setup_err:
 irq_setup_err:
 	gpiochip_remove(chip);
 	gpiochip_remove(chip);
 gpiochip_add_err:
 gpiochip_add_err:
-	clk_disable(at91_chip->clock);
 clk_enable_err:
 clk_enable_err:
-	clk_unprepare(at91_chip->clock);
-clk_prepare_err:
+	clk_disable_unprepare(at91_chip->clock);
 err:
 err:
 	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
 	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
 
 
@@ -1821,7 +1806,6 @@ static struct platform_driver at91_pinctrl_driver = {
 		.of_match_table = at91_pinctrl_of_match,
 		.of_match_table = at91_pinctrl_of_match,
 	},
 	},
 	.probe = at91_pinctrl_probe,
 	.probe = at91_pinctrl_probe,
-	.remove = at91_pinctrl_remove,
 };
 };
 
 
 static struct platform_driver * const drivers[] = {
 static struct platform_driver * const drivers[] = {

+ 4 - 11
drivers/pinctrl/pinctrl-digicolor.c

@@ -84,7 +84,7 @@ static struct pinctrl_ops dc_pinctrl_ops = {
 	.get_group_name		= dc_get_group_name,
 	.get_group_name		= dc_get_group_name,
 	.get_group_pins		= dc_get_group_pins,
 	.get_group_pins		= dc_get_group_pins,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 };
 };
 
 
 static const char *const dc_functions[] = {
 static const char *const dc_functions[] = {
@@ -280,7 +280,7 @@ static int dc_pinctrl_probe(struct platform_device *pdev)
 	struct pinctrl_desc *pctl_desc;
 	struct pinctrl_desc *pctl_desc;
 	char *pin_names;
 	char *pin_names;
 	int name_len = strlen("GP_xx") + 1;
 	int name_len = strlen("GP_xx") + 1;
-	int i, j, ret;
+	int i, j;
 
 
 	pmap = devm_kzalloc(&pdev->dev, sizeof(*pmap), GFP_KERNEL);
 	pmap = devm_kzalloc(&pdev->dev, sizeof(*pmap), GFP_KERNEL);
 	if (!pmap)
 	if (!pmap)
@@ -326,26 +326,19 @@ static int dc_pinctrl_probe(struct platform_device *pdev)
 
 
 	pmap->dev = &pdev->dev;
 	pmap->dev = &pdev->dev;
 
 
-	pmap->pctl = pinctrl_register(pctl_desc, &pdev->dev, pmap);
+	pmap->pctl = devm_pinctrl_register(&pdev->dev, pctl_desc, pmap);
 	if (IS_ERR(pmap->pctl)) {
 	if (IS_ERR(pmap->pctl)) {
 		dev_err(&pdev->dev, "pinctrl driver registration failed\n");
 		dev_err(&pdev->dev, "pinctrl driver registration failed\n");
 		return PTR_ERR(pmap->pctl);
 		return PTR_ERR(pmap->pctl);
 	}
 	}
 
 
-	ret = dc_gpiochip_add(pmap, pdev->dev.of_node);
-	if (ret < 0) {
-		pinctrl_unregister(pmap->pctl);
-		return ret;
-	}
-
-	return 0;
+	return dc_gpiochip_add(pmap, pdev->dev.of_node);
 }
 }
 
 
 static int dc_pinctrl_remove(struct platform_device *pdev)
 static int dc_pinctrl_remove(struct platform_device *pdev)
 {
 {
 	struct dc_pinmap *pmap = platform_get_drvdata(pdev);
 	struct dc_pinmap *pmap = platform_get_drvdata(pdev);
 
 
-	pinctrl_unregister(pmap->pctl);
 	gpiochip_remove(&pmap->chip);
 	gpiochip_remove(&pmap->chip);
 
 
 	return 0;
 	return 0;

+ 1 - 1
drivers/pinctrl/pinctrl-lantiq.c

@@ -336,7 +336,7 @@ int ltq_pinctrl_register(struct platform_device *pdev,
 	desc->pmxops = &ltq_pmx_ops;
 	desc->pmxops = &ltq_pmx_ops;
 	info->dev = &pdev->dev;
 	info->dev = &pdev->dev;
 
 
-	info->pctrl = pinctrl_register(desc, &pdev->dev, info);
+	info->pctrl = devm_pinctrl_register(&pdev->dev, desc, info);
 	if (IS_ERR(info->pctrl)) {
 	if (IS_ERR(info->pctrl)) {
 		dev_err(&pdev->dev, "failed to register LTQ pinmux driver\n");
 		dev_err(&pdev->dev, "failed to register LTQ pinmux driver\n");
 		return PTR_ERR(info->pctrl);
 		return PTR_ERR(info->pctrl);

+ 2 - 3
drivers/pinctrl/pinctrl-lpc18xx.c

@@ -1252,7 +1252,7 @@ static const struct pinctrl_ops lpc18xx_pctl_ops = {
 	.get_group_name		= lpc18xx_pctl_get_group_name,
 	.get_group_name		= lpc18xx_pctl_get_group_name,
 	.get_group_pins		= lpc18xx_pctl_get_group_pins,
 	.get_group_pins		= lpc18xx_pctl_get_group_pins,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 };
 };
 
 
 static struct pinctrl_desc lpc18xx_scu_desc = {
 static struct pinctrl_desc lpc18xx_scu_desc = {
@@ -1355,7 +1355,7 @@ static int lpc18xx_scu_probe(struct platform_device *pdev)
 
 
 	platform_set_drvdata(pdev, scu);
 	platform_set_drvdata(pdev, scu);
 
 
-	scu->pctl = pinctrl_register(&lpc18xx_scu_desc, &pdev->dev, scu);
+	scu->pctl = devm_pinctrl_register(&pdev->dev, &lpc18xx_scu_desc, scu);
 	if (IS_ERR(scu->pctl)) {
 	if (IS_ERR(scu->pctl)) {
 		dev_err(&pdev->dev, "Could not register pinctrl driver\n");
 		dev_err(&pdev->dev, "Could not register pinctrl driver\n");
 		clk_disable_unprepare(scu->clk);
 		clk_disable_unprepare(scu->clk);
@@ -1369,7 +1369,6 @@ static int lpc18xx_scu_remove(struct platform_device *pdev)
 {
 {
 	struct lpc18xx_scu_data *scu = platform_get_drvdata(pdev);
 	struct lpc18xx_scu_data *scu = platform_get_drvdata(pdev);
 
 
-	pinctrl_unregister(scu->pctl);
 	clk_disable_unprepare(scu->clk);
 	clk_disable_unprepare(scu->clk);
 
 
 	return 0;
 	return 0;

+ 3 - 11
drivers/pinctrl/pinctrl-palmas.c

@@ -656,7 +656,7 @@ static const struct pinctrl_ops palmas_pinctrl_ops = {
 	.get_group_name = palmas_pinctrl_get_group_name,
 	.get_group_name = palmas_pinctrl_get_group_name,
 	.get_group_pins = palmas_pinctrl_get_group_pins,
 	.get_group_pins = palmas_pinctrl_get_group_pins,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int palmas_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
 static int palmas_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
@@ -1043,7 +1043,8 @@ static int palmas_pinctrl_probe(struct platform_device *pdev)
 	palmas_pinctrl_desc.name = dev_name(&pdev->dev);
 	palmas_pinctrl_desc.name = dev_name(&pdev->dev);
 	palmas_pinctrl_desc.pins = palmas_pins_desc;
 	palmas_pinctrl_desc.pins = palmas_pins_desc;
 	palmas_pinctrl_desc.npins = ARRAY_SIZE(palmas_pins_desc);
 	palmas_pinctrl_desc.npins = ARRAY_SIZE(palmas_pins_desc);
-	pci->pctl = pinctrl_register(&palmas_pinctrl_desc, &pdev->dev, pci);
+	pci->pctl = devm_pinctrl_register(&pdev->dev, &palmas_pinctrl_desc,
+					  pci);
 	if (IS_ERR(pci->pctl)) {
 	if (IS_ERR(pci->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		return PTR_ERR(pci->pctl);
 		return PTR_ERR(pci->pctl);
@@ -1051,21 +1052,12 @@ static int palmas_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int palmas_pinctrl_remove(struct platform_device *pdev)
-{
-	struct palmas_pctrl_chip_info *pci = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(pci->pctl);
-	return 0;
-}
-
 static struct platform_driver palmas_pinctrl_driver = {
 static struct platform_driver palmas_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = "palmas-pinctrl",
 		.name = "palmas-pinctrl",
 		.of_match_table = palmas_pinctrl_of_match,
 		.of_match_table = palmas_pinctrl_of_match,
 	},
 	},
 	.probe = palmas_pinctrl_probe,
 	.probe = palmas_pinctrl_probe,
-	.remove = palmas_pinctrl_remove,
 };
 };
 
 
 module_platform_driver(palmas_pinctrl_driver);
 module_platform_driver(palmas_pinctrl_driver);

+ 3 - 2
drivers/pinctrl/pinctrl-pic32.c

@@ -1743,7 +1743,7 @@ static const struct pinctrl_ops pic32_pinctrl_ops = {
 	.get_group_name = pic32_pinctrl_get_group_name,
 	.get_group_name = pic32_pinctrl_get_group_name,
 	.get_group_pins = pic32_pinctrl_get_group_pins,
 	.get_group_pins = pic32_pinctrl_get_group_pins,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int pic32_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
 static int pic32_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
@@ -2194,7 +2194,8 @@ static int pic32_pinctrl_probe(struct platform_device *pdev)
 	pic32_pinctrl_desc.custom_params = pic32_mpp_bindings;
 	pic32_pinctrl_desc.custom_params = pic32_mpp_bindings;
 	pic32_pinctrl_desc.num_custom_params = ARRAY_SIZE(pic32_mpp_bindings);
 	pic32_pinctrl_desc.num_custom_params = ARRAY_SIZE(pic32_mpp_bindings);
 
 
-	pctl->pctldev = pinctrl_register(&pic32_pinctrl_desc, &pdev->dev, pctl);
+	pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pic32_pinctrl_desc,
+					      pctl);
 	if (IS_ERR(pctl->pctldev)) {
 	if (IS_ERR(pctl->pctldev)) {
 		dev_err(&pdev->dev, "Failed to register pinctrl device\n");
 		dev_err(&pdev->dev, "Failed to register pinctrl device\n");
 		return PTR_ERR(pctl->pctldev);
 		return PTR_ERR(pctl->pctldev);

+ 3 - 3
drivers/pinctrl/pinctrl-pistachio.c

@@ -913,7 +913,7 @@ static const struct pinctrl_ops pistachio_pinctrl_ops = {
 	.get_group_name = pistachio_pinctrl_get_group_name,
 	.get_group_name = pistachio_pinctrl_get_group_name,
 	.get_group_pins = pistachio_pinctrl_get_group_pins,
 	.get_group_pins = pistachio_pinctrl_get_group_pins,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 static int pistachio_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
 static int pistachio_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
@@ -1457,8 +1457,8 @@ static int pistachio_pinctrl_probe(struct platform_device *pdev)
 	pistachio_pinctrl_desc.pins = pctl->pins;
 	pistachio_pinctrl_desc.pins = pctl->pins;
 	pistachio_pinctrl_desc.npins = pctl->npins;
 	pistachio_pinctrl_desc.npins = pctl->npins;
 
 
-	pctl->pctldev = pinctrl_register(&pistachio_pinctrl_desc, &pdev->dev,
-					 pctl);
+	pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pistachio_pinctrl_desc,
+					      pctl);
 	if (IS_ERR(pctl->pctldev)) {
 	if (IS_ERR(pctl->pctldev)) {
 		dev_err(&pdev->dev, "Failed to register pinctrl device\n");
 		dev_err(&pdev->dev, "Failed to register pinctrl device\n");
 		return PTR_ERR(pctl->pctldev);
 		return PTR_ERR(pctl->pctldev);

+ 139 - 53
drivers/pinctrl/pinctrl-rockchip.c

@@ -98,6 +98,15 @@ enum rockchip_pin_drv_type {
 	DRV_TYPE_MAX
 	DRV_TYPE_MAX
 };
 };
 
 
+/**
+ * enum type index corresponding to rockchip_pull_list arrays index.
+ */
+enum rockchip_pin_pull_type {
+	PULL_TYPE_IO_DEFAULT = 0,
+	PULL_TYPE_IO_1V8_ONLY,
+	PULL_TYPE_MAX
+};
+
 /**
 /**
  * @drv_type: drive strength variant using rockchip_perpin_drv_type
  * @drv_type: drive strength variant using rockchip_perpin_drv_type
  * @offset: if initialized to -1 it will be autocalculated, by specifying
  * @offset: if initialized to -1 it will be autocalculated, by specifying
@@ -123,6 +132,7 @@ struct rockchip_drv {
  * @bank_num: number of the bank, to account for holes
  * @bank_num: number of the bank, to account for holes
  * @iomux: array describing the 4 iomux sources of the bank
  * @iomux: array describing the 4 iomux sources of the bank
  * @drv: array describing the 4 drive strength sources of the bank
  * @drv: array describing the 4 drive strength sources of the bank
+ * @pull_type: array describing the 4 pull type sources of the bank
  * @valid: are all necessary informations present
  * @valid: are all necessary informations present
  * @of_node: dt node of this bank
  * @of_node: dt node of this bank
  * @drvdata: common pinctrl basedata
  * @drvdata: common pinctrl basedata
@@ -143,6 +153,7 @@ struct rockchip_pin_bank {
 	u8				bank_num;
 	u8				bank_num;
 	struct rockchip_iomux		iomux[4];
 	struct rockchip_iomux		iomux[4];
 	struct rockchip_drv		drv[4];
 	struct rockchip_drv		drv[4];
+	enum rockchip_pin_pull_type	pull_type[4];
 	bool				valid;
 	bool				valid;
 	struct device_node		*of_node;
 	struct device_node		*of_node;
 	struct rockchip_pinctrl		*drvdata;
 	struct rockchip_pinctrl		*drvdata;
@@ -198,6 +209,31 @@ struct rockchip_pin_bank {
 		},							\
 		},							\
 	}
 	}
 
 
+#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1,	\
+				      drv2, drv3, pull0, pull1,		\
+				      pull2, pull3)			\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = -1 },		\
+			{ .drv_type = drv1, .offset = -1 },		\
+			{ .drv_type = drv2, .offset = -1 },		\
+			{ .drv_type = drv3, .offset = -1 },		\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
 #define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1,	\
 #define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1,	\
 					iom2, iom3, drv0, drv1, drv2,	\
 					iom2, iom3, drv0, drv1, drv2,	\
 					drv3, offset0, offset1,		\
 					drv3, offset0, offset1,		\
@@ -220,6 +256,34 @@ struct rockchip_pin_bank {
 		},							\
 		},							\
 	}
 	}
 
 
+#define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins,	\
+					      label, iom0, iom1, iom2,  \
+					      iom3, drv0, drv1, drv2,   \
+					      drv3, offset0, offset1,   \
+					      offset2, offset3, pull0,  \
+					      pull1, pull2, pull3)	\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = offset0 },	\
+			{ .drv_type = drv1, .offset = offset1 },	\
+			{ .drv_type = drv2, .offset = offset2 },	\
+			{ .drv_type = drv3, .offset = offset3 },	\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
 /**
 /**
  */
  */
 struct rockchip_pin_ctrl {
 struct rockchip_pin_ctrl {
@@ -1020,12 +1084,27 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 	return ret;
 	return ret;
 }
 }
 
 
+static int rockchip_pull_list[PULL_TYPE_MAX][4] = {
+	{
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_UP,
+		PIN_CONFIG_BIAS_PULL_DOWN,
+		PIN_CONFIG_BIAS_BUS_HOLD
+	},
+	{
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_DOWN,
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_UP
+	},
+};
+
 static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 {
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
 	struct rockchip_pinctrl *info = bank->drvdata;
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct regmap *regmap;
 	struct regmap *regmap;
-	int reg, ret;
+	int reg, ret, pull_type;
 	u8 bit;
 	u8 bit;
 	u32 data;
 	u32 data;
 
 
@@ -1048,22 +1127,11 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 	case RK3288:
 	case RK3288:
 	case RK3368:
 	case RK3368:
 	case RK3399:
 	case RK3399:
+		pull_type = bank->pull_type[pin_num / 8];
 		data >>= bit;
 		data >>= bit;
 		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
 		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
 
 
-		switch (data) {
-		case 0:
-			return PIN_CONFIG_BIAS_DISABLE;
-		case 1:
-			return PIN_CONFIG_BIAS_PULL_UP;
-		case 2:
-			return PIN_CONFIG_BIAS_PULL_DOWN;
-		case 3:
-			return PIN_CONFIG_BIAS_BUS_HOLD;
-		}
-
-		dev_err(info->dev, "unknown pull setting\n");
-		return -EIO;
+		return rockchip_pull_list[pull_type][data];
 	default:
 	default:
 		dev_err(info->dev, "unsupported pinctrl type\n");
 		dev_err(info->dev, "unsupported pinctrl type\n");
 		return -EINVAL;
 		return -EINVAL;
@@ -1076,7 +1144,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 	struct rockchip_pinctrl *info = bank->drvdata;
 	struct rockchip_pinctrl *info = bank->drvdata;
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct regmap *regmap;
 	struct regmap *regmap;
-	int reg, ret;
+	int reg, ret, i, pull_type;
 	unsigned long flags;
 	unsigned long flags;
 	u8 bit;
 	u8 bit;
 	u32 data, rmask;
 	u32 data, rmask;
@@ -1105,30 +1173,28 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 	case RK3288:
 	case RK3288:
 	case RK3368:
 	case RK3368:
 	case RK3399:
 	case RK3399:
+		pull_type = bank->pull_type[pin_num / 8];
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[pull_type]);
+			i++) {
+			if (rockchip_pull_list[pull_type][i] == pull) {
+				ret = i;
+				break;
+			}
+		}
+
+		if (ret < 0) {
+			dev_err(info->dev, "unsupported pull setting %d\n",
+				pull);
+			return ret;
+		}
+
 		spin_lock_irqsave(&bank->slock, flags);
 		spin_lock_irqsave(&bank->slock, flags);
 
 
 		/* enable the write to the equivalent lower bits */
 		/* enable the write to the equivalent lower bits */
 		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
 		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
 		rmask = data | (data >> 16);
 		rmask = data | (data >> 16);
-
-		switch (pull) {
-		case PIN_CONFIG_BIAS_DISABLE:
-			break;
-		case PIN_CONFIG_BIAS_PULL_UP:
-			data |= (1 << bit);
-			break;
-		case PIN_CONFIG_BIAS_PULL_DOWN:
-			data |= (2 << bit);
-			break;
-		case PIN_CONFIG_BIAS_BUS_HOLD:
-			data |= (3 << bit);
-			break;
-		default:
-			spin_unlock_irqrestore(&bank->slock, flags);
-			dev_err(info->dev, "unsupported pull setting %d\n",
-				pull);
-			return -EINVAL;
-		}
+		data |= (ret << bit);
 
 
 		ret = regmap_update_bits(regmap, reg, rmask, data);
 		ret = regmap_update_bits(regmap, reg, rmask, data);
 
 
@@ -1208,6 +1274,16 @@ static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
 	return 0;
 	return 0;
 }
 }
 
 
+static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+	struct rockchip_pin_bank *bank = gpiochip_get_data(chip);
+	u32 data;
+
+	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
+
+	return !(data & BIT(offset));
+}
+
 /*
 /*
  * The calls to gpio_direction_output() and gpio_direction_input()
  * The calls to gpio_direction_output() and gpio_direction_input()
  * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
  * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
@@ -1636,7 +1712,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info);
+	info->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, info);
 	if (IS_ERR(info->pctl_dev)) {
 	if (IS_ERR(info->pctl_dev)) {
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
 		return PTR_ERR(info->pctl_dev);
 		return PTR_ERR(info->pctl_dev);
@@ -1741,6 +1817,7 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
 	.free = gpiochip_generic_free,
 	.free = gpiochip_generic_free,
 	.set = rockchip_gpio_set,
 	.set = rockchip_gpio_set,
 	.get = rockchip_gpio_get,
 	.get = rockchip_gpio_get,
+	.get_direction	= rockchip_gpio_get_direction,
 	.direction_input = rockchip_gpio_direction_input,
 	.direction_input = rockchip_gpio_direction_input,
 	.direction_output = rockchip_gpio_direction_output,
 	.direction_output = rockchip_gpio_direction_output,
 	.to_irq = rockchip_gpio_to_irq,
 	.to_irq = rockchip_gpio_to_irq,
@@ -2541,19 +2618,24 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
 };
 };
 
 
 static struct rockchip_pin_bank rk3399_pin_banks[] = {
 static struct rockchip_pin_bank rk3399_pin_banks[] = {
-	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(0, 32, "gpio0", IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					DRV_TYPE_IO_1V8_ONLY,
-					DRV_TYPE_IO_1V8_ONLY,
-					DRV_TYPE_IO_DEFAULT,
-					DRV_TYPE_IO_DEFAULT,
-					0x0,
-					0x8,
-					-1,
-					-1
-					),
+	PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0",
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 DRV_TYPE_IO_1V8_ONLY,
+							 DRV_TYPE_IO_1V8_ONLY,
+							 DRV_TYPE_IO_DEFAULT,
+							 DRV_TYPE_IO_DEFAULT,
+							 0x0,
+							 0x8,
+							 -1,
+							 -1,
+							 PULL_TYPE_IO_1V8_ONLY,
+							 PULL_TYPE_IO_1V8_ONLY,
+							 PULL_TYPE_IO_DEFAULT,
+							 PULL_TYPE_IO_DEFAULT
+							),
 	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
 	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
 					IOMUX_SOURCE_PMU,
 					IOMUX_SOURCE_PMU,
 					IOMUX_SOURCE_PMU,
 					IOMUX_SOURCE_PMU,
@@ -2567,11 +2649,15 @@ static struct rockchip_pin_bank rk3399_pin_banks[] = {
 					0x30,
 					0x30,
 					0x38
 					0x38
 					),
 					),
-	PIN_BANK_DRV_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
-			   DRV_TYPE_IO_1V8_OR_3V0,
-			   DRV_TYPE_IO_1V8_ONLY,
-			   DRV_TYPE_IO_1V8_ONLY
-			   ),
+	PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
+				      DRV_TYPE_IO_1V8_OR_3V0,
+				      DRV_TYPE_IO_1V8_ONLY,
+				      DRV_TYPE_IO_1V8_ONLY,
+				      PULL_TYPE_IO_DEFAULT,
+				      PULL_TYPE_IO_DEFAULT,
+				      PULL_TYPE_IO_1V8_ONLY,
+				      PULL_TYPE_IO_1V8_ONLY
+				      ),
 	PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY,
 	PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY,
 			   DRV_TYPE_IO_3V3_ONLY,
 			   DRV_TYPE_IO_3V3_ONLY,
 			   DRV_TYPE_IO_3V3_ONLY,
 			   DRV_TYPE_IO_3V3_ONLY,

+ 1 - 1
drivers/pinctrl/pinctrl-st.c

@@ -1724,7 +1724,7 @@ static int st_pctl_probe(struct platform_device *pdev)
 	pctl_desc->confops	= &st_confops;
 	pctl_desc->confops	= &st_confops;
 	pctl_desc->name		= dev_name(&pdev->dev);
 	pctl_desc->name		= dev_name(&pdev->dev);
 
 
-	info->pctl = pinctrl_register(pctl_desc, &pdev->dev, info);
+	info->pctl = devm_pinctrl_register(&pdev->dev, pctl_desc, info);
 	if (IS_ERR(info->pctl)) {
 	if (IS_ERR(info->pctl)) {
 		dev_err(&pdev->dev, "Failed pinctrl registration\n");
 		dev_err(&pdev->dev, "Failed pinctrl registration\n");
 		return PTR_ERR(info->pctl);
 		return PTR_ERR(info->pctl);

+ 2 - 3
drivers/pinctrl/pinctrl-tb10x.c

@@ -582,7 +582,7 @@ static struct pinctrl_ops tb10x_pinctrl_ops = {
 	.get_group_name   = tb10x_get_group_name,
 	.get_group_name   = tb10x_get_group_name,
 	.get_group_pins   = tb10x_get_group_pins,
 	.get_group_pins   = tb10x_get_group_pins,
 	.dt_node_to_map   = tb10x_dt_node_to_map,
 	.dt_node_to_map   = tb10x_dt_node_to_map,
-	.dt_free_map      = pinctrl_utils_dt_free_map,
+	.dt_free_map      = pinctrl_utils_free_map,
 };
 };
 
 
 static int tb10x_get_functions_count(struct pinctrl_dev *pctl)
 static int tb10x_get_functions_count(struct pinctrl_dev *pctl)
@@ -806,7 +806,7 @@ static int tb10x_pinctrl_probe(struct platform_device *pdev)
 		}
 		}
 	}
 	}
 
 
-	state->pctl = pinctrl_register(&tb10x_pindesc, dev, state);
+	state->pctl = devm_pinctrl_register(dev, &tb10x_pindesc, state);
 	if (IS_ERR(state->pctl)) {
 	if (IS_ERR(state->pctl)) {
 		dev_err(dev, "could not register TB10x pin driver\n");
 		dev_err(dev, "could not register TB10x pin driver\n");
 		ret = PTR_ERR(state->pctl);
 		ret = PTR_ERR(state->pctl);
@@ -824,7 +824,6 @@ static int tb10x_pinctrl_remove(struct platform_device *pdev)
 {
 {
 	struct tb10x_pinctrl *state = platform_get_drvdata(pdev);
 	struct tb10x_pinctrl *state = platform_get_drvdata(pdev);
 
 
-	pinctrl_unregister(state->pctl);
 	mutex_destroy(&state->mutex);
 	mutex_destroy(&state->mutex);
 
 
 	return 0;
 	return 0;

+ 2 - 11
drivers/pinctrl/pinctrl-tz1090-pdc.c

@@ -947,7 +947,8 @@ static int tz1090_pdc_pinctrl_probe(struct platform_device *pdev)
 	if (IS_ERR(pmx->regs))
 	if (IS_ERR(pmx->regs))
 		return PTR_ERR(pmx->regs);
 		return PTR_ERR(pmx->regs);
 
 
-	pmx->pctl = pinctrl_register(&tz1090_pdc_pinctrl_desc, &pdev->dev, pmx);
+	pmx->pctl = devm_pinctrl_register(&pdev->dev, &tz1090_pdc_pinctrl_desc,
+					  pmx);
 	if (IS_ERR(pmx->pctl)) {
 	if (IS_ERR(pmx->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		return PTR_ERR(pmx->pctl);
 		return PTR_ERR(pmx->pctl);
@@ -960,15 +961,6 @@ static int tz1090_pdc_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int tz1090_pdc_pinctrl_remove(struct platform_device *pdev)
-{
-	struct tz1090_pdc_pmx *pmx = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(pmx->pctl);
-
-	return 0;
-}
-
 static const struct of_device_id tz1090_pdc_pinctrl_of_match[] = {
 static const struct of_device_id tz1090_pdc_pinctrl_of_match[] = {
 	{ .compatible = "img,tz1090-pdc-pinctrl", },
 	{ .compatible = "img,tz1090-pdc-pinctrl", },
 	{ },
 	{ },
@@ -980,7 +972,6 @@ static struct platform_driver tz1090_pdc_pinctrl_driver = {
 		.of_match_table	= tz1090_pdc_pinctrl_of_match,
 		.of_match_table	= tz1090_pdc_pinctrl_of_match,
 	},
 	},
 	.probe	= tz1090_pdc_pinctrl_probe,
 	.probe	= tz1090_pdc_pinctrl_probe,
-	.remove	= tz1090_pdc_pinctrl_remove,
 };
 };
 
 
 static int __init tz1090_pdc_pinctrl_init(void)
 static int __init tz1090_pdc_pinctrl_init(void)

+ 2 - 11
drivers/pinctrl/pinctrl-tz1090.c

@@ -1962,7 +1962,8 @@ static int tz1090_pinctrl_probe(struct platform_device *pdev)
 	if (IS_ERR(pmx->regs))
 	if (IS_ERR(pmx->regs))
 		return PTR_ERR(pmx->regs);
 		return PTR_ERR(pmx->regs);
 
 
-	pmx->pctl = pinctrl_register(&tz1090_pinctrl_desc, &pdev->dev, pmx);
+	pmx->pctl = devm_pinctrl_register(&pdev->dev, &tz1090_pinctrl_desc,
+					  pmx);
 	if (IS_ERR(pmx->pctl)) {
 	if (IS_ERR(pmx->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		return PTR_ERR(pmx->pctl);
 		return PTR_ERR(pmx->pctl);
@@ -1975,15 +1976,6 @@ static int tz1090_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int tz1090_pinctrl_remove(struct platform_device *pdev)
-{
-	struct tz1090_pmx *pmx = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(pmx->pctl);
-
-	return 0;
-}
-
 static const struct of_device_id tz1090_pinctrl_of_match[] = {
 static const struct of_device_id tz1090_pinctrl_of_match[] = {
 	{ .compatible = "img,tz1090-pinctrl", },
 	{ .compatible = "img,tz1090-pinctrl", },
 	{ },
 	{ },
@@ -1995,7 +1987,6 @@ static struct platform_driver tz1090_pinctrl_driver = {
 		.of_match_table	= tz1090_pinctrl_of_match,
 		.of_match_table	= tz1090_pinctrl_of_match,
 	},
 	},
 	.probe	= tz1090_pinctrl_probe,
 	.probe	= tz1090_pinctrl_probe,
-	.remove	= tz1090_pinctrl_remove,
 };
 };
 
 
 static int __init tz1090_pinctrl_init(void)
 static int __init tz1090_pinctrl_init(void)

+ 1 - 11
drivers/pinctrl/pinctrl-u300.c

@@ -1067,7 +1067,7 @@ static int u300_pmx_probe(struct platform_device *pdev)
 	if (IS_ERR(upmx->virtbase))
 	if (IS_ERR(upmx->virtbase))
 		return PTR_ERR(upmx->virtbase);
 		return PTR_ERR(upmx->virtbase);
 
 
-	upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
+	upmx->pctl = devm_pinctrl_register(&pdev->dev, &u300_pmx_desc, upmx);
 	if (IS_ERR(upmx->pctl)) {
 	if (IS_ERR(upmx->pctl)) {
 		dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
 		dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
 		return PTR_ERR(upmx->pctl);
 		return PTR_ERR(upmx->pctl);
@@ -1080,15 +1080,6 @@ static int u300_pmx_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int u300_pmx_remove(struct platform_device *pdev)
-{
-	struct u300_pmx *upmx = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(upmx->pctl);
-
-	return 0;
-}
-
 static const struct of_device_id u300_pinctrl_match[] = {
 static const struct of_device_id u300_pinctrl_match[] = {
 	{ .compatible = "stericsson,pinctrl-u300" },
 	{ .compatible = "stericsson,pinctrl-u300" },
 	{},
 	{},
@@ -1101,7 +1092,6 @@ static struct platform_driver u300_pmx_driver = {
 		.of_match_table = u300_pinctrl_match,
 		.of_match_table = u300_pinctrl_match,
 	},
 	},
 	.probe = u300_pmx_probe,
 	.probe = u300_pmx_probe,
-	.remove = u300_pmx_remove,
 };
 };
 
 
 static int __init u300_pmx_init(void)
 static int __init u300_pmx_init(void)

+ 2 - 2
drivers/pinctrl/pinctrl-utils.c

@@ -122,7 +122,7 @@ int pinctrl_utils_add_config(struct pinctrl_dev *pctldev,
 }
 }
 EXPORT_SYMBOL_GPL(pinctrl_utils_add_config);
 EXPORT_SYMBOL_GPL(pinctrl_utils_add_config);
 
 
-void pinctrl_utils_dt_free_map(struct pinctrl_dev *pctldev,
+void pinctrl_utils_free_map(struct pinctrl_dev *pctldev,
 	      struct pinctrl_map *map, unsigned num_maps)
 	      struct pinctrl_map *map, unsigned num_maps)
 {
 {
 	int i;
 	int i;
@@ -139,4 +139,4 @@ void pinctrl_utils_dt_free_map(struct pinctrl_dev *pctldev,
 	}
 	}
 	kfree(map);
 	kfree(map);
 }
 }
-EXPORT_SYMBOL_GPL(pinctrl_utils_dt_free_map);
+EXPORT_SYMBOL_GPL(pinctrl_utils_free_map);

+ 1 - 1
drivers/pinctrl/pinctrl-utils.h

@@ -37,7 +37,7 @@ int pinctrl_utils_add_map_configs(struct pinctrl_dev *pctldev,
 int pinctrl_utils_add_config(struct pinctrl_dev *pctldev,
 int pinctrl_utils_add_config(struct pinctrl_dev *pctldev,
 		unsigned long **configs, unsigned *num_configs,
 		unsigned long **configs, unsigned *num_configs,
 		unsigned long config);
 		unsigned long config);
-void pinctrl_utils_dt_free_map(struct pinctrl_dev *pctldev,
+void pinctrl_utils_free_map(struct pinctrl_dev *pctldev,
 		struct pinctrl_map *map, unsigned num_maps);
 		struct pinctrl_map *map, unsigned num_maps);
 
 
 #endif /* __PINCTRL_UTILS_H__ */
 #endif /* __PINCTRL_UTILS_H__ */

+ 2 - 12
drivers/pinctrl/pinctrl-zynq.c

@@ -862,7 +862,7 @@ static const struct pinctrl_ops zynq_pctrl_ops = {
 	.get_group_name = zynq_pctrl_get_group_name,
 	.get_group_name = zynq_pctrl_get_group_name,
 	.get_group_pins = zynq_pctrl_get_group_pins,
 	.get_group_pins = zynq_pctrl_get_group_pins,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 };
 
 
 /* pinmux */
 /* pinmux */
@@ -1195,7 +1195,7 @@ static int zynq_pinctrl_probe(struct platform_device *pdev)
 	pctrl->funcs = zynq_pmux_functions;
 	pctrl->funcs = zynq_pmux_functions;
 	pctrl->nfuncs = ARRAY_SIZE(zynq_pmux_functions);
 	pctrl->nfuncs = ARRAY_SIZE(zynq_pmux_functions);
 
 
-	pctrl->pctrl = pinctrl_register(&zynq_desc, &pdev->dev, pctrl);
+	pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &zynq_desc, pctrl);
 	if (IS_ERR(pctrl->pctrl))
 	if (IS_ERR(pctrl->pctrl))
 		return PTR_ERR(pctrl->pctrl);
 		return PTR_ERR(pctrl->pctrl);
 
 
@@ -1206,15 +1206,6 @@ static int zynq_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int zynq_pinctrl_remove(struct platform_device *pdev)
-{
-	struct zynq_pinctrl *pctrl = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(pctrl->pctrl);
-
-	return 0;
-}
-
 static const struct of_device_id zynq_pinctrl_of_match[] = {
 static const struct of_device_id zynq_pinctrl_of_match[] = {
 	{ .compatible = "xlnx,pinctrl-zynq" },
 	{ .compatible = "xlnx,pinctrl-zynq" },
 	{ }
 	{ }
@@ -1227,7 +1218,6 @@ static struct platform_driver zynq_pinctrl_driver = {
 		.of_match_table = zynq_pinctrl_of_match,
 		.of_match_table = zynq_pinctrl_of_match,
 	},
 	},
 	.probe = zynq_pinctrl_probe,
 	.probe = zynq_pinctrl_probe,
-	.remove = zynq_pinctrl_remove,
 };
 };
 
 
 static int __init zynq_pinctrl_init(void)
 static int __init zynq_pinctrl_init(void)

+ 9 - 1
drivers/pinctrl/pxa/Kconfig

@@ -6,12 +6,20 @@ config PINCTRL_PXA
 	select PINCONF
 	select PINCONF
 	select GENERIC_PINCONF
 	select GENERIC_PINCONF
 
 
+config PINCTRL_PXA25X
+	tristate "Marvell PXA25x pin controller driver"
+	select PINCTRL_PXA
+	default y if PXA25x
+	help
+	  This is the pinctrl, pinmux, pinconf driver for the Marvell
+	  PXA2xx block found in the pxa25x platforms.
+
 config PINCTRL_PXA27X
 config PINCTRL_PXA27X
 	tristate "Marvell PXA27x pin controller driver"
 	tristate "Marvell PXA27x pin controller driver"
 	select PINCTRL_PXA
 	select PINCTRL_PXA
 	default y if PXA27x
 	default y if PXA27x
 	help
 	help
 	  This is the pinctrl, pinmux, pinconf driver for the Marvell
 	  This is the pinctrl, pinmux, pinconf driver for the Marvell
-	  PXA2xx block found in the pxa25x and pxa27x platforms.
+	  PXA2xx block found in the pxa27x platforms.
 
 
 endif
 endif

+ 1 - 0
drivers/pinctrl/pxa/Makefile

@@ -1,2 +1,3 @@
 # Marvell PXA pin control drivers
 # Marvell PXA pin control drivers
+obj-$(CONFIG_PINCTRL_PXA25X)	+= pinctrl-pxa2xx.o pinctrl-pxa25x.o
 obj-$(CONFIG_PINCTRL_PXA27X)	+= pinctrl-pxa2xx.o pinctrl-pxa27x.o
 obj-$(CONFIG_PINCTRL_PXA27X)	+= pinctrl-pxa2xx.o pinctrl-pxa27x.o

+ 274 - 0
drivers/pinctrl/pxa/pinctrl-pxa25x.c

@@ -0,0 +1,274 @@
+/*
+ * Marvell PXA25x family pin control
+ *
+ * Copyright (C) 2016 Robert Jarzmik
+ *
+ * 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; version 2 of the License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-pxa2xx.h"
+
+static const struct pxa_desc_pin pxa25x_pins[] = {
+	PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(0)),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(1),
+		     PXA_FUNCTION(0, 1, "GP_RST")),
+	PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(2)),
+	PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(3)),
+	PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(4)),
+	PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(5)),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(6),
+		     PXA_FUNCTION(1, 1, "MMCCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(7),
+		     PXA_FUNCTION(1, 1, "48_MHz")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(8),
+		     PXA_FUNCTION(1, 1, "MMCCS0")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(9),
+		     PXA_FUNCTION(1, 1, "MMCCS1")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(10),
+		     PXA_FUNCTION(1, 1, "RTCCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(11),
+		     PXA_FUNCTION(1, 1, "3_6_MHz")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(12),
+		     PXA_FUNCTION(1, 1, "32_kHz")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(13),
+		     PXA_FUNCTION(1, 2, "MBGNT")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(14),
+		     PXA_FUNCTION(0, 1, "MBREQ")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(15),
+		     PXA_FUNCTION(1, 2, "nCS_1")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(16),
+		     PXA_FUNCTION(1, 2, "PWM0")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(17),
+		     PXA_FUNCTION(1, 2, "PWM1")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(18),
+		     PXA_FUNCTION(0, 1, "RDY")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(19),
+		     PXA_FUNCTION(0, 1, "DREQ[1]")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(20),
+		     PXA_FUNCTION(0, 1, "DREQ[0]")),
+	PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(21)),
+	PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(22)),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(23),
+		     PXA_FUNCTION(1, 2, "SCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(24),
+		     PXA_FUNCTION(1, 2, "SFRM")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(25),
+		     PXA_FUNCTION(1, 2, "TXD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(26),
+		     PXA_FUNCTION(0, 1, "RXD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(27),
+		     PXA_FUNCTION(0, 1, "EXTCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(28),
+		     PXA_FUNCTION(0, 1, "BITCLK"),
+		     PXA_FUNCTION(0, 2, "BITCLK"),
+		     PXA_FUNCTION(1, 1, "BITCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(29),
+		     PXA_FUNCTION(0, 1, "SDATA_IN0"),
+		     PXA_FUNCTION(0, 2, "SDATA_IN")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(30),
+		     PXA_FUNCTION(1, 1, "SDATA_OUT"),
+		     PXA_FUNCTION(1, 2, "SDATA_OUT")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(31),
+		     PXA_FUNCTION(1, 1, "SYNC"),
+		     PXA_FUNCTION(1, 2, "SYNC")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(32),
+		     PXA_FUNCTION(0, 1, "SDATA_IN1"),
+		     PXA_FUNCTION(1, 1, "SYSCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(33),
+		     PXA_FUNCTION(1, 2, "nCS[5]")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(34),
+		     PXA_FUNCTION(0, 1, "FFRXD"),
+		     PXA_FUNCTION(1, 2, "MMCCS0")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(35),
+		     PXA_FUNCTION(0, 1, "CTS")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(36),
+		     PXA_FUNCTION(0, 1, "DCD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(37),
+		     PXA_FUNCTION(0, 1, "DSR")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(38),
+		     PXA_FUNCTION(0, 1, "RI")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(39),
+		     PXA_FUNCTION(1, 1, "MMCC1"),
+		     PXA_FUNCTION(1, 2, "FFTXD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(40),
+		     PXA_FUNCTION(1, 2, "DTR")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(41),
+		     PXA_FUNCTION(1, 2, "RTS")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(42),
+		     PXA_FUNCTION(0, 1, "BTRXD"),
+		     PXA_FUNCTION(0, 3, "HWRXD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(43),
+		     PXA_FUNCTION(1, 2, "BTTXD"),
+		     PXA_FUNCTION(1, 3, "HWTXD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(44),
+		     PXA_FUNCTION(0, 1, "BTCTS"),
+		     PXA_FUNCTION(0, 3, "HWCTS")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(45),
+		     PXA_FUNCTION(1, 2, "BTRTS"),
+		     PXA_FUNCTION(1, 3, "HWRTS")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(46),
+		     PXA_FUNCTION(0, 1, "ICP_RXD"),
+		     PXA_FUNCTION(0, 2, "RXD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(47),
+		     PXA_FUNCTION(1, 1, "TXD"),
+		     PXA_FUNCTION(1, 2, "ICP_TXD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(48),
+		     PXA_FUNCTION(1, 1, "HWTXD"),
+		     PXA_FUNCTION(1, 2, "nPOE")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(49),
+		     PXA_FUNCTION(0, 1, "HWRXD"),
+		     PXA_FUNCTION(1, 2, "nPWE")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(50),
+		     PXA_FUNCTION(0, 1, "HWCTS"),
+		     PXA_FUNCTION(1, 2, "nPIOR")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(51),
+		     PXA_FUNCTION(1, 1, "HWRTS"),
+		     PXA_FUNCTION(1, 2, "nPIOW")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(52),
+		     PXA_FUNCTION(1, 2, "nPCE[1]")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(53),
+		     PXA_FUNCTION(1, 1, "MMCCLK"),
+		     PXA_FUNCTION(1, 2, "nPCE[2]")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(54),
+		     PXA_FUNCTION(1, 1, "MMCCLK"),
+		     PXA_FUNCTION(1, 2, "nPSKTSEL")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(55),
+		     PXA_FUNCTION(1, 2, "nPREG")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(56),
+		     PXA_FUNCTION(0, 1, "nPWAIT")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(57),
+		     PXA_FUNCTION(0, 1, "nIOIS16")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(58),
+		     PXA_FUNCTION(1, 2, "LDD<0>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(59),
+		     PXA_FUNCTION(1, 2, "LDD<1>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(60),
+		     PXA_FUNCTION(1, 2, "LDD<2>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(61),
+		     PXA_FUNCTION(1, 2, "LDD<3>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(62),
+		     PXA_FUNCTION(1, 2, "LDD<4>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(63),
+		     PXA_FUNCTION(1, 2, "LDD<5>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(64),
+		     PXA_FUNCTION(1, 2, "LDD<6>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(65),
+		     PXA_FUNCTION(1, 2, "LDD<7>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(66),
+		     PXA_FUNCTION(0, 1, "MBREQ"),
+		     PXA_FUNCTION(1, 2, "LDD<8>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(67),
+		     PXA_FUNCTION(1, 1, "MMCCS0"),
+		     PXA_FUNCTION(1, 2, "LDD<9>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(68),
+		     PXA_FUNCTION(1, 1, "MMCCS1"),
+		     PXA_FUNCTION(1, 2, "LDD<10>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(69),
+		     PXA_FUNCTION(1, 1, "MMCCLK"),
+		     PXA_FUNCTION(1, 2, "LDD<11>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(70),
+		     PXA_FUNCTION(1, 1, "RTCCLK"),
+		     PXA_FUNCTION(1, 2, "LDD<12>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(71),
+		     PXA_FUNCTION(1, 1, "3_6_MHz"),
+		     PXA_FUNCTION(1, 2, "LDD<13>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(72),
+		     PXA_FUNCTION(1, 1, "32_kHz"),
+		     PXA_FUNCTION(1, 2, "LDD<14>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(73),
+		     PXA_FUNCTION(1, 1, "MBGNT"),
+		     PXA_FUNCTION(1, 2, "LDD<15>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(74),
+		     PXA_FUNCTION(1, 2, "LCD_FCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(75),
+		     PXA_FUNCTION(1, 2, "LCD_LCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(76),
+		     PXA_FUNCTION(1, 2, "LCD_PCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(77),
+		     PXA_FUNCTION(1, 2, "LCD_ACBIAS")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(78),
+		     PXA_FUNCTION(1, 2, "nCS<2>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(79),
+		     PXA_FUNCTION(1, 2, "nCS<3>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(80),
+		     PXA_FUNCTION(1, 2, "nCS<4>")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(81),
+		     PXA_FUNCTION(0, 1, "NSSPSCLK"),
+		     PXA_FUNCTION(1, 1, "NSSPSCLK")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(82),
+		     PXA_FUNCTION(0, 1, "NSSPSFRM"),
+		     PXA_FUNCTION(1, 1, "NSSPSFRM")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(83),
+		     PXA_FUNCTION(0, 2, "NSSPRXD"),
+		     PXA_FUNCTION(1, 1, "NSSPTXD")),
+	PXA_GPIO_PIN(PXA_PINCTRL_PIN(84),
+		     PXA_FUNCTION(0, 2, "NSSPRXD"),
+		     PXA_FUNCTION(1, 1, "NSSPTXD")),
+};
+
+static int pxa25x_pinctrl_probe(struct platform_device *pdev)
+{
+	int ret, i;
+	void __iomem *base_af[8];
+	void __iomem *base_dir[4];
+	void __iomem *base_sleep[4];
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base_af[0] = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base_af[0]))
+		return PTR_ERR(base_af[0]);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	base_dir[0] = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base_dir[0]))
+		return PTR_ERR(base_dir[0]);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	base_dir[3] = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base_dir[3]))
+		return PTR_ERR(base_dir[3]);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+	base_sleep[0] = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base_sleep[0]))
+		return PTR_ERR(base_sleep[0]);
+
+	for (i = 0; i < ARRAY_SIZE(base_af); i++)
+		base_af[i] = base_af[0] + sizeof(base_af[0]) * i;
+	for (i = 0; i < 3; i++)
+		base_dir[i] = base_dir[0] + sizeof(base_dir[0]) * i;
+	for (i = 0; i < ARRAY_SIZE(base_sleep); i++)
+		base_sleep[i] = base_sleep[0] + sizeof(base_af[0]) * i;
+
+	ret = pxa2xx_pinctrl_init(pdev, pxa25x_pins, ARRAY_SIZE(pxa25x_pins),
+				  base_af, base_dir, base_sleep);
+	return ret;
+}
+
+static const struct of_device_id pxa25x_pinctrl_match[] = {
+	{ .compatible = "marvell,pxa25x-pinctrl", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pxa25x_pinctrl_match);
+
+static struct platform_driver pxa25x_pinctrl_driver = {
+	.probe	= pxa25x_pinctrl_probe,
+	.driver	= {
+		.name		= "pxa25x-pinctrl",
+		.of_match_table	= pxa25x_pinctrl_match,
+	},
+};
+module_platform_driver(pxa25x_pinctrl_driver);
+
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
+MODULE_DESCRIPTION("Marvell PXA25x pinctrl driver");
+MODULE_LICENSE("GPL v2");

+ 2 - 2
drivers/pinctrl/pxa/pinctrl-pxa2xx.c

@@ -57,7 +57,7 @@ static int pxa2xx_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
 static const struct pinctrl_ops pxa2xx_pctl_ops = {
 static const struct pinctrl_ops pxa2xx_pctl_ops = {
 #ifdef CONFIG_OF
 #ifdef CONFIG_OF
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_all,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_all,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 #endif
 #endif
 	.get_groups_count	= pxa2xx_pctrl_get_groups_count,
 	.get_groups_count	= pxa2xx_pctrl_get_groups_count,
 	.get_group_name		= pxa2xx_pctrl_get_group_name,
 	.get_group_name		= pxa2xx_pctrl_get_group_name,
@@ -416,7 +416,7 @@ int pxa2xx_pinctrl_init(struct platform_device *pdev,
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	pctl->pctl_dev = pinctrl_register(&pctl->desc, &pdev->dev, pctl);
+	pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->desc, pctl);
 	if (IS_ERR(pctl->pctl_dev)) {
 	if (IS_ERR(pctl->pctl_dev)) {
 		dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
 		return PTR_ERR(pctl->pctl_dev);
 		return PTR_ERR(pctl->pctl_dev);

+ 4 - 6
drivers/pinctrl/qcom/pinctrl-msm.c

@@ -101,7 +101,7 @@ static const struct pinctrl_ops msm_pinctrl_ops = {
 	.get_group_name		= msm_get_group_name,
 	.get_group_name		= msm_get_group_name,
 	.get_group_pins		= msm_get_group_pins,
 	.get_group_pins		= msm_get_group_pins,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 };
 };
 
 
 static int msm_get_functions_count(struct pinctrl_dev *pctldev)
 static int msm_get_functions_count(struct pinctrl_dev *pctldev)
@@ -898,17 +898,16 @@ int msm_pinctrl_probe(struct platform_device *pdev,
 	msm_pinctrl_desc.name = dev_name(&pdev->dev);
 	msm_pinctrl_desc.name = dev_name(&pdev->dev);
 	msm_pinctrl_desc.pins = pctrl->soc->pins;
 	msm_pinctrl_desc.pins = pctrl->soc->pins;
 	msm_pinctrl_desc.npins = pctrl->soc->npins;
 	msm_pinctrl_desc.npins = pctrl->soc->npins;
-	pctrl->pctrl = pinctrl_register(&msm_pinctrl_desc, &pdev->dev, pctrl);
+	pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &msm_pinctrl_desc,
+					     pctrl);
 	if (IS_ERR(pctrl->pctrl)) {
 	if (IS_ERR(pctrl->pctrl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		return PTR_ERR(pctrl->pctrl);
 		return PTR_ERR(pctrl->pctrl);
 	}
 	}
 
 
 	ret = msm_gpio_init(pctrl);
 	ret = msm_gpio_init(pctrl);
-	if (ret) {
-		pinctrl_unregister(pctrl->pctrl);
+	if (ret)
 		return ret;
 		return ret;
-	}
 
 
 	platform_set_drvdata(pdev, pctrl);
 	platform_set_drvdata(pdev, pctrl);
 
 
@@ -923,7 +922,6 @@ int msm_pinctrl_remove(struct platform_device *pdev)
 	struct msm_pinctrl *pctrl = platform_get_drvdata(pdev);
 	struct msm_pinctrl *pctrl = platform_get_drvdata(pdev);
 
 
 	gpiochip_remove(&pctrl->chip);
 	gpiochip_remove(&pctrl->chip);
-	pinctrl_unregister(pctrl->pctrl);
 
 
 	unregister_restart_handler(&pctrl->restart_nb);
 	unregister_restart_handler(&pctrl->restart_nb);
 
 

+ 3 - 6
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c

@@ -212,7 +212,7 @@ static const struct pinctrl_ops pmic_gpio_pinctrl_ops = {
 	.get_group_name		= pmic_gpio_get_group_name,
 	.get_group_name		= pmic_gpio_get_group_name,
 	.get_group_pins		= pmic_gpio_get_group_pins,
 	.get_group_pins		= pmic_gpio_get_group_pins,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 };
 };
 
 
 static int pmic_gpio_get_functions_count(struct pinctrl_dev *pctldev)
 static int pmic_gpio_get_functions_count(struct pinctrl_dev *pctldev)
@@ -764,14 +764,14 @@ static int pmic_gpio_probe(struct platform_device *pdev)
 	state->chip.of_gpio_n_cells = 2;
 	state->chip.of_gpio_n_cells = 2;
 	state->chip.can_sleep = false;
 	state->chip.can_sleep = false;
 
 
-	state->ctrl = pinctrl_register(pctrldesc, dev, state);
+	state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
 	if (IS_ERR(state->ctrl))
 	if (IS_ERR(state->ctrl))
 		return PTR_ERR(state->ctrl);
 		return PTR_ERR(state->ctrl);
 
 
 	ret = gpiochip_add_data(&state->chip, state);
 	ret = gpiochip_add_data(&state->chip, state);
 	if (ret) {
 	if (ret) {
 		dev_err(state->dev, "can't add gpio chip\n");
 		dev_err(state->dev, "can't add gpio chip\n");
-		goto err_chip;
+		return ret;
 	}
 	}
 
 
 	ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
 	ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
@@ -784,8 +784,6 @@ static int pmic_gpio_probe(struct platform_device *pdev)
 
 
 err_range:
 err_range:
 	gpiochip_remove(&state->chip);
 	gpiochip_remove(&state->chip);
-err_chip:
-	pinctrl_unregister(state->ctrl);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -794,7 +792,6 @@ static int pmic_gpio_remove(struct platform_device *pdev)
 	struct pmic_gpio_state *state = platform_get_drvdata(pdev);
 	struct pmic_gpio_state *state = platform_get_drvdata(pdev);
 
 
 	gpiochip_remove(&state->chip);
 	gpiochip_remove(&state->chip);
-	pinctrl_unregister(state->ctrl);
 	return 0;
 	return 0;
 }
 }
 
 

+ 3 - 6
drivers/pinctrl/qcom/pinctrl-spmi-mpp.c

@@ -235,7 +235,7 @@ static const struct pinctrl_ops pmic_mpp_pinctrl_ops = {
 	.get_group_name		= pmic_mpp_get_group_name,
 	.get_group_name		= pmic_mpp_get_group_name,
 	.get_group_pins		= pmic_mpp_get_group_pins,
 	.get_group_pins		= pmic_mpp_get_group_pins,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 };
 };
 
 
 static int pmic_mpp_get_functions_count(struct pinctrl_dev *pctldev)
 static int pmic_mpp_get_functions_count(struct pinctrl_dev *pctldev)
@@ -877,14 +877,14 @@ static int pmic_mpp_probe(struct platform_device *pdev)
 	state->chip.of_gpio_n_cells = 2;
 	state->chip.of_gpio_n_cells = 2;
 	state->chip.can_sleep = false;
 	state->chip.can_sleep = false;
 
 
-	state->ctrl = pinctrl_register(pctrldesc, dev, state);
+	state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
 	if (IS_ERR(state->ctrl))
 	if (IS_ERR(state->ctrl))
 		return PTR_ERR(state->ctrl);
 		return PTR_ERR(state->ctrl);
 
 
 	ret = gpiochip_add_data(&state->chip, state);
 	ret = gpiochip_add_data(&state->chip, state);
 	if (ret) {
 	if (ret) {
 		dev_err(state->dev, "can't add gpio chip\n");
 		dev_err(state->dev, "can't add gpio chip\n");
-		goto err_chip;
+		return ret;
 	}
 	}
 
 
 	ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
 	ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
@@ -897,8 +897,6 @@ static int pmic_mpp_probe(struct platform_device *pdev)
 
 
 err_range:
 err_range:
 	gpiochip_remove(&state->chip);
 	gpiochip_remove(&state->chip);
-err_chip:
-	pinctrl_unregister(state->ctrl);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -907,7 +905,6 @@ static int pmic_mpp_remove(struct platform_device *pdev)
 	struct pmic_mpp_state *state = platform_get_drvdata(pdev);
 	struct pmic_mpp_state *state = platform_get_drvdata(pdev);
 
 
 	gpiochip_remove(&state->chip);
 	gpiochip_remove(&state->chip);
-	pinctrl_unregister(state->ctrl);
 	return 0;
 	return 0;
 }
 }
 
 

+ 3 - 8
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c

@@ -200,7 +200,7 @@ static const struct pinctrl_ops pm8xxx_pinctrl_ops = {
 	.get_group_name		= pm8xxx_get_group_name,
 	.get_group_name		= pm8xxx_get_group_name,
 	.get_group_pins         = pm8xxx_get_group_pins,
 	.get_group_pins         = pm8xxx_get_group_pins,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 };
 };
 
 
 static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev)
 static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev)
@@ -729,7 +729,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
 	pctrl->desc.custom_conf_items = pm8xxx_conf_items;
 	pctrl->desc.custom_conf_items = pm8xxx_conf_items;
 #endif
 #endif
 
 
-	pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl);
+	pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
 	if (IS_ERR(pctrl->pctrl)) {
 	if (IS_ERR(pctrl->pctrl)) {
 		dev_err(&pdev->dev, "couldn't register pm8xxx gpio driver\n");
 		dev_err(&pdev->dev, "couldn't register pm8xxx gpio driver\n");
 		return PTR_ERR(pctrl->pctrl);
 		return PTR_ERR(pctrl->pctrl);
@@ -745,7 +745,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
 	ret = gpiochip_add_data(&pctrl->chip, pctrl);
 	ret = gpiochip_add_data(&pctrl->chip, pctrl);
 	if (ret) {
 	if (ret) {
 		dev_err(&pdev->dev, "failed register gpiochip\n");
 		dev_err(&pdev->dev, "failed register gpiochip\n");
-		goto unregister_pinctrl;
+		return ret;
 	}
 	}
 
 
 	ret = gpiochip_add_pin_range(&pctrl->chip,
 	ret = gpiochip_add_pin_range(&pctrl->chip,
@@ -765,9 +765,6 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
 unregister_gpiochip:
 unregister_gpiochip:
 	gpiochip_remove(&pctrl->chip);
 	gpiochip_remove(&pctrl->chip);
 
 
-unregister_pinctrl:
-	pinctrl_unregister(pctrl->pctrl);
-
 	return ret;
 	return ret;
 }
 }
 
 
@@ -777,8 +774,6 @@ static int pm8xxx_gpio_remove(struct platform_device *pdev)
 
 
 	gpiochip_remove(&pctrl->chip);
 	gpiochip_remove(&pctrl->chip);
 
 
-	pinctrl_unregister(pctrl->pctrl);
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 3 - 8
drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c

@@ -277,7 +277,7 @@ static const struct pinctrl_ops pm8xxx_pinctrl_ops = {
 	.get_group_name		= pm8xxx_get_group_name,
 	.get_group_name		= pm8xxx_get_group_name,
 	.get_group_pins         = pm8xxx_get_group_pins,
 	.get_group_pins         = pm8xxx_get_group_pins,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 };
 };
 
 
 static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev)
 static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev)
@@ -820,7 +820,7 @@ static int pm8xxx_mpp_probe(struct platform_device *pdev)
 	pctrl->desc.custom_conf_items = pm8xxx_conf_items;
 	pctrl->desc.custom_conf_items = pm8xxx_conf_items;
 #endif
 #endif
 
 
-	pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl);
+	pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
 	if (IS_ERR(pctrl->pctrl)) {
 	if (IS_ERR(pctrl->pctrl)) {
 		dev_err(&pdev->dev, "couldn't register pm8xxx mpp driver\n");
 		dev_err(&pdev->dev, "couldn't register pm8xxx mpp driver\n");
 		return PTR_ERR(pctrl->pctrl);
 		return PTR_ERR(pctrl->pctrl);
@@ -836,7 +836,7 @@ static int pm8xxx_mpp_probe(struct platform_device *pdev)
 	ret = gpiochip_add_data(&pctrl->chip, pctrl);
 	ret = gpiochip_add_data(&pctrl->chip, pctrl);
 	if (ret) {
 	if (ret) {
 		dev_err(&pdev->dev, "failed register gpiochip\n");
 		dev_err(&pdev->dev, "failed register gpiochip\n");
-		goto unregister_pinctrl;
+		return ret;
 	}
 	}
 
 
 	ret = gpiochip_add_pin_range(&pctrl->chip,
 	ret = gpiochip_add_pin_range(&pctrl->chip,
@@ -856,9 +856,6 @@ static int pm8xxx_mpp_probe(struct platform_device *pdev)
 unregister_gpiochip:
 unregister_gpiochip:
 	gpiochip_remove(&pctrl->chip);
 	gpiochip_remove(&pctrl->chip);
 
 
-unregister_pinctrl:
-	pinctrl_unregister(pctrl->pctrl);
-
 	return ret;
 	return ret;
 }
 }
 
 
@@ -868,8 +865,6 @@ static int pm8xxx_mpp_remove(struct platform_device *pdev)
 
 
 	gpiochip_remove(&pctrl->chip);
 	gpiochip_remove(&pctrl->chip);
 
 
-	pinctrl_unregister(pctrl->pctrl);
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 9 - 8
drivers/pinctrl/samsung/pinctrl-exynos5440.c

@@ -107,6 +107,7 @@ struct exynos5440_pmx_func {
  * @nr_groups: number of pin groups available.
  * @nr_groups: number of pin groups available.
  * @pmx_functions: list of pin functions parsed from device tree.
  * @pmx_functions: list of pin functions parsed from device tree.
  * @nr_functions: number of pin functions available.
  * @nr_functions: number of pin functions available.
+ * @range: gpio range to register with pinctrl
  */
  */
 struct exynos5440_pinctrl_priv_data {
 struct exynos5440_pinctrl_priv_data {
 	void __iomem			*reg_base;
 	void __iomem			*reg_base;
@@ -117,6 +118,7 @@ struct exynos5440_pinctrl_priv_data {
 	unsigned int			nr_groups;
 	unsigned int			nr_groups;
 	const struct exynos5440_pmx_func	*pmx_functions;
 	const struct exynos5440_pmx_func	*pmx_functions;
 	unsigned int			nr_functions;
 	unsigned int			nr_functions;
+	struct pinctrl_gpio_range	range;
 };
 };
 
 
 /**
 /**
@@ -742,7 +744,6 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
 	struct pinctrl_desc *ctrldesc;
 	struct pinctrl_desc *ctrldesc;
 	struct pinctrl_dev *pctl_dev;
 	struct pinctrl_dev *pctl_dev;
 	struct pinctrl_pin_desc *pindesc, *pdesc;
 	struct pinctrl_pin_desc *pindesc, *pdesc;
-	struct pinctrl_gpio_range grange;
 	char *pin_names;
 	char *pin_names;
 	int pin, ret;
 	int pin, ret;
 
 
@@ -788,18 +789,18 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, priv);
+	pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, priv);
 	if (IS_ERR(pctl_dev)) {
 	if (IS_ERR(pctl_dev)) {
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
 		return PTR_ERR(pctl_dev);
 		return PTR_ERR(pctl_dev);
 	}
 	}
 
 
-	grange.name = "exynos5440-pctrl-gpio-range";
-	grange.id = 0;
-	grange.base = 0;
-	grange.npins = EXYNOS5440_MAX_PINS;
-	grange.gc = priv->gc;
-	pinctrl_add_gpio_range(pctl_dev, &grange);
+	priv->range.name = "exynos5440-pctrl-gpio-range";
+	priv->range.id = 0;
+	priv->range.base = 0;
+	priv->range.npins = EXYNOS5440_MAX_PINS;
+	priv->range.gc = priv->gc;
+	pinctrl_add_gpio_range(pctl_dev, &priv->range);
 	return 0;
 	return 0;
 }
 }
 
 

+ 2 - 1
drivers/pinctrl/samsung/pinctrl-samsung.c

@@ -884,7 +884,8 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	drvdata->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, drvdata);
+	drvdata->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc,
+						  drvdata);
 	if (IS_ERR(drvdata->pctl_dev)) {
 	if (IS_ERR(drvdata->pctl_dev)) {
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
 		return PTR_ERR(drvdata->pctl_dev);
 		return PTR_ERR(drvdata->pctl_dev);

+ 16 - 4
drivers/pinctrl/sh-pfc/core.c

@@ -175,6 +175,21 @@ void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
 	BUG();
 	BUG();
 }
 }
 
 
+u32 sh_pfc_read_reg(struct sh_pfc *pfc, u32 reg, unsigned int width)
+{
+	return sh_pfc_read_raw_reg(sh_pfc_phys_to_virt(pfc, reg), width);
+}
+
+void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width, u32 data)
+{
+	if (pfc->info->unlock_reg)
+		sh_pfc_write_raw_reg(
+			sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
+			~data);
+
+	sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, reg), width, data);
+}
+
 static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
 static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
 				     const struct pinmux_cfg_reg *crp,
 				     const struct pinmux_cfg_reg *crp,
 				     unsigned int in_pos,
 				     unsigned int in_pos,
@@ -585,12 +600,9 @@ static int sh_pfc_probe(struct platform_device *pdev)
 
 
 static int sh_pfc_remove(struct platform_device *pdev)
 static int sh_pfc_remove(struct platform_device *pdev)
 {
 {
-	struct sh_pfc *pfc = platform_get_drvdata(pdev);
-
 #ifdef CONFIG_PINCTRL_SH_PFC_GPIO
 #ifdef CONFIG_PINCTRL_SH_PFC_GPIO
-	sh_pfc_unregister_gpiochip(pfc);
+	sh_pfc_unregister_gpiochip(platform_get_drvdata(pdev));
 #endif
 #endif
-	sh_pfc_unregister_pinctrl(pfc);
 
 
 	return 0;
 	return 0;
 }
 }

+ 3 - 2
drivers/pinctrl/sh-pfc/core.h

@@ -50,18 +50,19 @@ struct sh_pfc {
 	struct sh_pfc_chip *func;
 	struct sh_pfc_chip *func;
 #endif
 #endif
 
 
-	struct sh_pfc_pinctrl *pinctrl;
 };
 };
 
 
 int sh_pfc_register_gpiochip(struct sh_pfc *pfc);
 int sh_pfc_register_gpiochip(struct sh_pfc *pfc);
 int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc);
 int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc);
 
 
 int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
 int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
-int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc);
 
 
 u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width);
 u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width);
 void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
 void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
 			  u32 data);
 			  u32 data);
+u32 sh_pfc_read_reg(struct sh_pfc *pfc, u32 reg, unsigned int width);
+void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width,
+		      u32 data);
 
 
 int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin);
 int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin);
 int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type);
 int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type);

+ 53 - 1
drivers/pinctrl/sh-pfc/pfc-r8a7790.c

@@ -21,16 +21,21 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
  */
 
 
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 
 
 #include "core.h"
 #include "core.h"
 #include "sh_pfc.h"
 #include "sh_pfc.h"
 
 
+/*
+ * All pins assigned to GPIO bank 3 can be used for SD interfaces in
+ * which case they support both 3.3V and 1.8V signalling.
+ */
 #define CPU_ALL_PORT(fn, sfx)						\
 #define CPU_ALL_PORT(fn, sfx)						\
 	PORT_GP_32(0, fn, sfx),						\
 	PORT_GP_32(0, fn, sfx),						\
 	PORT_GP_30(1, fn, sfx),						\
 	PORT_GP_30(1, fn, sfx),						\
 	PORT_GP_30(2, fn, sfx),						\
 	PORT_GP_30(2, fn, sfx),						\
-	PORT_GP_32(3, fn, sfx),						\
+	PORT_GP_CFG_32(3, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE),		\
 	PORT_GP_32(4, fn, sfx),						\
 	PORT_GP_32(4, fn, sfx),						\
 	PORT_GP_32(5, fn, sfx)
 	PORT_GP_32(5, fn, sfx)
 
 
@@ -4691,6 +4696,47 @@ static const char * const vin3_groups[] = {
 	"vin3_clk",
 	"vin3_clk",
 };
 };
 
 
+#define IOCTRL6 0x8c
+
+static int r8a7790_get_io_voltage(struct sh_pfc *pfc, unsigned int pin)
+{
+	u32 data, mask;
+
+	if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin))
+		return -EINVAL;
+
+	data = ioread32(pfc->windows->virt + IOCTRL6),
+	/* Bits in IOCTRL6 are numbered in opposite order to pins */
+	mask = 0x80000000 >> (pin & 0x1f);
+
+	return (data & mask) ? 3300 : 1800;
+}
+
+static int r8a7790_set_io_voltage(struct sh_pfc *pfc, unsigned int pin, u16 mV)
+{
+	u32 data, mask;
+
+	if (WARN(pin < RCAR_GP_PIN(3, 0) || pin > RCAR_GP_PIN(3, 31), "invalid pin %#x", pin))
+		return -EINVAL;
+
+	if (mV != 1800 && mV != 3300)
+		return -EINVAL;
+
+	data = ioread32(pfc->windows->virt + IOCTRL6);
+	/* Bits in IOCTRL6 are numbered in opposite order to pins */
+	mask = 0x80000000 >> (pin & 0x1f);
+
+	if (mV == 3300)
+		data |= mask;
+	else
+		data &= ~mask;
+
+	iowrite32(~data, pfc->windows->virt); /* unlock reg */
+	iowrite32(data, pfc->windows->virt + IOCTRL6);
+
+	return 0;
+}
+
 static const struct sh_pfc_function pinmux_functions[] = {
 static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(audio_clk),
 	SH_PFC_FUNCTION(audio_clk),
 	SH_PFC_FUNCTION(avb),
 	SH_PFC_FUNCTION(avb),
@@ -5690,8 +5736,14 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ },
 	{ },
 };
 };
 
 
+static const struct sh_pfc_soc_operations pinmux_ops = {
+	.get_io_voltage = r8a7790_get_io_voltage,
+	.set_io_voltage = r8a7790_set_io_voltage,
+};
+
 const struct sh_pfc_soc_info r8a7790_pinmux_info = {
 const struct sh_pfc_soc_info r8a7790_pinmux_info = {
 	.name = "r8a77900_pfc",
 	.name = "r8a77900_pfc",
+	.ops = &pinmux_ops,
 	.unlock_reg = 0xe6060000, /* PMMR */
 	.unlock_reg = 0xe6060000, /* PMMR */
 
 
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },

+ 217 - 0
drivers/pinctrl/sh-pfc/pfc-r8a7794.c

@@ -1682,6 +1682,179 @@ static const unsigned int avb_avtp_match_b_pins[] = {
 static const unsigned int avb_avtp_match_b_mux[] = {
 static const unsigned int avb_avtp_match_b_mux[] = {
 	AVB_AVTP_MATCH_B_MARK,
 	AVB_AVTP_MATCH_B_MARK,
 };
 };
+/* - DU --------------------------------------------------------------------- */
+static const unsigned int du0_rgb666_pins[] = {
+	/* R[7:2], G[7:2], B[7:2] */
+	RCAR_GP_PIN(2, 7),  RCAR_GP_PIN(2, 6),  RCAR_GP_PIN(2, 5),
+	RCAR_GP_PIN(2, 4),  RCAR_GP_PIN(2, 3),  RCAR_GP_PIN(2, 2),
+	RCAR_GP_PIN(2, 15), RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13),
+	RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10),
+	RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 22), RCAR_GP_PIN(2, 21),
+	RCAR_GP_PIN(2, 20), RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 18),
+};
+static const unsigned int du0_rgb666_mux[] = {
+	DU0_DR7_MARK, DU0_DR6_MARK, DU0_DR5_MARK, DU0_DR4_MARK,
+	DU0_DR3_MARK, DU0_DR2_MARK,
+	DU0_DG7_MARK, DU0_DG6_MARK, DU0_DG5_MARK, DU0_DG4_MARK,
+	DU0_DG3_MARK, DU0_DG2_MARK,
+	DU0_DB7_MARK, DU0_DB6_MARK, DU0_DB5_MARK, DU0_DB4_MARK,
+	DU0_DB3_MARK, DU0_DB2_MARK,
+};
+static const unsigned int du0_rgb888_pins[] = {
+	/* R[7:0], G[7:0], B[7:0] */
+	RCAR_GP_PIN(2, 7),  RCAR_GP_PIN(2, 6),  RCAR_GP_PIN(2, 5),
+	RCAR_GP_PIN(2, 4),  RCAR_GP_PIN(2, 3),  RCAR_GP_PIN(2, 2),
+	RCAR_GP_PIN(2, 1),  RCAR_GP_PIN(2, 0),
+	RCAR_GP_PIN(2, 15), RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13),
+	RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10),
+	RCAR_GP_PIN(2, 9),  RCAR_GP_PIN(2, 8),
+	RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 22), RCAR_GP_PIN(2, 21),
+	RCAR_GP_PIN(2, 20), RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 18),
+	RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 16),
+};
+static const unsigned int du0_rgb888_mux[] = {
+	DU0_DR7_MARK, DU0_DR6_MARK, DU0_DR5_MARK, DU0_DR4_MARK,
+	DU0_DR3_MARK, DU0_DR2_MARK, DU0_DR1_MARK, DU0_DR0_MARK,
+	DU0_DG7_MARK, DU0_DG6_MARK, DU0_DG5_MARK, DU0_DG4_MARK,
+	DU0_DG3_MARK, DU0_DG2_MARK, DU0_DG1_MARK, DU0_DG0_MARK,
+	DU0_DB7_MARK, DU0_DB6_MARK, DU0_DB5_MARK, DU0_DB4_MARK,
+	DU0_DB3_MARK, DU0_DB2_MARK, DU0_DB1_MARK, DU0_DB0_MARK,
+};
+static const unsigned int du0_clk0_out_pins[] = {
+	/* DOTCLKOUT0 */
+	RCAR_GP_PIN(2, 25),
+};
+static const unsigned int du0_clk0_out_mux[] = {
+	DU0_DOTCLKOUT0_MARK
+};
+static const unsigned int du0_clk1_out_pins[] = {
+	/* DOTCLKOUT1 */
+	RCAR_GP_PIN(2, 26),
+};
+static const unsigned int du0_clk1_out_mux[] = {
+	DU0_DOTCLKOUT1_MARK
+};
+static const unsigned int du0_clk_in_pins[] = {
+	/* CLKIN */
+	RCAR_GP_PIN(2, 24),
+};
+static const unsigned int du0_clk_in_mux[] = {
+	DU0_DOTCLKIN_MARK
+};
+static const unsigned int du0_sync_pins[] = {
+	/* EXVSYNC/VSYNC, EXHSYNC/HSYNC */
+	RCAR_GP_PIN(2, 28), RCAR_GP_PIN(2, 27),
+};
+static const unsigned int du0_sync_mux[] = {
+	DU0_EXVSYNC_DU0_VSYNC_MARK, DU0_EXHSYNC_DU0_HSYNC_MARK
+};
+static const unsigned int du0_oddf_pins[] = {
+	/* EXODDF/ODDF/DISP/CDE */
+	RCAR_GP_PIN(2, 29),
+};
+static const unsigned int du0_oddf_mux[] = {
+	DU0_EXODDF_DU0_ODDF_DISP_CDE_MARK,
+};
+static const unsigned int du0_cde_pins[] = {
+	/* CDE */
+	RCAR_GP_PIN(2, 31),
+};
+static const unsigned int du0_cde_mux[] = {
+	DU0_CDE_MARK,
+};
+static const unsigned int du0_disp_pins[] = {
+	/* DISP */
+	RCAR_GP_PIN(2, 30),
+};
+static const unsigned int du0_disp_mux[] = {
+	DU0_DISP_MARK
+};
+static const unsigned int du1_rgb666_pins[] = {
+	/* R[7:2], G[7:2], B[7:2] */
+	RCAR_GP_PIN(4, 7),  RCAR_GP_PIN(4, 6),  RCAR_GP_PIN(4, 5),
+	RCAR_GP_PIN(4, 4),  RCAR_GP_PIN(4, 3),  RCAR_GP_PIN(4, 2),
+	RCAR_GP_PIN(4, 15), RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 13),
+	RCAR_GP_PIN(4, 12), RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 10),
+	RCAR_GP_PIN(4, 23), RCAR_GP_PIN(4, 22), RCAR_GP_PIN(4, 21),
+	RCAR_GP_PIN(4, 20), RCAR_GP_PIN(4, 19), RCAR_GP_PIN(4, 18),
+};
+static const unsigned int du1_rgb666_mux[] = {
+	DU1_DR7_MARK, DU1_DR6_MARK, DU1_DR5_MARK, DU1_DR4_MARK,
+	DU1_DR3_MARK, DU1_DR2_MARK,
+	DU1_DG7_MARK, DU1_DG6_MARK, DU1_DG5_MARK, DU1_DG4_MARK,
+	DU1_DG3_MARK, DU1_DG2_MARK,
+	DU1_DB7_MARK, DU1_DB6_MARK, DU1_DB5_MARK, DU1_DB4_MARK,
+	DU1_DB3_MARK, DU1_DB2_MARK,
+};
+static const unsigned int du1_rgb888_pins[] = {
+	/* R[7:0], G[7:0], B[7:0] */
+	RCAR_GP_PIN(4, 7),  RCAR_GP_PIN(4, 6),  RCAR_GP_PIN(4, 5),
+	RCAR_GP_PIN(4, 4),  RCAR_GP_PIN(4, 3),  RCAR_GP_PIN(4, 2),
+	RCAR_GP_PIN(4, 1),  RCAR_GP_PIN(4, 0),
+	RCAR_GP_PIN(4, 15), RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 13),
+	RCAR_GP_PIN(4, 12), RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 10),
+	RCAR_GP_PIN(4, 9),  RCAR_GP_PIN(4, 8),
+	RCAR_GP_PIN(4, 23), RCAR_GP_PIN(4, 22), RCAR_GP_PIN(4, 21),
+	RCAR_GP_PIN(4, 20), RCAR_GP_PIN(4, 19), RCAR_GP_PIN(4, 18),
+	RCAR_GP_PIN(4, 17), RCAR_GP_PIN(4, 16),
+};
+static const unsigned int du1_rgb888_mux[] = {
+	DU1_DR7_MARK, DU1_DR6_MARK, DU1_DR5_MARK, DU1_DR4_MARK,
+	DU1_DR3_MARK, DU1_DR2_MARK, DU1_DR1_MARK, DU1_DR0_MARK,
+	DU1_DG7_MARK, DU1_DG6_MARK, DU1_DG5_MARK, DU1_DG4_MARK,
+	DU1_DG3_MARK, DU1_DG2_MARK, DU1_DG1_MARK, DU1_DG0_MARK,
+	DU1_DB7_MARK, DU1_DB6_MARK, DU1_DB5_MARK, DU1_DB4_MARK,
+	DU1_DB3_MARK, DU1_DB2_MARK, DU1_DB1_MARK, DU1_DB0_MARK,
+};
+static const unsigned int du1_clk0_out_pins[] = {
+	/* DOTCLKOUT0 */
+	RCAR_GP_PIN(4, 25),
+};
+static const unsigned int du1_clk0_out_mux[] = {
+	DU1_DOTCLKOUT0_MARK
+};
+static const unsigned int du1_clk1_out_pins[] = {
+	/* DOTCLKOUT1 */
+	RCAR_GP_PIN(4, 26),
+};
+static const unsigned int du1_clk1_out_mux[] = {
+	DU1_DOTCLKOUT1_MARK
+};
+static const unsigned int du1_clk_in_pins[] = {
+	/* DOTCLKIN */
+	RCAR_GP_PIN(4, 24),
+};
+static const unsigned int du1_clk_in_mux[] = {
+	DU1_DOTCLKIN_MARK
+};
+static const unsigned int du1_sync_pins[] = {
+	/* EXVSYNC/VSYNC, EXHSYNC/HSYNC */
+	RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 27),
+};
+static const unsigned int du1_sync_mux[] = {
+	DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK
+};
+static const unsigned int du1_oddf_pins[] = {
+	/* EXODDF/ODDF/DISP/CDE */
+	RCAR_GP_PIN(4, 29),
+};
+static const unsigned int du1_oddf_mux[] = {
+	DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK,
+};
+static const unsigned int du1_cde_pins[] = {
+	/* CDE */
+	RCAR_GP_PIN(4, 31),
+};
+static const unsigned int du1_cde_mux[] = {
+	DU1_CDE_MARK
+};
+static const unsigned int du1_disp_pins[] = {
+	/* DISP */
+	RCAR_GP_PIN(4, 30),
+};
+static const unsigned int du1_disp_mux[] = {
+	DU1_DISP_MARK
+};
 /* - ETH -------------------------------------------------------------------- */
 /* - ETH -------------------------------------------------------------------- */
 static const unsigned int eth_link_pins[] = {
 static const unsigned int eth_link_pins[] = {
 	/* LINK */
 	/* LINK */
@@ -3364,6 +3537,24 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
 	SH_PFC_PIN_GROUP(avb_avtp_match),
 	SH_PFC_PIN_GROUP(avb_avtp_match),
 	SH_PFC_PIN_GROUP(avb_avtp_capture_b),
 	SH_PFC_PIN_GROUP(avb_avtp_capture_b),
 	SH_PFC_PIN_GROUP(avb_avtp_match_b),
 	SH_PFC_PIN_GROUP(avb_avtp_match_b),
+	SH_PFC_PIN_GROUP(du0_rgb666),
+	SH_PFC_PIN_GROUP(du0_rgb888),
+	SH_PFC_PIN_GROUP(du0_clk0_out),
+	SH_PFC_PIN_GROUP(du0_clk1_out),
+	SH_PFC_PIN_GROUP(du0_clk_in),
+	SH_PFC_PIN_GROUP(du0_sync),
+	SH_PFC_PIN_GROUP(du0_oddf),
+	SH_PFC_PIN_GROUP(du0_cde),
+	SH_PFC_PIN_GROUP(du0_disp),
+	SH_PFC_PIN_GROUP(du1_rgb666),
+	SH_PFC_PIN_GROUP(du1_rgb888),
+	SH_PFC_PIN_GROUP(du1_clk0_out),
+	SH_PFC_PIN_GROUP(du1_clk1_out),
+	SH_PFC_PIN_GROUP(du1_clk_in),
+	SH_PFC_PIN_GROUP(du1_sync),
+	SH_PFC_PIN_GROUP(du1_oddf),
+	SH_PFC_PIN_GROUP(du1_cde),
+	SH_PFC_PIN_GROUP(du1_disp),
 	SH_PFC_PIN_GROUP(eth_link),
 	SH_PFC_PIN_GROUP(eth_link),
 	SH_PFC_PIN_GROUP(eth_magic),
 	SH_PFC_PIN_GROUP(eth_magic),
 	SH_PFC_PIN_GROUP(eth_mdio),
 	SH_PFC_PIN_GROUP(eth_mdio),
@@ -3622,6 +3813,30 @@ static const char * const avb_groups[] = {
 	"avb_avtp_match_b",
 	"avb_avtp_match_b",
 };
 };
 
 
+static const char * const du0_groups[] = {
+	"du0_rgb666",
+	"du0_rgb888",
+	"du0_clk0_out",
+	"du0_clk1_out",
+	"du0_clk_in",
+	"du0_sync",
+	"du0_oddf",
+	"du0_cde",
+	"du0_disp",
+};
+
+static const char * const du1_groups[] = {
+	"du1_rgb666",
+	"du1_rgb888",
+	"du1_clk0_out",
+	"du1_clk1_out",
+	"du1_clk_in",
+	"du1_sync",
+	"du1_oddf",
+	"du1_cde",
+	"du1_disp",
+};
+
 static const char * const eth_groups[] = {
 static const char * const eth_groups[] = {
 	"eth_link",
 	"eth_link",
 	"eth_magic",
 	"eth_magic",
@@ -3969,6 +4184,8 @@ static const char * const vin1_groups[] = {
 static const struct sh_pfc_function pinmux_functions[] = {
 static const struct sh_pfc_function pinmux_functions[] = {
 	SH_PFC_FUNCTION(audio_clk),
 	SH_PFC_FUNCTION(audio_clk),
 	SH_PFC_FUNCTION(avb),
 	SH_PFC_FUNCTION(avb),
+	SH_PFC_FUNCTION(du0),
+	SH_PFC_FUNCTION(du1),
 	SH_PFC_FUNCTION(eth),
 	SH_PFC_FUNCTION(eth),
 	SH_PFC_FUNCTION(hscif0),
 	SH_PFC_FUNCTION(hscif0),
 	SH_PFC_FUNCTION(hscif1),
 	SH_PFC_FUNCTION(hscif1),

+ 210 - 8
drivers/pinctrl/sh-pfc/pfc-r8a7795.c

@@ -14,14 +14,14 @@
 #include "sh_pfc.h"
 #include "sh_pfc.h"
 
 
 #define CPU_ALL_PORT(fn, sfx)						\
 #define CPU_ALL_PORT(fn, sfx)						\
-	PORT_GP_16(0, fn, sfx),						\
-	PORT_GP_28(1, fn, sfx),						\
-	PORT_GP_15(2, fn, sfx),						\
-	PORT_GP_16(3, fn, sfx),						\
-	PORT_GP_18(4, fn, sfx),						\
-	PORT_GP_26(5, fn, sfx),						\
-	PORT_GP_32(6, fn, sfx),						\
-	PORT_GP_4(7, fn, sfx)
+	PORT_GP_CFG_16(0, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH),	\
+	PORT_GP_CFG_28(1, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH),	\
+	PORT_GP_CFG_15(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH),	\
+	PORT_GP_CFG_16(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH),	\
+	PORT_GP_CFG_18(4, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH),	\
+	PORT_GP_CFG_26(5, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH),	\
+	PORT_GP_CFG_32(6, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH),	\
+	PORT_GP_CFG_4(7, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH)
 /*
 /*
  * F_() : just information
  * F_() : just information
  * FM() : macro for FN_xxx / xxx_MARK
  * FM() : macro for FN_xxx / xxx_MARK
@@ -4564,6 +4564,207 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
 	{ },
 	{ },
 };
 };
 
 
+static const struct pinmux_drive_reg pinmux_drive_regs[] = {
+	{ PINMUX_DRIVE_REG("DRVCTRL3", 0xe606030c) {
+		{ RCAR_GP_PIN(2,  9),  8, 3 },	/* AVB_MDC */
+		{ RCAR_GP_PIN(2, 10),  4, 3 },	/* AVB_MAGIC */
+		{ RCAR_GP_PIN(2, 11),  0, 3 },	/* AVB_PHY_INT */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL4", 0xe6060310) {
+		{ RCAR_GP_PIN(2, 12), 28, 3 },	/* AVB_LINK */
+		{ RCAR_GP_PIN(2, 13), 24, 3 },	/* AVB_AVTP_MATCH */
+		{ RCAR_GP_PIN(2, 14), 20, 3 },	/* AVB_AVTP_CAPTURE */
+		{ RCAR_GP_PIN(2,  0), 16, 3 },	/* IRQ0 */
+		{ RCAR_GP_PIN(2,  1), 12, 3 },	/* IRQ1 */
+		{ RCAR_GP_PIN(2,  2),  8, 3 },	/* IRQ2 */
+		{ RCAR_GP_PIN(2,  3),  4, 3 },	/* IRQ3 */
+		{ RCAR_GP_PIN(2,  4),  0, 3 },	/* IRQ4 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL5", 0xe6060314) {
+		{ RCAR_GP_PIN(2,  5), 28, 3 },	/* IRQ5 */
+		{ RCAR_GP_PIN(2,  6), 24, 3 },	/* PWM0 */
+		{ RCAR_GP_PIN(2,  7), 20, 3 },	/* PWM1 */
+		{ RCAR_GP_PIN(2,  8), 16, 3 },	/* PWM2 */
+		{ RCAR_GP_PIN(1,  0), 12, 3 },	/* A0 */
+		{ RCAR_GP_PIN(1,  1),  8, 3 },	/* A1 */
+		{ RCAR_GP_PIN(1,  2),  4, 3 },	/* A2 */
+		{ RCAR_GP_PIN(1,  3),  0, 3 },	/* A3 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL6", 0xe6060318) {
+		{ RCAR_GP_PIN(1,  4), 28, 3 },	/* A4 */
+		{ RCAR_GP_PIN(1,  5), 24, 3 },	/* A5 */
+		{ RCAR_GP_PIN(1,  6), 20, 3 },	/* A6 */
+		{ RCAR_GP_PIN(1,  7), 16, 3 },	/* A7 */
+		{ RCAR_GP_PIN(1,  8), 12, 3 },	/* A8 */
+		{ RCAR_GP_PIN(1,  9),  8, 3 },	/* A9 */
+		{ RCAR_GP_PIN(1, 10),  4, 3 },	/* A10 */
+		{ RCAR_GP_PIN(1, 11),  0, 3 },	/* A11 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL7", 0xe606031c) {
+		{ RCAR_GP_PIN(1, 12), 28, 3 },	/* A12 */
+		{ RCAR_GP_PIN(1, 13), 24, 3 },	/* A13 */
+		{ RCAR_GP_PIN(1, 14), 20, 3 },	/* A14 */
+		{ RCAR_GP_PIN(1, 15), 16, 3 },	/* A15 */
+		{ RCAR_GP_PIN(1, 16), 12, 3 },	/* A16 */
+		{ RCAR_GP_PIN(1, 17),  8, 3 },	/* A17 */
+		{ RCAR_GP_PIN(1, 18),  4, 3 },	/* A18 */
+		{ RCAR_GP_PIN(1, 19),  0, 3 },	/* A19 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL8", 0xe6060320) {
+		{ RCAR_GP_PIN(1, 20), 24, 3 },	/* CS0 */
+		{ RCAR_GP_PIN(1, 21), 20, 3 },	/* CS1_A26 */
+		{ RCAR_GP_PIN(1, 22), 16, 3 },	/* BS */
+		{ RCAR_GP_PIN(1, 23), 12, 3 },	/* RD */
+		{ RCAR_GP_PIN(1, 24),  8, 3 },	/* RD_WR */
+		{ RCAR_GP_PIN(1, 25),  4, 3 },	/* WE0 */
+		{ RCAR_GP_PIN(1, 26),  0, 3 },	/* WE1 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) {
+		{ RCAR_GP_PIN(1, 27), 28, 3 },	/* EX_WAIT0 */
+		{ RCAR_GP_PIN(0,  0), 20, 3 },	/* D0 */
+		{ RCAR_GP_PIN(0,  1), 16, 3 },	/* D1 */
+		{ RCAR_GP_PIN(0,  2), 12, 3 },	/* D2 */
+		{ RCAR_GP_PIN(0,  3),  8, 3 },	/* D3 */
+		{ RCAR_GP_PIN(0,  4),  4, 3 },	/* D4 */
+		{ RCAR_GP_PIN(0,  5),  0, 3 },	/* D5 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL10", 0xe6060328) {
+		{ RCAR_GP_PIN(0,  6), 28, 3 },	/* D6 */
+		{ RCAR_GP_PIN(0,  7), 24, 3 },	/* D7 */
+		{ RCAR_GP_PIN(0,  8), 20, 3 },	/* D8 */
+		{ RCAR_GP_PIN(0,  9), 16, 3 },	/* D9 */
+		{ RCAR_GP_PIN(0, 10), 12, 3 },	/* D10 */
+		{ RCAR_GP_PIN(0, 11),  8, 3 },	/* D11 */
+		{ RCAR_GP_PIN(0, 12),  4, 3 },	/* D12 */
+		{ RCAR_GP_PIN(0, 13),  0, 3 },	/* D13 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL11", 0xe606032c) {
+		{ RCAR_GP_PIN(0, 14), 28, 3 },	/* D14 */
+		{ RCAR_GP_PIN(0, 15), 24, 3 },	/* D15 */
+		{ RCAR_GP_PIN(7,  0), 20, 3 },	/* AVS1 */
+		{ RCAR_GP_PIN(7,  1), 16, 3 },	/* AVS2 */
+		{ RCAR_GP_PIN(7,  2), 12, 3 },	/* HDMI0_CEC */
+		{ RCAR_GP_PIN(7,  3),  8, 3 },	/* HDMI1_CEC */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL13", 0xe6060334) {
+		{ RCAR_GP_PIN(3,  0), 20, 3 },	/* SD0_CLK */
+		{ RCAR_GP_PIN(3,  1), 16, 3 },	/* SD0_CMD */
+		{ RCAR_GP_PIN(3,  2), 12, 3 },	/* SD0_DAT0 */
+		{ RCAR_GP_PIN(3,  3),  8, 3 },	/* SD0_DAT1 */
+		{ RCAR_GP_PIN(3,  4),  4, 3 },	/* SD0_DAT2 */
+		{ RCAR_GP_PIN(3,  5),  0, 3 },	/* SD0_DAT3 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL14", 0xe6060338) {
+		{ RCAR_GP_PIN(3,  6), 28, 3 },	/* SD1_CLK */
+		{ RCAR_GP_PIN(3,  7), 24, 3 },	/* SD1_CMD */
+		{ RCAR_GP_PIN(3,  8), 20, 3 },	/* SD1_DAT0 */
+		{ RCAR_GP_PIN(3,  9), 16, 3 },	/* SD1_DAT1 */
+		{ RCAR_GP_PIN(3, 10), 12, 3 },	/* SD1_DAT2 */
+		{ RCAR_GP_PIN(3, 11),  8, 3 },	/* SD1_DAT3 */
+		{ RCAR_GP_PIN(4,  0),  4, 3 },	/* SD2_CLK */
+		{ RCAR_GP_PIN(4,  1),  0, 3 },	/* SD2_CMD */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL15", 0xe606033c) {
+		{ RCAR_GP_PIN(4,  2), 28, 3 },	/* SD2_DAT0 */
+		{ RCAR_GP_PIN(4,  3), 24, 3 },	/* SD2_DAT1 */
+		{ RCAR_GP_PIN(4,  4), 20, 3 },	/* SD2_DAT2 */
+		{ RCAR_GP_PIN(4,  5), 16, 3 },	/* SD2_DAT3 */
+		{ RCAR_GP_PIN(4,  6), 12, 3 },	/* SD2_DS */
+		{ RCAR_GP_PIN(4,  7),  8, 3 },	/* SD3_CLK */
+		{ RCAR_GP_PIN(4,  8),  4, 3 },	/* SD3_CMD */
+		{ RCAR_GP_PIN(4,  9),  0, 3 },	/* SD3_DAT0 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL16", 0xe6060340) {
+		{ RCAR_GP_PIN(4, 10), 28, 3 },	/* SD3_DAT1 */
+		{ RCAR_GP_PIN(4, 11), 24, 3 },	/* SD3_DAT2 */
+		{ RCAR_GP_PIN(4, 12), 20, 3 },	/* SD3_DAT3 */
+		{ RCAR_GP_PIN(4, 13), 16, 3 },	/* SD3_DAT4 */
+		{ RCAR_GP_PIN(4, 14), 12, 3 },	/* SD3_DAT5 */
+		{ RCAR_GP_PIN(4, 15),  8, 3 },	/* SD3_DAT6 */
+		{ RCAR_GP_PIN(4, 16),  4, 3 },	/* SD3_DAT7 */
+		{ RCAR_GP_PIN(4, 17),  0, 3 },	/* SD3_DS */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL17", 0xe6060344) {
+		{ RCAR_GP_PIN(3, 12), 28, 3 },	/* SD0_CD */
+		{ RCAR_GP_PIN(3, 13), 24, 3 },	/* SD0_WP */
+		{ RCAR_GP_PIN(3, 14), 20, 3 },	/* SD1_CD */
+		{ RCAR_GP_PIN(3, 15), 16, 3 },	/* SD1_WP */
+		{ RCAR_GP_PIN(5,  0), 12, 3 },	/* SCK0 */
+		{ RCAR_GP_PIN(5,  1),  8, 3 },	/* RX0 */
+		{ RCAR_GP_PIN(5,  2),  4, 3 },	/* TX0 */
+		{ RCAR_GP_PIN(5,  3),  0, 3 },	/* CTS0 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL18", 0xe6060348) {
+		{ RCAR_GP_PIN(5,  4), 28, 3 },	/* RTS0_TANS */
+		{ RCAR_GP_PIN(5,  5), 24, 3 },	/* RX1 */
+		{ RCAR_GP_PIN(5,  6), 20, 3 },	/* TX1 */
+		{ RCAR_GP_PIN(5,  7), 16, 3 },	/* CTS1 */
+		{ RCAR_GP_PIN(5,  8), 12, 3 },	/* RTS1_TANS */
+		{ RCAR_GP_PIN(5,  9),  8, 3 },	/* SCK2 */
+		{ RCAR_GP_PIN(5, 10),  4, 3 },	/* TX2 */
+		{ RCAR_GP_PIN(5, 11),  0, 3 },	/* RX2 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL19", 0xe606034c) {
+		{ RCAR_GP_PIN(5, 12), 28, 3 },	/* HSCK0 */
+		{ RCAR_GP_PIN(5, 13), 24, 3 },	/* HRX0 */
+		{ RCAR_GP_PIN(5, 14), 20, 3 },	/* HTX0 */
+		{ RCAR_GP_PIN(5, 15), 16, 3 },	/* HCTS0 */
+		{ RCAR_GP_PIN(5, 16), 12, 3 },	/* HRTS0 */
+		{ RCAR_GP_PIN(5, 17),  8, 3 },	/* MSIOF0_SCK */
+		{ RCAR_GP_PIN(5, 18),  4, 3 },	/* MSIOF0_SYNC */
+		{ RCAR_GP_PIN(5, 19),  0, 3 },	/* MSIOF0_SS1 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL20", 0xe6060350) {
+		{ RCAR_GP_PIN(5, 20), 28, 3 },	/* MSIOF0_TXD */
+		{ RCAR_GP_PIN(5, 21), 24, 3 },	/* MSIOF0_SS2 */
+		{ RCAR_GP_PIN(5, 22), 20, 3 },	/* MSIOF0_RXD */
+		{ RCAR_GP_PIN(5, 23), 16, 3 },	/* MLB_CLK */
+		{ RCAR_GP_PIN(5, 24), 12, 3 },	/* MLB_SIG */
+		{ RCAR_GP_PIN(5, 25),  8, 3 },	/* MLB_DAT */
+		{ RCAR_GP_PIN(6,  0),  0, 3 },	/* SSI_SCK01239 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL21", 0xe6060354) {
+		{ RCAR_GP_PIN(6,  1), 28, 3 },	/* SSI_WS01239 */
+		{ RCAR_GP_PIN(6,  2), 24, 3 },	/* SSI_SDATA0 */
+		{ RCAR_GP_PIN(6,  3), 20, 3 },	/* SSI_SDATA1 */
+		{ RCAR_GP_PIN(6,  4), 16, 3 },	/* SSI_SDATA2 */
+		{ RCAR_GP_PIN(6,  5), 12, 3 },	/* SSI_SCK34 */
+		{ RCAR_GP_PIN(6,  6),  8, 3 },	/* SSI_WS34 */
+		{ RCAR_GP_PIN(6,  7),  4, 3 },	/* SSI_SDATA3 */
+		{ RCAR_GP_PIN(6,  8),  0, 3 },	/* SSI_SCK4 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL22", 0xe6060358) {
+		{ RCAR_GP_PIN(6,  9), 28, 3 },	/* SSI_WS4 */
+		{ RCAR_GP_PIN(6, 10), 24, 3 },	/* SSI_SDATA4 */
+		{ RCAR_GP_PIN(6, 11), 20, 3 },	/* SSI_SCK5 */
+		{ RCAR_GP_PIN(6, 12), 16, 3 },	/* SSI_WS5 */
+		{ RCAR_GP_PIN(6, 13), 12, 3 },	/* SSI_SDATA5 */
+		{ RCAR_GP_PIN(6, 14),  8, 3 },	/* SSI_SCK6 */
+		{ RCAR_GP_PIN(6, 15),  4, 3 },	/* SSI_WS6 */
+		{ RCAR_GP_PIN(6, 16),  0, 3 },	/* SSI_SDATA6 */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL23", 0xe606035c) {
+		{ RCAR_GP_PIN(6, 17), 28, 3 },	/* SSI_SCK78 */
+		{ RCAR_GP_PIN(6, 18), 24, 3 },	/* SSI_WS78 */
+		{ RCAR_GP_PIN(6, 19), 20, 3 },	/* SSI_SDATA7 */
+		{ RCAR_GP_PIN(6, 20), 16, 3 },	/* SSI_SDATA8 */
+		{ RCAR_GP_PIN(6, 21), 12, 3 },	/* SSI_SDATA9 */
+		{ RCAR_GP_PIN(6, 22),  8, 3 },	/* AUDIO_CLKA */
+		{ RCAR_GP_PIN(6, 23),  4, 3 },	/* AUDIO_CLKB */
+		{ RCAR_GP_PIN(6, 24),  0, 3 },	/* USB0_PWEN */
+	} },
+	{ PINMUX_DRIVE_REG("DRVCTRL24", 0xe6060360) {
+		{ RCAR_GP_PIN(6, 25), 28, 3 },	/* USB0_OVC */
+		{ RCAR_GP_PIN(6, 26), 24, 3 },	/* USB1_PWEN */
+		{ RCAR_GP_PIN(6, 27), 20, 3 },	/* USB1_OVC */
+		{ RCAR_GP_PIN(6, 28), 16, 3 },	/* USB30_PWEN */
+		{ RCAR_GP_PIN(6, 29), 12, 3 },	/* USB30_OVC */
+		{ RCAR_GP_PIN(6, 30),  8, 3 },	/* USB31_PWEN */
+		{ RCAR_GP_PIN(6, 31),  4, 3 },	/* USB31_OVC */
+	} },
+	{ },
+};
+
 const struct sh_pfc_soc_info r8a7795_pinmux_info = {
 const struct sh_pfc_soc_info r8a7795_pinmux_info = {
 	.name = "r8a77950_pfc",
 	.name = "r8a77950_pfc",
 	.unlock_reg = 0xe6060000, /* PMMR */
 	.unlock_reg = 0xe6060000, /* PMMR */
@@ -4578,6 +4779,7 @@ const struct sh_pfc_soc_info r8a7795_pinmux_info = {
 	.nr_functions = ARRAY_SIZE(pinmux_functions),
 	.nr_functions = ARRAY_SIZE(pinmux_functions),
 
 
 	.cfg_regs = pinmux_config_regs,
 	.cfg_regs = pinmux_config_regs,
+	.drive_regs = pinmux_drive_regs,
 
 
 	.pinmux_data = pinmux_data,
 	.pinmux_data = pinmux_data,
 	.pinmux_data_size = ARRAY_SIZE(pinmux_data),
 	.pinmux_data_size = ARRAY_SIZE(pinmux_data),

+ 112 - 12
drivers/pinctrl/sh-pfc/pinctrl.c

@@ -476,6 +476,91 @@ static const struct pinmux_ops sh_pfc_pinmux_ops = {
 	.gpio_set_direction	= sh_pfc_gpio_set_direction,
 	.gpio_set_direction	= sh_pfc_gpio_set_direction,
 };
 };
 
 
+static u32 sh_pfc_pinconf_find_drive_strength_reg(struct sh_pfc *pfc,
+		unsigned int pin, unsigned int *offset, unsigned int *size)
+{
+	const struct pinmux_drive_reg_field *field;
+	const struct pinmux_drive_reg *reg;
+	unsigned int i;
+
+	for (reg = pfc->info->drive_regs; reg->reg; ++reg) {
+		for (i = 0; i < ARRAY_SIZE(reg->fields); ++i) {
+			field = &reg->fields[i];
+
+			if (field->size && field->pin == pin) {
+				*offset = field->offset;
+				*size = field->size;
+
+				return reg->reg;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int sh_pfc_pinconf_get_drive_strength(struct sh_pfc *pfc,
+					     unsigned int pin)
+{
+	unsigned long flags;
+	unsigned int offset;
+	unsigned int size;
+	u32 reg;
+	u32 val;
+
+	reg = sh_pfc_pinconf_find_drive_strength_reg(pfc, pin, &offset, &size);
+	if (!reg)
+		return -EINVAL;
+
+	spin_lock_irqsave(&pfc->lock, flags);
+	val = sh_pfc_read_reg(pfc, reg, 32);
+	spin_unlock_irqrestore(&pfc->lock, flags);
+
+	val = (val >> offset) & GENMASK(size - 1, 0);
+
+	/* Convert the value to mA based on a full drive strength value of 24mA.
+	 * We can make the full value configurable later if needed.
+	 */
+	return (val + 1) * (size == 2 ? 6 : 3);
+}
+
+static int sh_pfc_pinconf_set_drive_strength(struct sh_pfc *pfc,
+					     unsigned int pin, u16 strength)
+{
+	unsigned long flags;
+	unsigned int offset;
+	unsigned int size;
+	unsigned int step;
+	u32 reg;
+	u32 val;
+
+	reg = sh_pfc_pinconf_find_drive_strength_reg(pfc, pin, &offset, &size);
+	if (!reg)
+		return -EINVAL;
+
+	step = size == 2 ? 6 : 3;
+
+	if (strength < step || strength > 24)
+		return -EINVAL;
+
+	/* Convert the value from mA based on a full drive strength value of
+	 * 24mA. We can make the full value configurable later if needed.
+	 */
+	strength = strength / step - 1;
+
+	spin_lock_irqsave(&pfc->lock, flags);
+
+	val = sh_pfc_read_reg(pfc, reg, 32);
+	val &= ~GENMASK(offset + size - 1, offset);
+	val |= strength << offset;
+
+	sh_pfc_write_reg(pfc, reg, 32, val);
+
+	spin_unlock_irqrestore(&pfc->lock, flags);
+
+	return 0;
+}
+
 /* Check whether the requested parameter is supported for a pin. */
 /* Check whether the requested parameter is supported for a pin. */
 static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
 static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
 				    enum pin_config_param param)
 				    enum pin_config_param param)
@@ -493,6 +578,9 @@ static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 		return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
 		return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
 
 
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		return pin->configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH;
+
 	case PIN_CONFIG_POWER_SOURCE:
 	case PIN_CONFIG_POWER_SOURCE:
 		return pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE;
 		return pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE;
 
 
@@ -532,6 +620,17 @@ static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
 		break;
 		break;
 	}
 	}
 
 
+	case PIN_CONFIG_DRIVE_STRENGTH: {
+		int ret;
+
+		ret = sh_pfc_pinconf_get_drive_strength(pfc, _pin);
+		if (ret < 0)
+			return ret;
+
+		*config = ret;
+		break;
+	}
+
 	case PIN_CONFIG_POWER_SOURCE: {
 	case PIN_CONFIG_POWER_SOURCE: {
 		int ret;
 		int ret;
 
 
@@ -584,6 +683,18 @@ static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
 
 
 			break;
 			break;
 
 
+		case PIN_CONFIG_DRIVE_STRENGTH: {
+			unsigned int arg =
+				pinconf_to_config_argument(configs[i]);
+			int ret;
+
+			ret = sh_pfc_pinconf_set_drive_strength(pfc, _pin, arg);
+			if (ret < 0)
+				return ret;
+
+			break;
+		}
+
 		case PIN_CONFIG_POWER_SOURCE: {
 		case PIN_CONFIG_POWER_SOURCE: {
 			unsigned int arg =
 			unsigned int arg =
 				pinconf_to_config_argument(configs[i]);
 				pinconf_to_config_argument(configs[i]);
@@ -678,7 +789,6 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	pmx->pfc = pfc;
 	pmx->pfc = pfc;
-	pfc->pinctrl = pmx;
 
 
 	ret = sh_pfc_map_pins(pfc, pmx);
 	ret = sh_pfc_map_pins(pfc, pmx);
 	if (ret < 0)
 	if (ret < 0)
@@ -692,19 +802,9 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
 	pmx->pctl_desc.pins = pmx->pins;
 	pmx->pctl_desc.pins = pmx->pins;
 	pmx->pctl_desc.npins = pfc->info->nr_pins;
 	pmx->pctl_desc.npins = pfc->info->nr_pins;
 
 
-	pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx);
+	pmx->pctl = devm_pinctrl_register(pfc->dev, &pmx->pctl_desc, pmx);
 	if (IS_ERR(pmx->pctl))
 	if (IS_ERR(pmx->pctl))
 		return PTR_ERR(pmx->pctl);
 		return PTR_ERR(pmx->pctl);
 
 
 	return 0;
 	return 0;
 }
 }
-
-int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc)
-{
-	struct sh_pfc_pinctrl *pmx = pfc->pinctrl;
-
-	pinctrl_unregister(pmx->pctl);
-
-	pfc->pinctrl = NULL;
-	return 0;
-}

+ 18 - 1
drivers/pinctrl/sh-pfc/sh_pfc.h

@@ -28,6 +28,7 @@ enum {
 #define SH_PFC_PIN_CFG_PULL_UP		(1 << 2)
 #define SH_PFC_PIN_CFG_PULL_UP		(1 << 2)
 #define SH_PFC_PIN_CFG_PULL_DOWN	(1 << 3)
 #define SH_PFC_PIN_CFG_PULL_DOWN	(1 << 3)
 #define SH_PFC_PIN_CFG_IO_VOLTAGE	(1 << 4)
 #define SH_PFC_PIN_CFG_IO_VOLTAGE	(1 << 4)
+#define SH_PFC_PIN_CFG_DRIVE_STRENGTH	(1 << 5)
 #define SH_PFC_PIN_CFG_NO_GPIO		(1 << 31)
 #define SH_PFC_PIN_CFG_NO_GPIO		(1 << 31)
 
 
 struct sh_pfc_pin {
 struct sh_pfc_pin {
@@ -131,6 +132,21 @@ struct pinmux_cfg_reg {
 		{ var_fw0, var_fwn, 0 }, \
 		{ var_fw0, var_fwn, 0 }, \
 	.enum_ids = (const u16 [])
 	.enum_ids = (const u16 [])
 
 
+struct pinmux_drive_reg_field {
+	u16 pin;
+	u8 offset;
+	u8 size;
+};
+
+struct pinmux_drive_reg {
+	u32 reg;
+	const struct pinmux_drive_reg_field fields[8];
+};
+
+#define PINMUX_DRIVE_REG(name, r) \
+	.reg = r, \
+	.fields =
+
 struct pinmux_data_reg {
 struct pinmux_data_reg {
 	u32 reg;
 	u32 reg;
 	u8 reg_width;
 	u8 reg_width;
@@ -199,6 +215,7 @@ struct sh_pfc_soc_info {
 #endif
 #endif
 
 
 	const struct pinmux_cfg_reg *cfg_regs;
 	const struct pinmux_cfg_reg *cfg_regs;
+	const struct pinmux_drive_reg *drive_regs;
 	const struct pinmux_data_reg *data_regs;
 	const struct pinmux_data_reg *data_regs;
 
 
 	const u16 *pinmux_data;
 	const u16 *pinmux_data;
@@ -276,7 +293,7 @@ struct sh_pfc_soc_info {
  *   - msel: Module selector
  *   - msel: Module selector
  */
  */
 #define PINMUX_IPSR_MSEL(ipsr, fn, msel)				\
 #define PINMUX_IPSR_MSEL(ipsr, fn, msel)				\
-	PINMUX_DATA(fn##_MARK, FN_##msel, FN_##ipsr, FN_##fn)
+	PINMUX_DATA(fn##_MARK, FN_##msel, FN_##fn, FN_##ipsr)
 
 
 /*
 /*
  * Describe a pinmux configuration for a single-function pin with GPIO
  * Describe a pinmux configuration for a single-function pin with GPIO

+ 1 - 10
drivers/pinctrl/spear/pinctrl-spear.c

@@ -395,7 +395,7 @@ int spear_pinctrl_probe(struct platform_device *pdev,
 	spear_pinctrl_desc.pins = machdata->pins;
 	spear_pinctrl_desc.pins = machdata->pins;
 	spear_pinctrl_desc.npins = machdata->npins;
 	spear_pinctrl_desc.npins = machdata->npins;
 
 
-	pmx->pctl = pinctrl_register(&spear_pinctrl_desc, &pdev->dev, pmx);
+	pmx->pctl = devm_pinctrl_register(&pdev->dev, &spear_pinctrl_desc, pmx);
 	if (IS_ERR(pmx->pctl)) {
 	if (IS_ERR(pmx->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 		return PTR_ERR(pmx->pctl);
 		return PTR_ERR(pmx->pctl);
@@ -403,12 +403,3 @@ int spear_pinctrl_probe(struct platform_device *pdev,
 
 
 	return 0;
 	return 0;
 }
 }
-
-int spear_pinctrl_remove(struct platform_device *pdev)
-{
-	struct spear_pmx *pmx = platform_get_drvdata(pdev);
-
-	pinctrl_unregister(pmx->pctl);
-
-	return 0;
-}

+ 0 - 1
drivers/pinctrl/spear/pinctrl-spear.h

@@ -197,7 +197,6 @@ void pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
 				 unsigned count, u16 reg);
 				 unsigned count, u16 reg);
 int spear_pinctrl_probe(struct platform_device *pdev,
 int spear_pinctrl_probe(struct platform_device *pdev,
 			struct spear_pinctrl_machdata *machdata);
 			struct spear_pinctrl_machdata *machdata);
-int spear_pinctrl_remove(struct platform_device *pdev);
 
 
 #define SPEAR_PIN_0_TO_101		\
 #define SPEAR_PIN_0_TO_101		\
 	PINCTRL_PIN(0, "PLGPIO0"),	\
 	PINCTRL_PIN(0, "PLGPIO0"),	\

+ 0 - 6
drivers/pinctrl/spear/pinctrl-spear1310.c

@@ -2704,18 +2704,12 @@ static int spear1310_pinctrl_probe(struct platform_device *pdev)
 	return spear_pinctrl_probe(pdev, &spear1310_machdata);
 	return spear_pinctrl_probe(pdev, &spear1310_machdata);
 }
 }
 
 
-static int spear1310_pinctrl_remove(struct platform_device *pdev)
-{
-	return spear_pinctrl_remove(pdev);
-}
-
 static struct platform_driver spear1310_pinctrl_driver = {
 static struct platform_driver spear1310_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.name = DRIVER_NAME,
 		.of_match_table = spear1310_pinctrl_of_match,
 		.of_match_table = spear1310_pinctrl_of_match,
 	},
 	},
 	.probe = spear1310_pinctrl_probe,
 	.probe = spear1310_pinctrl_probe,
-	.remove = spear1310_pinctrl_remove,
 };
 };
 
 
 static int __init spear1310_pinctrl_init(void)
 static int __init spear1310_pinctrl_init(void)

+ 0 - 6
drivers/pinctrl/spear/pinctrl-spear1340.c

@@ -2020,18 +2020,12 @@ static int spear1340_pinctrl_probe(struct platform_device *pdev)
 	return spear_pinctrl_probe(pdev, &spear1340_machdata);
 	return spear_pinctrl_probe(pdev, &spear1340_machdata);
 }
 }
 
 
-static int spear1340_pinctrl_remove(struct platform_device *pdev)
-{
-	return spear_pinctrl_remove(pdev);
-}
-
 static struct platform_driver spear1340_pinctrl_driver = {
 static struct platform_driver spear1340_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.name = DRIVER_NAME,
 		.of_match_table = spear1340_pinctrl_of_match,
 		.of_match_table = spear1340_pinctrl_of_match,
 	},
 	},
 	.probe = spear1340_pinctrl_probe,
 	.probe = spear1340_pinctrl_probe,
-	.remove = spear1340_pinctrl_remove,
 };
 };
 
 
 static int __init spear1340_pinctrl_init(void)
 static int __init spear1340_pinctrl_init(void)

+ 0 - 6
drivers/pinctrl/spear/pinctrl-spear300.c

@@ -677,18 +677,12 @@ static int spear300_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int spear300_pinctrl_remove(struct platform_device *pdev)
-{
-	return spear_pinctrl_remove(pdev);
-}
-
 static struct platform_driver spear300_pinctrl_driver = {
 static struct platform_driver spear300_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.name = DRIVER_NAME,
 		.of_match_table = spear300_pinctrl_of_match,
 		.of_match_table = spear300_pinctrl_of_match,
 	},
 	},
 	.probe = spear300_pinctrl_probe,
 	.probe = spear300_pinctrl_probe,
-	.remove = spear300_pinctrl_remove,
 };
 };
 
 
 static int __init spear300_pinctrl_init(void)
 static int __init spear300_pinctrl_init(void)

+ 0 - 6
drivers/pinctrl/spear/pinctrl-spear310.c

@@ -400,18 +400,12 @@ static int spear310_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int spear310_pinctrl_remove(struct platform_device *pdev)
-{
-	return spear_pinctrl_remove(pdev);
-}
-
 static struct platform_driver spear310_pinctrl_driver = {
 static struct platform_driver spear310_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.name = DRIVER_NAME,
 		.of_match_table = spear310_pinctrl_of_match,
 		.of_match_table = spear310_pinctrl_of_match,
 	},
 	},
 	.probe = spear310_pinctrl_probe,
 	.probe = spear310_pinctrl_probe,
-	.remove = spear310_pinctrl_remove,
 };
 };
 
 
 static int __init spear310_pinctrl_init(void)
 static int __init spear310_pinctrl_init(void)

+ 0 - 6
drivers/pinctrl/spear/pinctrl-spear320.c

@@ -3441,18 +3441,12 @@ static int spear320_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int spear320_pinctrl_remove(struct platform_device *pdev)
-{
-	return spear_pinctrl_remove(pdev);
-}
-
 static struct platform_driver spear320_pinctrl_driver = {
 static struct platform_driver spear320_pinctrl_driver = {
 	.driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.name = DRIVER_NAME,
 		.of_match_table = spear320_pinctrl_of_match,
 		.of_match_table = spear320_pinctrl_of_match,
 	},
 	},
 	.probe = spear320_pinctrl_probe,
 	.probe = spear320_pinctrl_probe,
-	.remove = spear320_pinctrl_remove,
 };
 };
 
 
 static int __init spear320_pinctrl_init(void)
 static int __init spear320_pinctrl_init(void)

+ 180 - 5
drivers/pinctrl/stm32/pinctrl-stm32.c

@@ -358,7 +358,7 @@ static int stm32_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 		ret = stm32_pctrl_dt_subnode_to_map(pctldev, np, map,
 		ret = stm32_pctrl_dt_subnode_to_map(pctldev, np, map,
 				&reserved_maps, num_maps);
 				&reserved_maps, num_maps);
 		if (ret < 0) {
 		if (ret < 0) {
-			pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+			pinctrl_utils_free_map(pctldev, *map, *num_maps);
 			return ret;
 			return ret;
 		}
 		}
 	}
 	}
@@ -396,7 +396,7 @@ static int stm32_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
 
 
 static const struct pinctrl_ops stm32_pctrl_ops = {
 static const struct pinctrl_ops stm32_pctrl_ops = {
 	.dt_node_to_map		= stm32_pctrl_dt_node_to_map,
 	.dt_node_to_map		= stm32_pctrl_dt_node_to_map,
-	.dt_free_map		= pinctrl_utils_dt_free_map,
+	.dt_free_map		= pinctrl_utils_free_map,
 	.get_groups_count	= stm32_pctrl_get_groups_count,
 	.get_groups_count	= stm32_pctrl_get_groups_count,
 	.get_group_name		= stm32_pctrl_get_group_name,
 	.get_group_name		= stm32_pctrl_get_group_name,
 	.get_group_pins		= stm32_pctrl_get_group_pins,
 	.get_group_pins		= stm32_pctrl_get_group_pins,
@@ -454,6 +454,29 @@ static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
 	clk_disable(bank->clk);
 	clk_disable(bank->clk);
 }
 }
 
 
+static void stm32_pmx_get_mode(struct stm32_gpio_bank *bank,
+		int pin, u32 *mode, u32 *alt)
+{
+	u32 val;
+	int alt_shift = (pin % 8) * 4;
+	int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4;
+	unsigned long flags;
+
+	clk_enable(bank->clk);
+	spin_lock_irqsave(&bank->lock, flags);
+
+	val = readl_relaxed(bank->base + alt_offset);
+	val &= GENMASK(alt_shift + 3, alt_shift);
+	*alt = val >> alt_shift;
+
+	val = readl_relaxed(bank->base + STM32_GPIO_MODER);
+	val &= GENMASK(pin * 2 + 1, pin * 2);
+	*mode = val >> (pin * 2);
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+	clk_disable(bank->clk);
+}
+
 static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev,
 static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev,
 			    unsigned function,
 			    unsigned function,
 			    unsigned group)
 			    unsigned group)
@@ -525,6 +548,24 @@ static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
 	clk_disable(bank->clk);
 	clk_disable(bank->clk);
 }
 }
 
 
+static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
+	unsigned int offset)
+{
+	unsigned long flags;
+	u32 val;
+
+	clk_enable(bank->clk);
+	spin_lock_irqsave(&bank->lock, flags);
+
+	val = readl_relaxed(bank->base + STM32_GPIO_TYPER);
+	val &= BIT(offset);
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+	clk_disable(bank->clk);
+
+	return (val >> offset);
+}
+
 static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
 static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
 	unsigned offset, u32 speed)
 	unsigned offset, u32 speed)
 {
 {
@@ -543,6 +584,24 @@ static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
 	clk_disable(bank->clk);
 	clk_disable(bank->clk);
 }
 }
 
 
+static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
+	unsigned int offset)
+{
+	unsigned long flags;
+	u32 val;
+
+	clk_enable(bank->clk);
+	spin_lock_irqsave(&bank->lock, flags);
+
+	val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR);
+	val &= GENMASK(offset * 2 + 1, offset * 2);
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+	clk_disable(bank->clk);
+
+	return (val >> (offset * 2));
+}
+
 static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
 static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
 	unsigned offset, u32 bias)
 	unsigned offset, u32 bias)
 {
 {
@@ -561,6 +620,57 @@ static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
 	clk_disable(bank->clk);
 	clk_disable(bank->clk);
 }
 }
 
 
+static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
+	unsigned int offset)
+{
+	unsigned long flags;
+	u32 val;
+
+	clk_enable(bank->clk);
+	spin_lock_irqsave(&bank->lock, flags);
+
+	val = readl_relaxed(bank->base + STM32_GPIO_PUPDR);
+	val &= GENMASK(offset * 2 + 1, offset * 2);
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+	clk_disable(bank->clk);
+
+	return (val >> (offset * 2));
+}
+
+static bool stm32_pconf_input_get(struct stm32_gpio_bank *bank,
+	unsigned int offset)
+{
+	unsigned long flags;
+	u32 val;
+
+	clk_enable(bank->clk);
+	spin_lock_irqsave(&bank->lock, flags);
+
+	val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+	clk_disable(bank->clk);
+
+	return val;
+}
+
+static bool stm32_pconf_output_get(struct stm32_gpio_bank *bank,
+	unsigned int offset)
+{
+	unsigned long flags;
+	u32 val;
+
+	clk_enable(bank->clk);
+	spin_lock_irqsave(&bank->lock, flags);
+	val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) & BIT(offset));
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+	clk_disable(bank->clk);
+
+	return val;
+}
+
 static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
 static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
 		unsigned int pin, enum pin_config_param param,
 		unsigned int pin, enum pin_config_param param,
 		enum pin_config_param arg)
 		enum pin_config_param arg)
@@ -634,9 +744,73 @@ static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
 	return 0;
 	return 0;
 }
 }
 
 
+static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
+				 struct seq_file *s,
+				 unsigned int pin)
+{
+	struct pinctrl_gpio_range *range;
+	struct stm32_gpio_bank *bank;
+	int offset;
+	u32 mode, alt, drive, speed, bias;
+	static const char * const modes[] = {
+			"input", "output", "alternate", "analog" };
+	static const char * const speeds[] = {
+			"low", "medium", "high", "very high" };
+	static const char * const biasing[] = {
+			"floating", "pull up", "pull down", "" };
+	bool val;
+
+	range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin);
+	bank = gpio_range_to_bank(range);
+	offset = stm32_gpio_pin(pin);
+
+	stm32_pmx_get_mode(bank, offset, &mode, &alt);
+	bias = stm32_pconf_get_bias(bank, offset);
+
+	seq_printf(s, "%s ", modes[mode]);
+
+	switch (mode) {
+	/* input */
+	case 0:
+		val = stm32_pconf_input_get(bank, offset);
+		seq_printf(s, "- %s - %s",
+			   val ? "high" : "low",
+			   biasing[bias]);
+		break;
+
+	/* output */
+	case 1:
+		drive = stm32_pconf_get_driving(bank, offset);
+		speed = stm32_pconf_get_speed(bank, offset);
+		val = stm32_pconf_output_get(bank, offset);
+		seq_printf(s, "- %s - %s - %s - %s %s",
+			   val ? "high" : "low",
+			   drive ? "open drain" : "push pull",
+			   biasing[bias],
+			   speeds[speed], "speed");
+		break;
+
+	/* alternate */
+	case 2:
+		drive = stm32_pconf_get_driving(bank, offset);
+		speed = stm32_pconf_get_speed(bank, offset);
+		seq_printf(s, "%d - %s - %s - %s %s", alt,
+			   drive ? "open drain" : "push pull",
+			   biasing[bias],
+			   speeds[speed], "speed");
+		break;
+
+	/* analog */
+	case 3:
+		break;
+	}
+}
+
+
 static const struct pinconf_ops stm32_pconf_ops = {
 static const struct pinconf_ops stm32_pconf_ops = {
 	.pin_config_group_get	= stm32_pconf_group_get,
 	.pin_config_group_get	= stm32_pconf_group_get,
 	.pin_config_group_set	= stm32_pconf_group_set,
 	.pin_config_group_set	= stm32_pconf_group_set,
+	.pin_config_dbg_show	= stm32_pconf_dbg_show,
 };
 };
 
 
 static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl,
 static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl,
@@ -813,10 +987,11 @@ int stm32_pctl_probe(struct platform_device *pdev)
 	pctl->pctl_desc.pmxops = &stm32_pmx_ops;
 	pctl->pctl_desc.pmxops = &stm32_pmx_ops;
 	pctl->dev = &pdev->dev;
 	pctl->dev = &pdev->dev;
 
 
-	pctl->pctl_dev = pinctrl_register(&pctl->pctl_desc, &pdev->dev, pctl);
-	if (!pctl->pctl_dev) {
+	pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc,
+					       pctl);
+	if (IS_ERR(pctl->pctl_dev)) {
 		dev_err(&pdev->dev, "Failed pinctrl registration\n");
 		dev_err(&pdev->dev, "Failed pinctrl registration\n");
-		return -EINVAL;
+		return PTR_ERR(pctl->pctl_dev);
 	}
 	}
 
 
 	for (i = 0; i < pctl->nbanks; i++)
 	for (i = 0; i < pctl->nbanks; i++)

Some files were not shown because too many files changed in this diff