Merge branch 'pinctrl/next' into next

* pinctrl/next: (7 commits)
  LF-10523-16-2 pinctrl: imx: support i.MX9 SCMI
  LF-9720: arm64:dts:freescale:imx8mn: Fix typo on imx8mn-pinfunc.h for SAI3_RXD_PDM_BIT_STREAM1
  pinctrl: Add pinmuxing driver for S32V234
  dt-bindings: pinctrl: Add SIUL2 definitions
  MLK-11749: pinctrl: support pinctrl setting assertion via gpios
  ...
This commit is contained in:
Dong Aisheng 2023-11-22 17:04:55 +08:00
commit 41aee1e446
14 changed files with 2227 additions and 17 deletions

View File

@ -0,0 +1,19 @@
* Freescale SIUL2 iomux controller
See chapter 20 ("System Integration Unit Lite2 (SIUL2)") in the reference
manual[1].
Based on fsl,imx-pincontrol implementation.
Required properties:
- compatible: "fsl,s32v234-siul2"
- fsl,pins: two integers array, represents a group of pins mux and config
setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>
PIN_FUNC_ID - id of MSCR to be modified
CONFIG - configuration to be written in the MSCR/IMCR register
Even though IMCR register should be used as input register, it can be
set and addressed in the same way as MSCR, only instead of passing the
IMCR index, IMCR_IDX + 512 is passed[1].
[1] https://www.nxp.com/webapp/Download?colCode=S32V234RM

View File

@ -71,6 +71,13 @@ pinctrl-names: The list of names to assign states. List entry 0 defines the
name for integer state ID 0, list entry 1 for state ID 1, and
so on.
pinctrl-assert-gpios:
List of phandles, each pointing at a GPIO which is used by some
board design to steer pins between two peripherals on the board.
It plays like a board level pin multiplexer to choose different
functions for given pins by pulling up/down the GPIOs. See
bindings/gpio/gpio.txt for details of how to specify GPIO.
For example:
/* For a client device requiring named states */

View File

@ -225,9 +225,17 @@ config HAVE_IMX_BUSFREQ
config ARCH_S32
bool "NXP S32 SoC Family"
select ARCH_S32_CLK
select PINCTRL
help
This enables support for the NXP S32 family of processors.
if ARCH_S32
menu "S32 SOC selection"
config SOC_S32V234
bool "S32V234 SOC"
endmenu
endif
endif
config ARCH_MA35

View File

@ -474,7 +474,7 @@
#define MX8MN_IOMUXC_SAI3_RXD_UART2_DCE_RTS_B 0x1D4 0x43C 0x4F8 0x4 0x3
#define MX8MN_IOMUXC_SAI3_RXD_UART2_DTE_CTS_B 0x1D4 0x43C 0x000 0x4 0x0
#define MX8MN_IOMUXC_SAI3_RXD_GPIO4_IO30 0x1D4 0x43C 0x000 0x5 0x0
#define MX8MN_IOMUXC_SAI3_RXD_PDM_BIT_STREAM1 0x1D4 0x43C 0x538 0x6 0x10
#define MX8MN_IOMUXC_SAI3_RXD_PDM_BIT_STREAM1 0x1D4 0x43C 0x538 0x6 0xA
#define MX8MN_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0x1D8 0x440 0x000 0x0 0x0
#define MX8MN_IOMUXC_SAI3_TXFS_GPT1_CAPTURE2 0x1D8 0x440 0x5EC 0x1 0x0
#define MX8MN_IOMUXC_SAI3_TXFS_SAI5_RX_DATA1 0x1D8 0x440 0x4D8 0x2 0x1

View File

@ -7,6 +7,7 @@
#include <linux/device.h>
#include <linux/of.h>
#include <linux/gpio/consumer.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
@ -193,6 +194,30 @@ static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
return dt_remember_or_free_map(p, statename, NULL, map, 1);
}
static int dt_gpio_assert_pinctrl(struct pinctrl *p)
{
struct device_node *np = p->dev->of_node;
struct gpio_desc *gpio;
int index = 0;
int ret;
if (!of_find_property(np, "pinctrl-assert-gpios", NULL))
return 0; /* Missing the property, so nothing to be done */
for (;; index++) {
gpio = devm_gpiod_get_optional(p->dev, "pinctrl-assert",
GPIOD_OUT_HIGH);
ret = PTR_ERR(gpio);
if (ret < 0) {
if (PTR_ERR(gpio) == -EPROBE_DEFER)
return -EPROBE_DEFER;
break; /* End of the phandle list */
}
}
return 0;
}
int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
{
struct device_node *np = p->dev->of_node;
@ -213,6 +238,12 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
return 0;
}
ret = dt_gpio_assert_pinctrl(p);
if (ret) {
dev_dbg(p->dev, "failed to assert pinctrl setting: %d\n", ret);
return ret;
}
/* We may store pointers to property names within the node */
of_node_get(np);

View File

@ -217,3 +217,16 @@ config PINCTRL_IMXRT1170
select PINCTRL_IMX
help
Say Y here to enable the imxrt1170 pinctrl driver
config PINCTRL_S32V_CORE
bool "Core driver for the S32V pin controller"
help
Say Y here to enable the S32V pin controller
config PINCTRL_S32V234
bool "Freescale S32V234 pinctrl driver"
depends on SOC_S32V234
select PINCTRL_IMX
select PINCTRL_S32V_CORE
help
Say Y here to enable the Freescale S32V234 pinctrl driver

