Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,136 @@
#
# Renesas SH and SH Mobile PINCTRL drivers
#
if ARCH_SHMOBILE || SUPERH
config PINCTRL_SH_PFC
select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB
select PINMUX
select PINCONF
select GENERIC_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_R8A73A4
def_bool y
depends on ARCH_R8A73A4
select PINCTRL_SH_PFC
config PINCTRL_PFC_R8A7740
def_bool y
depends on ARCH_R8A7740
select PINCTRL_SH_PFC
config PINCTRL_PFC_R8A7778
def_bool y
depends on ARCH_R8A7778
select PINCTRL_SH_PFC
config PINCTRL_PFC_R8A7779
def_bool y
depends on ARCH_R8A7779
select PINCTRL_SH_PFC
config PINCTRL_PFC_R8A7790
def_bool y
depends on ARCH_R8A7790
select PINCTRL_SH_PFC
config PINCTRL_PFC_R8A7791
def_bool y
depends on ARCH_R8A7791
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7203
def_bool y
depends on CPU_SUBTYPE_SH7203
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7264
def_bool y
depends on CPU_SUBTYPE_SH7264
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7269
def_bool y
depends on CPU_SUBTYPE_SH7269
depends on GPIOLIB
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
select REGULATOR
config PINCTRL_PFC_SH7720
def_bool y
depends on CPU_SUBTYPE_SH7720
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7722
def_bool y
depends on CPU_SUBTYPE_SH7722
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7723
def_bool y
depends on CPU_SUBTYPE_SH7723
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7724
def_bool y
depends on CPU_SUBTYPE_SH7724
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7734
def_bool y
depends on CPU_SUBTYPE_SH7734
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7757
def_bool y
depends on CPU_SUBTYPE_SH7757
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7785
def_bool y
depends on CPU_SUBTYPE_SH7785
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SH7786
def_bool y
depends on CPU_SUBTYPE_SH7786
depends on GPIOLIB
select PINCTRL_SH_PFC
config PINCTRL_PFC_SHX3
def_bool y
depends on CPU_SUBTYPE_SHX3
depends on GPIOLIB
select PINCTRL_SH_PFC
endif

View file

@ -0,0 +1,25 @@
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_R8A73A4) += pfc-r8a73a4.o
obj-$(CONFIG_PINCTRL_PFC_R8A7740) += pfc-r8a7740.o
obj-$(CONFIG_PINCTRL_PFC_R8A7778) += pfc-r8a7778.o
obj-$(CONFIG_PINCTRL_PFC_R8A7779) += pfc-r8a7779.o
obj-$(CONFIG_PINCTRL_PFC_R8A7790) += pfc-r8a7790.o
obj-$(CONFIG_PINCTRL_PFC_R8A7791) += pfc-r8a7791.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

View file

