可锐资源网

技术资源分享平台,提供编程学习、网站建设、脚本开发教程

linux内核中syscon框架的使用_linux框架是什么

问题描述:

## Syscon框架的基本概念
Syscon框架是Linux内核提供的一种用于管理系统控制器寄存器的抽象层,它通过regmap接口为多个驱动程序提供对共享系统控制寄存器的统一访问方式。
Syscon框架封装了regmap接口,为驱动程序提供了简单、一致的寄存器访问接口。

## Syscon框架的使用场景
### 1. 多驱动共享系统控制器寄存器
当多个驱动程序需要访问同一组系统控制器寄存器时,syscon框架提供了统一的访问接口,避免了资源冲突。

示例场景 :

- 时钟控制器、电源管理器、复位控制器等多个驱动都需要访问系统控制寄存器
- 不同的外设驱动需要配置相同的系统控制寄存器中的不同位域

### 2. 系统级配置管理
系统启动和运行过程中的各种配置,如时钟 gating、电源域控制、复位控制等。

示例场景 :

- SoC系统初始化时的时钟配置
- 动态电源管理中的电源域开关控制
- 系统睡眠/唤醒过程中的寄存器配置

日志

添加打印日志信息

分析步骤

第1步:
第2步:
...

代码片段

设备树

/* 预留内存区域 */
reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    /* 4KB内存用于模拟寄存器 */
    syscon_mem: syscon-mem@10000000 {
        reg = <0x70000000 0x400>;
        no-map;
    };
};

/* syscon控制器 */
syscon_ctrl: syscon@0 {
    compatible = "syscon";
    reg = <0x70000000 0x400>;
    reg-io-width = <4>;
};

/* 测试设备 */
test_device0: test-device@0 {
    compatible = "demo,syscon-test";
    syscon = <&syscon_ctrl>;  /* 引用syscon控制器 */
    ctrl-reg = <0x00>;        /* 控制寄存器偏移 */
    data-reg = <0x04>;        /* 数据寄存器偏移 */
};

test_device1: test-device@1 {
    compatible = "demo,syscon-test1";
    syscon = <&syscon_ctrl>;  /* 引用syscon控制器 */
    ctrl-reg = <0x00>;        /* 控制寄存器偏移 */
    data-reg = <0x04>;        /* 数据寄存器偏移 */
};
设备驱动代码1:
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/of.h>

/* 寄存器位定义 */
#define CTRL_EN  BIT(0)
#define CTRL_RST BIT(1)

/* 驱动私有数据 */
struct test_dev_data {
    struct regmap *regmap;  /* syscon提供的regmap */
    u32 ctrl_reg;           /* 控制寄存器偏移 */
    u32 data_reg;           /* 数据寄存器偏移 */
};

/* 寄存器测试函数 */
static void test_reg_operations(struct test_dev_data *data)
{
    u32 val;

    /* 复位操作 */
    regmap_write(data->regmap, data->ctrl_reg, CTRL_RST);
    // msleep(10);

    /* 使能设备 */
    regmap_write(data->regmap, data->ctrl_reg, CTRL_EN);
    regmap_read(data->regmap, data->ctrl_reg, &val);
    pr_info("控制寄存器值: 0x%x (预期: 0x%x)\n", val, CTRL_EN);

    /* 数据读写测试 */
    regmap_write(data->regmap, data->data_reg, 0x55AA55AA);
    regmap_read(data->regmap, data->data_reg, &val);
    pr_info("数据寄存器值: 0x%x (预期: 0x55AA55AA)\n", val);
}

static int syscon_test_probe(struct platform_device *pdev)
{
    struct device *dev = &pdev->dev;
    struct test_dev_data *data;
    int ret;

    pr_info("syscon_test_probe\n");

    /* 分配私有数据 */
    data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    if (!data)
        return -ENOMEM;

    /* 获取syscon的regmap(核心操作) */
    data->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
    if (IS_ERR(data->regmap)) {
        ret = PTR_ERR(data->regmap);
        dev_err(dev, "获取syscon regmap失败: %d\n", ret);
        return ret;
    }

    /* 从设备树读取寄存器偏移 */
    ret = of_property_read_u32(dev->of_node, "ctrl-reg", &data->ctrl_reg);
    if (ret) {
        dev_err(dev, "缺少ctrl-reg属性\n");
        return ret;
    }

    ret = of_property_read_u32(dev->of_node, "data-reg", &data->data_reg);
    if (ret) {
        dev_err(dev, "缺少data-reg属性\n");
        return ret;
    }

    /* 执行寄存器测试 */
    test_reg_operations(data);

    platform_set_drvdata(pdev, data);
    dev_info(dev, "syscon测试驱动加载成功\n");
    return 0;
}

static int syscon_test_remove(struct platform_device *pdev)
{
    dev_info(&pdev->dev, "syscon测试驱动卸载\n");
    return 0;
}