View File

@ -33,3 +33,5 @@ obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o
obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o
obj-$(CONFIG_PINCTRL_IMXRT1050) += pinctrl-imxrt1050.o
obj-$(CONFIG_PINCTRL_IMXRT1170) += pinctrl-imxrt1170.o
obj-$(CONFIG_PINCTRL_S32V234) += pinctrl-s32v234.o
obj-$(CONFIG_PINCTRL_S32V_CORE) += pinctrl-s32v-core.o

View File

@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/seq_file.h>
@ -33,6 +34,29 @@
#define IMX_NO_PAD_CTL 0x80000000 /* no pin config need */
#define IMX_PAD_SION 0x40000000 /* set SION */
/*
* Each pin represented in fsl,pins consists of a number of u32 PIN_FUNC_ID
* and 1 u32 CONFIG, the total size is PIN_FUNC_ID + CONFIG for each pin.
* For generic_pinconf case, there's no extra u32 CONFIG.
*
* PIN_FUNC_ID format:
* Default:
* <mux_reg conf_reg input_reg mux_mode input_val>
* SHARE_MUX_CONF_REG:
* <mux_conf_reg input_reg mux_mode input_val>
* IMX_USE_SCU:
* <pin_id mux_mode>
*/
#define FSL_PIN_SIZE 24
#define FSL_PIN_SHARE_SIZE 20
#define FSL_SCU_PIN_SIZE 12
/* SCMI pin control types, aligned with SCMI firmware */
#define IMX_PIN_TYPE_MUX 192
#define IMX_PIN_TYPE_CONFIG 193
#define IMX_PIN_TYPE_DAISY_ID 194
#define IMX_PIN_TYPE_DAISY_CFG 195
static inline const struct group_desc *imx_pinctrl_find_group_by_name(
struct pinctrl_dev *pctldev,
const char *name)
@ -55,6 +79,95 @@ static void imx_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
seq_printf(s, "%s", dev_name(pctldev->dev));
}
#define IMX_SCMI_NUM_CFG 4
int imx_scmi_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np,
struct pinctrl_map **map, unsigned int *num_maps)
{
struct pinctrl_map *new_map;
const __be32 *list;
unsigned long *configs = NULL;
unsigned long cfg[IMX_SCMI_NUM_CFG];
int map_num, size, pin_size, pin_id, num_pins;
int mux_reg, conf_reg, input_reg, mux_val, conf_val, input_val;
int i, j;
uint32_t ncfg;
static uint32_t daisy_off;
if (!daisy_off) {
if (of_machine_is_compatible("fsl,imx93"))
daisy_off = 0x360;
else if (of_machine_is_compatible("fsl,imx95"))
daisy_off = 0x408;
else
dev_err(pctldev->dev, "platform not support scmi pinctrl\n");
}
list = of_get_property(np, "fsl,pins", &size);
if (!list) {
dev_err(pctldev->dev, "no fsl,pins property in node %pOF\n", np);
return -EINVAL;
}
pin_size = FSL_PIN_SIZE;
if (!size || size % pin_size) {
dev_err(pctldev->dev, "Invalid fsl,pins or pins property in node %pOF\n", np);
return -EINVAL;
}
num_pins = size / pin_size;
map_num = num_pins;
new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map),
GFP_KERNEL);
if (!new_map)
return -ENOMEM;
*map = new_map;
*num_maps = map_num;
/* create config map */
for (i = 0; i < num_pins; i++) {
j = 0;
ncfg = IMX_SCMI_NUM_CFG;
mux_reg = be32_to_cpu(*list++);
conf_reg = be32_to_cpu(*list++);
input_reg = be32_to_cpu(*list++);
mux_val = be32_to_cpu(*list++);
input_val = be32_to_cpu(*list++);
conf_val = be32_to_cpu(*list++);
if (conf_val & IMX_PAD_SION)
mux_val |= IOMUXC_CONFIG_SION;
pin_id = mux_reg / 4;
cfg[j++] = pinconf_to_config_packed(IMX_PIN_TYPE_MUX, mux_val);
if (!conf_reg || (conf_val & IMX_NO_PAD_CTL))
ncfg--;
else
cfg[j++] = pinconf_to_config_packed(IMX_PIN_TYPE_CONFIG, conf_val);
if (!input_reg) {
ncfg -= 2;
} else {
cfg[j++] = pinconf_to_config_packed(IMX_PIN_TYPE_DAISY_ID,
(input_reg - daisy_off) / 4);
cfg[j++] = pinconf_to_config_packed(IMX_PIN_TYPE_DAISY_CFG, input_val);
}
configs = kmemdup(cfg, ncfg * sizeof(unsigned long), GFP_KERNEL);
new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
new_map[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_id);
new_map[i].data.configs.configs = configs;
new_map[i].data.configs.num_configs = ncfg;
}
return 0;
}
EXPORT_SYMBOL_GPL(imx_scmi_dt_node_to_map);
static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map, unsigned *num_maps)
@ -441,22 +554,6 @@ static const struct pinconf_ops imx_pinconf_ops = {
.pin_config_group_dbg_show = imx_pinconf_group_dbg_show,
};
/*
* Each pin represented in fsl,pins consists of a number of u32 PIN_FUNC_ID
* and 1 u32 CONFIG, the total size is PIN_FUNC_ID + CONFIG for each pin.
*
* PIN_FUNC_ID format:
* Default:
* <mux_reg conf_reg input_reg mux_mode input_val>
* SHARE_MUX_CONF_REG:
* <mux_conf_reg input_reg mux_mode input_val>
* IMX_USE_SCU:
* <pin_id mux_mode>
*/
#define FSL_PIN_SIZE 24
#define FSL_PIN_SHARE_SIZE 20
#define FSL_SCU_PIN_SIZE 12
static void imx_pinctrl_parse_pin_mmio(struct imx_pinctrl *ipctl,
unsigned int *pin_id, struct imx_pin *pin,
const __be32 **list_p,

View File

@ -0,0 +1,527 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Core driver for the S32V pin controller
*
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
* Copyright (C) 2017 NXP
*
* Based on pinctrl-imx.c:
* Author: Dong Aisheng <dong.aisheng@linaro.org>
* Copyright (C) 2012 Freescale Semiconductor, Inc.
* Copyright (C) 2012 Linaro Ltd.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include "../core.h"
#include "pinctrl-s32v.h"
/**
* @dev: a pointer back to containing device
* @base: the offset to the controller in virtual memory
*/
struct s32v_pinctrl {
struct device *dev;
struct pinctrl_dev *pctl;
void __iomem *base;
const struct s32v_pinctrl_soc_info *info;
};
static const char *pin_get_name_from_info(struct s32v_pinctrl_soc_info *info,
const unsigned int pin_id)
{
int i;
for (i = 0; i < info->npins; i++) {
if (info->pins[i].number == pin_id)
return info->pins[i].name;
}
return NULL;
}
static inline const struct s32v_pin_group *s32v_pinctrl_find_group_by_name(
const struct s32v_pinctrl_soc_info *info,
const char *name)
{
const struct s32v_pin_group *grp = NULL;
unsigned int i;
for (i = 0; i < info->ngroups; i++) {
if (!strcmp(info->groups[i].name, name)) {
grp = &info->groups[i];
break;
}
}
return grp;
}
static int s32v_get_groups_count(struct pinctrl_dev *pctldev)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
return info->ngroups;
}
static const char *s32v_get_group_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
return info->groups[selector].name;
}
static int s32v_get_group_pins(struct pinctrl_dev *pctldev,
unsigned int selector, const unsigned int **pins,
unsigned int *npins)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
if (selector >= info->ngroups)
return -EINVAL;
*pins = info->groups[selector].pin_ids;
*npins = info->groups[selector].npins;
return 0;
}
static void s32v_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int offset)
{
seq_printf(s, "%s", dev_name(pctldev->dev));
}
static int s32v_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map, unsigned int *num_maps)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
const struct s32v_pin_group *grp;
struct pinctrl_map *new_map;
struct device_node *parent;
int map_num = 1;
int i, j;
/*
* first find the group of this node and check if we need create
* config maps for pins
*/
grp = s32v_pinctrl_find_group_by_name(info, np->name);
if (!grp) {
dev_err(info->dev, "unable to find group for node %s\n",
np->name);
return -EINVAL;
}
for (i = 0; i < grp->npins; i++)
map_num++;
new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map),
GFP_KERNEL);
if (!new_map)
return -ENOMEM;
*map = new_map;
*num_maps = map_num;
/* create mux map */
parent = of_get_parent(np);
if (!parent) {
kfree(new_map);
return -EINVAL;
}
new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
new_map[0].data.mux.function = parent->name;
new_map[0].data.mux.group = np->name;
of_node_put(parent);
/* create config map */
new_map++;
for (i = j = 0; i < grp->npins; i++) {
new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
new_map[j].data.configs.group_or_pin =
pin_get_name(pctldev, grp->pins[i].pin_id);
new_map[j].data.configs.configs = &grp->pins[i].config;
new_map[j].data.configs.num_configs = 1;
j++;
}
dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
(*map)->data.mux.function, (*map)->data.mux.group, map_num);
return 0;
}
static void s32v_dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned int num_maps)
{
kfree(map);
}
static const struct pinctrl_ops s32v_pctrl_ops = {
.get_groups_count = s32v_get_groups_count,
.get_group_name = s32v_get_group_name,
.get_group_pins = s32v_get_group_pins,
.pin_dbg_show = s32v_pin_dbg_show,
.dt_node_to_map = s32v_dt_node_to_map,
.dt_free_map = s32v_dt_free_map,
};
static int s32v_pmx_set(struct pinctrl_dev *pctldev, unsigned int selector,
unsigned int group)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
unsigned int npins, pin_id;
int i;
struct s32v_pin_group *grp;
/*
* Configure the mux mode for each pin in the group for a specific
* function.
*/
grp = &info->groups[group];
npins = grp->npins;
dev_dbg(ipctl->dev, "enable function %s group %s\n",
info->functions[selector].name, grp->name);
for (i = 0; i < npins; i++) {
struct s32v_pin *pin = &grp->pins[i];
pin_id = pin->pin_id;
writel(pin->config, ipctl->base + S32V_PAD_CONFIG(pin_id));
dev_dbg(ipctl->dev, "write: offset 0x%x val %lu\n",
S32V_PAD_CONFIG(pin_id), pin->config);
}
return 0;
}
static int s32v_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
return info->nfunctions;
}
static const char *s32v_pmx_get_func_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
return info->functions[selector].name;
}
static int s32v_pmx_get_groups(struct pinctrl_dev *pctldev,
unsigned int selector,
const char * const **groups,
unsigned int * const num_groups)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
*groups = info->functions[selector].groups;
*num_groups = info->functions[selector].num_groups;
return 0;
}
static const struct pinmux_ops s32v_pmx_ops = {
.get_functions_count = s32v_pmx_get_funcs_count,
.get_function_name = s32v_pmx_get_func_name,
.get_function_groups = s32v_pmx_get_groups,
.set_mux = s32v_pmx_set,
};
static int s32v_pinconf_get(struct pinctrl_dev *pctldev,
unsigned int pin_id, unsigned long *config)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
*config = readl(ipctl->base + S32V_PAD_CONFIG(pin_id));
return 0;
}
static int s32v_pinconf_set(struct pinctrl_dev *pctldev,
unsigned int pin_id, unsigned long *configs,
unsigned int num_configs)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
int i;
dev_dbg(ipctl->dev, "pinconf set pin %s\n",
pin_get_name(pctldev, pin_id));
for (i = 0; i < num_configs; i++) {
writel(configs[i], ipctl->base + S32V_PAD_CONFIG(pin_id));
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
S32V_PAD_CONFIG(pin_id), configs[i]);
} /* for each config */
return 0;
}
static void s32v_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned int pin_id)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
unsigned long config;
config = readl(ipctl->base + S32V_PAD_CONFIG(pin_id));
seq_printf(s, "0x%lx", config);
}
static void s32v_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned int group)
{
struct s32v_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32v_pinctrl_soc_info *info = ipctl->info;
struct s32v_pin_group *grp;
unsigned long config;
const char *name;
int i, ret;
if (group > info->ngroups)
return;
seq_puts(s, "\n");
grp = &info->groups[group];
for (i = 0; i < grp->npins; i++) {
struct s32v_pin *pin = &grp->pins[i];
name = pin_get_name(pctldev, pin->pin_id);
ret = s32v_pinconf_get(pctldev, pin->pin_id, &config);
if (ret)
return;
seq_printf(s, "%s: 0x%lx", name, config);
}
}
static const struct pinconf_ops s32v_pinconf_ops = {
.pin_config_get = s32v_pinconf_get,
.pin_config_set = s32v_pinconf_set,
.pin_config_dbg_show = s32v_pinconf_dbg_show,
.pin_config_group_dbg_show = s32v_pinconf_group_dbg_show,
};
static struct pinctrl_desc s32v_pinctrl_desc = {
.pctlops = &s32v_pctrl_ops,
.pmxops = &s32v_pmx_ops,
.confops = &s32v_pinconf_ops,
.owner = THIS_MODULE,
};
/*
* Each pin represented in fsl,pins consists of 5 u32 PIN_FUNC_ID and
* 1 u32 CONFIG, so 24 types in total for each pin.
*/
#define FSL_PIN_SIZE 24
#define SHARE_FSL_PIN_SIZE 20
static int s32v_pinctrl_parse_groups(struct device_node *np,
struct s32v_pin_group *grp,
struct s32v_pinctrl_soc_info *info,
u32 index)
{
int size, i;
const __be32 *list;
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
/* Initialise group */
grp->name = np->name;
/*
* the binding format is fsl,pins = <PIN CONFIG>,
* do sanity check and calculate pins number
*/
list = of_get_property(np, "fsl,pins", &size);
if (!list) {
dev_err(info->dev, "no fsl,pins property in node %s\n",
np->full_name);
return -EINVAL;
}
/* we do not check return since it's safe node passed down */
if (!size || size % S32V_PIN_SIZE) {
dev_err(info->dev, "Invalid fsl,pins property in node %s\n",
np->full_name);
return -EINVAL;
}
grp->npins = size / S32V_PIN_SIZE;
grp->pins = devm_kzalloc(info->dev,
grp->npins * sizeof(struct s32v_pin),
GFP_KERNEL);
grp->pin_ids = devm_kzalloc(info->dev,
grp->npins * sizeof(unsigned int),
GFP_KERNEL);
if (!grp->pins || !grp->pin_ids)
return -ENOMEM;
for (i = 0; i < grp->npins; i++) {
struct s32v_pin *pin = &grp->pins[i];
pin->pin_id = be32_to_cpu(*list++);
pin->config = be32_to_cpu(*list++);
grp->pin_ids[i] = grp->pins[i].pin_id;
dev_dbg(info->dev, "%s: 0x%08lx",
pin_get_name_from_info(info, pin->pin_id), pin->config);
}
return 0;
}
static int s32v_pinctrl_parse_functions(struct device_node *np,
struct s32v_pinctrl_soc_info *info,
u32 index)
{
struct device_node *child;
struct s32v_pmx_func *func;
struct s32v_pin_group *grp;
static u32 grp_index;
u32 i = 0;
dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
func = &info->functions[index];
/* Initialise function */
func->name = np->name;
func->num_groups = of_get_child_count(np);
if (func->num_groups == 0) {
dev_err(info->dev, "no groups defined in %s\n", np->full_name);
return -EINVAL;
}
func->groups = devm_kzalloc(info->dev,
func->num_groups * sizeof(char *),
GFP_KERNEL);
for_each_child_of_node(np, child) {
func->groups[i] = child->name;
grp = &info->groups[grp_index++];
s32v_pinctrl_parse_groups(child, grp, info, i++);
}
return 0;
}
static int s32v_pinctrl_probe_dt(struct platform_device *pdev,
struct s32v_pinctrl_soc_info *info)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
u32 nfuncs = 0;
u32 i = 0;
if (!np)
return -ENODEV;
nfuncs = of_get_child_count(np);
if (nfuncs <= 0) {
dev_err(&pdev->dev, "no functions defined\n");
return -EINVAL;
}
info->nfunctions = nfuncs;
info->functions = devm_kzalloc(&pdev->dev,
nfuncs * sizeof(struct s32v_pmx_func),
GFP_KERNEL);
if (!info->functions)
return -ENOMEM;
info->ngroups = 0;
for_each_child_of_node(np, child)
info->ngroups += of_get_child_count(child);
info->groups = devm_kzalloc(&pdev->dev, info->ngroups *
sizeof(struct s32v_pin_group),
GFP_KERNEL);
if (!info->groups)
return -ENOMEM;
for_each_child_of_node(np, child)
s32v_pinctrl_parse_functions(child, info, i++);
return 0;
}
int s32v_pinctrl_probe(struct platform_device *pdev,
struct s32v_pinctrl_soc_info *info)
{
struct s32v_pinctrl *ipctl;
struct resource *res;
int ret;
if (!info || !info->pins || !info->npins) {
dev_err(&pdev->dev, "wrong pinctrl info\n");
return -EINVAL;
}
info->dev = &pdev->dev;
/* Create state holders etc for this driver */
ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL);
if (!ipctl)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ipctl->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ipctl->base))
return PTR_ERR(ipctl->base);
s32v_pinctrl_desc.name = dev_name(&pdev->dev);
s32v_pinctrl_desc.pins = info->pins;
s32v_pinctrl_desc.npins = info->npins;
ret = s32v_pinctrl_probe_dt(pdev, info);
if (ret) {
dev_err(&pdev->dev, "fail to probe dt properties\n");
return ret;
}
ipctl->info = info;
ipctl->dev = info->dev;
platform_set_drvdata(pdev, ipctl);
ipctl->pctl = pinctrl_register(&s32v_pinctrl_desc, &pdev->dev, ipctl);
if (!ipctl->pctl) {
dev_err(&pdev->dev, "could not register s32 pinctrl driver\n");
return -EINVAL;
}
dev_info(&pdev->dev, "initialized s32 pinctrl driver\n");
return 0;
}
int s32v_pinctrl_remove(struct platform_device *pdev)
{
struct s32v_pinctrl *ipctl = platform_get_drvdata(pdev);
pinctrl_unregister(ipctl->pctl);
return 0;
}