@ -0,0 +1,672 @@
/*
* SuperH Pin Function Controller support.
*
* Copyright (C) 2008 Magnus Damm
* Copyright (C) 2009 - 2012 Paul Mundt
*
* 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.
*/
#define DRV_NAME "sh-pfc"
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "core.h"
static int sh_pfc_map_resources(struct sh_pfc *pfc,
struct platform_device *pdev)
{
unsigned int num_windows = 0;
unsigned int num_irqs = 0;
struct sh_pfc_window *windows;
unsigned int *irqs = NULL;
struct resource *res;
unsigned int i;
/* Count the MEM and IRQ resources. */
for (i = 0; i < pdev->num_resources; ++i) {
switch (resource_type(&pdev->resource[i])) {
case IORESOURCE_MEM:
num_windows++;
break;
case IORESOURCE_IRQ:
num_irqs++;
break;
}
}
if (num_windows == 0)
return -EINVAL;
/* Allocate memory windows and IRQs arrays. */
windows = devm_kzalloc(pfc->dev, num_windows * sizeof(*windows),
GFP_KERNEL);
if (windows == NULL)
return -ENOMEM;
pfc->num_windows = num_windows;
pfc->windows = windows;
if (num_irqs) {
irqs = devm_kzalloc(pfc->dev, num_irqs * sizeof(*irqs),
GFP_KERNEL);
if (irqs == NULL)
return -ENOMEM;
pfc->num_irqs = num_irqs;
pfc->irqs = irqs;
}
/* Fill them. */
for (i = 0, res = pdev->resource; i < pdev->num_resources; i++, res++) {
switch (resource_type(res)) {
case IORESOURCE_MEM:
windows->phys = res->start;
windows->size = resource_size(res);
windows->virt = devm_ioremap_resource(pfc->dev, res);
if (IS_ERR(windows->virt))
return -ENOMEM;
windows++;
break;
case IORESOURCE_IRQ:
*irqs++ = res->start;
break;
}
}
return 0;
}
static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc,
unsigned long address)
{
struct sh_pfc_window *window;
unsigned int i;
/* scan through physical windows and convert address */
for (i = 0; i < pfc->num_windows; i++) {
window = pfc->windows + i;
if (address < window->phys)
continue;
if (address >= (window->phys + window->size))
continue;
return window->virt + (address - window->phys);
}
BUG();
return NULL;
}
int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin)
{
unsigned int offset;
unsigned int i;
for (i = 0, offset = 0; i < pfc->nr_ranges; ++i) {
const struct sh_pfc_pin_range *range = &pfc->ranges[i];
if (pin <= range->end)
return pin >= range->start
? offset + pin - range->start : -1;
offset += range->end - range->start + 1;
}
return -EINVAL;
}
static int sh_pfc_enum_in_range(u16 enum_id, const struct pinmux_range *r)
{
if (enum_id < r->begin)
return 0;
if (enum_id > r->end)
return 0;
return 1;
}
unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width)
{
switch (reg_width) {
case 8:
return ioread8(mapped_reg);
case 16:
return ioread16(mapped_reg);
case 32:
return ioread32(mapped_reg);
}
BUG();
return 0;
}
void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
unsigned long data)
{
switch (reg_width) {
case 8:
iowrite8(data, mapped_reg);
return;
case 16:
iowrite16(data, mapped_reg);
return;
case 32:
iowrite32(data, mapped_reg);
return;
}
BUG();
}
static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
const struct pinmux_cfg_reg *crp,
unsigned long in_pos,
void __iomem **mapped_regp,
unsigned long *maskp,
unsigned long *posp)
{
unsigned int k;
*mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg);
if (crp->field_width) {
*maskp = (1 << crp->field_width) - 1;
*posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
} else {
*maskp = (1 << crp->var_field_width[in_pos]) - 1;
*posp = crp->reg_width;
for (k = 0; k <= in_pos; k++)
*posp -= crp->var_field_width[k];
}
}
static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
const struct pinmux_cfg_reg *crp,
unsigned long field, unsigned long value)
{
void __iomem *mapped_reg;
unsigned long mask, pos, data;
sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
dev_dbg(pfc->dev, "write_reg addr = %lx, value = %ld, field = %ld, "
"r_width = %ld, f_width = %ld\n",
crp->reg, value, field, crp->reg_width, crp->field_width);
mask = ~(mask << pos);
value = value << pos;
data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width);
data &= mask;
data |= value;
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(mapped_reg, crp->reg_width, data);
}
static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id,
const struct pinmux_cfg_reg **crp, int *fieldp,
int *valuep)
{
const struct pinmux_cfg_reg *config_reg;
unsigned long r_width, f_width, curr_width, ncomb;
unsigned int k, m, n, pos, bit_pos;
k = 0;
while (1) {
config_reg = pfc->info->cfg_regs + k;
r_width = config_reg->reg_width;
f_width = config_reg->field_width;
if (!r_width)
break;
pos = 0;
m = 0;
for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
if (f_width)
curr_width = f_width;
else
curr_width = config_reg->var_field_width[m];
ncomb = 1 << curr_width;
for (n = 0; n < ncomb; n++) {
if (config_reg->enum_ids[pos + n] == enum_id) {
*crp = config_reg;
*fieldp = m;
*valuep = n;
return 0;
}
}
pos += ncomb;
m++;
}
k++;
}
return -EINVAL;
}
static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos,
u16 *enum_idp)
{
const u16 *data = pfc->info->gpio_data;
unsigned int k;
if (pos) {
*enum_idp = data[pos + 1];
return pos + 1;
}
for (k = 0; k < pfc->info->gpio_data_size; k++) {
if (data[k] == mark) {
*enum_idp = data[k + 1];
return k + 1;
}
}
dev_err(pfc->dev, "cannot locate data/mark enum_id for mark %d\n",
mark);
return -EINVAL;
}
int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
{
const struct pinmux_cfg_reg *cr = NULL;
u16 enum_id;
const struct pinmux_range *range;
int in_range, pos, field, value;
int ret;
switch (pinmux_type) {
case PINMUX_TYPE_GPIO:
case PINMUX_TYPE_FUNCTION:
range = NULL;
break;
case PINMUX_TYPE_OUTPUT:
range = &pfc->info->output;
break;
case PINMUX_TYPE_INPUT:
range = &pfc->info->input;
break;
default:
return -EINVAL;
}
pos = 0;
enum_id = 0;
field = 0;
value = 0;
/* Iterate over all the configuration fields we need to update. */
while (1) {
pos = sh_pfc_mark_to_enum(pfc, mark, pos, &enum_id);
if (pos < 0)
return pos;
if (!enum_id)
break;
/* Check if the configuration field selects a function. If it
* doesn't, skip the field if it's not applicable to the
* requested pinmux type.
*/
in_range = sh_pfc_enum_in_range(enum_id, &pfc->info->function);
if (!in_range) {
if (pinmux_type == PINMUX_TYPE_FUNCTION) {
/* Functions are allowed to modify all
* fields.
*/
in_range = 1;
} else if (pinmux_type != PINMUX_TYPE_GPIO) {
/* Input/output types can only modify fields
* that correspond to their respective ranges.
*/
in_range = sh_pfc_enum_in_range(enum_id, range);
/*
* special case pass through for fixed
* input-only or output-only pins without
* function enum register association.
*/
if (in_range && enum_id == range->force)
continue;
}
/* GPIOs are only allowed to modify function fields. */
}
if (!in_range)
continue;
ret = sh_pfc_get_config_reg(pfc, enum_id, &cr, &field, &value);
if (ret < 0)
return ret;
sh_pfc_write_config_reg(pfc, cr, field, value);
}
return 0;
}
static int sh_pfc_init_ranges(struct sh_pfc *pfc)
{
struct sh_pfc_pin_range *range;
unsigned int nr_ranges;
unsigned int i;
if (pfc->info->pins[0].pin == (u16)-1) {
/* Pin number -1 denotes that the SoC doesn't report pin numbers
* in its pin arrays yet. Consider the pin numbers range as
* continuous and allocate a single range.
*/
pfc->nr_ranges = 1;
pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges),
GFP_KERNEL);
if (pfc->ranges == NULL)
return -ENOMEM;
pfc->ranges->start = 0;
pfc->ranges->end = pfc->info->nr_pins - 1;
pfc->nr_gpio_pins = pfc->info->nr_pins;
return 0;
}
/* Count, allocate and fill the ranges. The PFC SoC data pins array must
* be sorted by pin numbers, and pins without a GPIO port must come
* last.
*/
for (i = 1, nr_ranges = 1; i < pfc->info->nr_pins; ++i) {
if (pfc->info->pins[i-1].pin != pfc->info->pins[i].pin - 1)
nr_ranges++;
}
pfc->nr_ranges = nr_ranges;
pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges) * nr_ranges,
GFP_KERNEL);
if (pfc->ranges == NULL)
return -ENOMEM;
range = pfc->ranges;
range->start = pfc->info->pins[0].pin;
for (i = 1; i < pfc->info->nr_pins; ++i) {
if (pfc->info->pins[i-1].pin == pfc->info->pins[i].pin - 1)
continue;
range->end = pfc->info->pins[i-1].pin;
if (!(pfc->info->pins[i-1].configs & SH_PFC_PIN_CFG_NO_GPIO))
pfc->nr_gpio_pins = range->end + 1;
range++;
range->start = pfc->info->pins[i].pin;
}
range->end = pfc->info->pins[i-1].pin;
if (!(pfc->info->pins[i-1].configs & SH_PFC_PIN_CFG_NO_GPIO))
pfc->nr_gpio_pins = range->end + 1;
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id sh_pfc_of_table[] = {
#ifdef CONFIG_PINCTRL_PFC_R8A73A4
{
.compatible = "renesas,pfc-r8a73a4",
.data = &r8a73a4_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7740
{
.compatible = "renesas,pfc-r8a7740",
.data = &r8a7740_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7778
{
.compatible = "renesas,pfc-r8a7778",
.data = &r8a7778_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7779
{
.compatible = "renesas,pfc-r8a7779",
.data = &r8a7779_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7790
{
.compatible = "renesas,pfc-r8a7790",
.data = &r8a7790_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7791
{
.compatible = "renesas,pfc-r8a7791",
.data = &r8a7791_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7372
{
.compatible = "renesas,pfc-sh7372",
.data = &sh7372_pinmux_info,
},
#endif
#ifdef CONFIG_PINCTRL_PFC_SH73A0
{
.compatible = "renesas,pfc-sh73a0",
.data = &sh73a0_pinmux_info,
},
#endif
{ },
};
MODULE_DEVICE_TABLE(of, sh_pfc_of_table);
#endif
static int sh_pfc_probe(struct platform_device *pdev)
{
const struct platform_device_id *platid = platform_get_device_id(pdev);
#ifdef CONFIG_OF
struct device_node *np = pdev->dev.of_node;
#endif
const struct sh_pfc_soc_info *info;
struct sh_pfc *pfc;
int ret;
#ifdef CONFIG_OF
if (np)
info = of_match_device(sh_pfc_of_table, &pdev->dev)->data;
else
#endif
info = platid ? (const void *)platid->driver_data : NULL;
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 = sh_pfc_map_resources(pfc, pdev);
if (unlikely(ret < 0))
return ret;
spin_lock_init(&pfc->lock);
if (info->ops && info->ops->init) {
ret = info->ops->init(pfc);
if (ret < 0)
return ret;
}
pinctrl_provide_dummies();
ret = sh_pfc_init_ranges(pfc);
if (ret < 0)
return ret;
/*
* Initialize pinctrl bindings first
*/
ret = sh_pfc_register_pinctrl(pfc);
if (unlikely(ret != 0))
return ret;
#ifdef CONFIG_GPIO_SH_PFC
/*
* Then the GPIO chip
*/
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.
*/
dev_notice(pfc->dev, "failed to init GPIO chip, ignoring...\n");
}
#endif
platform_set_drvdata(pdev, pfc);
dev_info(pfc->dev, "%s support registered\n", info->name);
return 0;
}
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);
return 0;
}
static const struct platform_device_id sh_pfc_id_table[] = {
#ifdef CONFIG_PINCTRL_PFC_R8A73A4
{ "pfc-r8a73a4", (kernel_ulong_t)&r8a73a4_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7740
{ "pfc-r8a7740", (kernel_ulong_t)&r8a7740_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7778
{ "pfc-r8a7778", (kernel_ulong_t)&r8a7778_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7779
{ "pfc-r8a7779", (kernel_ulong_t)&r8a7779_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7790
{ "pfc-r8a7790", (kernel_ulong_t)&r8a7790_pinmux_info },
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7791
{ "pfc-r8a7791", (kernel_ulong_t)&r8a7791_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,
.of_match_table = of_match_ptr(sh_pfc_of_table),
},
};
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");

View file

@ -0,0 +1,89 @@
/*
* 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/spinlock.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_pin_range {
u16 start;
u16 end;
};
struct sh_pfc {
struct device *dev;
const struct sh_pfc_soc_info *info;
spinlock_t lock;
unsigned int num_windows;
struct sh_pfc_window *windows;
unsigned int num_irqs;
unsigned int *irqs;
struct sh_pfc_pin_range *ranges;
unsigned int nr_ranges;
unsigned int nr_gpio_pins;
struct sh_pfc_chip *gpio;
struct sh_pfc_chip *func;
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);
unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width);
void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
unsigned long data);
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);
extern const struct sh_pfc_soc_info r8a73a4_pinmux_info;
extern const struct sh_pfc_soc_info r8a7740_pinmux_info;
extern const struct sh_pfc_soc_info r8a7778_pinmux_info;
extern const struct sh_pfc_soc_info r8a7779_pinmux_info;
extern const struct sh_pfc_soc_info r8a7790_pinmux_info;
extern const struct sh_pfc_soc_info r8a7791_pinmux_info;
extern const struct sh_pfc_soc_info sh7203_pinmux_info;
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
extern const struct sh_pfc_soc_info sh7269_pinmux_info;
extern const struct sh_pfc_soc_info sh7372_pinmux_info;
extern const struct sh_pfc_soc_info sh73a0_pinmux_info;
extern const struct sh_pfc_soc_info sh7720_pinmux_info;
extern const struct sh_pfc_soc_info sh7722_pinmux_info;
extern const struct sh_pfc_soc_info sh7723_pinmux_info;
extern const struct sh_pfc_soc_info sh7724_pinmux_info;
extern const struct sh_pfc_soc_info sh7734_pinmux_info;
extern const struct sh_pfc_soc_info sh7757_pinmux_info;
extern const struct sh_pfc_soc_info sh7785_pinmux_info;
extern const struct sh_pfc_soc_info sh7786_pinmux_info;
extern const struct sh_pfc_soc_info shx3_pinmux_info;
#endif /* __SH_PFC_CORE_H__ */

View file

@ -0,0 +1,416 @@
/*
* SuperH Pin Function Controller GPIO driver.
*
* Copyright (C) 2008 Magnus Damm
* Copyright (C) 2009 - 2012 Paul Mundt
*
* 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.
*/
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include "core.h"
struct sh_pfc_gpio_data_reg {
const struct pinmux_data_reg *info;
unsigned long shadow;
};
struct sh_pfc_gpio_pin {
u8 dbit;
u8 dreg;
};
struct sh_pfc_chip {
struct sh_pfc *pfc;
struct gpio_chip gpio_chip;
struct sh_pfc_window *mem;
struct sh_pfc_gpio_data_reg *regs;
struct sh_pfc_gpio_pin *pins;
};
static struct sh_pfc_chip *gpio_to_pfc_chip(struct gpio_chip *gc)
{
return container_of(gc, struct sh_pfc_chip, gpio_chip);
}
static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc)
{
return gpio_to_pfc_chip(gc)->pfc;
}
static void gpio_get_data_reg(struct sh_pfc_chip *chip, unsigned int offset,
struct sh_pfc_gpio_data_reg **reg,
unsigned int *bit)
{
int idx = sh_pfc_get_pin_index(chip->pfc, offset);
struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx];
*reg = &chip->regs[gpio_pin->dreg];
*bit = gpio_pin->dbit;
}
static unsigned long gpio_read_data_reg(struct sh_pfc_chip *chip,
const struct pinmux_data_reg *dreg)
{
void __iomem *mem = dreg->reg - chip->mem->phys + chip->mem->virt;
return sh_pfc_read_raw_reg(mem, dreg->reg_width);
}
static void gpio_write_data_reg(struct sh_pfc_chip *chip,
const struct pinmux_data_reg *dreg,
unsigned long value)
{
void __iomem *mem = dreg->reg - chip->mem->phys + chip->mem->virt;
sh_pfc_write_raw_reg(mem, dreg->reg_width, value);
}
static void gpio_setup_data_reg(struct sh_pfc_chip *chip, unsigned idx)
{
struct sh_pfc *pfc = chip->pfc;
struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx];
const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
const struct pinmux_data_reg *dreg;
unsigned int bit;
unsigned int i;
for (i = 0, dreg = pfc->info->data_regs; dreg->reg; ++i, ++dreg) {
for (bit = 0; bit < dreg->reg_width; bit++) {
if (dreg->enum_ids[bit] == pin->enum_id) {
gpio_pin->dreg = i;
gpio_pin->dbit = bit;
return;
}
}
}
BUG();
}
static int gpio_setup_data_regs(struct sh_pfc_chip *chip)
{
struct sh_pfc *pfc = chip->pfc;
const struct pinmux_data_reg *dreg;
unsigned int i;
/* Count the number of data registers, allocate memory and initialize
* them.
*/
for (i = 0; pfc->info->data_regs[i].reg_width; ++i)
;
chip->regs = devm_kzalloc(pfc->dev, i * sizeof(*chip->regs),
GFP_KERNEL);
if (chip->regs == NULL)
return -ENOMEM;
for (i = 0, dreg = pfc->info->data_regs; dreg->reg_width; ++i, ++dreg) {
chip->regs[i].info = dreg;
chip->regs[i].shadow = gpio_read_data_reg(chip, dreg);
}
for (i = 0; i < pfc->info->nr_pins; i++) {
if (pfc->info->pins[i].enum_id == 0)
continue;
gpio_setup_data_reg(chip, i);
}
return 0;
}
/* -----------------------------------------------------------------------------
* Pin GPIOs
*/
static int gpio_pin_request(struct gpio_chip *gc, unsigned offset)
{
struct sh_pfc *pfc = gpio_to_pfc(gc);
int idx = sh_pfc_get_pin_index(pfc, offset);
if (idx < 0 || pfc->info->pins[idx].enum_id == 0)
return -EINVAL;
return pinctrl_request_gpio(offset);
}
static void gpio_pin_free(struct gpio_chip *gc, unsigned offset)
{
return pinctrl_free_gpio(offset);
}
static void gpio_pin_set_value(struct sh_pfc_chip *chip, unsigned offset,
int value)
{
struct sh_pfc_gpio_data_reg *reg;
unsigned long pos;
unsigned int bit;
gpio_get_data_reg(chip, offset, &reg, &bit);
pos = reg->info->reg_width - (bit + 1);
if (value)
set_bit(pos, &reg->shadow);
else
clear_bit(pos, &reg->shadow);
gpio_write_data_reg(chip, reg->info, reg->shadow);
}
static int gpio_pin_direction_input(struct gpio_chip *gc, unsigned offset)
{
return pinctrl_gpio_direction_input(offset);
}
static int gpio_pin_direction_output(struct gpio_chip *gc, unsigned offset,
int value)
{
gpio_pin_set_value(gpio_to_pfc_chip(gc), offset, value);
return pinctrl_gpio_direction_output(offset);
}
static int gpio_pin_get(struct gpio_chip *gc, unsigned offset)
{
struct sh_pfc_chip *chip = gpio_to_pfc_chip(gc);
struct sh_pfc_gpio_data_reg *reg;
unsigned long pos;
unsigned int bit;
gpio_get_data_reg(chip, offset, &reg, &bit);
pos = reg->info->reg_width - (bit + 1);
return (gpio_read_data_reg(chip, reg->info) >> pos) & 1;
}
static void gpio_pin_set(struct gpio_chip *gc, unsigned offset, int value)
{
gpio_pin_set_value(gpio_to_pfc_chip(gc), offset, value);
}
static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct sh_pfc *pfc = gpio_to_pfc(gc);
unsigned int i, k;
for (i = 0; i < pfc->info->gpio_irq_size; i++) {
const short *gpios = pfc->info->gpio_irq[i].gpios;
for (k = 0; gpios[k] >= 0; k++) {
if (gpios[k] == offset)
goto found;
}
}
return -ENOSYS;
found:
if (pfc->num_irqs)
return pfc->irqs[i];
else
return pfc->info->gpio_irq[i].irq;
}
static int gpio_pin_setup(struct sh_pfc_chip *chip)
{
struct sh_pfc *pfc = chip->pfc;
struct gpio_chip *gc = &chip->gpio_chip;
int ret;
chip->pins = devm_kzalloc(pfc->dev, pfc->info->nr_pins *
sizeof(*chip->pins), GFP_KERNEL);
if (chip->pins == NULL)
return -ENOMEM;
ret = gpio_setup_data_regs(chip);
if (ret < 0)
return ret;
gc->request = gpio_pin_request;
gc->free = gpio_pin_free;
gc->direction_input = gpio_pin_direction_input;
gc->get = gpio_pin_get;
gc->direction_output = gpio_pin_direction_output;
gc->set = gpio_pin_set;
gc->to_irq = gpio_pin_to_irq;
gc->label = pfc->info->name;
gc->dev = pfc->dev;
gc->owner = THIS_MODULE;
gc->base = 0;
gc->ngpio = pfc->nr_gpio_pins;
return 0;
}
/* -----------------------------------------------------------------------------
* Function GPIOs
*/
static int gpio_function_request(struct gpio_chip *gc, unsigned offset)
{
static bool __print_once;
struct sh_pfc *pfc = gpio_to_pfc(gc);
unsigned int mark = pfc->info->func_gpios[offset].enum_id;
unsigned long flags;
int ret;
if (!__print_once) {
dev_notice(pfc->dev,
"Use of GPIO API for function requests is deprecated."
" Convert to pinctrl\n");
__print_once = true;
}
if (mark == 0)
return -EINVAL;
spin_lock_irqsave(&pfc->lock, flags);
ret = sh_pfc_config_mux(pfc, mark, PINMUX_TYPE_FUNCTION);
spin_unlock_irqrestore(&pfc->lock, flags);
return ret;
}
static void gpio_function_free(struct gpio_chip *gc, unsigned offset)
{
}
static int gpio_function_setup(struct sh_pfc_chip *chip)
{
struct sh_pfc *pfc = chip->pfc;
struct gpio_chip *gc = &chip->gpio_chip;
gc->request = gpio_function_request;
gc->free = gpio_function_free;
gc->label = pfc->info->name;
gc->owner = THIS_MODULE;
gc->base = pfc->nr_gpio_pins;
gc->ngpio = pfc->info->nr_func_gpios;
return 0;
}
/* -----------------------------------------------------------------------------
* Register/unregister
*/
static struct sh_pfc_chip *
sh_pfc_add_gpiochip(struct sh_pfc *pfc, int(*setup)(struct sh_pfc_chip *),
struct sh_pfc_window *mem)
{
struct sh_pfc_chip *chip;
int ret;
chip = devm_kzalloc(pfc->dev, sizeof(*chip), GFP_KERNEL);
if (unlikely(!chip))
return ERR_PTR(-ENOMEM);
chip->mem = mem;
chip->pfc = pfc;
ret = setup(chip);
if (ret < 0)
return ERR_PTR(ret);
ret = gpiochip_add(&chip->gpio_chip);
if (unlikely(ret < 0))
return ERR_PTR(ret);
dev_info(pfc->dev, "%s handling gpio %u -> %u\n",
chip->gpio_chip.label, chip->gpio_chip.base,
chip->gpio_chip.base + chip->gpio_chip.ngpio - 1);
return chip;
}
int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
{
struct sh_pfc_chip *chip;
unsigned int i;
int ret;
if (pfc->info->data_regs == NULL)
return 0;
/* Find the memory window that contain the GPIO registers. Boards that
* register a separate GPIO device will not supply a memory resource
* that covers the data registers. In that case don't try to handle
* GPIOs.
*/
for (i = 0; i < pfc->num_windows; ++i) {
struct sh_pfc_window *window = &pfc->windows[i];
if (pfc->info->data_regs[0].reg >= window->phys &&
pfc->info->data_regs[0].reg < window->phys + window->size)
break;
}
if (i == pfc->num_windows)
return 0;
/* If we have IRQ resources make sure their number is correct. */
if (pfc->num_irqs && pfc->num_irqs != pfc->info->gpio_irq_size) {
dev_err(pfc->dev, "invalid number of IRQ resources\n");
return -EINVAL;
}
/* Register the real GPIOs chip. */
chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]);
if (IS_ERR(chip))
return PTR_ERR(chip);
pfc->gpio = chip;
/* Register the GPIO to pin mappings. As pins with GPIO ports must come
* first in the ranges, skip the pins without GPIO ports by stopping at
* the first range that contains such a pin.
*/
for (i = 0; i < pfc->nr_ranges; ++i) {
const struct sh_pfc_pin_range *range = &pfc->ranges[i];
if (range->start >= pfc->nr_gpio_pins)
break;
ret = gpiochip_add_pin_range(&chip->gpio_chip,
dev_name(pfc->dev),
range->start, range->start,
range->end - range->start + 1);
if (ret < 0)
return ret;
}
/* Register the function GPIOs chip. */
if (pfc->info->nr_func_gpios == 0)
return 0;
chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup, NULL);
if (IS_ERR(chip))
return PTR_ERR(chip);
pfc->func = chip;
return 0;
}
int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc)
{
gpiochip_remove(&pfc->gpio->gpio_chip);
gpiochip_remove(&pfc->func->gpio_chip);
return 0;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,818 @@
/*
* SH7786 Pinmux
*
* Copyright (C) 2008, 2009 Renesas Solutions Corp.
* Kuninori Morimoto <morimoto.kuninori@renesas.com>
*
* Based on SH7785 pinmux
*
* Copyright (C) 2008 Magnus Damm
*
* 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.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <cpu/sh7786.h>
#include "sh_pfc.h"
enum {
PINMUX_RESERVED = 0,
PINMUX_DATA_BEGIN,
PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA,
PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA,
PE7_DATA, PE6_DATA,
PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA,
PG7_DATA, PG6_DATA, PG5_DATA,
PH7_DATA, PH6_DATA, PH5_DATA, PH4_DATA,
PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA,
PJ7_DATA, PJ6_DATA, PJ5_DATA, PJ4_DATA,
PJ3_DATA, PJ2_DATA, PJ1_DATA,
PINMUX_DATA_END,
PINMUX_INPUT_BEGIN,
PA7_IN, PA6_IN, PA5_IN, PA4_IN,
PA3_IN, PA2_IN, PA1_IN, PA0_IN,
PB7_IN, PB6_IN, PB5_IN, PB4_IN,
PB3_IN, PB2_IN, PB1_IN, PB0_IN,
PC7_IN, PC6_IN, PC5_IN, PC4_IN,
PC3_IN, PC2_IN, PC1_IN, PC0_IN,
PD7_IN, PD6_IN, PD5_IN, PD4_IN,
PD3_IN, PD2_IN, PD1_IN, PD0_IN,
PE7_IN, PE6_IN,
PF7_IN, PF6_IN, PF5_IN, PF4_IN,
PF3_IN, PF2_IN, PF1_IN, PF0_IN,
PG7_IN, PG6_IN, PG5_IN,
PH7_IN, PH6_IN, PH5_IN, PH4_IN,
PH3_IN, PH2_IN, PH1_IN, PH0_IN,
PJ7_IN, PJ6_IN, PJ5_IN, PJ4_IN,
PJ3_IN, PJ2_IN, PJ1_IN,
PINMUX_INPUT_END,
PINMUX_OUTPUT_BEGIN,
PA7_OUT, PA6_OUT, PA5_OUT, PA4_OUT,
PA3_OUT, PA2_OUT, PA1_OUT, PA0_OUT,
PB7_OUT, PB6_OUT, PB5_OUT, PB4_OUT,
PB3_OUT, PB2_OUT, PB1_OUT, PB0_OUT,
PC7_OUT, PC6_OUT, PC5_OUT, PC4_OUT,
PC3_OUT, PC2_OUT, PC1_OUT, PC0_OUT,
PD7_OUT, PD6_OUT, PD5_OUT, PD4_OUT,
PD3_OUT, PD2_OUT, PD1_OUT, PD0_OUT,
PE7_OUT, PE6_OUT,
PF7_OUT, PF6_OUT, PF5_OUT, PF4_OUT,
PF3_OUT, PF2_OUT, PF1_OUT, PF0_OUT,
PG7_OUT, PG6_OUT, PG5_OUT,
PH7_OUT, PH6_OUT, PH5_OUT, PH4_OUT,
PH3_OUT, PH2_OUT, PH1_OUT, PH0_OUT,
PJ7_OUT, PJ6_OUT, PJ5_OUT, PJ4_OUT,
PJ3_OUT, PJ2_OUT, PJ1_OUT,
PINMUX_OUTPUT_END,
PINMUX_FUNCTION_BEGIN,
PA7_FN, PA6_FN, PA5_FN, PA4_FN,
PA3_FN, PA2_FN, PA1_FN, PA0_FN,
PB7_FN, PB6_FN, PB5_FN, PB4_FN,
PB3_FN, PB2_FN, PB1_FN, PB0_FN,
PC7_FN, PC6_FN, PC5_FN, PC4_FN,
PC3_FN, PC2_FN, PC1_FN, PC0_FN,
PD7_FN, PD6_FN, PD5_FN, PD4_FN,
PD3_FN, PD2_FN, PD1_FN, PD0_FN,
PE7_FN, PE6_FN,
PF7_FN, PF6_FN, PF5_FN, PF4_FN,
PF3_FN, PF2_FN, PF1_FN, PF0_FN,
PG7_FN, PG6_FN, PG5_FN,
PH7_FN, PH6_FN, PH5_FN, PH4_FN,
PH3_FN, PH2_FN, PH1_FN, PH0_FN,
PJ7_FN, PJ6_FN, PJ5_FN, PJ4_FN,
PJ3_FN, PJ2_FN, PJ1_FN,
P1MSEL14_0, P1MSEL14_1,
P1MSEL13_0, P1MSEL13_1,
P1MSEL12_0, P1MSEL12_1,
P1MSEL11_0, P1MSEL11_1,
P1MSEL10_0, P1MSEL10_1,
P1MSEL9_0, P1MSEL9_1,
P1MSEL8_0, P1MSEL8_1,
P1MSEL7_0, P1MSEL7_1,
P1MSEL6_0, P1MSEL6_1,
P1MSEL5_0, P1MSEL5_1,
P1MSEL4_0, P1MSEL4_1,
P1MSEL3_0, P1MSEL3_1,
P1MSEL2_0, P1MSEL2_1,
P1MSEL1_0, P1MSEL1_1,
P1MSEL0_0, P1MSEL0_1,
P2MSEL15_0, P2MSEL15_1,
P2MSEL14_0, P2MSEL14_1,
P2MSEL13_0, P2MSEL13_1,
P2MSEL12_0, P2MSEL12_1,
P2MSEL11_0, P2MSEL11_1,
P2MSEL10_0, P2MSEL10_1,
P2MSEL9_0, P2MSEL9_1,
P2MSEL8_0, P2MSEL8_1,
P2MSEL7_0, P2MSEL7_1,
P2MSEL6_0, P2MSEL6_1,
P2MSEL5_0, P2MSEL5_1,
P2MSEL4_0, P2MSEL4_1,
P2MSEL3_0, P2MSEL3_1,
P2MSEL2_0, P2MSEL2_1,
P2MSEL1_0, P2MSEL1_1,
P2MSEL0_0, P2MSEL0_1,
PINMUX_FUNCTION_END,
PINMUX_MARK_BEGIN,
DCLKIN_MARK, DCLKOUT_MARK, ODDF_MARK,
VSYNC_MARK, HSYNC_MARK, CDE_MARK, DISP_MARK,
DR0_MARK, DR1_MARK, DR2_MARK, DR3_MARK, DR4_MARK, DR5_MARK,
DG0_MARK, DG1_MARK, DG2_MARK, DG3_MARK, DG4_MARK, DG5_MARK,
DB0_MARK, DB1_MARK, DB2_MARK, DB3_MARK, DB4_MARK, DB5_MARK,
ETH_MAGIC_MARK, ETH_LINK_MARK, ETH_TX_ER_MARK, ETH_TX_EN_MARK,
ETH_MDIO_MARK, ETH_RX_CLK_MARK, ETH_MDC_MARK, ETH_COL_MARK,
ETH_TX_CLK_MARK, ETH_CRS_MARK, ETH_RX_DV_MARK, ETH_RX_ER_MARK,
ETH_TXD3_MARK, ETH_TXD2_MARK, ETH_TXD1_MARK, ETH_TXD0_MARK,
ETH_RXD3_MARK, ETH_RXD2_MARK, ETH_RXD1_MARK, ETH_RXD0_MARK,
HSPI_CLK_MARK, HSPI_CS_MARK, HSPI_RX_MARK, HSPI_TX_MARK,
SCIF0_CTS_MARK, SCIF0_RTS_MARK,
SCIF0_SCK_MARK, SCIF0_RXD_MARK, SCIF0_TXD_MARK,
SCIF1_SCK_MARK, SCIF1_RXD_MARK, SCIF1_TXD_MARK,
SCIF3_SCK_MARK, SCIF3_RXD_MARK, SCIF3_TXD_MARK,
SCIF4_SCK_MARK, SCIF4_RXD_MARK, SCIF4_TXD_MARK,
SCIF5_SCK_MARK, SCIF5_RXD_MARK, SCIF5_TXD_MARK,
BREQ_MARK, IOIS16_MARK, CE2B_MARK, CE2A_MARK, BACK_MARK,
FALE_MARK, FRB_MARK, FSTATUS_MARK,
FSE_MARK, FCLE_MARK,
DACK0_MARK, DACK1_MARK, DACK2_MARK, DACK3_MARK,
DREQ0_MARK, DREQ1_MARK, DREQ2_MARK, DREQ3_MARK,
DRAK0_MARK, DRAK1_MARK, DRAK2_MARK, DRAK3_MARK,
USB_OVC1_MARK, USB_OVC0_MARK,
USB_PENC1_MARK, USB_PENC0_MARK,
HAC_RES_MARK,
HAC1_SDOUT_MARK, HAC1_SDIN_MARK, HAC1_SYNC_MARK, HAC1_BITCLK_MARK,
HAC0_SDOUT_MARK, HAC0_SDIN_MARK, HAC0_SYNC_MARK, HAC0_BITCLK_MARK,
SSI0_SDATA_MARK, SSI0_SCK_MARK, SSI0_WS_MARK, SSI0_CLK_MARK,
SSI1_SDATA_MARK, SSI1_SCK_MARK, SSI1_WS_MARK, SSI1_CLK_MARK,
SSI2_SDATA_MARK, SSI2_SCK_MARK, SSI2_WS_MARK,
SSI3_SDATA_MARK, SSI3_SCK_MARK, SSI3_WS_MARK,
SDIF1CMD_MARK, SDIF1CD_MARK, SDIF1WP_MARK, SDIF1CLK_MARK,
SDIF1D3_MARK, SDIF1D2_MARK, SDIF1D1_MARK, SDIF1D0_MARK,
SDIF0CMD_MARK, SDIF0CD_MARK, SDIF0WP_MARK, SDIF0CLK_MARK,
SDIF0D3_MARK, SDIF0D2_MARK, SDIF0D1_MARK, SDIF0D0_MARK,
TCLK_MARK,
IRL7_MARK, IRL6_MARK, IRL5_MARK, IRL4_MARK,
PINMUX_MARK_END,
};
static const u16 pinmux_data[] = {
/* PA GPIO */
PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT),
PINMUX_DATA(PA6_DATA, PA6_IN, PA6_OUT),
PINMUX_DATA(PA5_DATA, PA5_IN, PA5_OUT),
PINMUX_DATA(PA4_DATA, PA4_IN, PA4_OUT),
PINMUX_DATA(PA3_DATA, PA3_IN, PA3_OUT),
PINMUX_DATA(PA2_DATA, PA2_IN, PA2_OUT),
PINMUX_DATA(PA1_DATA, PA1_IN, PA1_OUT),
PINMUX_DATA(PA0_DATA, PA0_IN, PA0_OUT),
/* PB GPIO */
PINMUX_DATA(PB7_DATA, PB7_IN, PB7_OUT),
PINMUX_DATA(PB6_DATA, PB6_IN, PB6_OUT),
PINMUX_DATA(PB5_DATA, PB5_IN, PB5_OUT),
PINMUX_DATA(PB4_DATA, PB4_IN, PB4_OUT),
PINMUX_DATA(PB3_DATA, PB3_IN, PB3_OUT),
PINMUX_DATA(PB2_DATA, PB2_IN, PB2_OUT),
PINMUX_DATA(PB1_DATA, PB1_IN, PB1_OUT),
PINMUX_DATA(PB0_DATA, PB0_IN, PB0_OUT),
/* PC GPIO */
PINMUX_DATA(PC7_DATA, PC7_IN, PC7_OUT),
PINMUX_DATA(PC6_DATA, PC6_IN, PC6_OUT),
PINMUX_DATA(PC5_DATA, PC5_IN, PC5_OUT),
PINMUX_DATA(PC4_DATA, PC4_IN, PC4_OUT),
PINMUX_DATA(PC3_DATA, PC3_IN, PC3_OUT),
PINMUX_DATA(PC2_DATA, PC2_IN, PC2_OUT),
PINMUX_DATA(PC1_DATA, PC1_IN, PC1_OUT),
PINMUX_DATA(PC0_DATA, PC0_IN, PC0_OUT),
/* PD GPIO */
PINMUX_DATA(PD7_DATA, PD7_IN, PD7_OUT),
PINMUX_DATA(PD6_DATA, PD6_IN, PD6_OUT),
PINMUX_DATA(PD5_DATA, PD5_IN, PD5_OUT),
PINMUX_DATA(PD4_DATA, PD4_IN, PD4_OUT),
PINMUX_DATA(PD3_DATA, PD3_IN, PD3_OUT),
PINMUX_DATA(PD2_DATA, PD2_IN, PD2_OUT),
PINMUX_DATA(PD1_DATA, PD1_IN, PD1_OUT),
PINMUX_DATA(PD0_DATA, PD0_IN, PD0_OUT),
/* PE GPIO */
PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT),
PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT),
/* PF GPIO */
PINMUX_DATA(PF7_DATA, PF7_IN, PF7_OUT),
PINMUX_DATA(PF6_DATA, PF6_IN, PF6_OUT),
PINMUX_DATA(PF5_DATA, PF5_IN, PF5_OUT),
PINMUX_DATA(PF4_DATA, PF4_IN, PF4_OUT),
PINMUX_DATA(PF3_DATA, PF3_IN, PF3_OUT),
PINMUX_DATA(PF2_DATA, PF2_IN, PF2_OUT),
PINMUX_DATA(PF1_DATA, PF1_IN, PF1_OUT),
PINMUX_DATA(PF0_DATA, PF0_IN, PF0_OUT),
/* PG GPIO */
PINMUX_DATA(PG7_DATA, PG7_IN, PG7_OUT),
PINMUX_DATA(PG6_DATA, PG6_IN, PG6_OUT),
PINMUX_DATA(PG5_DATA, PG5_IN, PG5_OUT),
/* PH GPIO */
PINMUX_DATA(PH7_DATA, PH7_IN, PH7_OUT),
PINMUX_DATA(PH6_DATA, PH6_IN, PH6_OUT),
PINMUX_DATA(PH5_DATA, PH5_IN, PH5_OUT),
PINMUX_DATA(PH4_DATA, PH4_IN, PH4_OUT),
PINMUX_DATA(PH3_DATA, PH3_IN, PH3_OUT),
PINMUX_DATA(PH2_DATA, PH2_IN, PH2_OUT),
PINMUX_DATA(PH1_DATA, PH1_IN, PH1_OUT),
PINMUX_DATA(PH0_DATA, PH0_IN, PH0_OUT),
/* PJ GPIO */
PINMUX_DATA(PJ7_DATA, PJ7_IN, PJ7_OUT),
PINMUX_DATA(PJ6_DATA, PJ6_IN, PJ6_OUT),
PINMUX_DATA(PJ5_DATA, PJ5_IN, PJ5_OUT),
PINMUX_DATA(PJ4_DATA, PJ4_IN, PJ4_OUT),
PINMUX_DATA(PJ3_DATA, PJ3_IN, PJ3_OUT),
PINMUX_DATA(PJ2_DATA, PJ2_IN, PJ2_OUT),
PINMUX_DATA(PJ1_DATA, PJ1_IN, PJ1_OUT),
/* PA FN */
PINMUX_DATA(CDE_MARK, P1MSEL2_0, PA7_FN),
PINMUX_DATA(DISP_MARK, P1MSEL2_0, PA6_FN),
PINMUX_DATA(DR5_MARK, P1MSEL2_0, PA5_FN),
PINMUX_DATA(DR4_MARK, P1MSEL2_0, PA4_FN),
PINMUX_DATA(DR3_MARK, P1MSEL2_0, PA3_FN),
PINMUX_DATA(DR2_MARK, P1MSEL2_0, PA2_FN),
PINMUX_DATA(DR1_MARK, P1MSEL2_0, PA1_FN),
PINMUX_DATA(DR0_MARK, P1MSEL2_0, PA0_FN),
PINMUX_DATA(ETH_MAGIC_MARK, P1MSEL2_1, PA7_FN),
PINMUX_DATA(ETH_LINK_MARK, P1MSEL2_1, PA6_FN),
PINMUX_DATA(ETH_TX_ER_MARK, P1MSEL2_1, PA5_FN),
PINMUX_DATA(ETH_TX_EN_MARK, P1MSEL2_1, PA4_FN),
PINMUX_DATA(ETH_TXD3_MARK, P1MSEL2_1, PA3_FN),
PINMUX_DATA(ETH_TXD2_MARK, P1MSEL2_1, PA2_FN),
PINMUX_DATA(ETH_TXD1_MARK, P1MSEL2_1, PA1_FN),
PINMUX_DATA(ETH_TXD0_MARK, P1MSEL2_1, PA0_FN),
/* PB FN */
PINMUX_DATA(VSYNC_MARK, P1MSEL3_0, PB7_FN),
PINMUX_DATA(ODDF_MARK, P1MSEL3_0, PB6_FN),
PINMUX_DATA(DG5_MARK, P1MSEL2_0, PB5_FN),
PINMUX_DATA(DG4_MARK, P1MSEL2_0, PB4_FN),
PINMUX_DATA(DG3_MARK, P1MSEL2_0, PB3_FN),
PINMUX_DATA(DG2_MARK, P1MSEL2_0, PB2_FN),
PINMUX_DATA(DG1_MARK, P1MSEL2_0, PB1_FN),
PINMUX_DATA(DG0_MARK, P1MSEL2_0, PB0_FN),
PINMUX_DATA(HSPI_CLK_MARK, P1MSEL3_1, PB7_FN),
PINMUX_DATA(HSPI_CS_MARK, P1MSEL3_1, PB6_FN),
PINMUX_DATA(ETH_MDIO_MARK, P1MSEL2_1, PB5_FN),
PINMUX_DATA(ETH_RX_CLK_MARK, P1MSEL2_1, PB4_FN),
PINMUX_DATA(ETH_MDC_MARK, P1MSEL2_1, PB3_FN),
PINMUX_DATA(ETH_COL_MARK, P1MSEL2_1, PB2_FN),
PINMUX_DATA(ETH_TX_CLK_MARK, P1MSEL2_1, PB1_FN),
PINMUX_DATA(ETH_CRS_MARK, P1MSEL2_1, PB0_FN),
/* PC FN */
PINMUX_DATA(DCLKIN_MARK, P1MSEL3_0, PC7_FN),
PINMUX_DATA(HSYNC_MARK, P1MSEL3_0, PC6_FN),
PINMUX_DATA(DB5_MARK, P1MSEL2_0, PC5_FN),
PINMUX_DATA(DB4_MARK, P1MSEL2_0, PC4_FN),
PINMUX_DATA(DB3_MARK, P1MSEL2_0, PC3_FN),
PINMUX_DATA(DB2_MARK, P1MSEL2_0, PC2_FN),
PINMUX_DATA(DB1_MARK, P1MSEL2_0, PC1_FN),
PINMUX_DATA(DB0_MARK, P1MSEL2_0, PC0_FN),
PINMUX_DATA(HSPI_RX_MARK, P1MSEL3_1, PC7_FN),
PINMUX_DATA(HSPI_TX_MARK, P1MSEL3_1, PC6_FN),
PINMUX_DATA(ETH_RXD3_MARK, P1MSEL2_1, PC5_FN),
PINMUX_DATA(ETH_RXD2_MARK, P1MSEL2_1, PC4_FN),
PINMUX_DATA(ETH_RXD1_MARK, P1MSEL2_1, PC3_FN),
PINMUX_DATA(ETH_RXD0_MARK, P1MSEL2_1, PC2_FN),
PINMUX_DATA(ETH_RX_DV_MARK, P1MSEL2_1, PC1_FN),
PINMUX_DATA(ETH_RX_ER_MARK, P1MSEL2_1, PC0_FN),
/* PD FN */
PINMUX_DATA(DCLKOUT_MARK, PD7_FN),
PINMUX_DATA(SCIF1_SCK_MARK, PD6_FN),
PINMUX_DATA(SCIF1_RXD_MARK, PD5_FN),
PINMUX_DATA(SCIF1_TXD_MARK, PD4_FN),
PINMUX_DATA(DACK1_MARK, P1MSEL13_1, P1MSEL12_0, PD3_FN),
PINMUX_DATA(BACK_MARK, P1MSEL13_0, P1MSEL12_1, PD3_FN),
PINMUX_DATA(FALE_MARK, P1MSEL13_0, P1MSEL12_0, PD3_FN),
PINMUX_DATA(DACK0_MARK, P1MSEL14_1, PD2_FN),
PINMUX_DATA(FCLE_MARK, P1MSEL14_0, PD2_FN),
PINMUX_DATA(DREQ1_MARK, P1MSEL10_0, P1MSEL9_1, PD1_FN),
PINMUX_DATA(BREQ_MARK, P1MSEL10_1, P1MSEL9_0, PD1_FN),
PINMUX_DATA(USB_OVC1_MARK, P1MSEL10_0, P1MSEL9_0, PD1_FN),
PINMUX_DATA(DREQ0_MARK, P1MSEL11_1, PD0_FN),
PINMUX_DATA(USB_OVC0_MARK, P1MSEL11_0, PD0_FN),
/* PE FN */
PINMUX_DATA(USB_PENC1_MARK, PE7_FN),
PINMUX_DATA(USB_PENC0_MARK, PE6_FN),
/* PF FN */
PINMUX_DATA(HAC1_SDOUT_MARK, P2MSEL15_0, P2MSEL14_0, PF7_FN),
PINMUX_DATA(HAC1_SDIN_MARK, P2MSEL15_0, P2MSEL14_0, PF6_FN),
PINMUX_DATA(HAC1_SYNC_MARK, P2MSEL15_0, P2MSEL14_0, PF5_FN),
PINMUX_DATA(HAC1_BITCLK_MARK, P2MSEL15_0, P2MSEL14_0, PF4_FN),
PINMUX_DATA(HAC0_SDOUT_MARK, P2MSEL13_0, P2MSEL12_0, PF3_FN),
PINMUX_DATA(HAC0_SDIN_MARK, P2MSEL13_0, P2MSEL12_0, PF2_FN),
PINMUX_DATA(HAC0_SYNC_MARK, P2MSEL13_0, P2MSEL12_0, PF1_FN),
PINMUX_DATA(HAC0_BITCLK_MARK, P2MSEL13_0, P2MSEL12_0, PF0_FN),
PINMUX_DATA(SSI1_SDATA_MARK, P2MSEL15_0, P2MSEL14_1, PF7_FN),
PINMUX_DATA(SSI1_SCK_MARK, P2MSEL15_0, P2MSEL14_1, PF6_FN),
PINMUX_DATA(SSI1_WS_MARK, P2MSEL15_0, P2MSEL14_1, PF5_FN),
PINMUX_DATA(SSI1_CLK_MARK, P2MSEL15_0, P2MSEL14_1, PF4_FN),
PINMUX_DATA(SSI0_SDATA_MARK, P2MSEL13_0, P2MSEL12_1, PF3_FN),
PINMUX_DATA(SSI0_SCK_MARK, P2MSEL13_0, P2MSEL12_1, PF2_FN),
PINMUX_DATA(SSI0_WS_MARK, P2MSEL13_0, P2MSEL12_1, PF1_FN),
PINMUX_DATA(SSI0_CLK_MARK, P2MSEL13_0, P2MSEL12_1, PF0_FN),
PINMUX_DATA(SDIF1CMD_MARK, P2MSEL15_1, P2MSEL14_0, PF7_FN),
PINMUX_DATA(SDIF1CD_MARK, P2MSEL15_1, P2MSEL14_0, PF6_FN),
PINMUX_DATA(SDIF1WP_MARK, P2MSEL15_1, P2MSEL14_0, PF5_FN),
PINMUX_DATA(SDIF1CLK_MARK, P2MSEL15_1, P2MSEL14_0, PF4_FN),
PINMUX_DATA(SDIF1D3_MARK, P2MSEL13_1, P2MSEL12_0, PF3_FN),
PINMUX_DATA(SDIF1D2_MARK, P2MSEL13_1, P2MSEL12_0, PF2_FN),
PINMUX_DATA(SDIF1D1_MARK, P2MSEL13_1, P2MSEL12_0, PF1_FN),
PINMUX_DATA(SDIF1D0_MARK, P2MSEL13_1, P2MSEL12_0, PF0_FN),
/* PG FN */
PINMUX_DATA(SCIF3_SCK_MARK, P1MSEL8_0, PG7_FN),
PINMUX_DATA(SSI2_SDATA_MARK, P1MSEL8_1, PG7_FN),
PINMUX_DATA(SCIF3_RXD_MARK, P1MSEL7_0, P1MSEL6_0, PG6_FN),
PINMUX_DATA(SSI2_SCK_MARK, P1MSEL7_1, P1MSEL6_0, PG6_FN),
PINMUX_DATA(TCLK_MARK, P1MSEL7_0, P1MSEL6_1, PG6_FN),
PINMUX_DATA(SCIF3_TXD_MARK, P1MSEL5_0, P1MSEL4_0, PG5_FN),
PINMUX_DATA(SSI2_WS_MARK, P1MSEL5_1, P1MSEL4_0, PG5_FN),
PINMUX_DATA(HAC_RES_MARK, P1MSEL5_0, P1MSEL4_1, PG5_FN),
/* PH FN */
PINMUX_DATA(DACK3_MARK, P2MSEL4_0, PH7_FN),
PINMUX_DATA(SDIF0CMD_MARK, P2MSEL4_1, PH7_FN),
PINMUX_DATA(DACK2_MARK, P2MSEL4_0, PH6_FN),
PINMUX_DATA(SDIF0CD_MARK, P2MSEL4_1, PH6_FN),
PINMUX_DATA(DREQ3_MARK, P2MSEL4_0, PH5_FN),
PINMUX_DATA(SDIF0WP_MARK, P2MSEL4_1, PH5_FN),
PINMUX_DATA(DREQ2_MARK, P2MSEL3_0, P2MSEL2_1, PH4_FN),
PINMUX_DATA(SDIF0CLK_MARK, P2MSEL3_1, P2MSEL2_0, PH4_FN),
PINMUX_DATA(SCIF0_CTS_MARK, P2MSEL3_0, P2MSEL2_0, PH4_FN),
PINMUX_DATA(SDIF0D3_MARK, P2MSEL1_1, P2MSEL0_0, PH3_FN),
PINMUX_DATA(SCIF0_RTS_MARK, P2MSEL1_0, P2MSEL0_0, PH3_FN),
PINMUX_DATA(IRL7_MARK, P2MSEL1_0, P2MSEL0_1, PH3_FN),
PINMUX_DATA(SDIF0D2_MARK, P2MSEL1_1, P2MSEL0_0, PH2_FN),
PINMUX_DATA(SCIF0_SCK_MARK, P2MSEL1_0, P2MSEL0_0, PH2_FN),
PINMUX_DATA(IRL6_MARK, P2MSEL1_0, P2MSEL0_1, PH2_FN),
PINMUX_DATA(SDIF0D1_MARK, P2MSEL1_1, P2MSEL0_0, PH1_FN),
PINMUX_DATA(SCIF0_RXD_MARK, P2MSEL1_0, P2MSEL0_0, PH1_FN),
PINMUX_DATA(IRL5_MARK, P2MSEL1_0, P2MSEL0_1, PH1_FN),
PINMUX_DATA(SDIF0D0_MARK, P2MSEL1_1, P2MSEL0_0, PH0_FN),
PINMUX_DATA(SCIF0_TXD_MARK, P2MSEL1_0, P2MSEL0_0, PH0_FN),
PINMUX_DATA(IRL4_MARK, P2MSEL1_0, P2MSEL0_1, PH0_FN),
/* PJ FN */
PINMUX_DATA(SCIF5_SCK_MARK, P2MSEL11_1, PJ7_FN),
PINMUX_DATA(FRB_MARK, P2MSEL11_0, PJ7_FN),
PINMUX_DATA(SCIF5_RXD_MARK, P2MSEL10_0, PJ6_FN),
PINMUX_DATA(IOIS16_MARK, P2MSEL10_1, PJ6_FN),
PINMUX_DATA(SCIF5_TXD_MARK, P2MSEL10_0, PJ5_FN),
PINMUX_DATA(CE2B_MARK, P2MSEL10_1, PJ5_FN),
PINMUX_DATA(DRAK3_MARK, P2MSEL7_0, PJ4_FN),
PINMUX_DATA(CE2A_MARK, P2MSEL7_1, PJ4_FN),
PINMUX_DATA(SCIF4_SCK_MARK, P2MSEL9_0, P2MSEL8_0, PJ3_FN),
PINMUX_DATA(DRAK2_MARK, P2MSEL9_0, P2MSEL8_1, PJ3_FN),
PINMUX_DATA(SSI3_WS_MARK, P2MSEL9_1, P2MSEL8_0, PJ3_FN),
PINMUX_DATA(SCIF4_RXD_MARK, P2MSEL6_1, P2MSEL5_0, PJ2_FN),
PINMUX_DATA(DRAK1_MARK, P2MSEL6_0, P2MSEL5_1, PJ2_FN),
PINMUX_DATA(FSTATUS_MARK, P2MSEL6_0, P2MSEL5_0, PJ2_FN),
PINMUX_DATA(SSI3_SDATA_MARK, P2MSEL6_1, P2MSEL5_1, PJ2_FN),
PINMUX_DATA(SCIF4_TXD_MARK, P2MSEL6_1, P2MSEL5_0, PJ1_FN),
PINMUX_DATA(DRAK0_MARK, P2MSEL6_0, P2MSEL5_1, PJ1_FN),
PINMUX_DATA(FSE_MARK, P2MSEL6_0, P2MSEL5_0, PJ1_FN),
PINMUX_DATA(SSI3_SCK_MARK, P2MSEL6_1, P2MSEL5_1, PJ1_FN),
};
static const struct sh_pfc_pin pinmux_pins[] = {
/* PA */
PINMUX_GPIO(PA7),
PINMUX_GPIO(PA6),
PINMUX_GPIO(PA5),
PINMUX_GPIO(PA4),
PINMUX_GPIO(PA3),
PINMUX_GPIO(PA2),
PINMUX_GPIO(PA1),
PINMUX_GPIO(PA0),
/* PB */
PINMUX_GPIO(PB7),
PINMUX_GPIO(PB6),
PINMUX_GPIO(PB5),
PINMUX_GPIO(PB4),
PINMUX_GPIO(PB3),
PINMUX_GPIO(PB2),
PINMUX_GPIO(PB1),
PINMUX_GPIO(PB0),
/* PC */
PINMUX_GPIO(PC7),
PINMUX_GPIO(PC6),
PINMUX_GPIO(PC5),
PINMUX_GPIO(PC4),
PINMUX_GPIO(PC3),
PINMUX_GPIO(PC2),
PINMUX_GPIO(PC1),
PINMUX_GPIO(PC0),
/* PD */
PINMUX_GPIO(PD7),
PINMUX_GPIO(PD6),
PINMUX_GPIO(PD5),
PINMUX_GPIO(PD4),
PINMUX_GPIO(PD3),
PINMUX_GPIO(PD2),
PINMUX_GPIO(PD1),
PINMUX_GPIO(PD0),
/* PE */
PINMUX_GPIO(PE7),
PINMUX_GPIO(PE6),
/* PF */
PINMUX_GPIO(PF7),
PINMUX_GPIO(PF6),
PINMUX_GPIO(PF5),
PINMUX_GPIO(PF4),
PINMUX_GPIO(PF3),
PINMUX_GPIO(PF2),
PINMUX_GPIO(PF1),
PINMUX_GPIO(PF0),
/* PG */
PINMUX_GPIO(PG7),
PINMUX_GPIO(PG6),
PINMUX_GPIO(PG5),
/* PH */
PINMUX_GPIO(PH7),
PINMUX_GPIO(PH6),
PINMUX_GPIO(PH5),
PINMUX_GPIO(PH4),
PINMUX_GPIO(PH3),
PINMUX_GPIO(PH2),
PINMUX_GPIO(PH1),
PINMUX_GPIO(PH0),
/* PJ */
PINMUX_GPIO(PJ7),
PINMUX_GPIO(PJ6),
PINMUX_GPIO(PJ5),
PINMUX_GPIO(PJ4),
PINMUX_GPIO(PJ3),
PINMUX_GPIO(PJ2),
PINMUX_GPIO(PJ1),
};
#define PINMUX_FN_BASE ARRAY_SIZE(pinmux_pins)
static const struct pinmux_func pinmux_func_gpios[] = {
/* FN */
GPIO_FN(CDE),
GPIO_FN(ETH_MAGIC),
GPIO_FN(DISP),
GPIO_FN(ETH_LINK),
GPIO_FN(DR5),
GPIO_FN(ETH_TX_ER),
GPIO_FN(DR4),
GPIO_FN(ETH_TX_EN),
GPIO_FN(DR3),
GPIO_FN(ETH_TXD3),
GPIO_FN(DR2),
GPIO_FN(ETH_TXD2),
GPIO_FN(DR1),
GPIO_FN(ETH_TXD1),
GPIO_FN(DR0),
GPIO_FN(ETH_TXD0),
GPIO_FN(VSYNC),
GPIO_FN(HSPI_CLK),
GPIO_FN(ODDF),
GPIO_FN(HSPI_CS),
GPIO_FN(DG5),
GPIO_FN(ETH_MDIO),
GPIO_FN(DG4),
GPIO_FN(ETH_RX_CLK),
GPIO_FN(DG3),
GPIO_FN(ETH_MDC),
GPIO_FN(DG2),
GPIO_FN(ETH_COL),
GPIO_FN(DG1),
GPIO_FN(ETH_TX_CLK),
GPIO_FN(DG0),
GPIO_FN(ETH_CRS),
GPIO_FN(DCLKIN),
GPIO_FN(HSPI_RX),
GPIO_FN(HSYNC),
GPIO_FN(HSPI_TX),
GPIO_FN(DB5),
GPIO_FN(ETH_RXD3),
GPIO_FN(DB4),
GPIO_FN(ETH_RXD2),
GPIO_FN(DB3),
GPIO_FN(ETH_RXD1),
GPIO_FN(DB2),
GPIO_FN(ETH_RXD0),
GPIO_FN(DB1),
GPIO_FN(ETH_RX_DV),
GPIO_FN(DB0),
GPIO_FN(ETH_RX_ER),
GPIO_FN(DCLKOUT),
GPIO_FN(SCIF1_SCK),
GPIO_FN(SCIF1_RXD),
GPIO_FN(SCIF1_TXD),
GPIO_FN(DACK1),
GPIO_FN(BACK),
GPIO_FN(FALE),
GPIO_FN(DACK0),
GPIO_FN(FCLE),
GPIO_FN(DREQ1),
GPIO_FN(BREQ),
GPIO_FN(USB_OVC1),
GPIO_FN(DREQ0),
GPIO_FN(USB_OVC0),
GPIO_FN(USB_PENC1),
GPIO_FN(USB_PENC0),
GPIO_FN(HAC1_SDOUT),
GPIO_FN(SSI1_SDATA),
GPIO_FN(SDIF1CMD),
GPIO_FN(HAC1_SDIN),
GPIO_FN(SSI1_SCK),
GPIO_FN(SDIF1CD),
GPIO_FN(HAC1_SYNC),
GPIO_FN(SSI1_WS),
GPIO_FN(SDIF1WP),
GPIO_FN(HAC1_BITCLK),
GPIO_FN(SSI1_CLK),
GPIO_FN(SDIF1CLK),
GPIO_FN(HAC0_SDOUT),
GPIO_FN(SSI0_SDATA),
GPIO_FN(SDIF1D3),
GPIO_FN(HAC0_SDIN),
GPIO_FN(SSI0_SCK),
GPIO_FN(SDIF1D2),
GPIO_FN(HAC0_SYNC),
GPIO_FN(SSI0_WS),
GPIO_FN(SDIF1D1),
GPIO_FN(HAC0_BITCLK),
GPIO_FN(SSI0_CLK),
GPIO_FN(SDIF1D0),
GPIO_FN(SCIF3_SCK),
GPIO_FN(SSI2_SDATA),
GPIO_FN(SCIF3_RXD),
GPIO_FN(TCLK),
GPIO_FN(SSI2_SCK),
GPIO_FN(SCIF3_TXD),
GPIO_FN(HAC_RES),
GPIO_FN(SSI2_WS),
GPIO_FN(DACK3),
GPIO_FN(SDIF0CMD),
GPIO_FN(DACK2),
GPIO_FN(SDIF0CD),
GPIO_FN(DREQ3),
GPIO_FN(SDIF0WP),
GPIO_FN(SCIF0_CTS),
GPIO_FN(DREQ2),
GPIO_FN(SDIF0CLK),
GPIO_FN(SCIF0_RTS),
GPIO_FN(IRL7),
GPIO_FN(SDIF0D3),
GPIO_FN(SCIF0_SCK),
GPIO_FN(IRL6),
GPIO_FN(SDIF0D2),
GPIO_FN(SCIF0_RXD),
GPIO_FN(IRL5),
GPIO_FN(SDIF0D1),
GPIO_FN(SCIF0_TXD),
GPIO_FN(IRL4),
GPIO_FN(SDIF0D0),
GPIO_FN(SCIF5_SCK),
GPIO_FN(FRB),
GPIO_FN(SCIF5_RXD),
GPIO_FN(IOIS16),
GPIO_FN(SCIF5_TXD),
GPIO_FN(CE2B),
GPIO_FN(DRAK3),
GPIO_FN(CE2A),
GPIO_FN(SCIF4_SCK),
GPIO_FN(DRAK2),
GPIO_FN(SSI3_WS),
GPIO_FN(SCIF4_RXD),
GPIO_FN(DRAK1),
GPIO_FN(SSI3_SDATA),
GPIO_FN(FSTATUS),
GPIO_FN(SCIF4_TXD),
GPIO_FN(DRAK0),
GPIO_FN(SSI3_SCK),
GPIO_FN(FSE),
};
static const struct pinmux_cfg_reg pinmux_config_regs[] = {
{ PINMUX_CFG_REG("PACR", 0xffcc0000, 16, 2) {
PA7_FN, PA7_OUT, PA7_IN, 0,
PA6_FN, PA6_OUT, PA6_IN, 0,
PA5_FN, PA5_OUT, PA5_IN, 0,
PA4_FN, PA4_OUT, PA4_IN, 0,
PA3_FN, PA3_OUT, PA3_IN, 0,
PA2_FN, PA2_OUT, PA2_IN, 0,
PA1_FN, PA1_OUT, PA1_IN, 0,
PA0_FN, PA0_OUT, PA0_IN, 0 }
},
{ PINMUX_CFG_REG("PBCR", 0xffcc0002, 16, 2) {
PB7_FN, PB7_OUT, PB7_IN, 0,
PB6_FN, PB6_OUT, PB6_IN, 0,
PB5_FN, PB5_OUT, PB5_IN, 0,
PB4_FN, PB4_OUT, PB4_IN, 0,
PB3_FN, PB3_OUT, PB3_IN, 0,
PB2_FN, PB2_OUT, PB2_IN, 0,
PB1_FN, PB1_OUT, PB1_IN, 0,
PB0_FN, PB0_OUT, PB0_IN, 0 }
},
{ PINMUX_CFG_REG("PCCR", 0xffcc0004, 16, 2) {
PC7_FN, PC7_OUT, PC7_IN, 0,
PC6_FN, PC6_OUT, PC6_IN, 0,
PC5_FN, PC5_OUT, PC5_IN, 0,
PC4_FN, PC4_OUT, PC4_IN, 0,
PC3_FN, PC3_OUT, PC3_IN, 0,
PC2_FN, PC2_OUT, PC2_IN, 0,
PC1_FN, PC1_OUT, PC1_IN, 0,
PC0_FN, PC0_OUT, PC0_IN, 0 }
},
{ PINMUX_CFG_REG("PDCR", 0xffcc0006, 16, 2) {
PD7_FN, PD7_OUT, PD7_IN, 0,
PD6_FN, PD6_OUT, PD6_IN, 0,
PD5_FN, PD5_OUT, PD5_IN, 0,
PD4_FN, PD4_OUT, PD4_IN, 0,
PD3_FN, PD3_OUT, PD3_IN, 0,
PD2_FN, PD2_OUT, PD2_IN, 0,
PD1_FN, PD1_OUT, PD1_IN, 0,
PD0_FN, PD0_OUT, PD0_IN, 0 }
},
{ PINMUX_CFG_REG("PECR", 0xffcc0008, 16, 2) {
PE7_FN, PE7_OUT, PE7_IN, 0,
PE6_FN, PE6_OUT, PE6_IN, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0, }
},
{ PINMUX_CFG_REG("PFCR", 0xffcc000a, 16, 2) {
PF7_FN, PF7_OUT, PF7_IN, 0,
PF6_FN, PF6_OUT, PF6_IN, 0,
PF5_FN, PF5_OUT, PF5_IN, 0,
PF4_FN, PF4_OUT, PF4_IN, 0,
PF3_FN, PF3_OUT, PF3_IN, 0,
PF2_FN, PF2_OUT, PF2_IN, 0,
PF1_FN, PF1_OUT, PF1_IN, 0,
PF0_FN, PF0_OUT, PF0_IN, 0 }
},
{ PINMUX_CFG_REG("PGCR", 0xffcc000c, 16, 2) {
PG7_FN, PG7_OUT, PG7_IN, 0,
PG6_FN, PG6_OUT, PG6_IN, 0,
PG5_FN, PG5_OUT, PG5_IN, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0, }
},
{ PINMUX_CFG_REG("PHCR", 0xffcc000e, 16, 2) {
PH7_FN, PH7_OUT, PH7_IN, 0,
PH6_FN, PH6_OUT, PH6_IN, 0,
PH5_FN, PH5_OUT, PH5_IN, 0,
PH4_FN, PH4_OUT, PH4_IN, 0,
PH3_FN, PH3_OUT, PH3_IN, 0,
PH2_FN, PH2_OUT, PH2_IN, 0,
PH1_FN, PH1_OUT, PH1_IN, 0,
PH0_FN, PH0_OUT, PH0_IN, 0 }
},
{ PINMUX_CFG_REG("PJCR", 0xffcc0010, 16, 2) {
PJ7_FN, PJ7_OUT, PJ7_IN, 0,
PJ6_FN, PJ6_OUT, PJ6_IN, 0,
PJ5_FN, PJ5_OUT, PJ5_IN, 0,
PJ4_FN, PJ4_OUT, PJ4_IN, 0,
PJ3_FN, PJ3_OUT, PJ3_IN, 0,
PJ2_FN, PJ2_OUT, PJ2_IN, 0,
PJ1_FN, PJ1_OUT, PJ1_IN, 0,
0, 0, 0, 0, }
},
{ PINMUX_CFG_REG("P1MSELR", 0xffcc0080, 16, 1) {
0, 0,
P1MSEL14_0, P1MSEL14_1,
P1MSEL13_0, P1MSEL13_1,
P1MSEL12_0, P1MSEL12_1,
P1MSEL11_0, P1MSEL11_1,
P1MSEL10_0, P1MSEL10_1,
P1MSEL9_0, P1MSEL9_1,
P1MSEL8_0, P1MSEL8_1,
P1MSEL7_0, P1MSEL7_1,
P1MSEL6_0, P1MSEL6_1,
P1MSEL5_0, P1MSEL5_1,
P1MSEL4_0, P1MSEL4_1,
P1MSEL3_0, P1MSEL3_1,
P1MSEL2_0, P1MSEL2_1,
P1MSEL1_0, P1MSEL1_1,
P1MSEL0_0, P1MSEL0_1 }
},
{ PINMUX_CFG_REG("P2MSELR", 0xffcc0082, 16, 1) {
P2MSEL15_0, P2MSEL15_1,
P2MSEL14_0, P2MSEL14_1,
P2MSEL13_0, P2MSEL13_1,
P2MSEL12_0, P2MSEL12_1,
P2MSEL11_0, P2MSEL11_1,
P2MSEL10_0, P2MSEL10_1,
P2MSEL9_0, P2MSEL9_1,
P2MSEL8_0, P2MSEL8_1,
P2MSEL7_0, P2MSEL7_1,
P2MSEL6_0, P2MSEL6_1,
P2MSEL5_0, P2MSEL5_1,
P2MSEL4_0, P2MSEL4_1,
P2MSEL3_0, P2MSEL3_1,
P2MSEL2_0, P2MSEL2_1,
P2MSEL1_0, P2MSEL1_1,
P2MSEL0_0, P2MSEL0_1 }
},
{}
};
static const struct pinmux_data_reg pinmux_data_regs[] = {
{ PINMUX_DATA_REG("PADR", 0xffcc0020, 8) {
PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA }
},
{ PINMUX_DATA_REG("PBDR", 0xffcc0022, 8) {
PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA }
},
{ PINMUX_DATA_REG("PCDR", 0xffcc0024, 8) {
PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA }
},
{ PINMUX_DATA_REG("PDDR", 0xffcc0026, 8) {
PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA }
},
{ PINMUX_DATA_REG("PEDR", 0xffcc0028, 8) {
PE7_DATA, PE6_DATA,
0, 0, 0, 0, 0, 0 }
},
{ PINMUX_DATA_REG("PFDR", 0xffcc002a, 8) {
PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA }
},
{ PINMUX_DATA_REG("PGDR", 0xffcc002c, 8) {
PG7_DATA, PG6_DATA, PG5_DATA, 0,
0, 0, 0, 0 }
},
{ PINMUX_DATA_REG("PHDR", 0xffcc002e, 8) {
PH7_DATA, PH6_DATA, PH5_DATA, PH4_DATA,
PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA }
},
{ PINMUX_DATA_REG("PJDR", 0xffcc0030, 8) {
PJ7_DATA, PJ6_DATA, PJ5_DATA, PJ4_DATA,
PJ3_DATA, PJ2_DATA, PJ1_DATA, 0 }
},
{ },
};
const struct sh_pfc_soc_info sh7786_pinmux_info = {
.name = "sh7786_pfc",
.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
.pins = pinmux_pins,
.nr_pins = ARRAY_SIZE(pinmux_pins),
.func_gpios = pinmux_func_gpios,
.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
.gpio_data = pinmux_data,
.gpio_data_size = ARRAY_SIZE(pinmux_data),
};

