Files
2026-08-24 14:17:12 +08:00

553 lines
19 KiB
C

// SPDX-License-Identifier: GPL-2.0
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <asm/io.h>
#include <linux/seq_file.h>
#include "core.h"
#include "pinctrl-utils.h"
/*
useful groups:
"sata_led", "gmac1", "dvo0_lio_uart", "dvo1_camera", "can0", "can1",
"hda_i2s", "i2c0", "i2c1", "uart0", "uart1", "uart2", "nand",
"pwm0", "pwm1", "pwm2", "pwm3", "sdio"
*/
/*
useful functions:
"sata_led", "gpio", "gmac1", "dvo0", "lio",
"uart1_4", "uart1_2", "uart1_1", "uart2_4", "uart2_2", "uart2_1",
"dvo1", "camera", "can0", "can1", "hda", "i2s", "i2c0", "i2c1",
"uart0_4", "uart0_2", "uart0_1",
"nand", "pwm0", "pwm1", "pwm2", "pwm3", "sdio"
*/
/*
* usage:
uart2_4_default:uart2_4 {
mux {
groups = "uart2";
function = "uart2_4";
};
};
----------------------------------
uart_group1: bus1 {
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
pinctrl-names = "default";
pinctrl-0 = <&uart1_4_default>;
groups 能用什么 functions 见于 使用FUNCTION_GROUP_MAP_CREATE宏的代码
一份dts里面理论上不能出现同样的 groups的使用。像上面的声明可以有相同的组
但是在 类似 uart_group1: bus1 里面 pinctrl-0这样就不能用到同样的 groups
*/
#define PMX_GROUP(group_name) \
{ \
.name = #group_name, \
.pins = group_name ## _pins, \
.num_pins = ARRAY_SIZE(group_name ## _pins), \
.bit_size = ARRAY_SIZE(group_name ## _reg), \
.reg = group_name ## _reg, \
.bit = group_name ## _bit, \
.bit_width = group_name ## _bit_width, \
}
#define FUNCTION_GROUP_MAP_CREATE(function, single_groups) \
static const char * const function##_function_groups[] = { \
single_groups \
}
#define FUNCTION(fn, handle_func, value, mask) \
{ \
.name = #fn, \
.groups = fn ## _function_groups, \
.num_groups = ARRAY_SIZE(fn ## _function_groups), \
.mul_bit_zone_handle_func = handle_func, \
.bit_value = value,\
.bit_mask = mask,\
}
struct ls2k_pinctrl {
struct device *dev;
struct pinctrl_dev *pcdev;
struct pinctrl_desc desc;
struct device_node *of_node;
raw_spinlock_t lock;
void * __iomem reg_base;
};
struct ls2k_pmx_group {
const char *name;
const unsigned int *pins;
unsigned int num_pins;
unsigned char bit_size;
unsigned int* reg;
unsigned int* bit;
unsigned char* bit_width;
};
struct ls2k_pmx_func {
const char *name;
const char * const *groups;
unsigned int num_groups;
int (*mul_bit_zone_handle_func)(unsigned long, unsigned int);
unsigned int* bit_value;
unsigned char* bit_mask;
};
/*
* register pin desc but not so important
* because ls2k1000 pin No is compilcate such as Y22
* so dont match to all pin
*/
#define LS2K_PIN(pin_num, groups) PINCTRL_PIN(pin_num, groups)
static const struct pinctrl_pin_desc ls2k_pctrl_pins[] = {
LS2K_PIN(1, "SATA_LEDN"),
LS2K_PIN(2, "GMAC1_14_pin"),
LS2K_PIN(17, "uart1_dvo0_pin"),
LS2K_PIN(3, "uart2_dvo0_pin"),
LS2K_PIN(4, "dvo1_camera_pin"),
LS2K_PIN(5, "can0"), LS2K_PIN(6, "can1"),
LS2K_PIN(7, "hda_i2s"),
LS2K_PIN(8, "i2c0"), LS2K_PIN(9, "i2c1"),
LS2K_PIN(10, "uart0"),
LS2K_PIN(11, "nand"),
LS2K_PIN(12, "pwm0"), LS2K_PIN(13, "pwm1"), LS2K_PIN(14, "pwm2"), LS2K_PIN(15, "pwm3"),
LS2K_PIN(16, "sdio"),
};
/*
* 下面的数组 可以观测得知 一共分为 _pins _reg _bit _bit_width四大组
* 然后每个数组的前缀都是groups里面的一个 比如 sata_led uart等等
* 如果需要添加,那么希望按照这个规则添加
* 因为这些都是为了契合 PMX_GROUP 这个宏
* 而这个宏的目的 就是为了 填充 ls2k_pmx_group 变量
* group_name ## _pins 这样是把宏参数和_pins拼接,那么就明白为什么数组的名字要这样命名。
* _pins 数组是groups包括的引脚的物理编号的集合,呼应ls2k_pctrl_pins,事实上如果为空或者乱填也没关系。
* _reg 数组是配置寄存器相对于基地址的偏移值的集合 有多少个要设置的位域就要有多少个元素
* _bit 数组是配置寄存器中要设置的位域的最低位的偏移值 从0开始算,芯片手册的配置寄存器可知。
* _bit_width 数组是配置寄存器中要设置的位域的位宽,和 _bit 数组就能描述这个位域的位置。
*/
static const unsigned int sata_led_pins[]={1};
static const unsigned int gmac1_pins[]={2};
static const unsigned int dvo0_lio_uart_pins[]={3, 17};
static const unsigned int uart1_pins[]={17};
static const unsigned int uart2_pins[]={3};
static const unsigned int dvo1_camera_pins[]={4};
static const unsigned int can0_pins[]={5};
static const unsigned int can1_pins[]={6};
static const unsigned int hda_i2s_pins[]={7};
static const unsigned int i2c0_pins[]={8};
static const unsigned int i2c1_pins[]={9};
static const unsigned int uart0_pins[]={10};
static const unsigned int nand_pins[]={11};
static const unsigned int pwm0_pins[]={12};
static const unsigned int pwm1_pins[]={13};
static const unsigned int pwm2_pins[]={14};
static const unsigned int pwm3_pins[]={15};
static const unsigned int sdio_pins[]={16};
static unsigned int sata_led_reg[] = {0};
static unsigned int gmac1_reg[] = {0};
static unsigned int dvo0_lio_uart_reg[] = {0x10, 0x8, 0x8, 0, 0x8, 0x8};
static unsigned int uart1_reg[] = {0x10, 0x8, 0x8, 0, 0x8, 0x8};
static unsigned int uart2_reg[] = {0x10, 0x8, 0x8, 0, 0x8, 0x8};
static unsigned int dvo1_camera_reg[] = {0x10, 0x10};
static unsigned int can0_reg[] = {0};
static unsigned int can1_reg[] = {0};
static unsigned int hda_i2s_reg[] = {0, 0};
static unsigned int i2c0_reg[] = {0};
static unsigned int i2c1_reg[] = {0};
static unsigned int uart0_reg[] = {0x8};
static unsigned int nand_reg[] = {0};
static unsigned int pwm0_reg[] = {0};
static unsigned int pwm1_reg[] = {0};
static unsigned int pwm2_reg[] = {0};
static unsigned int pwm3_reg[] = {0};
static unsigned int sdio_reg[] = {0};
static unsigned int sata_led_bit[] = {8};
static unsigned int gmac1_bit[] = {3};
static unsigned int dvo0_lio_uart_bit[] = {1, 12, 13, 7, 4, 8};
static unsigned int uart1_bit[] = {1, 12, 13, 7, 4, 8};
static unsigned int uart2_bit[] = {1, 12, 13, 7, 4, 8};
static unsigned int dvo1_camera_bit[] = {4, 5};
static unsigned int can0_bit[] = {16};
static unsigned int can1_bit[] = {17};
static unsigned int hda_i2s_bit[] = {6, 4};
static unsigned int i2c0_bit[] = {10};
static unsigned int i2c1_bit[] = {11};
static unsigned int uart0_bit[] = {0};
static unsigned int nand_bit[] = {9};
static unsigned int pwm0_bit[] = {12};
static unsigned int pwm1_bit[] = {13};
static unsigned int pwm2_bit[] = {14};
static unsigned int pwm3_bit[] = {15};
static unsigned int sdio_bit[] = {20};
static unsigned char sata_led_bit_width[] = {1};
static unsigned char gmac1_bit_width[] = {1};
static unsigned char dvo0_lio_uart_bit_width[] = {1, 1, 1, 1, 4, 4};
static unsigned char uart1_bit_width[] = {1, 1, 1, 1, 4, 4};
static unsigned char uart2_bit_width[] = {1, 1, 1, 1, 4, 4};
static unsigned char dvo1_camera_bit_width[] = {1, 1};
static unsigned char can0_bit_width[] = {1};
static unsigned char can1_bit_width[] = {1};
static unsigned char hda_i2s_bit_width[] = {1, 1};
static unsigned char i2c0_bit_width[] = {1};
static unsigned char i2c1_bit_width[] = {1};
static unsigned char uart0_bit_width[] = {4};
static unsigned char nand_bit_width[] = {1};
static unsigned char pwm0_bit_width[] = {1};
static unsigned char pwm1_bit_width[] = {1};
static unsigned char pwm2_bit_width[] = {1};
static unsigned char pwm3_bit_width[] = {1};
static unsigned char sdio_bit_width[] = {1};
//上面的数组就是在这里用的。
static struct ls2k_pmx_group ls2k_pmx_groups[] = {
PMX_GROUP(sata_led),
PMX_GROUP(gmac1),
PMX_GROUP(dvo0_lio_uart),
PMX_GROUP(uart1),
PMX_GROUP(uart2),
PMX_GROUP(dvo1_camera),
PMX_GROUP(can0),
PMX_GROUP(can1),
PMX_GROUP(hda_i2s),
PMX_GROUP(i2c0),
PMX_GROUP(i2c1),
PMX_GROUP(uart0),
PMX_GROUP(nand),
PMX_GROUP(pwm0),
PMX_GROUP(pwm1),
PMX_GROUP(pwm2),
PMX_GROUP(pwm3),
PMX_GROUP(sdio),
};
/*
* 这里管理的是function
* 包括 function所属的groups(这个groups可以设置的functions) 和 怎么设置配置寄存器让function生效
* FUNCTION_GROUP_MAP_CREATE 做的工作其实就是声明一个 _function_groups数组
* 这个数组里面的字符串就是宏参数。
* 数组前缀是function的名字 数组里面的内容是groups的名字
* 这里的含义就是 function所属的groups(这个groups可以设置的functions) 的声明
* 接着下面的那些数字的数组,就是functions生效的那些配置寄存器的位域的值
* 那些数组还要对应上面的_bit _bit_width 数组 见芯片手册
* 比如 dvo0 lio uart12 这样的复用 要控制6个位域 所以对应有6个值
* 但是uart1 和 uart2 是能共存的 所以在 uart1_4_bit_mask 和类似的数组 里面 会有0
* 0 代表对应的位域不设置,这样就能实现共存。
*
* FUNCTION 宏代表的是 ls2k_pmx_func 变量的填充
* 第1个参数是 fucntion的名字 会用在填充 对应 _function_groups 数组到对应的变量中
* 第2个 是指代function有多个 groups的情况 比如 gpio 这个function
* 可以发现很多个groups都是可以用的,那么如果还是用给定数组来设置位域,那么将会多很多代码
* 所以把这个过程 使用一个回调函数来实现 见于 ls2k_pmx_set_mux_handle_gpio 的实现
* 如果 满足通用的设置方法 那么 填入 NULL 并 写好 第3 4参数
* 第 3 和 第4个参数 就是 位域的值的数组填充,使用另外一套生效办法 这套办法是通用的。
*/
//create const char * const[] name {func}_function_groups to use in ls2k_pmx_functions
FUNCTION_GROUP_MAP_CREATE(sata_led, "sata_led");
static const char * const gpio_function_groups[] = {
"sdio", "can1", "can0", "pwm3", "pwm2", "pwm1", "pwm0", "i2c1",
"i2c0", "nand", "sata_led", "hda_i2s"
};
FUNCTION_GROUP_MAP_CREATE(gmac1, "gmac1");
FUNCTION_GROUP_MAP_CREATE(dvo0, "dvo0_lio_uart");
FUNCTION_GROUP_MAP_CREATE(lio, "dvo0_lio_uart");
FUNCTION_GROUP_MAP_CREATE(uart1_4, "uart1");
FUNCTION_GROUP_MAP_CREATE(uart1_2, "uart1");
FUNCTION_GROUP_MAP_CREATE(uart1_1, "uart1");
FUNCTION_GROUP_MAP_CREATE(uart2_4, "uart2");
FUNCTION_GROUP_MAP_CREATE(uart2_2, "uart2");
FUNCTION_GROUP_MAP_CREATE(uart2_1, "uart2");
FUNCTION_GROUP_MAP_CREATE(dvo1, "dvo1_camera");
FUNCTION_GROUP_MAP_CREATE(camera, "dvo1_camera");
FUNCTION_GROUP_MAP_CREATE(can0, "can0");
FUNCTION_GROUP_MAP_CREATE(can1, "can1");
FUNCTION_GROUP_MAP_CREATE(hda, "hda_i2s");
FUNCTION_GROUP_MAP_CREATE(i2s, "hda_i2s");
FUNCTION_GROUP_MAP_CREATE(i2c0, "i2c0");
FUNCTION_GROUP_MAP_CREATE(i2c1, "i2c1");
FUNCTION_GROUP_MAP_CREATE(uart0_4, "uart0");
FUNCTION_GROUP_MAP_CREATE(uart0_2, "uart0");
FUNCTION_GROUP_MAP_CREATE(uart0_1, "uart0");
FUNCTION_GROUP_MAP_CREATE(nand, "nand");
FUNCTION_GROUP_MAP_CREATE(pwm0, "pwm0");
FUNCTION_GROUP_MAP_CREATE(pwm1, "pwm1");
FUNCTION_GROUP_MAP_CREATE(pwm2, "pwm2");
FUNCTION_GROUP_MAP_CREATE(pwm3, "pwm3");
FUNCTION_GROUP_MAP_CREATE(sdio, "sdio");
static unsigned int single_bit_1_on_value[] = {1};
static unsigned int dvo0_bit_value[] = {1, 0, 0, 0, 0, 0};
static unsigned int lio_bit_value[] = {0, 0, 0, 1, 0, 0};
static unsigned int uart1_4_bit_value[] = {0, 1, 0, 0, 0xf, 0};
static unsigned int uart1_2_bit_value[] = {0, 1, 0, 0, 0x3, 0};
static unsigned int uart1_1_bit_value[] = {0, 1, 0, 0, 0x1, 0};
static unsigned int uart2_4_bit_value[] = {0, 0, 1, 0, 0, 0xf};
static unsigned int uart2_2_bit_value[] = {0, 0, 1, 0, 0, 0x3};
static unsigned int uart2_1_bit_value[] = {0, 0, 1, 0, 0, 0x1};
static unsigned int dvo1_bit_value[] = {1, 0};
static unsigned int camera_bit_value[] = {0, 1};
static unsigned int hda_bit_value[] = {0, 1};
static unsigned int i2s_bit_value[] = {1, 0};
static unsigned int gen_uart_mode4_value[] = {0xf};
static unsigned int gen_uart_mode2_value[] = {0x3};
static unsigned int gen_uart_mode1_value[] = {0x1};
static unsigned char dvo0_bit_mask[] = {1, 1, 1, 1, 0, 0};
static unsigned char lio_bit_mask[] = {1, 1, 1, 1, 0, 0};
static unsigned char uart1_4_bit_mask[] = {1, 1, 0, 1, 1, 0};
static unsigned char uart1_2_bit_mask[] = {1, 1, 0, 1, 1, 0};
static unsigned char uart1_1_bit_mask[] = {1, 1, 0, 1, 1, 0};
static unsigned char uart2_4_bit_mask[] = {1, 0, 1, 1, 0, 1};
static unsigned char uart2_2_bit_mask[] = {1, 0, 1, 1, 0, 1};
static unsigned char uart2_1_bit_mask[] = {1, 0, 1, 1, 0, 1};
static int ls2k_pmx_set_mux_handle_gpio(unsigned long reg_base, unsigned int group_num);
static struct ls2k_pmx_func ls2k_pmx_functions[] = {
FUNCTION(sata_led, NULL, single_bit_1_on_value, NULL),
FUNCTION(gmac1, NULL, single_bit_1_on_value, NULL),
FUNCTION(gpio, ls2k_pmx_set_mux_handle_gpio, NULL, NULL),
FUNCTION(dvo0, NULL, dvo0_bit_value, dvo0_bit_mask),
FUNCTION(lio, NULL, lio_bit_value, lio_bit_mask),
FUNCTION(uart1_4, NULL, uart1_4_bit_value, uart1_4_bit_mask),
FUNCTION(uart1_2, NULL, uart1_2_bit_value, uart1_2_bit_mask),
FUNCTION(uart1_1, NULL, uart1_1_bit_value, uart1_1_bit_mask),
FUNCTION(uart2_4, NULL, uart2_4_bit_value, uart2_4_bit_mask),
FUNCTION(uart2_2, NULL, uart2_2_bit_value, uart2_2_bit_mask),
FUNCTION(uart2_1, NULL, uart2_1_bit_value, uart2_1_bit_mask),
FUNCTION(dvo1, NULL, dvo1_bit_value, NULL),
FUNCTION(camera, NULL, camera_bit_value, NULL),
FUNCTION(can0, NULL, single_bit_1_on_value, NULL),
FUNCTION(can1, NULL, single_bit_1_on_value, NULL),
FUNCTION(hda, NULL, hda_bit_value, NULL),
FUNCTION(i2s, NULL, i2s_bit_value, NULL),
FUNCTION(i2c0, NULL, single_bit_1_on_value, NULL),
FUNCTION(i2c1, NULL, single_bit_1_on_value, NULL),
FUNCTION(uart0_4, NULL, gen_uart_mode4_value, NULL),
FUNCTION(uart0_2, NULL, gen_uart_mode2_value, NULL),
FUNCTION(uart0_1, NULL, gen_uart_mode1_value, NULL),
FUNCTION(nand, NULL, single_bit_1_on_value, NULL),
FUNCTION(pwm0, NULL, single_bit_1_on_value, NULL),
FUNCTION(pwm1, NULL, single_bit_1_on_value, NULL),
FUNCTION(pwm2, NULL, single_bit_1_on_value, NULL),
FUNCTION(pwm3, NULL, single_bit_1_on_value, NULL),
FUNCTION(sdio, NULL, single_bit_1_on_value, NULL),
};
static int ls2k_get_groups_count(struct pinctrl_dev *pcdev)
{
return ARRAY_SIZE(ls2k_pmx_groups);
}
static const char *ls2k_get_group_name(struct pinctrl_dev *pcdev,
unsigned int selector)
{
return ls2k_pmx_groups[selector].name;
}
static int ls2k_get_group_pins(struct pinctrl_dev *pcdev, unsigned int selector,
const unsigned int **pins, unsigned int *num_pins)
{
*pins = ls2k_pmx_groups[selector].pins;
*num_pins = ls2k_pmx_groups[selector].num_pins;
return 0;
}
static void ls2k_pin_dbg_show(struct pinctrl_dev *pcdev, struct seq_file *s,
unsigned int offset)
{
seq_printf(s, " %s", dev_name(pcdev->dev));
}
static const struct pinctrl_ops ls2k_pctrl_ops = {
.get_groups_count = ls2k_get_groups_count,
.get_group_name = ls2k_get_group_name,
.get_group_pins = ls2k_get_group_pins,
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
.dt_free_map = pinctrl_utils_free_map,
.pin_dbg_show = ls2k_pin_dbg_show,
};
static int ls2k_pmx_set_mux_handle_gpio(unsigned long reg_base, unsigned int group_num)
{
int i;
unsigned char bit_size = ls2k_pmx_groups[group_num].bit_size;
unsigned int* reg_offset = ls2k_pmx_groups[group_num].reg;
unsigned int* bit = ls2k_pmx_groups[group_num].bit;
unsigned long reg_temp;
unsigned int val;
for(i = 0; i < bit_size; ++i) {
reg_temp = reg_base + reg_offset[i];
val = readl((void *)reg_temp);
val &= ~(1 << bit[i]); //gpio always be bit-0
writel(val, (void *)reg_temp);
}
return 0;
}
static int ls2k_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned int func_num,
unsigned int group_num)
{
int ret;
int i;
struct ls2k_pinctrl *pctrl = pinctrl_dev_get_drvdata(pcdev);
int (*handle_func)(unsigned long, unsigned int) = ls2k_pmx_functions[func_num].mul_bit_zone_handle_func;
unsigned int* bit_value = ls2k_pmx_functions[func_num].bit_value;
unsigned char* bit_mask = ls2k_pmx_functions[func_num].bit_mask;
unsigned char bit_size = ls2k_pmx_groups[group_num].bit_size;
unsigned int* reg_offset = ls2k_pmx_groups[group_num].reg;
unsigned int* bit = ls2k_pmx_groups[group_num].bit;
unsigned char* bit_width = ls2k_pmx_groups[group_num].bit_width;
unsigned long reg_base = (unsigned long)pctrl->reg_base;
unsigned long reg_temp;
unsigned int bit_value_temp;
unsigned int val;
unsigned int val_mask;
unsigned long flags;
raw_spin_lock_irqsave(&pctrl->lock, flags);
if(handle_func)
ret = handle_func(reg_base, group_num);
else {
for(i = 0; i < bit_size; ++i) {
reg_temp = reg_base + reg_offset[i];
if(!bit_mask || bit_mask[i]) {
bit_value_temp = bit_value[i];
bit_value_temp <<= bit[i];
//make bit filed mask
val_mask = 1 << bit_width[i];
--val_mask;
val_mask <<= bit[i];
val = readl((void *)reg_temp);
val &= ~val_mask; //use mask clear bit filed
val |= bit_value_temp; //value fix bit filed
writel(val, (void *)reg_temp);
}
}
ret = 0;
}
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return ret;
}
static int ls2k_pmx_get_funcs_count(struct pinctrl_dev *pcdev)
{
return ARRAY_SIZE(ls2k_pmx_functions);
}
static const char *ls2k_pmx_get_func_name(struct pinctrl_dev *pcdev,
unsigned int selector)
{
return ls2k_pmx_functions[selector].name;
}
static int ls2k_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned int selector,
const char * const **groups,
unsigned int * const num_groups)
{
*groups = ls2k_pmx_functions[selector].groups;
*num_groups = ls2k_pmx_functions[selector].num_groups;
return 0;
}
const struct pinmux_ops ls2k_pmx_ops = {
.set_mux = ls2k_pmx_set_mux,
.get_functions_count = ls2k_pmx_get_funcs_count,
.get_function_name = ls2k_pmx_get_func_name,
.get_function_groups = ls2k_pmx_get_groups,
};
static int ls2k_pinctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ls2k_pinctrl *pctrl;
struct resource *res;
pctrl = devm_kzalloc(dev, sizeof(struct ls2k_pinctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pctrl->reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(pctrl->reg_base))
return PTR_ERR(pctrl->reg_base);
raw_spin_lock_init(&pctrl->lock);
pctrl->dev = dev;
pctrl->desc.name = "pinctrl-ls2k";
pctrl->desc.owner = THIS_MODULE;
pctrl->desc.pctlops = &ls2k_pctrl_ops;
pctrl->desc.pmxops = &ls2k_pmx_ops;
pctrl->desc.confops = NULL;
pctrl->desc.pins = ls2k_pctrl_pins;
pctrl->desc.npins = ARRAY_SIZE(ls2k_pctrl_pins);
pctrl->pcdev = devm_pinctrl_register(pctrl->dev, &pctrl->desc, pctrl);
if (IS_ERR(pctrl->pcdev)) {
dev_err(pctrl->dev, "can't register pinctrl device");
return PTR_ERR(pctrl->pcdev);
}
return 0;
}
static const struct of_device_id ls2k_pinctrl_dt_match[] = {
{
.compatible = "loongson,2k1000-pinctrl",
},
{
.compatible = "loongson,ls2k-pinctrl",
},
{ },
};
static struct platform_driver ls2k_pinctrl_driver = {
.probe = ls2k_pinctrl_probe,
.driver = {
.name = "ls2k-pinctrl",
.of_match_table = ls2k_pinctrl_dt_match,
},
};
static int __init ls2k_pinctrl_init(void)
{
return platform_driver_register(&ls2k_pinctrl_driver);
}
arch_initcall(ls2k_pinctrl_init);
static void __exit ls2k_pinctrl_exit(void)
{
platform_driver_unregister(&ls2k_pinctrl_driver);
}
module_exit(ls2k_pinctrl_exit);