如何为字符设备模块添加设备树支持和DMA分配?

huangapple go评论47阅读模式
英文:

How to add device tree support and DMA assignement to character device module?

问题

你好,开发者们,

我正在开发一个Linux内核模块,它使用DMA通道来在STM32MP157F上传输内存。

这个功能已经实现,但还需要进行额外的调整。STM mdma内核模块通过使用以下私有配置结构来实现这一点:

struct stm32_mdma_chan_config {
    u32 request;
    u32 priority_level;
    u32 transfer_config;
    u32 mask_addr;
    u32 mask_data;
    bool m2m_hw;
};

我想将优先级从0x0设置为0x3,这是其允许的最大值。

变量priority_levelstm32_mdma_of_xlate函数中设置:

static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
					    struct of_dma *ofdma)
{
    struct stm32_mdma_chan_config config;

    config.request = dma_spec->args[0];
    config.priority_level = dma_spec->args[1];
    // 其他操作
}

系统中的其他模块/驱动程序使用设备树设置,例如以下用于其所使用的DMA通道配置:

spi@44004000 {
    #address-cells = <0x01>;
    #size-cells = <0x00>;
    dmas = <0x0e 0x25 0x400 0x01 0x0e 0x26 0x400 0x01>;
    dma-names = "rx
spi@44004000 {
    #address-cells = <0x01>;
    #size-cells = <0x00>;
    dmas = <0x0e 0x25 0x400 0x01 0x0e 0x26 0x400 0x01>;
    dma-names = "rx\0tx";
};
tx";
};

spi-stm32.c在其stm32_spi_probe函数中调用of_match_device。我相信DMA配置是在其执行过程中完成的。

我想为我的字符设备驱动程序实现类似的功能:

mydriver@0 {
    compatible = "mydriver";
    dmas = <&mdma1 36 0x0 0x40008 0x0 0x0>,
           <&mdma1 37 0x0 0x40002 0x0 0x0>;
    dma-names = "rx", "tx";
};

但目前这被忽略了,因为我没有平台设备可以用来调用of_match_device。我似乎被太多的源代码所迷惑...

对我有什么建议吗?

更新:
目前正在研究http://xillybus.com/tutorials/device-tree-zynq-3

祝好 Gunther

英文:

Hello fellow developers,

I am developing a Linux kernel module that uses a DMA channel to transfer memory
(on STM32MP157F).

This works but additional tuning should be made. The STM mdma kernel module makes this possible by using this private configuration struct:

struct stm32_mdma_chan_config {
	u32 request;
    u32 priority_level;
    u32 transfer_config;
    u32 mask_addr;
    u32 mask_data;
    bool m2m_hw;
};

I would like set the priority from 0x0 to 0x3 which is its maximum allowed value.

The variable priority_level is set in stm32_mdma_of_xlate function:

static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
					    struct of_dma *ofdma)
{
	struct stm32_mdma_chan_config config;


	config.request = dma_spec-&gt;args[0];
	config.priority_level = dma_spec-&gt;args[1];
    ....
}

Other modules/drivers in the system use a device tree setting like this for its and the used DMA channel configuration.

spi@44004000 {
	#address-cells = &lt;0x01&gt;;
	#size-cells = &lt;0x00&gt;;
	dmas = &lt;0x0e 0x25 0x400 0x01 0x0e 0x26 0x400 0x01&gt;;
	dma-names = &quot;rx
spi@44004000 {
#address-cells = &lt;0x01&gt;;
#size-cells = &lt;0x00&gt;;
dmas = &lt;0x0e 0x25 0x400 0x01 0x0e 0x26 0x400 0x01&gt;;
dma-names = &quot;rx\0tx&quot;;
};
tx&quot;; };

spi-stm32.c calls of_match_device in its stm32_spi_probe function. I believe the dma configuration is done during its execution.

I would like something similar for my character device driver:

mydriver@0 {
 	compatible = &quot;mydriver&quot;;
	dmas = &lt;&amp;mdma1 36 0x0 0x40008 0x0 0x0&gt;,
	       &lt;&amp;mdma1 37 0x0 0x40002 0x0 0x0&gt;;
	dma-names = &quot;rx&quot;, &quot;tx&quot;;
};