View file

@ -0,0 +1,561 @@
/*
* SH-X3 prototype CPU pinmux
*
* Copyright (C) 2010 Paul Mundt
*
* 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.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <cpu/shx3.h>
#include "sh_pfc.h"
enum {
PINMUX_RESERVED = 0,
PINMUX_DATA_BEGIN,
PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA,
PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA,
PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA,
PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA,
PH5_DATA, PH4_DATA,
PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA,
PINMUX_DATA_END,
PINMUX_INPUT_BEGIN,
PA7_IN, PA6_IN, PA5_IN, PA4_IN,
PA3_IN, PA2_IN, PA1_IN, PA0_IN,
PB7_IN, PB6_IN, PB5_IN, PB4_IN,
PB3_IN, PB2_IN, PB1_IN, PB0_IN,
PC7_IN, PC6_IN, PC5_IN, PC4_IN,
PC3_IN, PC2_IN, PC1_IN, PC0_IN,
PD7_IN, PD6_IN, PD5_IN, PD4_IN,
PD3_IN, PD2_IN, PD1_IN, PD0_IN,
PE7_IN, PE6_IN, PE5_IN, PE4_IN,
PE3_IN, PE2_IN, PE1_IN, PE0_IN,
PF7_IN, PF6_IN, PF5_IN, PF4_IN,
PF3_IN, PF2_IN, PF1_IN, PF0_IN,
PG7_IN, PG6_IN, PG5_IN, PG4_IN,
PG3_IN, PG2_IN, PG1_IN, PG0_IN,
PH5_IN, PH4_IN,
PH3_IN, PH2_IN, PH1_IN, PH0_IN,
PINMUX_INPUT_END,
PINMUX_OUTPUT_BEGIN,
PA7_OUT, PA6_OUT, PA5_OUT, PA4_OUT,
PA3_OUT, PA2_OUT, PA1_OUT, PA0_OUT,
PB7_OUT, PB6_OUT, PB5_OUT, PB4_OUT,
PB3_OUT, PB2_OUT, PB1_OUT, PB0_OUT,
PC7_OUT, PC6_OUT, PC5_OUT, PC4_OUT,
PC3_OUT, PC2_OUT, PC1_OUT, PC0_OUT,
PD7_OUT, PD6_OUT, PD5_OUT, PD4_OUT,
PD3_OUT, PD2_OUT, PD1_OUT, PD0_OUT,
PE7_OUT, PE6_OUT, PE5_OUT, PE4_OUT,
PE3_OUT, PE2_OUT, PE1_OUT, PE0_OUT,
PF7_OUT, PF6_OUT, PF5_OUT, PF4_OUT,
PF3_OUT, PF2_OUT, PF1_OUT, PF0_OUT,
PG7_OUT, PG6_OUT, PG5_OUT, PG4_OUT,
PG3_OUT, PG2_OUT, PG1_OUT, PG0_OUT,
PH5_OUT, PH4_OUT,
PH3_OUT, PH2_OUT, PH1_OUT, PH0_OUT,
PINMUX_OUTPUT_END,
PINMUX_FUNCTION_BEGIN,
PA7_FN, PA6_FN, PA5_FN, PA4_FN,
PA3_FN, PA2_FN, PA1_FN, PA0_FN,
PB7_FN, PB6_FN, PB5_FN, PB4_FN,
PB3_FN, PB2_FN, PB1_FN, PB0_FN,
PC7_FN, PC6_FN, PC5_FN, PC4_FN,
PC3_FN, PC2_FN, PC1_FN, PC0_FN,
PD7_FN, PD6_FN, PD5_FN, PD4_FN,
PD3_FN, PD2_FN, PD1_FN, PD0_FN,
PE7_FN, PE6_FN, PE5_FN, PE4_FN,
PE3_FN, PE2_FN, PE1_FN, PE0_FN,
PF7_FN, PF6_FN, PF5_FN, PF4_FN,
PF3_FN, PF2_FN, PF1_FN, PF0_FN,
PG7_FN, PG6_FN, PG5_FN, PG4_FN,
PG3_FN, PG2_FN, PG1_FN, PG0_FN,
PH5_FN, PH4_FN,
PH3_FN, PH2_FN, PH1_FN, PH0_FN,
PINMUX_FUNCTION_END,
PINMUX_MARK_BEGIN,
D31_MARK, D30_MARK, D29_MARK, D28_MARK, D27_MARK, D26_MARK,
D25_MARK, D24_MARK, D23_MARK, D22_MARK, D21_MARK, D20_MARK,
D19_MARK, D18_MARK, D17_MARK, D16_MARK,
BACK_MARK, BREQ_MARK,
WE3_MARK, WE2_MARK,
CS6_MARK, CS5_MARK, CS4_MARK,
CLKOUTENB_MARK,
DACK3_MARK, DACK2_MARK, DACK1_MARK, DACK0_MARK,
DREQ3_MARK, DREQ2_MARK, DREQ1_MARK, DREQ0_MARK,
IRQ3_MARK, IRQ2_MARK, IRQ1_MARK, IRQ0_MARK,
DRAK3_MARK, DRAK2_MARK, DRAK1_MARK, DRAK0_MARK,
SCK3_MARK, SCK2_MARK, SCK1_MARK, SCK0_MARK,
IRL3_MARK, IRL2_MARK, IRL1_MARK, IRL0_MARK,
TXD3_MARK, TXD2_MARK, TXD1_MARK, TXD0_MARK,
RXD3_MARK, RXD2_MARK, RXD1_MARK, RXD0_MARK,
CE2B_MARK, CE2A_MARK, IOIS16_MARK,
STATUS1_MARK, STATUS0_MARK,
IRQOUT_MARK,
PINMUX_MARK_END,
};
static const u16 pinmux_data[] = {
/* PA GPIO */
PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT),
PINMUX_DATA(PA6_DATA, PA6_IN, PA6_OUT),
PINMUX_DATA(PA5_DATA, PA5_IN, PA5_OUT),
PINMUX_DATA(PA4_DATA, PA4_IN, PA4_OUT),
PINMUX_DATA(PA3_DATA, PA3_IN, PA3_OUT),
PINMUX_DATA(PA2_DATA, PA2_IN, PA2_OUT),
PINMUX_DATA(PA1_DATA, PA1_IN, PA1_OUT),
PINMUX_DATA(PA0_DATA, PA0_IN, PA0_OUT),
/* PB GPIO */
PINMUX_DATA(PB7_DATA, PB7_IN, PB7_OUT),
PINMUX_DATA(PB6_DATA, PB6_IN, PB6_OUT),
PINMUX_DATA(PB5_DATA, PB5_IN, PB5_OUT),
PINMUX_DATA(PB4_DATA, PB4_IN, PB4_OUT),
PINMUX_DATA(PB3_DATA, PB3_IN, PB3_OUT),
PINMUX_DATA(PB2_DATA, PB2_IN, PB2_OUT),
PINMUX_DATA(PB1_DATA, PB1_IN, PB1_OUT),
PINMUX_DATA(PB0_DATA, PB0_IN, PB0_OUT),
/* PC GPIO */
PINMUX_DATA(PC7_DATA, PC7_IN, PC7_OUT),
PINMUX_DATA(PC6_DATA, PC6_IN, PC6_OUT),
PINMUX_DATA(PC5_DATA, PC5_IN, PC5_OUT),
PINMUX_DATA(PC4_DATA, PC4_IN, PC4_OUT),
PINMUX_DATA(PC3_DATA, PC3_IN, PC3_OUT),
PINMUX_DATA(PC2_DATA, PC2_IN, PC2_OUT),
PINMUX_DATA(PC1_DATA, PC1_IN, PC1_OUT),
PINMUX_DATA(PC0_DATA, PC0_IN, PC0_OUT),
/* PD GPIO */
PINMUX_DATA(PD7_DATA, PD7_IN, PD7_OUT),
PINMUX_DATA(PD6_DATA, PD6_IN, PD6_OUT),
PINMUX_DATA(PD5_DATA, PD5_IN, PD5_OUT),
PINMUX_DATA(PD4_DATA, PD4_IN, PD4_OUT),
PINMUX_DATA(PD3_DATA, PD3_IN, PD3_OUT),
PINMUX_DATA(PD2_DATA, PD2_IN, PD2_OUT),
PINMUX_DATA(PD1_DATA, PD1_IN, PD1_OUT),
PINMUX_DATA(PD0_DATA, PD0_IN, PD0_OUT),
/* PE GPIO */
PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT),
PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT),
PINMUX_DATA(PE5_DATA, PE5_IN, PE5_OUT),
PINMUX_DATA(PE4_DATA, PE4_IN, PE4_OUT),
PINMUX_DATA(PE3_DATA, PE3_IN, PE3_OUT),
PINMUX_DATA(PE2_DATA, PE2_IN, PE2_OUT),
PINMUX_DATA(PE1_DATA, PE1_IN, PE1_OUT),
PINMUX_DATA(PE0_DATA, PE0_IN, PE0_OUT),
/* PF GPIO */
PINMUX_DATA(PF7_DATA, PF7_IN, PF7_OUT),
PINMUX_DATA(PF6_DATA, PF6_IN, PF6_OUT),
PINMUX_DATA(PF5_DATA, PF5_IN, PF5_OUT),
PINMUX_DATA(PF4_DATA, PF4_IN, PF4_OUT),
PINMUX_DATA(PF3_DATA, PF3_IN, PF3_OUT),
PINMUX_DATA(PF2_DATA, PF2_IN, PF2_OUT),
PINMUX_DATA(PF1_DATA, PF1_IN, PF1_OUT),
PINMUX_DATA(PF0_DATA, PF0_IN, PF0_OUT),
/* PG GPIO */
PINMUX_DATA(PG7_DATA, PG7_IN, PG7_OUT),
PINMUX_DATA(PG6_DATA, PG6_IN, PG6_OUT),
PINMUX_DATA(PG5_DATA, PG5_IN, PG5_OUT),
PINMUX_DATA(PG4_DATA, PG4_IN, PG4_OUT),
PINMUX_DATA(PG3_DATA, PG3_IN, PG3_OUT),
PINMUX_DATA(PG2_DATA, PG2_IN, PG2_OUT),
PINMUX_DATA(PG1_DATA, PG1_IN, PG1_OUT),
PINMUX_DATA(PG0_DATA, PG0_IN, PG0_OUT),
/* PH GPIO */
PINMUX_DATA(PH5_DATA, PH5_IN, PH5_OUT),
PINMUX_DATA(PH4_DATA, PH4_IN, PH4_OUT),
PINMUX_DATA(PH3_DATA, PH3_IN, PH3_OUT),
PINMUX_DATA(PH2_DATA, PH2_IN, PH2_OUT),
PINMUX_DATA(PH1_DATA, PH1_IN, PH1_OUT),
PINMUX_DATA(PH0_DATA, PH0_IN, PH0_OUT),
/* PA FN */
PINMUX_DATA(D31_MARK, PA7_FN),
PINMUX_DATA(D30_MARK, PA6_FN),
PINMUX_DATA(D29_MARK, PA5_FN),
PINMUX_DATA(D28_MARK, PA4_FN),
PINMUX_DATA(D27_MARK, PA3_FN),
PINMUX_DATA(D26_MARK, PA2_FN),
PINMUX_DATA(D25_MARK, PA1_FN),
PINMUX_DATA(D24_MARK, PA0_FN),
/* PB FN */
PINMUX_DATA(D23_MARK, PB7_FN),
PINMUX_DATA(D22_MARK, PB6_FN),
PINMUX_DATA(D21_MARK, PB5_FN),
PINMUX_DATA(D20_MARK, PB4_FN),
PINMUX_DATA(D19_MARK, PB3_FN),
PINMUX_DATA(D18_MARK, PB2_FN),
PINMUX_DATA(D17_MARK, PB1_FN),
PINMUX_DATA(D16_MARK, PB0_FN),
/* PC FN */
PINMUX_DATA(BACK_MARK, PC7_FN),
PINMUX_DATA(BREQ_MARK, PC6_FN),
PINMUX_DATA(WE3_MARK, PC5_FN),
PINMUX_DATA(WE2_MARK, PC4_FN),
PINMUX_DATA(CS6_MARK, PC3_FN),
PINMUX_DATA(CS5_MARK, PC2_FN),
PINMUX_DATA(CS4_MARK, PC1_FN),
PINMUX_DATA(CLKOUTENB_MARK, PC0_FN),
/* PD FN */
PINMUX_DATA(DACK3_MARK, PD7_FN),
PINMUX_DATA(DACK2_MARK, PD6_FN),
PINMUX_DATA(DACK1_MARK, PD5_FN),
PINMUX_DATA(DACK0_MARK, PD4_FN),
PINMUX_DATA(DREQ3_MARK, PD3_FN),
PINMUX_DATA(DREQ2_MARK, PD2_FN),
PINMUX_DATA(DREQ1_MARK, PD1_FN),
PINMUX_DATA(DREQ0_MARK, PD0_FN),
/* PE FN */
PINMUX_DATA(IRQ3_MARK, PE7_FN),
PINMUX_DATA(IRQ2_MARK, PE6_FN),
PINMUX_DATA(IRQ1_MARK, PE5_FN),
PINMUX_DATA(IRQ0_MARK, PE4_FN),
PINMUX_DATA(DRAK3_MARK, PE3_FN),
PINMUX_DATA(DRAK2_MARK, PE2_FN),
PINMUX_DATA(DRAK1_MARK, PE1_FN),
PINMUX_DATA(DRAK0_MARK, PE0_FN),
/* PF FN */
PINMUX_DATA(SCK3_MARK, PF7_FN),
PINMUX_DATA(SCK2_MARK, PF6_FN),
PINMUX_DATA(SCK1_MARK, PF5_FN),
PINMUX_DATA(SCK0_MARK, PF4_FN),
PINMUX_DATA(IRL3_MARK, PF3_FN),
PINMUX_DATA(IRL2_MARK, PF2_FN),
PINMUX_DATA(IRL1_MARK, PF1_FN),
PINMUX_DATA(IRL0_MARK, PF0_FN),
/* PG FN */
PINMUX_DATA(TXD3_MARK, PG7_FN),
PINMUX_DATA(TXD2_MARK, PG6_FN),
PINMUX_DATA(TXD1_MARK, PG5_FN),
PINMUX_DATA(TXD0_MARK, PG4_FN),
PINMUX_DATA(RXD3_MARK, PG3_FN),
PINMUX_DATA(RXD2_MARK, PG2_FN),
PINMUX_DATA(RXD1_MARK, PG1_FN),
PINMUX_DATA(RXD0_MARK, PG0_FN),
/* PH FN */
PINMUX_DATA(CE2B_MARK, PH5_FN),
PINMUX_DATA(CE2A_MARK, PH4_FN),
PINMUX_DATA(IOIS16_MARK, PH3_FN),
PINMUX_DATA(STATUS1_MARK, PH2_FN),
PINMUX_DATA(STATUS0_MARK, PH1_FN),
PINMUX_DATA(IRQOUT_MARK, PH0_FN),
};
static const struct sh_pfc_pin pinmux_pins[] = {
/* PA */
PINMUX_GPIO(PA7),
PINMUX_GPIO(PA6),
PINMUX_GPIO(PA5),
PINMUX_GPIO(PA4),
PINMUX_GPIO(PA3),
PINMUX_GPIO(PA2),
PINMUX_GPIO(PA1),
PINMUX_GPIO(PA0),
/* PB */
PINMUX_GPIO(PB7),
PINMUX_GPIO(PB6),
PINMUX_GPIO(PB5),
PINMUX_GPIO(PB4),
PINMUX_GPIO(PB3),
PINMUX_GPIO(PB2),
PINMUX_GPIO(PB1),
PINMUX_GPIO(PB0),
/* PC */
PINMUX_GPIO(PC7),
PINMUX_GPIO(PC6),
PINMUX_GPIO(PC5),
PINMUX_GPIO(PC4),
PINMUX_GPIO(PC3),
PINMUX_GPIO(PC2),
PINMUX_GPIO(PC1),
PINMUX_GPIO(PC0),
/* PD */
PINMUX_GPIO(PD7),
PINMUX_GPIO(PD6),
PINMUX_GPIO(PD5),
PINMUX_GPIO(PD4),
PINMUX_GPIO(PD3),
PINMUX_GPIO(PD2),
PINMUX_GPIO(PD1),
PINMUX_GPIO(PD0),
/* PE */
PINMUX_GPIO(PE7),
PINMUX_GPIO(PE6),
PINMUX_GPIO(PE5),
PINMUX_GPIO(PE4),
PINMUX_GPIO(PE3),
PINMUX_GPIO(PE2),
PINMUX_GPIO(PE1),
PINMUX_GPIO(PE0),
/* PF */
PINMUX_GPIO(PF7),
PINMUX_GPIO(PF6),
PINMUX_GPIO(PF5),
PINMUX_GPIO(PF4),
PINMUX_GPIO(PF3),
PINMUX_GPIO(PF2),
PINMUX_GPIO(PF1),
PINMUX_GPIO(PF0),
/* PG */
PINMUX_GPIO(PG7),
PINMUX_GPIO(PG6),
PINMUX_GPIO(PG5),
PINMUX_GPIO(PG4),
PINMUX_GPIO(PG3),
PINMUX_GPIO(PG2),
PINMUX_GPIO(PG1),
PINMUX_GPIO(PG0),
/* PH */
PINMUX_GPIO(PH5),
PINMUX_GPIO(PH4),
PINMUX_GPIO(PH3),
PINMUX_GPIO(PH2),
PINMUX_GPIO(PH1),
PINMUX_GPIO(PH0),
};
#define PINMUX_FN_BASE ARRAY_SIZE(pinmux_pins)
static const struct pinmux_func pinmux_func_gpios[] = {
/* FN */
GPIO_FN(D31),
GPIO_FN(D30),
GPIO_FN(D29),
GPIO_FN(D28),
GPIO_FN(D27),
GPIO_FN(D26),
GPIO_FN(D25),
GPIO_FN(D24),
GPIO_FN(D23),
GPIO_FN(D22),
GPIO_FN(D21),
GPIO_FN(D20),
GPIO_FN(D19),
GPIO_FN(D18),
GPIO_FN(D17),
GPIO_FN(D16),
GPIO_FN(BACK),
GPIO_FN(BREQ),
GPIO_FN(WE3),
GPIO_FN(WE2),
GPIO_FN(CS6),
GPIO_FN(CS5),
GPIO_FN(CS4),
GPIO_FN(CLKOUTENB),
GPIO_FN(DACK3),
GPIO_FN(DACK2),
GPIO_FN(DACK1),
GPIO_FN(DACK0),
GPIO_FN(DREQ3),
GPIO_FN(DREQ2),
GPIO_FN(DREQ1),
GPIO_FN(DREQ0),
GPIO_FN(IRQ3),
GPIO_FN(IRQ2),
GPIO_FN(IRQ1),
GPIO_FN(IRQ0),
GPIO_FN(DRAK3),
GPIO_FN(DRAK2),
GPIO_FN(DRAK1),
GPIO_FN(DRAK0),
GPIO_FN(SCK3),
GPIO_FN(SCK2),
GPIO_FN(SCK1),
GPIO_FN(SCK0),
GPIO_FN(IRL3),
GPIO_FN(IRL2),
GPIO_FN(IRL1),
GPIO_FN(IRL0),
GPIO_FN(TXD3),
GPIO_FN(TXD2),
GPIO_FN(TXD1),
GPIO_FN(TXD0),
GPIO_FN(RXD3),
GPIO_FN(RXD2),
GPIO_FN(RXD1),
GPIO_FN(RXD0),
GPIO_FN(CE2B),
GPIO_FN(CE2A),
GPIO_FN(IOIS16),
GPIO_FN(STATUS1),
GPIO_FN(STATUS0),
GPIO_FN(IRQOUT),
};
static const struct pinmux_cfg_reg pinmux_config_regs[] = {
{ PINMUX_CFG_REG("PABCR", 0xffc70000, 32, 2) {
PA7_FN, PA7_OUT, PA7_IN, 0,
PA6_FN, PA6_OUT, PA6_IN, 0,
PA5_FN, PA5_OUT, PA5_IN, 0,
PA4_FN, PA4_OUT, PA4_IN, 0,
PA3_FN, PA3_OUT, PA3_IN, 0,
PA2_FN, PA2_OUT, PA2_IN, 0,
PA1_FN, PA1_OUT, PA1_IN, 0,
PA0_FN, PA0_OUT, PA0_IN, 0,
PB7_FN, PB7_OUT, PB7_IN, 0,
PB6_FN, PB6_OUT, PB6_IN, 0,
PB5_FN, PB5_OUT, PB5_IN, 0,
PB4_FN, PB4_OUT, PB4_IN, 0,
PB3_FN, PB3_OUT, PB3_IN, 0,
PB2_FN, PB2_OUT, PB2_IN, 0,
PB1_FN, PB1_OUT, PB1_IN, 0,
PB0_FN, PB0_OUT, PB0_IN, 0, },
},
{ PINMUX_CFG_REG("PCDCR", 0xffc70004, 32, 2) {
PC7_FN, PC7_OUT, PC7_IN, 0,
PC6_FN, PC6_OUT, PC6_IN, 0,
PC5_FN, PC5_OUT, PC5_IN, 0,
PC4_FN, PC4_OUT, PC4_IN, 0,
PC3_FN, PC3_OUT, PC3_IN, 0,
PC2_FN, PC2_OUT, PC2_IN, 0,
PC1_FN, PC1_OUT, PC1_IN, 0,
PC0_FN, PC0_OUT, PC0_IN, 0,
PD7_FN, PD7_OUT, PD7_IN, 0,
PD6_FN, PD6_OUT, PD6_IN, 0,
PD5_FN, PD5_OUT, PD5_IN, 0,
PD4_FN, PD4_OUT, PD4_IN, 0,
PD3_FN, PD3_OUT, PD3_IN, 0,
PD2_FN, PD2_OUT, PD2_IN, 0,
PD1_FN, PD1_OUT, PD1_IN, 0,
PD0_FN, PD0_OUT, PD0_IN, 0, },
},
{ PINMUX_CFG_REG("PEFCR", 0xffc70008, 32, 2) {
PE7_FN, PE7_OUT, PE7_IN, 0,
PE6_FN, PE6_OUT, PE6_IN, 0,
PE5_FN, PE5_OUT, PE5_IN, 0,
PE4_FN, PE4_OUT, PE4_IN, 0,
PE3_FN, PE3_OUT, PE3_IN, 0,
PE2_FN, PE2_OUT, PE2_IN, 0,
PE1_FN, PE1_OUT, PE1_IN, 0,
PE0_FN, PE0_OUT, PE0_IN, 0,
PF7_FN, PF7_OUT, PF7_IN, 0,
PF6_FN, PF6_OUT, PF6_IN, 0,
PF5_FN, PF5_OUT, PF5_IN, 0,
PF4_FN, PF4_OUT, PF4_IN, 0,
PF3_FN, PF3_OUT, PF3_IN, 0,
PF2_FN, PF2_OUT, PF2_IN, 0,
PF1_FN, PF1_OUT, PF1_IN, 0,
PF0_FN, PF0_OUT, PF0_IN, 0, },
},
{ PINMUX_CFG_REG("PGHCR", 0xffc7000c, 32, 2) {
PG7_FN, PG7_OUT, PG7_IN, 0,
PG6_FN, PG6_OUT, PG6_IN, 0,
PG5_FN, PG5_OUT, PG5_IN, 0,
PG4_FN, PG4_OUT, PG4_IN, 0,
PG3_FN, PG3_OUT, PG3_IN, 0,
PG2_FN, PG2_OUT, PG2_IN, 0,
PG1_FN, PG1_OUT, PG1_IN, 0,
PG0_FN, PG0_OUT, PG0_IN, 0,
0, 0, 0, 0,
0, 0, 0, 0,
PH5_FN, PH5_OUT, PH5_IN, 0,
PH4_FN, PH4_OUT, PH4_IN, 0,
PH3_FN, PH3_OUT, PH3_IN, 0,
PH2_FN, PH2_OUT, PH2_IN, 0,
PH1_FN, PH1_OUT, PH1_IN, 0,
PH0_FN, PH0_OUT, PH0_IN, 0, },
},
{ },
};
static const struct pinmux_data_reg pinmux_data_regs[] = {
{ PINMUX_DATA_REG("PABDR", 0xffc70010, 32) {
0, 0, 0, 0, 0, 0, 0, 0,
PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
0, 0, 0, 0, 0, 0, 0, 0,
PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA, },
},
{ PINMUX_DATA_REG("PCDDR", 0xffc70014, 32) {
0, 0, 0, 0, 0, 0, 0, 0,
PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
0, 0, 0, 0, 0, 0, 0, 0,
PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA, },
},
{ PINMUX_DATA_REG("PEFDR", 0xffc70018, 32) {
0, 0, 0, 0, 0, 0, 0, 0,
PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
0, 0, 0, 0, 0, 0, 0, 0,
PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA, },
},
{ PINMUX_DATA_REG("PGHDR", 0xffc7001c, 32) {
0, 0, 0, 0, 0, 0, 0, 0,
PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, PH5_DATA, PH4_DATA,
PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA, },
},
{ },
};
const struct sh_pfc_soc_info shx3_pinmux_info = {
.name = "shx3_pfc",
.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
.pins = pinmux_pins,
.nr_pins = ARRAY_SIZE(pinmux_pins),
.func_gpios = pinmux_func_gpios,
.nr_func_gpios = ARRAY_SIZE(pinmux_func_gpios),
.gpio_data = pinmux_data,
.gpio_data_size = ARRAY_SIZE(pinmux_data),
.cfg_regs = pinmux_config_regs,
.data_regs = pinmux_data_regs,
};