/* 设备树匹配表 */
static const struct of_device_id syscon_test_of_match[] = {
    { .compatible = "demo,syscon-test" },
    { /* 哨兵 */ }
};
MODULE_DEVICE_TABLE(of, syscon_test_of_match);

static struct platform_driver syscon_test_driver = {
    .probe = syscon_test_probe,
    .remove = syscon_test_remove,
    .driver = {
        .name = "syscon-test-driver",
        .of_match_table = syscon_test_of_match,
    },
};
module_platform_driver(syscon_test_driver);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("简化的syscon测试驱动");


设备驱动代码2:
/*
 * @Author: your name
 * @Date: 2025-09-12 18:30:03
 * @LastEditTime: 2025-09-12 18:56:22
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \linux-4.4.159\drivers\gpu\drm\test\memsyscon copy.c
 */
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/of.h>

/* 寄存器位定义 */
#define CTRL_EN  BIT(0)
#define CTRL_RST BIT(1)

/* 驱动私有数据 */
struct test_dev_data {
    struct regmap *regmap;  /* syscon提供的regmap */
    u32 ctrl_reg;           /* 控制寄存器偏移 */
    u32 data_reg;           /* 数据寄存器偏移 */
};

/* 寄存器测试函数 */
static void test_reg_operations(struct test_dev_data *data)
{
    u32 val;

    /* 复位操作 */
    regmap_write(data->regmap, data->ctrl_reg, CTRL_RST);
    // msleep(10);

    /* 使能设备 */
    regmap_write(data->regmap, data->ctrl_reg, CTRL_EN);
    regmap_read(data->regmap, data->ctrl_reg, &val);
    pr_info("控制寄存器值: 0x%x (预期: 0x%x)\n", val, CTRL_EN);

    /* 数据读写测试 */
    regmap_write(data->regmap, data->data_reg, 0x55AA55AA);
    regmap_read(data->regmap, data->data_reg, &val);
    pr_info("数据寄存器值: 0x%x (预期: 0x55AA55AA)\n", val);
}

static int syscon_test_probe1(struct platform_device *pdev)
{
    struct device *dev = &pdev->dev;
    struct test_dev_data *data;
    int ret;

    pr_info("syscon_test_probe1\n");

    /* 分配私有数据 */
    data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    if (!data)
        return -ENOMEM;

    /* 获取syscon的regmap(核心操作) */
    data->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
    if (IS_ERR(data->regmap)) {
        ret = PTR_ERR(data->regmap);
        dev_err(dev, "获取syscon regmap失败: %d\n", ret);
        return ret;
    }

    /* 从设备树读取寄存器偏移 */
    ret = of_property_read_u32(dev->of_node, "ctrl-reg", &data->ctrl_reg);
    if (ret) {
        dev_err(dev, "缺少ctrl-reg属性\n");
        return ret;
    }

    ret = of_property_read_u32(dev->of_node, "data-reg", &data->data_reg);
    if (ret) {
        dev_err(dev, "缺少data-reg属性\n");
        return ret;
    }

    /* 执行寄存器测试 */
    test_reg_operations(data);

    platform_set_drvdata(pdev, data);
    dev_info(dev, "syscon测试驱动加载成功\n");
    return 0;
}

static int syscon_test_remove1(struct platform_device *pdev)
{
    dev_info(&pdev->dev, "syscon测试驱动卸载\n");
    return 0;
}

/* 设备树匹配表 */
static const struct of_device_id syscon_test_of_match[] = {
    { .compatible = "demo,syscon-test1" },
    { /* 哨兵 */ }
};
MODULE_DEVICE_TABLE(of, syscon_test_of_match);

static struct platform_driver syscon_test_driver1 = {
    .probe = syscon_test_probe1,
    .remove = syscon_test_remove1,
    .driver = {
        .name = "syscon-test-driver1",
        .of_match_table = syscon_test_of_match,
    },
};
module_platform_driver(syscon_test_driver1);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("简化的syscon测试驱动");
日志如下:
/ko # insmod memsyscon.ko
syscon_test_probe
控制寄存器值: 0x1 (预期: 0x1)
数据寄存器值: 0x55aa55aa (预期: 0x55AA55AA)
syscon-test-driver test-device@0: syscon测试驱动加载成功
/ko # insmod memsyscon1.ko
syscon_test_probe1
控制寄存器值: 0x1 (预期: 0x1)
数据寄存器值: 0x55aa55aa (预期: 0x55AA55AA)
syscon-test-driver1 test-device@1: syscon测试驱动加载成功

/ko # devmem 0x70000000 32
0x00000001
/ko # devmem 0x70000004 32
0x55AA55AA

图片

结论

输出结论

待查资料问题

  • 问题 1:?
  • 问题 2:?

参考链接

  • 官方文档
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言