Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pwm: Add the S32G support in the Freescale FTM driver

The Automotive S32G2 and S32G3 platforms include two FTM timers for
pwm. Each FTM has 6 PWM channels.

The current Freescale FTM driver supports the iMX8 and the Vybrid
Family FTM IP. The FTM IP found on the S32G platforms is almost
identical except for the number of channels and the register mapping.

These changes allow to deal with different number of channels and
support the holes found in the register memory mapping for s32gx for
suspend / resume. The fault register does not exist on the s32gx and
at resume time all the mapping is wrote back leading to a kernel
crash.

/* restore all registers from cache */
regcache_cache_only(fpc->regmap, false);
regcache_sync(fpc->regmap);

The regmap callbacks 'writeable_reg()' and 'readable_reg()' will skip
the address corresponding to a register which is not present.

Tested on a s32g274-rdb2 J5 PWM pin output with signal visualization
on oscilloscope.

Signed-off-by: Ghennadi Procopciuc <Ghennadi.Procopciuc@nxp.com>
Co-developed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20250812200036.3432917-3-daniel.lezcano@linaro.org
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>

authored by

Ghennadi Procopciuc and committed by
Uwe Kleine-König
d8af3812 3513752c

+33 -2
+33 -2
drivers/pwm/pwm-fsl-ftm.c
··· 3 3 * Freescale FlexTimer Module (FTM) PWM Driver 4 4 * 5 5 * Copyright 2012-2013 Freescale Semiconductor, Inc. 6 + * Copyright 2020-2025 NXP 6 7 */ 7 8 8 9 #include <linux/clk.h> ··· 31 30 32 31 struct fsl_ftm_soc { 33 32 bool has_enable_bits; 33 + bool has_flt_reg; 34 + unsigned int npwm; 34 35 }; 35 36 36 37 struct fsl_pwm_periodcfg { ··· 377 374 return false; 378 375 } 379 376 377 + static bool fsl_pwm_is_reg(struct device *dev, unsigned int reg) 378 + { 379 + struct pwm_chip *chip = dev_get_drvdata(dev); 380 + struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 381 + 382 + if (reg >= FTM_CSC(fpc->soc->npwm) && reg < FTM_CNTIN) 383 + return false; 384 + 385 + if ((reg == FTM_FLTCTRL || reg == FTM_FLTPOL) && !fpc->soc->has_flt_reg) 386 + return false; 387 + 388 + return true; 389 + } 390 + 380 391 static const struct regmap_config fsl_pwm_regmap_config = { 381 392 .reg_bits = 32, 382 393 .reg_stride = 4, ··· 399 382 .max_register = FTM_PWMLOAD, 400 383 .volatile_reg = fsl_pwm_volatile_reg, 401 384 .cache_type = REGCACHE_FLAT, 385 + .writeable_reg = fsl_pwm_is_reg, 386 + .readable_reg = fsl_pwm_is_reg, 402 387 }; 403 388 404 389 static int fsl_pwm_probe(struct platform_device *pdev) 405 390 { 391 + const struct fsl_ftm_soc *soc = of_device_get_match_data(&pdev->dev); 406 392 struct pwm_chip *chip; 407 393 struct fsl_pwm_chip *fpc; 408 394 void __iomem *base; 409 395 int ret; 410 396 411 - chip = devm_pwmchip_alloc(&pdev->dev, 8, sizeof(*fpc)); 397 + chip = devm_pwmchip_alloc(&pdev->dev, soc->npwm, sizeof(*fpc)); 412 398 if (IS_ERR(chip)) 413 399 return PTR_ERR(chip); 414 400 fpc = to_fsl_chip(chip); 415 401 416 - fpc->soc = of_device_get_match_data(&pdev->dev); 402 + fpc->soc = soc; 417 403 418 404 base = devm_platform_ioremap_resource(pdev, 0); 419 405 if (IS_ERR(base)) ··· 532 512 533 513 static const struct fsl_ftm_soc vf610_ftm_pwm = { 534 514 .has_enable_bits = false, 515 + .has_flt_reg = true, 516 + .npwm = 8, 535 517 }; 536 518 537 519 static const struct fsl_ftm_soc imx8qm_ftm_pwm = { 538 520 .has_enable_bits = true, 521 + .has_flt_reg = true, 522 + .npwm = 8, 523 + }; 524 + 525 + static const struct fsl_ftm_soc s32g2_ftm_pwm = { 526 + .has_enable_bits = true, 527 + .has_flt_reg = false, 528 + .npwm = 6, 539 529 }; 540 530 541 531 static const struct of_device_id fsl_pwm_dt_ids[] = { 542 532 { .compatible = "fsl,vf610-ftm-pwm", .data = &vf610_ftm_pwm }, 543 533 { .compatible = "fsl,imx8qm-ftm-pwm", .data = &imx8qm_ftm_pwm }, 534 + { .compatible = "nxp,s32g2-ftm-pwm", .data = &s32g2_ftm_pwm }, 544 535 { /* sentinel */ } 545 536 }; 546 537 MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids);