SOC由于外设众多管脚不够用普片使用管脚复用,在LINUX下专门有个Pinctrl的子系统进行复用管脚的管理。我再这就描述相关的系统架构,只是简单的描述一下实例和使用说明。我使用的810芯片CAN1管脚需要配置复用,下面是我操作实现方式。
详细介绍建议查看https://blog.csdn.net/u012830148/article/details/80609337 相关说明。
添加一个Pintrl定义CAN1
LINUX驱动下SOC的PIN管脚控制已经完整的定义好了,无需要去修改。我们添加一个Pintrl的定义其实只是提供一个Pin的复用选择组合,我们拿CAN1的Pintrl添加进行说明。
1.首先是添加一个CAN1 pin管脚组合,pin管脚组合表示CAN1要使用到哪个管脚:
static const u32 can_1_pins[] = {8, 9};
其中管脚定义8 9 从下面来的,SOC中的CAN和UART1_RXD、UART1_TXD复用。在管脚描述时只用了UART1的名称。但是没有关系只是个名称不影响使用,我们直接选用8、9。
static const struct pinctrl_pin_desc oa**1_pins[] = {
/* Pins along the ***1 Pin Assignment Table */
DEFINE_PINCTRL_REG(6, "UART0_RXD", &pin_6_func),
DEFINE_PINCTRL_REG(7, "UART0_TXD", &pin_7_func),
DEFINE_PINCTRL_REG(8, "UART1_RXD", &pin_8_func),
DEFINE_PINCTRL_REG(9, "UART1_TXD", &pin_9_func),
******
2.在添加DEFINE_OA***1_PINCTRL_GRP(can_1, 1), 注意后面的是1,表明复用选择是复用1而不是上电默认复用0。
static const struct OA***1_pctrl_group OA***1_pctrl_groups[] = {
******
DEFINE_OA***1_PINCTRL_GRP(can_1, 1),
DEFINE_OA***1_PINCTRL_GRP(ext_irq, 1),
******
3.需要确认一下pin_8和pin_9的pin share设置有加入,而且是加入到对应的第二项。
static const struct pin_share_reg pin_8[] = {
PIN_SHARE_REG(0, 0x190, 4, 0, 0x198, 21, 0), /* UART1 RXD */
PIN_SHARE_REG(1, 0x190, 4, 1, 0x198, 21, 0), /* CAN1 RXD */
PIN_SHARE_REG(2, 0x190, 4, 0, 0x198, 21, 1), /* 2ND GPIO 35 */
};
static const struct pin_function pin_8_func = PIN_SHARE_FUN(pin_8);
static const struct pin_share_reg pin_9[] = {
PIN_SHARE_REG(0, 0x190, 4, 0, 0x198, 22, 0), /* UART1 TXD */
PIN_SHARE_REG(1, 0x190, 4, 1, 0x198, 22, 0), /* CAN1 TXD */
PIN_SHARE_REG(2, 0x190, 4, 0, 0x198, 22, 1), /* 2ND GPIO 36 */
};
static const struct pin_function pin_9_func = PIN_SHARE_FUN(pin_9);
4.添加funtion groups 这个部分将和DTS中的管脚复用选择关联。
static const char *const can_1_groups[] = {"can_1_grp"};
5.在定义中加入can_1的枚举(注意该部分和后面的 pmux_functions有关联,添加顺序要对应)
enum oa***1_pmux_functions_e {
*****
oa***1_pmux_can_0,
oa***1_pmux_can_1,
oa***1_pmux_ext_irq,
*****
5.添加一个const struct 对应的can1 ,需要注意的是这个部分和前面的enum oa***1_pmux_functions_e有关联,相关添加内容位置要对应。
#define DEFINE_OA***1_PINMUX_FUNCTION(fname) \
[oa***1_pmux_##fname] = { \
.name = #fname, \
.groups = fname##_groups, \
.ngroups = ARRAY_SIZE(fname##_groups), \
}
static const struct oa***1_pmux_function oa***1_pmux_functions[] = {
*****
DEFINE_OA***1_PINCTRL_GRP(can_0, 0),
DEFINE_OA***1_PINCTRL_GRP(can_1, 1),
DEFINE_OA***1_PINCTRL_GRP(ext_irq, 1),
*****
已配置好的管脚复用使用说明
如果相关的管脚配置在程序中已经配置完成了只需在你的DTS对应的模块中添加相关选择:
目录:
在pinctrl的DST中添加,注意名称对应关系
pinctrl: pinctrl@0xf0c20000 {
*****
mux {
function = "can_1";//对应驱动中的DEFINE_OA***1_PINCTRL_GRP(can_1, 1),
groups = "can_1_grp";//对应驱动中的static const char *const can_1_groups[] = {"can_1_grp"};
};
*****
};
例如CAN 添加 pinctrl-0 = <&can_0>; 如果有多个复用pinctrl-names比如有2个,可以继续添加 pinctrl-1 = <&**>对应pinctrl-names的第二个;
这样当初始化该模块功能是对应的Pintrl将自动初始化对应GPIO复用功能。
can1@f0bd0000 {
compatible = “XXX,sja1000”;
reg = <0xf0bd0000 0x4000>;
interrupts = <0 41 4>;
clocks = <&high_apb_clk>;
orbita,external-clock-frequency = <100000000>;
orbita,tx-output-config = <0x16>;
orbita,no-comparator-bypass;
reg-io-width = <0x4>;
pinctrl-names = “default”;
pinctrl-0 = <&can_1>;
status = “okay”;
};
SPI 外扩CAN
&pio {
exti-nirqs = <16>;
adc22:adc22{
pins = "PB5";
function = "adc22_ir";
};
gpio_mcp_out:gpio_mcp_out{//MCP TX PIN
pins = "PA2", "PA3", "PA4";
function = "gpio";
xrobot,drive = <xrobot_PINCTRL_2_MA>;
xrobot,pull = <xrobot_PINCTRL_PULL_UP>;
};
};
&spi1 {
status = "okay";
compatible = "XXXX,r7-spi";
dmas = <&dma0 DMA0_HARDTRIG_SRC_SPI1_RX>, <&dma0 DMA0_HARDTRIG_SRC_SPI1_TX>;
dma-names = "rx", "tx";
fifo_trig_level = <8>;
pinctrl-names = "default";
#if 0
pinctrl-0 = <&spi1_9 &gpio_mcp_out>;//多个并列
#else
pinctrl-0 = <&spi1_9>;
#endif
//pinctrl-0 = <&spi0_5>;
//bus-width = <1>;
mcp251x0: can@1 {
compatible = "microchip,mcp2515";
reg = <0>;
clocks = <&clk20m>;
reset-gpios = <&pio 5 13 GPIO_ACTIVE_HIGH>; /* PF13 */
interrupt-parent = <&pio>;
interrupts = <94 IRQ_TYPE_EDGE_FALLING>;/* PF14=16*5+14 */
spi-max-frequency = <10000000>;
status = "okay";
};
};