View file

@ -0,0 +1,642 @@
/*
* SuperH Pin Function Controller pinmux support.
*
* Copyright (C) 2012 Paul Mundt
*
* 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.
*/
#define DRV_NAME "sh-pfc"
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include "core.h"
#include "../core.h"
#include "../pinconf.h"
struct sh_pfc_pin_config {
u32 type;
};
struct sh_pfc_pinctrl {
struct pinctrl_dev *pctl;
struct pinctrl_desc pctl_desc;
struct sh_pfc *pfc;
struct pinctrl_pin_desc *pins;
struct sh_pfc_pin_config *configs;
};
static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
return pmx->pfc->info->nr_groups;
}
static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
return pmx->pfc->info->groups[selector].name;
}
static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
const unsigned **pins, unsigned *num_pins)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
*pins = pmx->pfc->info->groups[selector].pins;
*num_pins = pmx->pfc->info->groups[selector].nr_pins;
return 0;
}
static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset)
{
seq_printf(s, "%s", DRV_NAME);
}
#ifdef CONFIG_OF
static int sh_pfc_map_add_config(struct pinctrl_map *map,
const char *group_or_pin,
enum pinctrl_map_type type,
unsigned long *configs,
unsigned int num_configs)
{
unsigned long *cfgs;
cfgs = kmemdup(configs, num_configs * sizeof(*cfgs),
GFP_KERNEL);
if (cfgs == NULL)
return -ENOMEM;
map->type = type;
map->data.configs.group_or_pin = group_or_pin;
map->data.configs.configs = cfgs;
map->data.configs.num_configs = num_configs;
return 0;
}
static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
struct pinctrl_map **map,
unsigned int *num_maps, unsigned int *index)
{
struct pinctrl_map *maps = *map;
unsigned int nmaps = *num_maps;
unsigned int idx = *index;
unsigned int num_configs;
const char *function = NULL;
unsigned long *configs;
struct property *prop;
unsigned int num_groups;
unsigned int num_pins;
const char *group;
const char *pin;
int ret;
/* Parse the function and configuration properties. At least a function
* or one configuration must be specified.
*/
ret = of_property_read_string(np, "renesas,function", &function);
if (ret < 0 && ret != -EINVAL) {
dev_err(dev, "Invalid function in DT\n");
return ret;
}
ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
if (ret < 0)
return ret;
if (!function && num_configs == 0) {
dev_err(dev,
"DT node must contain at least a function or config\n");
goto done;
}
/* Count the number of pins and groups and reallocate mappings. */
ret = of_property_count_strings(np, "renesas,pins");
if (ret == -EINVAL) {
num_pins = 0;
} else if (ret < 0) {
dev_err(dev, "Invalid pins list in DT\n");
goto done;
} else {
num_pins = ret;
}
ret = of_property_count_strings(np, "renesas,groups");
if (ret == -EINVAL) {
num_groups = 0;
} else if (ret < 0) {
dev_err(dev, "Invalid pin groups list in DT\n");
goto done;
} else {
num_groups = ret;
}
if (!num_pins && !num_groups) {
dev_err(dev, "No pin or group provided in DT node\n");
ret = -ENODEV;
goto done;
}
if (function)
nmaps += num_groups;
if (configs)
nmaps += num_pins + num_groups;
maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL);
if (maps == NULL) {
ret = -ENOMEM;
goto done;
}
*map = maps;
*num_maps = nmaps;
/* Iterate over pins and groups and create the mappings. */
of_property_for_each_string(np, "renesas,groups", prop, group) {
if (function) {
maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
maps[idx].data.mux.group = group;
maps[idx].data.mux.function = function;
idx++;
}
if (configs) {
ret = sh_pfc_map_add_config(&maps[idx], group,
PIN_MAP_TYPE_CONFIGS_GROUP,
configs, num_configs);
if (ret < 0)
goto done;
idx++;
}
}
if (!configs) {
ret = 0;
goto done;
}
of_property_for_each_string(np, "renesas,pins", prop, pin) {
ret = sh_pfc_map_add_config(&maps[idx], pin,
PIN_MAP_TYPE_CONFIGS_PIN,
configs, num_configs);
if (ret < 0)
goto done;
idx++;
}
done:
*index = idx;
kfree(configs);
return ret;
}
static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
unsigned int i;
if (map == NULL)
return;
for (i = 0; i < num_maps; ++i) {
if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP ||
map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
kfree(map[i].data.configs.configs);
}
kfree(map);
}
static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map, unsigned *num_maps)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
struct device *dev = pmx->pfc->dev;
struct device_node *child;
unsigned int index;
int ret;
*map = NULL;
*num_maps = 0;
index = 0;
for_each_child_of_node(np, child) {
ret = sh_pfc_dt_subnode_to_map(dev, child, map, num_maps,
&index);
if (ret < 0)
goto done;
}
/* If no mapping has been found in child nodes try the config node. */
if (*num_maps == 0) {
ret = sh_pfc_dt_subnode_to_map(dev, np, map, num_maps, &index);
if (ret < 0)
goto done;
}
if (*num_maps)
return 0;
dev_err(dev, "no mapping found in node %s\n", np->full_name);
ret = -EINVAL;
done:
if (ret < 0)
sh_pfc_dt_free_map(pctldev, *map, *num_maps);
return ret;
}
#endif /* CONFIG_OF */
static const struct pinctrl_ops sh_pfc_pinctrl_ops = {
.get_groups_count = sh_pfc_get_groups_count,
.get_group_name = sh_pfc_get_group_name,
.get_group_pins = sh_pfc_get_group_pins,
.pin_dbg_show = sh_pfc_pin_dbg_show,
#ifdef CONFIG_OF
.dt_node_to_map = sh_pfc_dt_node_to_map,
.dt_free_map = sh_pfc_dt_free_map,
#endif
};
static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
return pmx->pfc->info->nr_functions;
}
static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
return pmx->pfc->info->functions[selector].name;
}
static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev,
unsigned selector,
const char * const **groups,
unsigned * const num_groups)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
*groups = pmx->pfc->info->functions[selector].groups;
*num_groups = pmx->pfc->info->functions[selector].nr_groups;
return 0;
}
static int sh_pfc_func_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
struct sh_pfc *pfc = pmx->pfc;
const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
unsigned long flags;
unsigned int i;
int ret = 0;
spin_lock_irqsave(&pfc->lock, flags);
for (i = 0; i < grp->nr_pins; ++i) {
int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]);
struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
if (cfg->type != PINMUX_TYPE_NONE) {
ret = -EBUSY;
goto done;
}
}
for (i = 0; i < grp->nr_pins; ++i) {
ret = sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION);
if (ret < 0)
break;
}
done:
spin_unlock_irqrestore(&pfc->lock, flags);
return ret;
}
static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
struct sh_pfc *pfc = pmx->pfc;
int idx = sh_pfc_get_pin_index(pfc, offset);
struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
unsigned long flags;
int ret;
spin_lock_irqsave(&pfc->lock, flags);
if (cfg->type != PINMUX_TYPE_NONE) {
dev_err(pfc->dev,
"Pin %u is busy, can't configure it as GPIO.\n",
offset);
ret = -EBUSY;
goto done;
}
if (!pfc->gpio) {
/* If GPIOs are handled externally the pin mux type need to be
* set to GPIO here.
*/
const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
ret = sh_pfc_config_mux(pfc, pin->enum_id, PINMUX_TYPE_GPIO);
if (ret < 0)
goto done;
}
cfg->type = PINMUX_TYPE_GPIO;
ret = 0;
done:
spin_unlock_irqrestore(&pfc->lock, flags);
return ret;
}
static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
struct sh_pfc *pfc = pmx->pfc;
int idx = sh_pfc_get_pin_index(pfc, offset);
struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
unsigned long flags;
spin_lock_irqsave(&pfc->lock, flags);
cfg->type = PINMUX_TYPE_NONE;
spin_unlock_irqrestore(&pfc->lock, flags);
}
static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset, bool input)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
struct sh_pfc *pfc = pmx->pfc;
int new_type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT;
int idx = sh_pfc_get_pin_index(pfc, offset);
const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
unsigned long flags;
unsigned int dir;
int ret;
/* Check if the requested direction is supported by the pin. Not all SoC
* provide pin config data, so perform the check conditionally.
*/
if (pin->configs) {
dir = input ? SH_PFC_PIN_CFG_INPUT : SH_PFC_PIN_CFG_OUTPUT;
if (!(pin->configs & dir))
return -EINVAL;
}
spin_lock_irqsave(&pfc->lock, flags);
ret = sh_pfc_config_mux(pfc, pin->enum_id, new_type);
if (ret < 0)
goto done;
cfg->type = new_type;
done:
spin_unlock_irqrestore(&pfc->lock, flags);
return ret;
}
static const struct pinmux_ops sh_pfc_pinmux_ops = {
.get_functions_count = sh_pfc_get_functions_count,
.get_function_name = sh_pfc_get_function_name,
.get_function_groups = sh_pfc_get_function_groups,
.set_mux = sh_pfc_func_set_mux,
.gpio_request_enable = sh_pfc_gpio_request_enable,
.gpio_disable_free = sh_pfc_gpio_disable_free,
.gpio_set_direction = sh_pfc_gpio_set_direction,
};
/* Check whether the requested parameter is supported for a pin. */
static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin,
enum pin_config_param param)
{
int idx = sh_pfc_get_pin_index(pfc, _pin);
const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
return true;
case PIN_CONFIG_BIAS_PULL_UP:
return pin->configs & SH_PFC_PIN_CFG_PULL_UP;
case PIN_CONFIG_BIAS_PULL_DOWN:
return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN;
default:
return false;
}
}
static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin,
unsigned long *config)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
struct sh_pfc *pfc = pmx->pfc;
enum pin_config_param param = pinconf_to_config_param(*config);
unsigned long flags;
unsigned int bias;
if (!sh_pfc_pinconf_validate(pfc, _pin, param))
return -ENOTSUPP;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
if (!pfc->info->ops || !pfc->info->ops->get_bias)
return -ENOTSUPP;
spin_lock_irqsave(&pfc->lock, flags);
bias = pfc->info->ops->get_bias(pfc, _pin);
spin_unlock_irqrestore(&pfc->lock, flags);
if (bias != param)
return -EINVAL;
*config = 0;
break;
default:
return -ENOTSUPP;
}
return 0;
}
static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin,
unsigned long *configs, unsigned num_configs)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
struct sh_pfc *pfc = pmx->pfc;
enum pin_config_param param;
unsigned long flags;
unsigned int i;
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
if (!sh_pfc_pinconf_validate(pfc, _pin, param))
return -ENOTSUPP;
switch (param) {
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_DISABLE:
if (!pfc->info->ops || !pfc->info->ops->set_bias)
return -ENOTSUPP;
spin_lock_irqsave(&pfc->lock, flags);
pfc->info->ops->set_bias(pfc, _pin, param);
spin_unlock_irqrestore(&pfc->lock, flags);
break;
default:
return -ENOTSUPP;
}
} /* for each config */
return 0;
}
static int sh_pfc_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
unsigned long *configs,
unsigned num_configs)
{
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
const unsigned int *pins;
unsigned int num_pins;
unsigned int i;
pins = pmx->pfc->info->groups[group].pins;
num_pins = pmx->pfc->info->groups[group].nr_pins;
for (i = 0; i < num_pins; ++i)
sh_pfc_pinconf_set(pctldev, pins[i], configs, num_configs);
return 0;
}
static const struct pinconf_ops sh_pfc_pinconf_ops = {
.is_generic = true,
.pin_config_get = sh_pfc_pinconf_get,
.pin_config_set = sh_pfc_pinconf_set,
.pin_config_group_set = sh_pfc_pinconf_group_set,
.pin_config_config_dbg_show = pinconf_generic_dump_config,
};
/* PFC ranges -> pinctrl pin descs */
static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
{
unsigned int i;
/* Allocate and initialize the pins and configs arrays. */
pmx->pins = devm_kzalloc(pfc->dev,
sizeof(*pmx->pins) * pfc->info->nr_pins,
GFP_KERNEL);
if (unlikely(!pmx->pins))
return -ENOMEM;
pmx->configs = devm_kzalloc(pfc->dev,
sizeof(*pmx->configs) * pfc->info->nr_pins,
GFP_KERNEL);
if (unlikely(!pmx->configs))
return -ENOMEM;
for (i = 0; i < pfc->info->nr_pins; ++i) {
const struct sh_pfc_pin *info = &pfc->info->pins[i];
struct sh_pfc_pin_config *cfg = &pmx->configs[i];
struct pinctrl_pin_desc *pin = &pmx->pins[i];
/* If the pin number is equal to -1 all pins are considered */
pin->number = info->pin != (u16)-1 ? info->pin : i;
pin->name = info->name;
cfg->type = PINMUX_TYPE_NONE;
}
return 0;
}
int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
{
struct sh_pfc_pinctrl *pmx;
int ret;
pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL);
if (unlikely(!pmx))
return -ENOMEM;
pmx->pfc = pfc;
pfc->pinctrl = pmx;
ret = sh_pfc_map_pins(pfc, pmx);
if (ret < 0)
return ret;
pmx->pctl_desc.name = DRV_NAME;
pmx->pctl_desc.owner = THIS_MODULE;
pmx->pctl_desc.pctlops = &sh_pfc_pinctrl_ops;
pmx->pctl_desc.pmxops = &sh_pfc_pinmux_ops;
pmx->pctl_desc.confops = &sh_pfc_pinconf_ops;
pmx->pctl_desc.pins = pmx->pins;
pmx->pctl_desc.npins = pfc->info->nr_pins;
pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx);
if (pmx->pctl == NULL)
return -EINVAL;
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;
}

