柚子快报邀请码778899分享:syscon 的使用【转】
转自:https://blog.csdn.net/tiantao2012/article/details/73770520
如果在dts中有如下节点, dsaf0: dsa@c7000000 { #address-cells = <1>; #size-cells = <0>; compatible = "hisilicon,hns-dsaf-v2"; mode = "6port-16rss"; reg = <0x0 0xc5000000 0x0 0x890000 0x0 0xc7000000 0x0 0x600000>; reg-names = "ppe-base", "dsaf-base"; interrupt-parent = <&mbigen_dsaf0>; subctrl-syscon = <&dsa_subctrl>; }我们可以通过of_parse_phandle 就能拿到subctrl-sysconnp_temp = of_parse_phandle(np, "subctrl-syscon", 0);
这里subctrl-syscon的之定义如下:
dsa_subctrl: dsa_subctrl@c0000000 { compatible = "hisilicon,dsa-subctrl", "syscon"; reg = <0x0 0xc0000000 0x0 0x10000>; };然后我们就可以通过syscon_node_to_regmap来为np_temp 做映射,这里的syscon的类型是 struct regmap *syscon;
syscon = syscon_node_to_regmap(np_temp);
这样后续就可以通过写dsa_subctrl 中定义的reg寄存器dsaf_write_syscon(dsaf_dev->sub_ctrl, reg, val);static inline void dsaf_write_syscon(struct regmap *base, u32 reg, u32 value){ regmap_write(base, reg, value);}
那下来我们看看syscon_node_to_regmap的实现,其源代码同样在/drivers/mfd/syscon.c 中struct regmap *syscon_node_to_regmap(struct device_node *np)118 {119 struct syscon *entry, *syscon = NULL;120 121 spin_lock(&syscon_list_slock);122 //首先在syscon_list 中查找是否已经有syscon,第一次的话,肯定是没有123 list_for_each_entry(entry, &syscon_list, list)124 if (entry->np == np) {125 syscon = entry;126 break;127 }128 129 spin_unlock(&syscon_list_slock);130 //第一次syscon是空的,调用of_syscon_register131 if (!syscon)132 syscon = of_syscon_register(np);133 134 if (IS_ERR(syscon))135 return ERR_CAST(syscon);136 137 return syscon->regmap;138 }
45 static struct syscon *of_syscon_register(struct device_node *np)46 {47 struct syscon *syscon;48 struct regmap *regmap;49 void __iomem *base;50 u32 reg_io_width;51 int ret;52 struct regmap_config syscon_config = syscon_regmap_config;53 struct resource res;54 //如果dts中不包含syscon,则直接退出55 if (!of_device_is_compatible(np, "syscon"))56 return ERR_PTR(-EINVAL);57 //申请空间,调用kzalloc申请的空间自动清零了,免去额外调用memset清零的动作58 syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);59 if (!syscon)60 return ERR_PTR(-ENOMEM);61 //得到resource 资源,也就是上面dts中定义的reg62 if (of_address_to_resource(np, 0, &res)) {63 ret = -ENOMEM;64 goto err_map;65 }66 //对res做虚拟地址的映射67 base = ioremap(res.start, resource_size(&res));68 if (!base) {69 ret = -ENOMEM;70 goto err_map;71 }72 //字符的格式是big-endian/little-endian/native-endian73 /* Parse the device's DT node for an endianness specification */74 if (of_property_read_bool(np, "big-endian"))75 syscon_config.val_format_endian = REGMAP_ENDIAN_BIG;76 else if (of_property_read_bool(np, "little-endian"))77 syscon_config.val_format_endian = REGMAP_ENDIAN_LITTLE;78 else if (of_property_read_bool(np, "native-endian"))79 syscon_config.val_format_endian = REGMAP_ENDIAN_NATIVE;80 81 /*82 * search for reg-io-width property in DT. If it is not provided,83 * default to 4 bytes. regmap_init_mmio will return an error if values84 * are invalid so there is no need to check them here.85 */ 得到寄存器的长度,默认是4个byte86 ret = of_property_read_u32(np, "reg-io-width", ®_io_width);87 if (ret)88 reg_io_width = 4;89 90 syscon_config.reg_stride = reg_io_width;91 syscon_config.val_bits = reg_io_width * 8;92 syscon_config.max_register = resource_size(&res) - reg_io_width;93 94 regmap = regmap_init_mmio(NULL, base, &syscon_config);95 if (IS_ERR(regmap)) {96 pr_err("regmap init failed\n");97 ret = PTR_ERR(regmap);98 goto err_regmap;99 }100 101 syscon->regmap = regmap;102 syscon->np = np;103 104 spin_lock(&syscon_list_slock); //将这里初始化的syscon 添加到全局变量syscon_list 中,这样下一次调用syscon_node_to_regmap 时就会在syscon_list 中找到了105 list_add_tail(&syscon->list, &syscon_list);106 spin_unlock(&syscon_list_slock);107 108 return syscon;109 110 err_regmap:111 iounmap(base);112 err_map:113 kfree(syscon);114 return ERR_PTR(ret);115 }
继续看regmap_init_mmio
624 #define regmap_init_mmio(dev, regs, config) \625 regmap_init_mmio_clk(dev, NULL, regs, config)626
726 #define devm_regmap_init_mmio_clk(dev, clk_id, regs, config) \727 __regmap_lockdep_wrapper(__devm_regmap_init_mmio_clk, #config, \728 dev, clk_id, regs, config)729 前面的文章分析过__regmap_lockdep_wrapper 是空函数,因此devm_regmap_init_mmio_clk 就等于__devm_regmap_init_mmio_clk,而这个函数之前已经分析过了。————————————————版权声明:本文为CSDN博主「tiantao2012」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/tiantao2012/article/details/73770520
柚子快报邀请码778899分享:syscon 的使用【转】
精彩链接
发表评论