#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/slab.h>
#include <linux/regmap.h>
#include "core.h"
#include "pinconf.h"
#include "pinmux.h"
#include "virt_pinctrl_driver.h"
#define VIRT_PIN_SIZE (4*4)
#define VIRT_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
enum virt_pinctrl_pads {
VIRT_PINCTRL_PAD_PIN0 = 0,
VIRT_PINCTRL_PAD_PIN1 = 1,
VIRT_PINCTRL_PAD_PIN2 = 2,
VIRT_PINCTRL_PAD_PIN3 = 3,
VIRT_PINCTRL_PAD_PIN4 = 4,
VIRT_PINCTRL_PAD_PIN5 = 5,
VIRT_PINCTRL_PAD_PIN6 = 6,
VIRT_PINCTRL_PAD_PIN7 = 7,
VIRT_PINCTRL_PAD_PIN8 = 8,
VIRT_PINCTRL_PAD_PIN9 = 9,
VIRT_PINCTRL_PAD_PIN10 = 10,
VIRT_PINCTRL_PAD_PIN11 = 11,
VIRT_PINCTRL_PAD_PIN12 = 12,
VIRT_PINCTRL_PAD_PIN13 = 13,
VIRT_PINCTRL_PAD_PIN14 = 14,
VIRT_PINCTRL_PAD_PIN15 = 15,
};
/* Pad names for the pinmux subsystem */
static const struct pinctrl_pin_desc virt_pinctrl_pads[] = {
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN0),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN1),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN2),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN3),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN4),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN5),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN6),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN7),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN8),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN9),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN10),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN11),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN12),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN13),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN14),
VIRT_PINCTRL_PIN(VIRT_PINCTRL_PAD_PIN15),
};
static inline const struct group_desc *virt_pinctrl_find_group_by_name(
struct pinctrl_dev *pctldev,
const char *name)
{
const struct group_desc *grp = NULL;
int i;
for (i = 0; i < pctldev->num_groups; i++) {
grp = pinctrl_generic_get_group(pctldev, i);
if (grp && !strcmp(grp->name, name))
break;
}
return grp;
}
static void virt_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset)
{
seq_printf(s, "%s", dev_name(pctldev->dev));
}
static int virt_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map, unsigned *num_maps)
{
int i, j;
int map_num = 1;
struct virt_pin *pin;
struct device_node *parent;
struct pinctrl_map *new_map;
const struct group_desc *grp;
struct virt_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
grp = virt_pinctrl_find_group_by_name(pctldev, np->name);
if (!grp) {
dev_err(ipctl->dev, "unable to find group for node %pOFn\n", np);
return -EINVAL;
}
map_num += grp->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 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->num_pins; i++) {
pin = &((struct virt_pin *)(grp->data))[i];
new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
new_map[j].data.configs.group_or_pin = pin_get_name(pctldev, pin->pin);
new_map[j].data.configs.configs = (unsigned long *)&pin->config;
new_map[j].data.configs.num_configs = 1;
j++;
}
printk("maps: function %s group %s num %d\n",
(*map)->data.mux.function, (*map)->data.mux.group, map_num);
return 0;
}
static void virt_dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
kfree(map);
}
static const struct pinctrl_ops virt_pctrl_ops = {
.get_groups_count = pinctrl_generic_get_group_count,
.get_group_name = pinctrl_generic_get_group_name,
.get_group_pins = pinctrl_generic_get_group_pins,
.pin_dbg_show = virt_pin_dbg_show,
.dt_node_to_map = virt_dt_node_to_map,
.dt_free_map = virt_dt_free_map,
};
static int virt_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group)
{
struct virt_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
struct function_desc *func;
struct group_desc *grp;
struct virt_pin *pin;
unsigned int npins;
int i;
/*
* Configure the mux mode for each pin in the group for a specific
* function.
*/
grp = pinctrl_generic_get_group(pctldev, group);
if (!grp)
return -EINVAL;
func = pinmux_generic_get_function(pctldev, selector);
if (!func)
return -EINVAL;
npins = grp->num_pins;
printk("enable function %s group %s\n", func->name, grp->name);
for (i = 0; i < npins; i++) {
pin = &((struct virt_pin *)(grp->data))[i];
/**
* 设置Pin的配置到具体的寄存器。
* 因为是虚拟Pinctrl,所以在这里只是打印,忽略具体操作。
*/
printk("%s() Pin[%02d] = {0x%X, 0x%X, 0x%X}\n", __func__, pin->pin, pin->config.reg_addr, pin->config.mux_mode, pin->config.pin_conf);
ipctl->configs[pin->pin].reg_addr = pin->config.reg_addr; // 保存Pin的寄存器地址
ipctl->configs[pin->pin].mux_mode = pin->config.mux_mode; // 模拟写入Mux复用寄存器,将Pin设置到对应的模式。
}
return 0;
}
struct pinmux_ops virt_pmx_ops = {
.get_functions_count = pinmux_generic_get_function_count,
.get_function_name = pinmux_generic_get_function_name,
.get_function_groups = pinmux_generic_get_function_groups,
.set_mux = virt_pmx_set,
};
static int virt_pinconf_set(struct pinctrl_dev *pctldev,
unsigned pin_id, unsigned long *configs,
unsigned num_configs)
{
struct virt_pin_config *config = (struct virt_pin_config *)configs;
struct virt_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
// Note:num_configs在这里为1,virt_dt_node_to_map函数里面每个Pin都只有一个Config
ipctl->configs[pin_id].reg_addr = config->reg_addr; // 保存Pin的寄存器地址
ipctl->configs[pin_id].pin_conf = config->pin_conf; // 模拟写入Config配置寄存器,将Pin设置到对应的配置。
printk("%s() Pin[%02d] = {0x%X, 0x%X, 0x%X}\n", __func__,
pin_id, ipctl->configs[pin_id].reg_addr, ipctl->configs[pin_id].mux_mode, ipctl->configs[pin_id].pin_conf);
return 0;
}
static void virt_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
{
struct virt_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
seq_printf(s, "Mux=0x%x Config=0x%x", ipctl->configs[pin_id].mux_mode, ipctl->configs[pin_id].pin_conf);
}
static void virt_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned group)
{
struct group_desc *grp;
const char *name;
int i;
if (group >= pctldev->num_groups)
return;
seq_puts(s, "\n");
grp = pinctrl_generic_get_group(pctldev, group);
if (!grp)
return;
for (i = 0; i < grp->num_pins; i++) {
struct virt_pin *pin = &((struct virt_pin *)(grp->data))[i];
name = pin_get_name(pctldev, pin->pin);
seq_printf(s, " %s: Mux=0x%x Config=0x%x\n", name, pin->config.mux_mode, pin->config.pin_conf);
}
}
static const struct pinconf_ops virt_pinconf_ops = {
.pin_config_set = virt_pinconf_set,
.pin_config_dbg_show = virt_pinconf_dbg_show,
.pin_config_group_dbg_show = virt_pinconf_group_dbg_show,
};
static void virt_pinctrl_parse_pin_config(struct virt_pinctrl *ipctl,
unsigned int *pin_id, struct virt_pin *pin,
const __be32 **list_p,
struct device_node *np)
{
const __be32 *list = *list_p;
struct virt_pin_config *pin_confi
没有合适的资源?快使用搜索试试~ 我知道了~
虚拟Pinctrl Demo驱动
共6个文件
c:2个
h:2个
makefile:1个
需积分: 16 5 下载量 31 浏览量
2022-10-04
11:03:03
上传
评论
收藏 10KB RAR 举报
温馨提示
基于linux平台虚拟的pinctrl demo驱动,适用于嵌入linux pinctrl子系统架构学习。对应参考的博客地址:https://blog.csdn.net/ZHONGCAI0901/article/details/127140709
资源详情
资源评论
资源推荐
收起资源包目录
10_virt_pinctrl.rar (6个子文件)
10_virt_pinctrl
virt_pinctrl_driver.h 537B
virt_pinctrl_client.c 2KB
imx6ull-benjamin-emmc.dts 18KB
virt_pinctrl_driver.c 13KB
imx6ull-benjamin-pinfun.h 1KB
Makefile 869B
共 6 条
- 1
ZHONGCAI0901
- 粉丝: 197
- 资源: 31
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0