View file

@ -0,0 +1,319 @@
/*
* SuperH Pin Function Controller Support
*
* Copyright (c) 2008 Magnus Damm
*
* 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_H
#define __SH_PFC_H
#include <linux/bug.h>
#include <linux/stringify.h>
enum {
PINMUX_TYPE_NONE,
PINMUX_TYPE_FUNCTION,
PINMUX_TYPE_GPIO,
PINMUX_TYPE_OUTPUT,
PINMUX_TYPE_INPUT,
};
#define SH_PFC_PIN_CFG_INPUT (1 << 0)
#define SH_PFC_PIN_CFG_OUTPUT (1 << 1)
#define SH_PFC_PIN_CFG_PULL_UP (1 << 2)
#define SH_PFC_PIN_CFG_PULL_DOWN (1 << 3)
#define SH_PFC_PIN_CFG_NO_GPIO (1 << 31)
struct sh_pfc_pin {
u16 pin;
u16 enum_id;
const char *name;
unsigned int configs;
};
#define SH_PFC_PIN_GROUP(n) \
{ \
.name = #n, \
.pins = n##_pins, \
.mux = n##_mux, \
.nr_pins = ARRAY_SIZE(n##_pins), \
}
struct sh_pfc_pin_group {
const char *name;
const unsigned int *pins;
const unsigned int *mux;
unsigned int nr_pins;
};
#define SH_PFC_FUNCTION(n) \
{ \
.name = #n, \
.groups = n##_groups, \
.nr_groups = ARRAY_SIZE(n##_groups), \
}
struct sh_pfc_function {
const char *name;
const char * const *groups;
unsigned int nr_groups;
};
struct pinmux_func {
u16 enum_id;
const char *name;
};
struct pinmux_cfg_reg {
unsigned long reg, reg_width, field_width;
const u16 *enum_ids;
const unsigned long *var_field_width;
};
#define PINMUX_CFG_REG(name, r, r_width, f_width) \
.reg = r, .reg_width = r_width, .field_width = f_width, \
.enum_ids = (const u16 [(r_width / f_width) * (1 << f_width)])
#define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
.reg = r, .reg_width = r_width, \
.var_field_width = (const unsigned long [r_width]) \
{ var_fw0, var_fwn, 0 }, \
.enum_ids = (const u16 [])
struct pinmux_data_reg {
unsigned long reg, reg_width;
const u16 *enum_ids;
};
#define PINMUX_DATA_REG(name, r, r_width) \
.reg = r, .reg_width = r_width, \
.enum_ids = (const u16 [r_width]) \
struct pinmux_irq {
int irq;
const short *gpios;
};
#ifdef CONFIG_ARCH_MULTIPLATFORM
#define PINMUX_IRQ(irq_nr, ids...) \
{ .gpios = (const short []) { ids, -1 } }
#else
#define PINMUX_IRQ(irq_nr, ids...) \
{ .irq = irq_nr, .gpios = (const short []) { ids, -1 } }
#endif
struct pinmux_range {
u16 begin;
u16 end;
u16 force;
};
struct sh_pfc;
struct sh_pfc_soc_operations {
int (*init)(struct sh_pfc *pfc);
unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin);
void (*set_bias)(struct sh_pfc *pfc, unsigned int pin,
unsigned int bias);
};
struct sh_pfc_soc_info {
const char *name;
const struct sh_pfc_soc_operations *ops;
struct pinmux_range input;
struct pinmux_range output;
struct pinmux_range function;
const struct sh_pfc_pin *pins;
unsigned int nr_pins;
const struct sh_pfc_pin_group *groups;
unsigned int nr_groups;
const struct sh_pfc_function *functions;
unsigned int nr_functions;
const struct pinmux_func *func_gpios;
unsigned int nr_func_gpios;
const struct pinmux_cfg_reg *cfg_regs;
const struct pinmux_data_reg *data_regs;
const u16 *gpio_data;
unsigned int gpio_data_size;
const struct pinmux_irq *gpio_irq;
unsigned int gpio_irq_size;
unsigned long unlock_reg;
};
/* -----------------------------------------------------------------------------
* Helper macros to create pin and port lists
*/
/*
* sh_pfc_soc_info gpio_data array macros
*/
#define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0
#define PINMUX_IPSR_NOGP(ispr, fn) \
PINMUX_DATA(fn##_MARK, FN_##fn)
#define PINMUX_IPSR_DATA(ipsr, fn) \
PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr)
#define PINMUX_IPSR_NOGM(ispr, fn, ms) \
PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ms)
#define PINMUX_IPSR_MSEL(ipsr, fn, ms) \
PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr, FN_##ms)
#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) \
PINMUX_DATA(fn##_MARK, FN_##ms, FN_##ipsr, FN_##fn)
/*
* GP port style (32 ports banks)
*/
#define PORT_GP_1(bank, pin, fn, sfx) fn(bank, pin, GP_##bank##_##pin, sfx)
#define PORT_GP_32(bank, fn, sfx) \
PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx), \
PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx), \
PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx), \
PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx), \
PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx), \
PORT_GP_1(bank, 30, fn, sfx), PORT_GP_1(bank, 31, fn, sfx)
#define PORT_GP_32_REV(bank, fn, sfx) \
PORT_GP_1(bank, 31, fn, sfx), PORT_GP_1(bank, 30, fn, sfx), \
PORT_GP_1(bank, 29, fn, sfx), PORT_GP_1(bank, 28, fn, sfx), \
PORT_GP_1(bank, 27, fn, sfx), PORT_GP_1(bank, 26, fn, sfx), \
PORT_GP_1(bank, 25, fn, sfx), PORT_GP_1(bank, 24, fn, sfx), \
PORT_GP_1(bank, 23, fn, sfx), PORT_GP_1(bank, 22, fn, sfx), \
PORT_GP_1(bank, 21, fn, sfx), PORT_GP_1(bank, 20, fn, sfx), \
PORT_GP_1(bank, 19, fn, sfx), PORT_GP_1(bank, 18, fn, sfx), \
PORT_GP_1(bank, 17, fn, sfx), PORT_GP_1(bank, 16, fn, sfx), \
PORT_GP_1(bank, 15, fn, sfx), PORT_GP_1(bank, 14, fn, sfx), \
PORT_GP_1(bank, 13, fn, sfx), PORT_GP_1(bank, 12, fn, sfx), \
PORT_GP_1(bank, 11, fn, sfx), PORT_GP_1(bank, 10, fn, sfx), \
PORT_GP_1(bank, 9, fn, sfx), PORT_GP_1(bank, 8, fn, sfx), \
PORT_GP_1(bank, 7, fn, sfx), PORT_GP_1(bank, 6, fn, sfx), \
PORT_GP_1(bank, 5, fn, sfx), PORT_GP_1(bank, 4, fn, sfx), \
PORT_GP_1(bank, 3, fn, sfx), PORT_GP_1(bank, 2, fn, sfx), \
PORT_GP_1(bank, 1, fn, sfx), PORT_GP_1(bank, 0, fn, sfx)
/* GP_ALL(suffix) - Expand to a list of GP_#_#_suffix */
#define _GP_ALL(bank, pin, name, sfx) name##_##sfx
#define GP_ALL(str) CPU_ALL_PORT(_GP_ALL, str)
/* PINMUX_GPIO_GP_ALL - Expand to a list of sh_pfc_pin entries */
#define _GP_GPIO(bank, _pin, _name, sfx) \
[(bank * 32) + _pin] = { \
.pin = (bank * 32) + _pin, \
.name = __stringify(_name), \
.enum_id = _name##_DATA, \
}
#define PINMUX_GPIO_GP_ALL() CPU_ALL_PORT(_GP_GPIO, unused)
/* PINMUX_DATA_GP_ALL - Expand to a list of name_DATA, name_FN marks */
#define _GP_DATA(bank, pin, name, sfx) PINMUX_DATA(name##_DATA, name##_FN)
#define PINMUX_DATA_GP_ALL() CPU_ALL_PORT(_GP_DATA, unused)
/*
* PORT style (linear pin space)
*/
#define PORT_1(pn, fn, pfx, sfx) fn(pn, pfx, sfx)
#define PORT_10(pn, fn, pfx, sfx) \
PORT_1(pn, fn, pfx##0, sfx), PORT_1(pn+1, fn, pfx##1, sfx), \
PORT_1(pn+2, fn, pfx##2, sfx), PORT_1(pn+3, fn, pfx##3, sfx), \
PORT_1(pn+4, fn, pfx##4, sfx), PORT_1(pn+5, fn, pfx##5, sfx), \
PORT_1(pn+6, fn, pfx##6, sfx), PORT_1(pn+7, fn, pfx##7, sfx), \
PORT_1(pn+8, fn, pfx##8, sfx), PORT_1(pn+9, fn, pfx##9, sfx)
#define PORT_90(pn, fn, pfx, sfx) \
PORT_10(pn+10, fn, pfx##1, sfx), PORT_10(pn+20, fn, pfx##2, sfx), \
PORT_10(pn+30, fn, pfx##3, sfx), PORT_10(pn+40, fn, pfx##4, sfx), \
PORT_10(pn+50, fn, pfx##5, sfx), PORT_10(pn+60, fn, pfx##6, sfx), \
PORT_10(pn+70, fn, pfx##7, sfx), PORT_10(pn+80, fn, pfx##8, sfx), \
PORT_10(pn+90, fn, pfx##9, sfx)
/* PORT_ALL(suffix) - Expand to a list of PORT_#_suffix */
#define _PORT_ALL(pn, pfx, sfx) pfx##_##sfx
#define PORT_ALL(str) CPU_ALL_PORT(_PORT_ALL, PORT, str)
/* PINMUX_GPIO - Expand to a sh_pfc_pin entry */
#define PINMUX_GPIO(_pin) \
[GPIO_##_pin] = { \
.pin = (u16)-1, \
.name = __stringify(GPIO_##_pin), \
.enum_id = _pin##_DATA, \
}
/* SH_PFC_PIN_CFG - Expand to a sh_pfc_pin entry (named PORT#) with config */
#define SH_PFC_PIN_CFG(_pin, cfgs) \
{ \
.pin = _pin, \
.name = __stringify(PORT##_pin), \
.enum_id = PORT##_pin##_DATA, \
.configs = cfgs, \
}
/* SH_PFC_PIN_NAMED - Expand to a sh_pfc_pin entry with the given name */
#define SH_PFC_PIN_NAMED(row, col, _name) \
{ \
.pin = PIN_NUMBER(row, col), \
.name = __stringify(PIN_##_name), \
.configs = SH_PFC_PIN_CFG_NO_GPIO, \
}
/* PINMUX_DATA_ALL - Expand to a list of PORT_name_DATA, PORT_name_FN0,
* PORT_name_OUT, PORT_name_IN marks
*/
#define _PORT_DATA(pn, pfx, sfx) \
PINMUX_DATA(PORT##pfx##_DATA, PORT##pfx##_FN0, \
PORT##pfx##_OUT, PORT##pfx##_IN)
#define PINMUX_DATA_ALL() CPU_ALL_PORT(_PORT_DATA, , unused)
/* GPIO_FN(name) - Expand to a sh_pfc_pin entry for a function GPIO */
#define PINMUX_GPIO_FN(gpio, base, data_or_mark) \
[gpio - (base)] = { \
.name = __stringify(gpio), \
.enum_id = data_or_mark, \
}
#define GPIO_FN(str) \
PINMUX_GPIO_FN(GPIO_FN_##str, PINMUX_FN_BASE, str##_MARK)
/*
* PORTnCR macro
*/
#define _PCRH(in, in_pd, in_pu, out) \
0, (out), (in), 0, \
0, 0, 0, 0, \
0, 0, (in_pd), 0, \
0, 0, (in_pu), 0
#define PORTCR(nr, reg) \
{ \
PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \
_PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \
PORT##nr##_FN0, PORT##nr##_FN1, \
PORT##nr##_FN2, PORT##nr##_FN3, \
PORT##nr##_FN4, PORT##nr##_FN5, \
PORT##nr##_FN6, PORT##nr##_FN7 } \
}
#endif /* __SH_PFC_H */