简体   繁体   中英

PWM in Linux driver insmod

I am trying to insmod a pwm triple timer counter(TTC) driver for Zynq PS. The dmesg log is:

TTC: Inside probe function
pwm-cadence f8001000.timer: PWM 0 has clock source 0 at 108333336 Hz
pwm-cadence f8001000.timer: PWM 1 has clock source 0 at 108333336 Hz
pwm-cadence f8001000.timer: PWM 2 has clock source 0 at 108333336 Hz
pwm-cadence f8001000.timer: cannot add pwm chip (error -22)

Does the EINVAL (error -22) function occur when certain fields in struct cpwm->chip are uninitialised? I am a newbie in this field. So any tips would be appreciated.

static int cadence_pwm_probe(struct platform_device *pdev)
{
    struct cadence_pwm_chip *cpwm;
    struct resource *r_mem;
    int ret;
    struct device_node *node = pdev->dev.of_node;
    const __be32 *value;
    int rlen;
    char propname[24];
    int i;
    struct cadence_pwm_pwm *pwm;
    printk(KERN_DEBUG "TTC: Inside probe function\n");
    cpwm = devm_kzalloc(&pdev->dev, sizeof(*cpwm), GFP_KERNEL);
    if (!cpwm)
        return -ENOMEM;

    r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    cpwm->base = devm_ioremap_resource(&pdev->dev, r_mem);
    if (IS_ERR(cpwm->base))
       return PTR_ERR(cpwm->base);

    for (i = 0; i < CPWM_NUM_PWM; i ++) {
       pwm = cpwm->pwms + i;

    snprintf(propname, sizeof(propname), "xlnx,ttc-clk%d-freq-hz", i);

    value = of_get_property(node, propname, &rlen);
    if (value)
       pwm->clk_hz = be32_to_cpup(value);
    else {
       dev_err(&pdev->dev, "missing %s property1", propname);
       return -ENODEV;
    }

    snprintf(propname, sizeof(propname), "xlnx,ttc-clk%d-clksrc", i);

    value = of_get_property(node, propname, &rlen);
    if (value)
       pwm->source = be32_to_cpup(value);
    else {
       dev_err(&pdev->dev, "missing %s property2", propname);
       return -ENODEV;
    }

    dev_info(&pdev->dev, "PWM %d has clock source %d at %d Hz", i, pwm->source, pwm->clk_hz);

}

cpwm->chip.dev = &pdev->dev;
cpwm->chip.ops = &cadence_pwm_ops;
cpwm->chip.npwm = CPWM_NUM_PWM;
cpwm->chip.base = -1;

ret = pwmchip_add(&cpwm->chip);
if (ret < 0) {
    dev_err(&pdev->dev, "cannot add pwm chip (error %d)", ret);
    return ret;
}

Well, the code looks decent. This means that adding PWM chip must not fail - all fields required are set and they are fine.

However, EINVAL could still be returned as per the only remaining reason, namely, because support for PWM ( CONFIG_PWM ) has been disabled in the kernel build config. This follows from include/linux/pwm.h file where conditional compilation is used. So, if CONFIG_PWM option has been enabled, then a proper symbol exists. And, when you build your driver, this function prototype will be used from the header. But if the kernel has been built without PWM support, then inline function will be used during driver compilation, which is a simple stub to return EINVAL in any case.

All in all, you need to check your build configuration properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM