aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 15:00:16 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 15:00:16 -0800
commit7ae1c76ee5b58fe5bd55a07f99a3359333270b86 (patch)
tree2e6907d46978dadebdef488c6b5f9bca34023a72 /drivers
parentb274776c54c320763bc12eb035c0e244f76ccb43 (diff)
parent62508a5d25e355cc19c3ade3c3b7dddc6d326cc5 (diff)
Merge tag 'sh-pinmux' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull sh-mobile pinctrl conversion from Arnd Bergmann: "This is another cleanup series, containing the move of the Renesas SH-Mobile pin controller code from arch/arm/mach-shmobile over to the generic pinctrl subsystem, changing it over to the common interfaces in the process. Based on agreement between Olof, Paul Mundt, Linus Walleij and Simon, we're merging this large branch of pinctrl conversion through arm-soc, even though it contains the corresponding conversions for arch/sh. Main reason for this is tight dependencies (that will now mostly be broken) between the arch/sh and mach-shmobile implementations. There will be more of this in 3.10 to do device-tree bindings, but this is the initial conversion." * tag 'sh-pinmux' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (81 commits) sh-pfc: sh_pfc_probe() sizeof() fix sh-pfc: Move sh_pfc.h from include/linux/ to driver directory sh-pfc: Remove pinmux_info definition sh: Remove unused sh_pfc_register_info() function sh: shx3: pinmux: Use driver-provided pinmux info sh: sh7786: pinmux: Use driver-provided pinmux info sh: sh7785: pinmux: Use driver-provided pinmux info sh: sh7757: pinmux: Use driver-provided pinmux info sh: sh7734: pinmux: Use driver-provided pinmux info sh: sh7724: pinmux: Use driver-provided pinmux info sh: sh7723: pinmux: Use driver-provided pinmux info sh: sh7722: pinmux: Use driver-provided pinmux info sh: sh7720: pinmux: Use driver-provided pinmux info sh: sh7269: pinmux: Use driver-provided pinmux info sh: sh7264: pinmux: Use driver-provided pinmux info sh: sh7203: pinmux: Use driver-provided pinmux info ARM: shmobile: sh73a0: Use driver-provided pinmux info ARM: shmobile: sh7372: Use driver-provided pinmux info ARM: shmobile: r8a7779: Use driver-provided pinmux info ARM: shmobile: r8a7740: Use driver-provided pinmux info ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pinctrl/Kconfig2
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/sh-pfc/Kconfig116
-rw-r--r--drivers/pinctrl/sh-pfc/Makefile21
-rw-r--r--drivers/pinctrl/sh-pfc/core.c (renamed from drivers/sh/pfc/core.c)355
-rw-r--r--drivers/pinctrl/sh-pfc/core.h72
-rw-r--r--drivers/pinctrl/sh-pfc/gpio.c (renamed from drivers/sh/pfc/gpio.c)114
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7740.c2612
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7779.c2624
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7203.c1592
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7264.c2131
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7269.c2834
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7372.c1658
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh73a0.c2798
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7720.c1236
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7722.c1779
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7723.c1903
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7724.c2225
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7734.c2475
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7757.c2282
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7785.c1304
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7786.c837
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-shx3.c582
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c (renamed from drivers/sh/pfc/pinctrl.c)164
-rw-r--r--drivers/pinctrl/sh-pfc/sh_pfc.h195
-rw-r--r--drivers/sh/Kconfig1
-rw-r--r--drivers/sh/Makefile1
-rw-r--r--drivers/sh/pfc/Kconfig26
-rw-r--r--drivers/sh/pfc/Makefile3
29 files changed, 31564 insertions, 380 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 393b0ecf4ca..34f51d2d90d 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -227,7 +227,7 @@ config PINCTRL_EXYNOS5440
select PINCONF
source "drivers/pinctrl/mvebu/Kconfig"
-
+source "drivers/pinctrl/sh-pfc/Kconfig"
source "drivers/pinctrl/spear/Kconfig"
config PINCTRL_XWAY
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 0fd5f57fcb5..f82cc5baf76 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -49,4 +49,6 @@ obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
obj-$(CONFIG_PLAT_ORION) += mvebu/
+obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
+obj-$(CONFIG_SUPERH) += sh-pfc/
obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig
new file mode 100644
index 00000000000..c3340f54d2a
--- /dev/null
+++ b/drivers/pinctrl/sh-pfc/Kconfig
@@ -0,0 +1,116 @@
+#
+# Renesas SH and SH Mobile PINCTRL drivers
+#
+
+if ARCH_SHMOBILE || SUPERH
+
+config PINCTRL_SH_PFC
+ # XXX move off the gpio dependency
+ depends on GENERIC_GPIO
+ select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB
+ select PINMUX
+ select PINCONF
+ def_bool y
+ help
+ This enables pin control drivers for SH and SH Mobile platforms
+
+config GPIO_SH_PFC
+ bool "SuperH PFC GPIO support"
+ depends on PINCTRL_SH_PFC && GPIOLIB
+ help
+ This enables support for GPIOs within the SoC's pin function
+ controller.
+
+config PINCTRL_PFC_R8A7740
+ def_bool y
+ depends on ARCH_R8A7740
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_R8A7779
+ def_bool y
+ depends on ARCH_R8A7779
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7203
+ def_bool y
+ depends on CPU_SUBTYPE_SH7203
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7264
+ def_bool y
+ depends on CPU_SUBTYPE_SH7264
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7269
+ def_bool y
+ depends on CPU_SUBTYPE_SH7269
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7372
+ def_bool y
+ depends on ARCH_SH7372
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH73A0
+ def_bool y
+ depends on ARCH_SH73A0
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7720
+ def_bool y
+ depends on CPU_SUBTYPE_SH7720
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7722
+ def_bool y
+ depends on CPU_SUBTYPE_SH7722
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7723
+ def_bool y
+ depends on CPU_SUBTYPE_SH7723
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7724
+ def_bool y
+ depends on CPU_SUBTYPE_SH7724
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7734
+ def_bool y
+ depends on CPU_SUBTYPE_SH7734
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7757
+ def_bool y
+ depends on CPU_SUBTYPE_SH7757
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7785
+ def_bool y
+ depends on CPU_SUBTYPE_SH7785
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SH7786
+ def_bool y
+ depends on CPU_SUBTYPE_SH7786
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+config PINCTRL_PFC_SHX3
+ def_bool y
+ depends on CPU_SUBTYPE_SHX3
+ depends on GENERIC_GPIO
+ select PINCTRL_SH_PFC
+
+endif
diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile
new file mode 100644
index 00000000000..e8b9562c47e
--- /dev/null
+++ b/drivers/pinctrl/sh-pfc/Makefile
@@ -0,0 +1,21 @@
+sh-pfc-objs = core.o pinctrl.o
+ifeq ($(CONFIG_GPIO_SH_PFC),y)
+sh-pfc-objs += gpio.o
+endif
+obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc.o
+obj-$(CONFIG_PINCTRL_PFC_R8A7740) += pfc-r8a7740.o
+obj-$(CONFIG_PINCTRL_PFC_R8A7779) += pfc-r8a7779.o
+obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o
+obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
+obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o
+obj-$(CONFIG_PINCTRL_PFC_SH7372) += pfc-sh7372.o
+obj-$(CONFIG_PINCTRL_PFC_SH73A0) += pfc-sh73a0.o
+obj-$(CONFIG_PINCTRL_PFC_SH7720) += pfc-sh7720.o
+obj-$(CONFIG_PINCTRL_PFC_SH7722) += pfc-sh7722.o
+obj-$(CONFIG_PINCTRL_PFC_SH7723) += pfc-sh7723.o
+obj-$(CONFIG_PINCTRL_PFC_SH7724) += pfc-sh7724.o
+obj-$(CONFIG_PINCTRL_PFC_SH7734) += pfc-sh7734.o
+obj-$(CONFIG_PINCTRL_PFC_SH7757) += pfc-sh7757.o
+obj-$(CONFIG_PINCTRL_PFC_SH7785) += pfc-sh7785.o
+obj-$(CONFIG_PINCTRL_PFC_SH7786) += pfc-sh7786.o
+obj-$(CONFIG_PINCTRL_PFC_SHX3) += pfc-shx3.o
diff --git a/drivers/sh/pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index 68169373c98..970ddff2b0b 100644
--- a/drivers/sh/pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -8,78 +8,61 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-#define pr_fmt(fmt) "sh_pfc " KBUILD_MODNAME ": " fmt
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sh_pfc.h>
-#include <linux/module.h>
+#define DRV_NAME "sh-pfc"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitops.h>
#include <linux/err.h>
+#include <linux/errno.h>
#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/pinctrl/machine.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
-static struct sh_pfc *sh_pfc __read_mostly;
-
-static inline bool sh_pfc_initialized(void)
-{
- return !!sh_pfc;
-}
-
-static void pfc_iounmap(struct sh_pfc *pfc)
-{
- int k;
-
- for (k = 0; k < pfc->num_resources; k++)
- if (pfc->window[k].virt)
- iounmap(pfc->window[k].virt);
-
- kfree(pfc->window);
- pfc->window = NULL;
-}
+#include "core.h"
-static int pfc_ioremap(struct sh_pfc *pfc)
+static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev)
{
struct resource *res;
int k;
- if (!pfc->num_resources)
+ if (pdev->num_resources == 0) {
+ pfc->num_windows = 0;
return 0;
+ }
- pfc->window = kzalloc(pfc->num_resources * sizeof(*pfc->window),
- GFP_NOWAIT);
+ pfc->window = devm_kzalloc(pfc->dev, pdev->num_resources *
+ sizeof(*pfc->window), GFP_NOWAIT);
if (!pfc->window)
- goto err1;
+ return -ENOMEM;
- for (k = 0; k < pfc->num_resources; k++) {
- res = pfc->resource + k;
+ pfc->num_windows = pdev->num_resources;
+
+ for (k = 0, res = pdev->resource; k < pdev->num_resources; k++, res++) {
WARN_ON(resource_type(res) != IORESOURCE_MEM);
pfc->window[k].phys = res->start;
pfc->window[k].size = resource_size(res);
- pfc->window[k].virt = ioremap_nocache(res->start,
- resource_size(res));
+ pfc->window[k].virt = devm_ioremap_nocache(pfc->dev, res->start,
+ resource_size(res));
if (!pfc->window[k].virt)
- goto err2;
+ return -ENOMEM;
}
return 0;
-
-err2:
- pfc_iounmap(pfc);
-err1:
- return -1;
}
-static void __iomem *pfc_phys_to_virt(struct sh_pfc *pfc,
- unsigned long address)
+static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc,
+ unsigned long address)
{
- struct pfc_window *window;
+ struct sh_pfc_window *window;
int k;
/* scan through physical windows and convert address */
- for (k = 0; k < pfc->num_resources; k++) {
+ for (k = 0; k < pfc->num_windows; k++) {
window = pfc->window + k;
if (address < window->phys)
@@ -95,7 +78,7 @@ static void __iomem *pfc_phys_to_virt(struct sh_pfc *pfc,
return (void __iomem *)address;
}
-static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
+static int sh_pfc_enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
{
if (enum_id < r->begin)
return 0;
@@ -106,8 +89,8 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
return 1;
}
-static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
- unsigned long reg_width)
+static unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
+ unsigned long reg_width)
{
switch (reg_width) {
case 8:
@@ -122,9 +105,8 @@ static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
return 0;
}
-static void gpio_write_raw_reg(void __iomem *mapped_reg,
- unsigned long reg_width,
- unsigned long data)
+static void sh_pfc_write_raw_reg(void __iomem *mapped_reg,
+ unsigned long reg_width, unsigned long data)
{
switch (reg_width) {
case 8:
@@ -150,9 +132,8 @@ int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos)
pr_debug("read_bit: addr = %lx, pos = %ld, "
"r_width = %ld\n", dr->reg, pos, dr->reg_width);
- return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
+ return (sh_pfc_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
}
-EXPORT_SYMBOL_GPL(sh_pfc_read_bit);
void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos,
unsigned long value)
@@ -170,20 +151,19 @@ void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos,
else
clear_bit(pos, &dr->reg_shadow);
- gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
+ sh_pfc_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
}
-EXPORT_SYMBOL_GPL(sh_pfc_write_bit);
-
-static void config_reg_helper(struct sh_pfc *pfc,
- struct pinmux_cfg_reg *crp,
- unsigned long in_pos,
- void __iomem **mapped_regp,
- unsigned long *maskp,
- unsigned long *posp)
+
+static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long in_pos,
+ void __iomem **mapped_regp,
+ unsigned long *maskp,
+ unsigned long *posp)
{
int k;
- *mapped_regp = pfc_phys_to_virt(pfc, crp->reg);
+ *mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg);
if (crp->field_width) {
*maskp = (1 << crp->field_width) - 1;
@@ -196,30 +176,30 @@ static void config_reg_helper(struct sh_pfc *pfc,
}
}
-static int read_config_reg(struct sh_pfc *pfc,
- struct pinmux_cfg_reg *crp,
- unsigned long field)
+static int sh_pfc_read_config_reg(struct sh_pfc *pfc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long field)
{
void __iomem *mapped_reg;
unsigned long mask, pos;
- config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
+ sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
pr_debug("read_reg: addr = %lx, field = %ld, "
"r_width = %ld, f_width = %ld\n",
crp->reg, field, crp->reg_width, crp->field_width);
- return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
+ return (sh_pfc_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
}
-static void write_config_reg(struct sh_pfc *pfc,
- struct pinmux_cfg_reg *crp,
- unsigned long field, unsigned long value)
+static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long field, unsigned long value)
{
void __iomem *mapped_reg;
unsigned long mask, pos, data;
- config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
+ sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
"r_width = %ld, f_width = %ld\n",
@@ -228,34 +208,35 @@ static void write_config_reg(struct sh_pfc *pfc,
mask = ~(mask << pos);
value = value << pos;
- data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
+ data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width);
data &= mask;
data |= value;
- if (pfc->unlock_reg)
- gpio_write_raw_reg(pfc_phys_to_virt(pfc, pfc->unlock_reg),
- 32, ~data);
+ if (pfc->info->unlock_reg)
+ sh_pfc_write_raw_reg(
+ sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
+ ~data);
- gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
+ sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
}
-static int setup_data_reg(struct sh_pfc *pfc, unsigned gpio)
+static int sh_pfc_setup_data_reg(struct sh_pfc *pfc, unsigned gpio)
{
- struct pinmux_gpio *gpiop = &pfc->gpios[gpio];
+ struct pinmux_gpio *gpiop = &pfc->info->gpios[gpio];
struct pinmux_data_reg *data_reg;
int k, n;
- if (!enum_in_range(gpiop->enum_id, &pfc->data))
+ if (!sh_pfc_enum_in_range(gpiop->enum_id, &pfc->info->data))
return -1;
k = 0;
while (1) {
- data_reg = pfc->data_regs + k;
+ data_reg = pfc->info->data_regs + k;
if (!data_reg->reg_width)
break;
- data_reg->mapped_reg = pfc_phys_to_virt(pfc, data_reg->reg);
+ data_reg->mapped_reg = sh_pfc_phys_to_virt(pfc, data_reg->reg);
for (n = 0; n < data_reg->reg_width; n++) {
if (data_reg->enum_ids[n] == gpiop->enum_id) {
@@ -274,23 +255,23 @@ static int setup_data_reg(struct sh_pfc *pfc, unsigned gpio)
return -1;
}
-static void setup_data_regs(struct sh_pfc *pfc)
+static void sh_pfc_setup_data_regs(struct sh_pfc *pfc)
{
struct pinmux_data_reg *drp;
int k;
- for (k = pfc->first_gpio; k <= pfc->last_gpio; k++)
- setup_data_reg(pfc, k);
+ for (k = pfc->info->first_gpio; k <= pfc->info->last_gpio; k++)
+ sh_pfc_setup_data_reg(pfc, k);
k = 0;
while (1) {
- drp = pfc->data_regs + k;
+ drp = pfc->info->data_regs + k;
if (!drp->reg_width)
break;
- drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
- drp->reg_width);
+ drp->reg_shadow = sh_pfc_read_raw_reg(drp->mapped_reg,
+ drp->reg_width);
k++;
}
}
@@ -298,24 +279,22 @@ static void setup_data_regs(struct sh_pfc *pfc)
int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio,
struct pinmux_data_reg **drp, int *bitp)
{
- struct pinmux_gpio *gpiop = &pfc->gpios[gpio];
+ struct pinmux_gpio *gpiop = &pfc->info->gpios[gpio];
int k, n;
- if (!enum_in_range(gpiop->enum_id, &pfc->data))
+ if (!sh_pfc_enum_in_range(gpiop->enum_id, &pfc->info->data))
return -1;
k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
- *drp = pfc->data_regs + k;
+ *drp = pfc->info->data_regs + k;
*bitp = n;
return 0;
}
-EXPORT_SYMBOL_GPL(sh_pfc_get_data_reg);
-static int get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
- struct pinmux_cfg_reg **crp,
- int *fieldp, int *valuep,
- unsigned long **cntp)
+static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
+ struct pinmux_cfg_reg **crp, int *fieldp,
+ int *valuep, unsigned long **cntp)
{
struct pinmux_cfg_reg *config_reg;
unsigned long r_width, f_width, curr_width, ncomb;
@@ -323,7 +302,7 @@ static int get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
k = 0;
while (1) {
- config_reg = pfc->cfg_regs + k;
+ config_reg = pfc->info->cfg_regs + k;
r_width = config_reg->reg_width;
f_width = config_reg->field_width;
@@ -361,12 +340,12 @@ static int get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos,
pinmux_enum_t *enum_idp)
{
- pinmux_enum_t enum_id = pfc->gpios[gpio].enum_id;
- pinmux_enum_t *data = pfc->gpio_data;
+ pinmux_enum_t enum_id = pfc->info->gpios[gpio].enum_id;
+ pinmux_enum_t *data = pfc->info->gpio_data;
int k;
- if (!enum_in_range(enum_id, &pfc->data)) {
- if (!enum_in_range(enum_id, &pfc->mark)) {
+ if (!sh_pfc_enum_in_range(enum_id, &pfc->info->data)) {
+ if (!sh_pfc_enum_in_range(enum_id, &pfc->info->mark)) {
pr_err("non data/mark enum_id for gpio %d\n", gpio);
return -1;
}
@@ -377,7 +356,7 @@ int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos,
return pos + 1;
}
- for (k = 0; k < pfc->gpio_data_size; k++) {
+ for (k = 0; k < pfc->info->gpio_data_size; k++) {
if (data[k] == enum_id) {
*enum_idp = data[k + 1];
return k + 1;
@@ -387,7 +366,6 @@ int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos,
pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio);
return -1;
}
-EXPORT_SYMBOL_GPL(sh_pfc_gpio_to_enum);
int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
int cfg_mode)
@@ -405,19 +383,19 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
break;
case PINMUX_TYPE_OUTPUT:
- range = &pfc->output;
+ range = &pfc->info->output;
break;
case PINMUX_TYPE_INPUT:
- range = &pfc->input;
+ range = &pfc->info->input;
break;
case PINMUX_TYPE_INPUT_PULLUP:
- range = &pfc->input_pu;
+ range = &pfc->info->input_pu;
break;
case PINMUX_TYPE_INPUT_PULLDOWN:
- range = &pfc->input_pd;
+ range = &pfc->info->input_pd;
break;
default:
@@ -437,7 +415,7 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
break;
/* first check if this is a function enum */
- in_range = enum_in_range(enum_id, &pfc->function);
+ in_range = sh_pfc_enum_in_range(enum_id, &pfc->info->function);
if (!in_range) {
/* not a function enum */
if (range) {
@@ -449,7 +427,7 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
* for this case we only allow function enums
* and the enums that match the other range.
*/
- in_range = enum_in_range(enum_id, range);
+ in_range = sh_pfc_enum_in_range(enum_id, range);
/*
* special case pass through for fixed
@@ -474,19 +452,19 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
if (!in_range)
continue;
- if (get_config_reg(pfc, enum_id, &cr,
- &field, &value, &cntp) != 0)
+ if (sh_pfc_get_config_reg(pfc, enum_id, &cr,
+ &field, &value, &cntp) != 0)
goto out_err;
switch (cfg_mode) {
case GPIO_CFG_DRYRUN:
if (!*cntp ||
- (read_config_reg(pfc, cr, field) != value))
+ (sh_pfc_read_config_reg(pfc, cr, field) != value))
continue;
break;
case GPIO_CFG_REQ:
- write_config_reg(pfc, cr, field, value);
+ sh_pfc_write_config_reg(pfc, cr, field, value);
*cntp = *cntp + 1;
break;
@@ -500,11 +478,11 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
out_err:
return -1;
}
-EXPORT_SYMBOL_GPL(sh_pfc_config_gpio);
-int register_sh_pfc(struct sh_pfc *pfc)
+static int sh_pfc_probe(struct platform_device *pdev)
{
- int (*initroutine)(struct sh_pfc *) = NULL;
+ struct sh_pfc_soc_info *info;
+ struct sh_pfc *pfc;
int ret;
/*
@@ -512,61 +490,146 @@ int register_sh_pfc(struct sh_pfc *pfc)
*/
BUILD_BUG_ON(PINMUX_FLAG_TYPE > ((1 << PINMUX_FLAG_DBIT_SHIFT) - 1));
- if (sh_pfc)
- return -EBUSY;
+ info = pdev->id_entry->driver_data
+ ? (void *)pdev->id_entry->driver_data : pdev->dev.platform_data;
+ if (info == NULL)
+ return -ENODEV;
+
+ pfc = devm_kzalloc(&pdev->dev, sizeof(*pfc), GFP_KERNEL);
+ if (pfc == NULL)
+ return -ENOMEM;
+
+ pfc->info = info;
+ pfc->dev = &pdev->dev;
- ret = pfc_ioremap(pfc);
+ ret = sh_pfc_ioremap(pfc, pdev);
if (unlikely(ret < 0))
return ret;
spin_lock_init(&pfc->lock);
pinctrl_provide_dummies();
- setup_data_regs(pfc);
-
- sh_pfc = pfc;
+ sh_pfc_setup_data_regs(pfc);
/*
* Initialize pinctrl bindings first
*/
- initroutine = symbol_request(sh_pfc_register_pinctrl);
- if (initroutine) {
- ret = (*initroutine)(pfc);
- symbol_put_addr(initroutine);
-
- if (unlikely(ret != 0))
- goto err;
- } else {
- pr_err("failed to initialize pinctrl bindings\n");
- goto err;
- }
+ ret = sh_pfc_register_pinctrl(pfc);
+ if (unlikely(ret != 0))
+ return ret;
+#ifdef CONFIG_GPIO_SH_PFC
/*
* Then the GPIO chip
*/
- initroutine = symbol_request(sh_pfc_register_gpiochip);
- if (initroutine) {
- ret = (*initroutine)(pfc);
- symbol_put_addr(initroutine);
-
+ ret = sh_pfc_register_gpiochip(pfc);
+ if (unlikely(ret != 0)) {
/*
* If the GPIO chip fails to come up we still leave the
* PFC state as it is, given that there are already
* extant users of it that have succeeded by this point.
*/
- if (unlikely(ret != 0)) {
- pr_notice("failed to init GPIO chip, ignoring...\n");
- ret = 0;
- }
+ pr_notice("failed to init GPIO chip, ignoring...\n");
}
+#endif
+
+ platform_set_drvdata(pdev, pfc);
- pr_info("%s support registered\n", pfc->name);
+ pr_info("%s support registered\n", info->name);
return 0;
+}
-err:
- pfc_iounmap(pfc);
- sh_pfc = NULL;
+static int sh_pfc_remove(struct platform_device *pdev)
+{
+ struct sh_pfc *pfc = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_GPIO_SH_PFC
+ sh_pfc_unregister_gpiochip(pfc);
+#endif
+ sh_pfc_unregister_pinctrl(pfc);
+
+ platform_set_drvdata(pdev, NULL);
- return ret;
+ return 0;
}
+
+static const struct platform_device_id sh_pfc_id_table[] = {
+#ifdef CONFIG_PINCTRL_PFC_R8A7740
+ { "pfc-r8a7740", (kernel_ulong_t)&r8a7740_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7779
+ { "pfc-r8a7779", (kernel_ulong_t)&r8a7779_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7203
+ { "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7264
+ { "pfc-sh7264", (kernel_ulong_t)&sh7264_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7269
+ { "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7372
+ { "pfc-sh7372", (kernel_ulong_t)&sh7372_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH73A0
+ { "pfc-sh73a0", (kernel_ulong_t)&sh73a0_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7720
+ { "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7722
+ { "pfc-sh7722", (kernel_ulong_t)&sh7722_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7723
+ { "pfc-sh7723", (kernel_ulong_t)&sh7723_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7724
+ { "pfc-sh7724", (kernel_ulong_t)&sh7724_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7734
+ { "pfc-sh7734", (kernel_ulong_t)&sh7734_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7757
+ { "pfc-sh7757", (kernel_ulong_t)&sh7757_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7785
+ { "pfc-sh7785", (kernel_ulong_t)&sh7785_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SH7786
+ { "pfc-sh7786", (kernel_ulong_t)&sh7786_pinmux_info },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_SHX3
+ { "pfc-shx3", (kernel_ulong_t)&shx3_pinmux_info },
+#endif
+ { "sh-pfc", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, sh_pfc_id_table);
+
+static struct platform_driver sh_pfc_driver = {
+ .probe = sh_pfc_probe,
+ .remove = sh_pfc_remove,
+ .id_table = sh_pfc_id_table,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init sh_pfc_init(void)
+{
+ return platform_driver_register(&sh_pfc_driver);
+}
+postcore_initcall(sh_pfc_init);
+
+static void __exit sh_pfc_exit(void)
+{
+ platform_driver_unregister(&sh_pfc_driver);
+}
+module_exit(sh_pfc_exit);
+
+MODULE_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart");
+MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
new file mode 100644
index 00000000000..ba7c33c3359
--- /dev/null
+++ b/drivers/pinctrl/sh-pfc/core.h
@@ -0,0 +1,72 @@
+/*
+ * SuperH Pin Function Controller support.
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __SH_PFC_CORE_H__
+#define __SH_PFC_CORE_H__
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include "sh_pfc.h"
+
+struct sh_pfc_window {
+ phys_addr_t phys;
+ void __iomem *virt;
+ unsigned long size;
+};
+
+struct sh_pfc_chip;
+struct sh_pfc_pinctrl;
+
+struct sh_pfc {
+ struct device *dev;
+ struct sh_pfc_soc_info *info;
+ spinlock_t lock;
+
+ unsigned int num_windows;
+ struct sh_pfc_window *window;
+
+ struct sh_pfc_chip *gpio;
+ struct sh_pfc_pinctrl *pinctrl;
+};
+
+int sh_pfc_register_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_unregister_pinctrl(struct sh_pfc *pfc);
+
+int sh_pfc_read_bit(struct