View File

@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* S32V pinmux core definitions
*
* Copyright (C) 2017 NXP
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
* Copyright (C) 2012 Linaro Ltd.
*
* Based on pinctrl-imx.h, by Dong Aisheng <dong.aisheng@linaro.org>
*/
#ifndef __DRIVERS_PINCTRL_S32V_H
#define __DRIVERS_PINCTRL_S32V_H
struct platform_device;
/**
* struct s32v_pin - describes a single S32V pin
* @pin_id: the pin_id of this pin
* @config: the config for this pin.
*/
struct s32v_pin {
unsigned int pin_id;
unsigned long config;
};
/**
* struct s32v_pin_group - describes an S32V pin group
* @name: the name of this specific pin group
* @npins: the number of pins in this group array, i.e. the number of
* elements in .pins so we can iterate over that array
* @pin_ids: array of pin_ids. pinctrl forces us to maintain such an array
* @pins: array of pins
*/
struct s32v_pin_group {
const char *name;
unsigned int npins;
unsigned int *pin_ids;
struct s32v_pin *pins;
};
/**
* struct s32v_pmx_func - describes S32V pinmux functions
* @name: the name of this specific function
* @groups: corresponding pin groups
* @num_groups: the number of groups
*/
struct s32v_pmx_func {
const char *name;
const char **groups;
unsigned int num_groups;
};
struct s32v_pinctrl_soc_info {
struct device *dev;
const struct pinctrl_pin_desc *pins;
unsigned int npins;
struct s32v_pin_group *groups;
unsigned int ngroups;
struct s32v_pmx_func *functions;
unsigned int nfunctions;
unsigned int flags;
};
#define S32V_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
#define S32V_PAD_CONFIG(idx) (0x240 + (idx) * 4)
#define S32V_PIN_SIZE (8)
int s32v_pinctrl_probe(struct platform_device *pdev,
struct s32v_pinctrl_soc_info *info);
int s32v_pinctrl_remove(struct platform_device *pdev);
#endif /* __DRIVERS_PINCTRL_S32V_H */

