On 4/24/24 17:29, Xilin Wu via B4 Relay wrote:
From: Junhao Xie <bigfoot@xxxxxxxxxxx> Add a new driver for the SI-EN SN3112 12-channel 8-bit PWM LED controller. Signed-off-by: Junhao Xie <bigfoot@xxxxxxxxxxx> ---
[...]
+static int sn3112_set_en_reg(struct sn3112 *priv, unsigned int channel, + bool enabled, bool write) +{ + unsigned int reg, bit; + + if (channel >= SN3112_CHANNELS) + return -EINVAL; + + /* LED_EN1: BIT5:BIT3 = OUT3:OUT1 */ + if (channel >= 0 && channel <= 2) + reg = 0, bit = channel + 3; + /* LED_EN2: BIT5:BIT0 = OUT9:OUT4 */ + else if (channel >= 3 && channel <= 8) + reg = 1, bit = channel - 3; + /* LED_EN3: BIT2:BIT0 = OUT12:OUT10 */ + else if (channel >= 9 && channel <= 11) + reg = 2, bit = channel - 9; + else + return -EINVAL; + + dev_dbg(priv->pdev, "channel %u enabled %u\n", channel, enabled); + dev_dbg(priv->pdev, "reg %u bit %u\n", reg, bit); + if (enabled) + set_bit(bit, (ulong *)&priv->pwm_en_reg[reg]); + else + clear_bit(bit, (ulong *)&priv->pwm_en_reg[reg]); + dev_dbg(priv->pdev, "set enable reg %u to %u\n", reg, + priv->pwm_en_reg[reg]); + + if (!write) + return 0; + return sn3112_write_reg(priv, SN3112_REG_PWM_EN + reg, + priv->pwm_en_reg[reg]);
This looks like a weird reimplementation of regmap_update_bits
+} + +static int sn3112_set_val_reg(struct sn3112 *priv, unsigned int channel, + uint8_t val, bool write) +{ + if (channel >= SN3112_CHANNELS) + return -EINVAL; + priv->pwm_val[channel] = val; + dev_dbg(priv->pdev, "set value reg %u to %u\n", channel, + priv->pwm_val[channel]); + + if (!write) + return 0;
There's only a single call, with write == true
+ return sn3112_write_reg(priv, SN3112_REG_PWM_VAL + channel, + priv->pwm_val[channel]); +} + +static int sn3112_write_all(struct sn3112 *priv) +{ + int i, ret; + + /* regenerate enable register values */ + for (i = 0; i < SN3112_CHANNELS; i++) { + ret = sn3112_set_en_reg(priv, i, priv->pwm_en[i], false); + if (ret != 0) + return ret; + } + + /* use random value to clear all registers */ + ret = sn3112_write_reg(priv, SN3112_REG_RESET, 0x66); + if (ret != 0)
if (ret) is the same as if (ret != 0) [...]
+ + /* use random value to apply changes */ + ret = sn3112_write_reg(priv, SN3112_REG_APPLY, 0x66);
"a random value"? sounds suspicious..
+ if (ret != 0) + return ret; + + dev_dbg(priv->pdev, "reinitialized\n");
Please remove such "got here" messages once you're done with testing the driver locally [...]
+ +#if IS_ENABLED(CONFIG_GPIOLIB)
I'm not sure this would be ever disabled on any embedded system nowadays. Especially with I2C. [...]
+ + dev_info(&client->dev, + "Found SI-EN SN3112 12-channel 8-bit PWM LED controller\n");
This sort of message only makes sense if there's a CHIP_ID register that you can actually validate. If you bind this driver to a device at the same expected address, it will say it's there even if it's not.
+ return 0; +} + +static void sn3112_pwm_remove(struct i2c_client *client) +{ + struct pwm_chip *chip = i2c_get_clientdata(client); + struct sn3112 *priv = pwmchip_get_drvdata(chip); + + dev_dbg(priv->pdev, "remove\n"); + + /* set software enable register */ + sn3112_write_reg(priv, SN3112_REG_ENABLE, 0); + + /* use random value to apply changes */ + sn3112_write_reg(priv, SN3112_REG_APPLY, 0x66); + +#if IS_ENABLED(CONFIG_GPIOLIB) + /* enable hardware shutdown pin */ + if (priv->sdb) + gpiod_set_value(priv->sdb, 1); +#endif + + /* power-off sn5112 power vdd */ + regulator_disable(priv->vdd); + + pwmchip_remove(chip);
devm_pwmchip_add? Konrad