On Tue, Mar 18, 2025 at 05:26:20PM +0100, mathieu.dubois-briand@xxxxxxxxxxx wrote: > From: Kamel Bouhara <kamel.bouhara@xxxxxxxxxxx> > > Add driver for Maxim Integrated MAX7360 PWM controller, supporting up to > 8 independent PWM outputs. ... > +#include <linux/bits.h> > +#include <linux/dev_printk.h> > +#include <linux/err.h> > +#include <linux/math64.h> > +#include <linux/mfd/max7360.h> > +#include <linux/minmax.h> > +#include <linux/mod_devicetable.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/pwm.h> > +#include <linux/regmap.h> > +#include <linux/time.h> > +#include <linux/types.h> ... > +static void max7360_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) > +{ > + struct regmap *regmap; > + struct device *dev; > + > + regmap = pwmchip_get_drvdata(chip); > + dev = regmap_get_device(regmap); Huh?! > +} ... > +static int max7360_pwm_round_waveform_tohw(struct pwm_chip *chip, > + struct pwm_device *pwm, > + const struct pwm_waveform *wf, > + void *_wfhw) I would expect other way around, i.e. naming with leading underscore(s) to be private / local. Ditto for all similar cases. ... > +static int max7360_pwm_write_waveform(struct pwm_chip *chip, > + struct pwm_device *pwm, > + const void *_wfhw) > +{ > + const struct max7360_pwm_waveform *wfhw = _wfhw; > + struct regmap *regmap; > + unsigned int val; > + int ret; > + > + regmap = pwmchip_get_drvdata(chip); > + val = (wfhw->enabled) ? BIT(pwm->hwpwm) : 0; Redundant parentheses. > + ret = regmap_write_bits(regmap, MAX7360_REG_GPIOCTRL, BIT(pwm->hwpwm), val); > + if (ret) > + return ret; > + > + if (wfhw->duty_steps) > + return regmap_write(regmap, MAX7360_REG_PWM(pwm->hwpwm), wfhw->duty_steps); > + > + return 0; > +} ... > +static int max7360_pwm_read_waveform(struct pwm_chip *chip, > + struct pwm_device *pwm, > + void *_wfhw) > +{ > + struct max7360_pwm_waveform *wfhw = _wfhw; > + struct regmap *regmap; > + unsigned int val; > + int ret; > + > + regmap = pwmchip_get_drvdata(chip); > + > + ret = regmap_read(regmap, MAX7360_REG_GPIOCTRL, &val); > + if (ret) > + return ret; > + > + if (val & BIT(pwm->hwpwm)) { > + wfhw->enabled = true; Also can be (but up to you) wfhw->enabled = val & BIT(pwm->hwpwm); if (wfhw->enabled) { And also see below. Perhaps it is not a good suggestion after all. > + ret = regmap_read(regmap, MAX7360_REG_PWM(pwm->hwpwm), &val); > + wfhw->duty_steps = val; Set to a garbage in case of error, why? > + } else { > + wfhw->enabled = false; > + wfhw->duty_steps = 0; > + } > + > + return ret; > +} ... > +static int max7360_pwm_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct pwm_chip *chip; > + struct regmap *regmap; > + int ret; > + > + if (!dev->parent) > + return dev_err_probe(dev, -ENODEV, "no parent device\n"); Why? Code most likely will fail on the regmap retrieval. Just do that first. > + chip = devm_pwmchip_alloc(dev->parent, MAX7360_NUM_PWMS, 0); This is quite worrying. The devm_ to parent makes a lot of assumptions that may not be realised. If you really need this, it has to have a very good comment explaining why and object lifetimes. > + if (IS_ERR(chip)) > + return PTR_ERR(chip); > + chip->ops = &max7360_pwm_ops; > + > + regmap = dev_get_regmap(dev->parent, NULL); > + if (!regmap) > + return dev_err_probe(dev, -ENODEV, "could not get parent regmap\n"); > + > + pwmchip_set_drvdata(chip, regmap); > + > + ret = devm_pwmchip_add(dev, chip); > + if (ret) > + return dev_err_probe(dev, ret, "failed to add PWM chip\n"); > + > + return 0; > +} -- With Best Regards, Andy Shevchenko