View File

@ -0,0 +1,251 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* s32v234 pinctrl driver based on imx pinmux and pinconf core
*
* Copyright 2015-2016 Freescale Semiconductor, Inc.
* Copyright 2017, 2019 NXP
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <dt-bindings/pinctrl/s32v234-pinctrl.h>
#include "pinctrl-s32v.h"
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc s32v234_pinctrl_pads[] = {
S32V_PINCTRL_PIN(S32V234_MSCR_PA0),
S32V_PINCTRL_PIN(S32V234_MSCR_PA1),
S32V_PINCTRL_PIN(S32V234_MSCR_PA2),
S32V_PINCTRL_PIN(S32V234_MSCR_PA3),
S32V_PINCTRL_PIN(S32V234_MSCR_PA4),
S32V_PINCTRL_PIN(S32V234_MSCR_PA5),
S32V_PINCTRL_PIN(S32V234_MSCR_PA6),
S32V_PINCTRL_PIN(S32V234_MSCR_PA7),
S32V_PINCTRL_PIN(S32V234_MSCR_PA8),
S32V_PINCTRL_PIN(S32V234_MSCR_PA9),
S32V_PINCTRL_PIN(S32V234_MSCR_PA10),
S32V_PINCTRL_PIN(S32V234_MSCR_PA11),
S32V_PINCTRL_PIN(S32V234_MSCR_PA12),
S32V_PINCTRL_PIN(S32V234_MSCR_PA13),
S32V_PINCTRL_PIN(S32V234_MSCR_PA14),
S32V_PINCTRL_PIN(S32V234_MSCR_PA15),
S32V_PINCTRL_PIN(S32V234_MSCR_PB0),
S32V_PINCTRL_PIN(S32V234_MSCR_PB1),
S32V_PINCTRL_PIN(S32V234_MSCR_PB2),
S32V_PINCTRL_PIN(S32V234_MSCR_PB3),
S32V_PINCTRL_PIN(S32V234_MSCR_PB4),
S32V_PINCTRL_PIN(S32V234_MSCR_PB5),
S32V_PINCTRL_PIN(S32V234_MSCR_PB6),
S32V_PINCTRL_PIN(S32V234_MSCR_PB7),
S32V_PINCTRL_PIN(S32V234_MSCR_PB8),
S32V_PINCTRL_PIN(S32V234_MSCR_PB9),
S32V_PINCTRL_PIN(S32V234_MSCR_PB10),
S32V_PINCTRL_PIN(S32V234_MSCR_PB11),
S32V_PINCTRL_PIN(S32V234_MSCR_PB12),
S32V_PINCTRL_PIN(S32V234_MSCR_PB13),
S32V_PINCTRL_PIN(S32V234_MSCR_PB14),
S32V_PINCTRL_PIN(S32V234_MSCR_PB15),
S32V_PINCTRL_PIN(S32V234_MSCR_PC0),
S32V_PINCTRL_PIN(S32V234_MSCR_PC1),
S32V_PINCTRL_PIN(S32V234_MSCR_PC2),
S32V_PINCTRL_PIN(S32V234_MSCR_PC3),
S32V_PINCTRL_PIN(S32V234_MSCR_PC4),
S32V_PINCTRL_PIN(S32V234_MSCR_PC5),
S32V_PINCTRL_PIN(S32V234_MSCR_PC6),
S32V_PINCTRL_PIN(S32V234_MSCR_PC7),
S32V_PINCTRL_PIN(S32V234_MSCR_PC8),
S32V_PINCTRL_PIN(S32V234_MSCR_PC9),
S32V_PINCTRL_PIN(S32V234_MSCR_PC10),
S32V_PINCTRL_PIN(S32V234_MSCR_PC11),
S32V_PINCTRL_PIN(S32V234_MSCR_PC12),
S32V_PINCTRL_PIN(S32V234_MSCR_PC13),
S32V_PINCTRL_PIN(S32V234_MSCR_PC14),
S32V_PINCTRL_PIN(S32V234_MSCR_PC15),
S32V_PINCTRL_PIN(S32V234_MSCR_PD0),
S32V_PINCTRL_PIN(S32V234_MSCR_PD1),
S32V_PINCTRL_PIN(S32V234_MSCR_PD2),
S32V_PINCTRL_PIN(S32V234_MSCR_PD3),
S32V_PINCTRL_PIN(S32V234_MSCR_PD4),
S32V_PINCTRL_PIN(S32V234_MSCR_PD5),
S32V_PINCTRL_PIN(S32V234_MSCR_PD6),
S32V_PINCTRL_PIN(S32V234_MSCR_PD7),
S32V_PINCTRL_PIN(S32V234_MSCR_PD8),
S32V_PINCTRL_PIN(S32V234_MSCR_PD9),
S32V_PINCTRL_PIN(S32V234_MSCR_PD10),
S32V_PINCTRL_PIN(S32V234_MSCR_PD11),
S32V_PINCTRL_PIN(S32V234_MSCR_PD12),
S32V_PINCTRL_PIN(S32V234_MSCR_PD13),
S32V_PINCTRL_PIN(S32V234_MSCR_PD14),
S32V_PINCTRL_PIN(S32V234_MSCR_PD15),
S32V_PINCTRL_PIN(S32V234_MSCR_PE0),
S32V_PINCTRL_PIN(S32V234_MSCR_PE1),
S32V_PINCTRL_PIN(S32V234_MSCR_PE2),
S32V_PINCTRL_PIN(S32V234_MSCR_PE3),
S32V_PINCTRL_PIN(S32V234_MSCR_PE4),
S32V_PINCTRL_PIN(S32V234_MSCR_PE5),
S32V_PINCTRL_PIN(S32V234_MSCR_PE6),
S32V_PINCTRL_PIN(S32V234_MSCR_PE7),
S32V_PINCTRL_PIN(S32V234_MSCR_PE8),
S32V_PINCTRL_PIN(S32V234_MSCR_PE9),
S32V_PINCTRL_PIN(S32V234_MSCR_PE10),
S32V_PINCTRL_PIN(S32V234_MSCR_PE11),
S32V_PINCTRL_PIN(S32V234_MSCR_PE12),
S32V_PINCTRL_PIN(S32V234_MSCR_PE13),
S32V_PINCTRL_PIN(S32V234_MSCR_PE14),
S32V_PINCTRL_PIN(S32V234_MSCR_PE15),
S32V_PINCTRL_PIN(S32V234_MSCR_PF0),
S32V_PINCTRL_PIN(S32V234_MSCR_PF1),
S32V_PINCTRL_PIN(S32V234_MSCR_PF2),
S32V_PINCTRL_PIN(S32V234_MSCR_PF3),
S32V_PINCTRL_PIN(S32V234_MSCR_PF4),
S32V_PINCTRL_PIN(S32V234_MSCR_PF5),
S32V_PINCTRL_PIN(S32V234_MSCR_PF6),
S32V_PINCTRL_PIN(S32V234_MSCR_PF7),
S32V_PINCTRL_PIN(S32V234_MSCR_PF8),
S32V_PINCTRL_PIN(S32V234_MSCR_PF9),
S32V_PINCTRL_PIN(S32V234_MSCR_PF10),
S32V_PINCTRL_PIN(S32V234_MSCR_PF11),
S32V_PINCTRL_PIN(S32V234_MSCR_PF12),
S32V_PINCTRL_PIN(S32V234_MSCR_PF13),
S32V_PINCTRL_PIN(S32V234_MSCR_PF14),
S32V_PINCTRL_PIN(S32V234_MSCR_PF15),
S32V_PINCTRL_PIN(S32V234_MSCR_PG0),
S32V_PINCTRL_PIN(S32V234_MSCR_PG1),
S32V_PINCTRL_PIN(S32V234_MSCR_PG2),
S32V_PINCTRL_PIN(S32V234_MSCR_PG3),
S32V_PINCTRL_PIN(S32V234_MSCR_PG4),
S32V_PINCTRL_PIN(S32V234_MSCR_PG5),
S32V_PINCTRL_PIN(S32V234_MSCR_PG6),
S32V_PINCTRL_PIN(S32V234_MSCR_PG7),
S32V_PINCTRL_PIN(S32V234_MSCR_PG8),
S32V_PINCTRL_PIN(S32V234_MSCR_PG9),
S32V_PINCTRL_PIN(S32V234_MSCR_PG10),
S32V_PINCTRL_PIN(S32V234_MSCR_PG11),
S32V_PINCTRL_PIN(S32V234_MSCR_PG12),
S32V_PINCTRL_PIN(S32V234_MSCR_PG13),
S32V_PINCTRL_PIN(S32V234_MSCR_PG14),
S32V_PINCTRL_PIN(S32V234_MSCR_PG15),
S32V_PINCTRL_PIN(S32V234_MSCR_PH0),
S32V_PINCTRL_PIN(S32V234_MSCR_PH1),
S32V_PINCTRL_PIN(S32V234_MSCR_PH2),
S32V_PINCTRL_PIN(S32V234_MSCR_PH3),
S32V_PINCTRL_PIN(S32V234_MSCR_PH4),
S32V_PINCTRL_PIN(S32V234_MSCR_PH5),
S32V_PINCTRL_PIN(S32V234_MSCR_PH6),
S32V_PINCTRL_PIN(S32V234_MSCR_PH7),
S32V_PINCTRL_PIN(S32V234_MSCR_PH8),
S32V_PINCTRL_PIN(S32V234_MSCR_PH9),
S32V_PINCTRL_PIN(S32V234_MSCR_PH10),
S32V_PINCTRL_PIN(S32V234_MSCR_PH11),
S32V_PINCTRL_PIN(S32V234_MSCR_PH12),
S32V_PINCTRL_PIN(S32V234_MSCR_PH13),
S32V_PINCTRL_PIN(S32V234_MSCR_PH14),
S32V_PINCTRL_PIN(S32V234_MSCR_PH15),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ0),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ1),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ2),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ3),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ4),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ5),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ6),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ7),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ8),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ9),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ10),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ11),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ12),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ13),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ14),
S32V_PINCTRL_PIN(S32V234_MSCR_PJ15),
S32V_PINCTRL_PIN(S32V234_MSCR_PK0),
S32V_PINCTRL_PIN(S32V234_MSCR_PK1),
S32V_PINCTRL_PIN(S32V234_MSCR_PK2),
S32V_PINCTRL_PIN(S32V234_MSCR_PK3),
S32V_PINCTRL_PIN(S32V234_MSCR_PK4),
S32V_PINCTRL_PIN(S32V234_MSCR_PK5),
S32V_PINCTRL_PIN(S32V234_MSCR_PK6),
S32V_PINCTRL_PIN(S32V234_MSCR_PK7),
S32V_PINCTRL_PIN(S32V234_MSCR_PK8),
S32V_PINCTRL_PIN(S32V234_MSCR_PK9),
S32V_PINCTRL_PIN(S32V234_MSCR_PK10),
S32V_PINCTRL_PIN(S32V234_MSCR_PK11),
S32V_PINCTRL_PIN(S32V234_MSCR_PK12),
S32V_PINCTRL_PIN(S32V234_MSCR_PK13),
S32V_PINCTRL_PIN(S32V234_MSCR_PK14),
S32V_PINCTRL_PIN(S32V234_MSCR_PK15),
S32V_PINCTRL_PIN(S32V234_MSCR_PL0),
S32V_PINCTRL_PIN(S32V234_MSCR_PL1),
S32V_PINCTRL_PIN(S32V234_MSCR_PL2),
S32V_PINCTRL_PIN(S32V234_MSCR_PL3),
S32V_PINCTRL_PIN(S32V234_MSCR_PL4),
S32V_PINCTRL_PIN(S32V234_MSCR_PL5),
S32V_PINCTRL_PIN(S32V234_MSCR_PL8),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_CLK),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_CMD),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_DAT0),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_DAT1),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_DAT2),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_DAT3),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_DAT4),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_DAT5),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_DAT6),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_DAT7),
S32V_PINCTRL_PIN(S32V234_IMCR_CAN_FD0_RXD),
S32V_PINCTRL_PIN(S32V234_IMCR_CAN_FD1_RXD),
S32V_PINCTRL_PIN(S32V234_IMCR_UART0_RXD),
S32V_PINCTRL_PIN(S32V234_IMCR_UART1_RXD),
S32V_PINCTRL_PIN(S32V234_IMCR_USDHC_WP),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_RX_ER),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_COL),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_CRS),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_RX_DV),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_RX_D0),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_RX_D1),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_RX_D2),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_RX_D3),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_TX_CLK),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_RX_CLK),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_MDIO),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_TIMER0),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_TIMER1),
S32V_PINCTRL_PIN(S32V234_IMCR_Ethernet_TIMER2),
};
static struct s32v_pinctrl_soc_info s32v234_pinctrl_info = {
.pins = s32v234_pinctrl_pads,
.npins = ARRAY_SIZE(s32v234_pinctrl_pads),
};
static const struct of_device_id s32v234_pinctrl_of_match[] = {
{ .compatible = "fsl,s32v234-siul2", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, s32v234_pinctrl_of_match);
static int s32v234_pinctrl_probe(struct platform_device *pdev)
{
return s32v_pinctrl_probe(pdev, &s32v234_pinctrl_info);
}
static struct platform_driver s32v234_pinctrl_driver = {
.driver = {
.name = "s32v234-siul2",
.owner = THIS_MODULE,
.of_match_table = s32v234_pinctrl_of_match,
},
.probe = s32v234_pinctrl_probe,
.remove = s32v_pinctrl_remove,
};
module_platform_driver(s32v234_pinctrl_driver);
MODULE_DESCRIPTION("Freescale S32V234 pinctrl driver");
MODULE_LICENSE("GPL v2");

View File

@ -747,6 +747,7 @@
#define IMX8QXP_QSPI0B_SS1_B_LSIO_QSPI1A_SS1_B IMX8QXP_QSPI0B_SS1_B 1
#define IMX8QXP_QSPI0B_SS1_B_LSIO_KPP0_ROW3 IMX8QXP_QSPI0B_SS1_B 2
#define IMX8QXP_QSPI0B_SS1_B_LSIO_GPIO3_IO24 IMX8QXP_QSPI0B_SS1_B 4
#define IMX8QXP_COMP_CTL_GPIO_1V8_3V3_GPIORHB_PAD IMX8QXP_COMP_CTL_GPIO_1V8_3V3_GPIORHB 0
/*!
* @name Fake Pad Mux Definitions

File diff suppressed because it is too large Load Diff

View File

@ -435,6 +435,15 @@
#define IMX6SX_GPR4_FEC_ENET1_STOP_REQ (0x1 << 3)
#define IMX6SX_GPR4_FEC_ENET2_STOP_REQ (0x1 << 4)
#define IMX6SX_GPR2_MQS_OVERSAMPLE_MASK (0x1 << 26)
#define IMX6SX_GPR2_MQS_OVERSAMPLE_SHIFT (26)
#define IMX6SX_GPR2_MQS_EN_MASK (0x1 << 25)
#define IMX6SX_GPR2_MQS_EN_SHIFT (25)
#define IMX6SX_GPR2_MQS_SW_RST_MASK (0x1 << 24)
#define IMX6SX_GPR2_MQS_SW_RST_SHIFT (24)
#define IMX6SX_GPR2_MQS_CLK_DIV_MASK (0xFF << 16)
#define IMX6SX_GPR2_MQS_CLK_DIV_SHIFT (16)
#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_MASK (0x1 << 3)
#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF1 (0x0 << 3)
#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF2 (0x1 << 3)