But this is currently ignored because I do not have a platform device I could use to call
of_match_device. I seem to be blinded by to much source code to look at ...

Any tips for me?

Update:
Currently studying http://xillybus.com/tutorials/device-tree-zynq-3

Best regards Gunther

答案1

得分: 2

我在进行了一些额外的研究后解决了我的问题。以下是这些步骤:

我不得不向设备树添加一个自定义条目:

mydriver_0: mydriver@0 {
    compatible = "mydriver";
    dmas = <&mdma1 22 0x3 0x1200000a 0x48001008 0x00000020 1>;
    dma-names = "dma0";
};

使驱动程序可以作为平台驱动程序加载。创建一个与设备树条目匹配的of_device_id匹配表。将module_init()更改为调用platform_driver_register()以注册匹配表。然后实现一个探测函数,调用先前的初始化函数。存储pdev

static int mydriver_drv_probe(struct platform_device *pdev)
{
  // 为以后调用 dma_channel_req(&pdev->dev, "dma0"); 存储 pdev    
  // TODO 初始化驱动程序    
  return 0;
}

/* 与设备树的连接 */
static struct of_device_id mydriver_of_match[] =
{
    { .compatible = "mydriver" },
    {}
};
MODULE_DEVICE_TABLE(of, mydriver_of_match);

static struct platform_driver mydriver_platform_driver = {
  .probe = mydriver_drv_probe,
  .remove = mydriver_drv_remove,
  .driver = {
    .name = "mydriver",
    .owner = THIS_MODULE,
    .of_match_table = mydriver_of_match,
  },
};

static int __init _mydriver_driver_init(void)
{
    return platform_driver_register(&mydriver_platform_driver);
}
module_init(_mydriver_driver_init);

获取正确配置的DMA通道:

chan = dma_request_chan(&pdev->dev, "dma0");

我测试过这个,它有效。所请求的DMA通道是使用我的设备树中的"dmas"条目配置的。

希望对其他人有所帮助!

英文:

I solved my issues after doing some extra research.
These are the steps:

I had to add a custom entry to the device tree:

<!-- language: lang-dts -->

mydriver_0: mydriver@0 {
    compatible = &quot;mydriver&quot;;
    dmas = &lt;&amp;mdma1 22 0x3 0x1200000a 0x48001008 0x00000020 1&gt;;
    dma-names = &quot;dma0&quot;;
};

Make the driver loadable as a platform driver. Create an of_device_id match table matching the device tree entry. Change module_init() to call platform_driver_register() to register the matching table. Then implement a probe function calling the previous init function. Store pdev.

<!-- language: lang-c -->

static int mydriver_drv_probe(struct platform_device *pdev)
{
  // store pdev for later call to: dma_channel_req(&amp;pdev-&gt;dev, &quot;dma0&quot;);    
  // TODO init driver    
  return 0;
}

/* Connection to device tree */
static struct of_device_id mydriver_of_match[] =
{
    { .compatible = &quot;mydriver&quot; },
    {}
};
MODULE_DEVICE_TABLE(of, mydriver_of_match);

static struct platform_driver mydriver_platform_driver = {
  .probe = mydriver_drv_probe,
  .remove = mydriver_drv_remove,
  .driver = {
    .name = &quot;mydriver&quot;,
    .owner = THIS_MODULE,
    .of_match_table = mydriver_of_match,
  },
};

static int __init _mydriver_driver_init(void)
{
    return platform_driver_register(&amp;mydriver_platform_driver);
}
module_init(_mydriver_driver_init);

Get the correctly configured DMA channel:

<!-- language: lang-c -->

chan = dma_request_chan(&amp;pdev-&gt;dev, &quot;dma0&quot;);

I tested this and it worked. The requested DMA channel is configured using the my device tree "dmas" entry.

I hope this of use for somebody else!

huangapple
  • 本文由 发表于 2023年2月14日 20:05:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75447594.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定