柚子快报邀请码778899分享:syscon 的使用【转】

http://yzkb.51969.com/

转自: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 的使用【转】

http://yzkb.51969.com/

精彩链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。