This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] AM625:关于 TI EHRPWM 驱动程序和内核抽象(pwm.h API)

Guru**** 2538930 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1432888/am625-about-ti-ehrpwm-driver-and-kernel-abstraction-pwm-h-api

器件型号:AM625

工具与软件:

我将在内核级别恢复对 ePWM 模块的操作。 我完成了激活 kconfig 的过程以及内核中的 TI API 本身、使用探针本身为模块创建驱动程序。 好的、到目前为止都很好。

echo val > /sys/class/pwm/pwmchip0/pwm0/duty_cycle

但根据我在 TI 示例中看到的内容、唯一的方法是直接通过 sysfs 进行操作交互。 很好、但是、我如何使用内核的标准 PWM API 来操纵 TExaS 驱动程序?

dts 中的相关节点为:

	epwm0: pwm@23000000 {
		compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
		#pwm-cells = <3>;
		reg = <0x00 0x23000000 0x00 0x100>;
		power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
		clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
		clock-names = "tbclk", "fck";
		status = "disabled";
	};

pwm-tiehrpwm.c 在内核中注册 ehrpwmchip 驱动程序的方式、通过探测器、是:

static int ehrpwm_pwm_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct ehrpwm_pwm_chip *pc;
	struct clk *clk;
	int ret;

	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
	if (!pc)
		return -ENOMEM;

	clk = devm_clk_get(&pdev->dev, "fck");
	if (IS_ERR(clk)) {
		if (of_device_is_compatible(np, "ti,am33xx-ecap")) {
			dev_warn(&pdev->dev, "Binding is obsolete.\n");
			clk = devm_clk_get(pdev->dev.parent, "fck");
		}
	}

	if (IS_ERR(clk))
		return dev_err_probe(&pdev->dev, PTR_ERR(clk), "Failed to get fck\n");

	pc->clk_rate = clk_get_rate(clk);
	if (!pc->clk_rate) {
		dev_err(&pdev->dev, "failed to get clock rate\n");
		return -EINVAL;
	}

	pc->chip.dev = &pdev->dev;
	pc->chip.ops = &ehrpwm_pwm_ops;
	pc->chip.npwm = NUM_PWM_CHANNEL;

	pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(pc->mmio_base))
		return PTR_ERR(pc->mmio_base);

	/* Acquire tbclk for Time Base EHRPWM submodule */
	pc->tbclk = devm_clk_get(&pdev->dev, "tbclk");
	if (IS_ERR(pc->tbclk))
		return dev_err_probe(&pdev->dev, PTR_ERR(pc->tbclk), "Failed to get tbclk\n");

	ret = clk_prepare(pc->tbclk);
	if (ret < 0) {
		dev_err(&pdev->dev, "clk_prepare() failed: %d\n", ret);
		return ret;
	}

	ret = pwmchip_add(&pc->chip);
	if (ret < 0) {
		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
		goto err_clk_unprepare;
	}

	platform_set_drvdata(pdev, pc);
	pm_runtime_enable(&pdev->dev);

	return 0;

err_clk_unprepare:
	clk_unprepare(pc->tbclk);

	return ret;
}

目前、我正在尝试通过内核的标准 PWM API 来获取器件、如下所示:

- module_node 从 dtsi 指向上面的节点。

    struct platform_device *module_device   = NULL;
    struct pwm_device *epwm_module          = NULL;
    
    module_device = of_find_device_by_node(module_node);
    if(module_device == NULL)
    {
        printk(KERN_ERR "%s: Error searching epwm device\n", DEVICE_NAME);
    }

    epwm_module = (struct pwm_device *)platform_get_drvdata(module_device);
    if(epwm_module == NULL)
    {
        printk(KERN_ERR "%s: Error alloc epwm device\n", DEVICE_NAME);
    }

要操作该模块、我将使用此片段:

struct pwm_device *epwm_module;
    
struct pwm_state state;
struct pwm_device *device;
struct pwm_chip *chip;
    
device  = epwm_module;
chip    = epwm_module->chip;
    
state.period = frequency;
state.duty_cycle = duty_cycle;
state.polarity = 0;
state.enabled = (command != DISABLE) ? true : false;

epwm_module->chip->ops->apply(chip, device, &state);

但是、在执行这些操作时出现内核异常。 我在研究中没有找到任何关于在德州驱动程序中使用的内核 pwm.h API 的示例。 我看到它有自己的结构来描述器件。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    拉斐尔、您好!

    很遗憾、我们无法在 TI 论坛上支持有关定制驱动程序开发的问题。

    尽管如此、我们的 PWM 通常用于背光等外设。 也许您可以通过查看示例 devicetre 文件来找到驱动程序、并看看这些文件的工作原理?

    此致、

    Nick