[PATCH] MAX8952 PMIC Driver Initial Release
Mark Brown
broonie at opensource.wolfsonmicro.com
Thu Aug 19 06:46:54 EDT 2010
On Thu, Aug 19, 2010 at 04:05:15PM +0900, MyungJoo Ham wrote:
> If MAX8952's EN is not going to be changed by this driver, the user
> should set gpio_en_writable as false. In S5PC210/UNIVERSL board,
> controlling EN pin at MAX8952 driver can be dangerous because this gpio
> pin is shared with another PMIC.
If you're including this sort of board specific comment in the driver
for a generic chip like a regulator it should be a bit of a warning sign
-
> +static int max8952_i2c_read(struct i2c_client *client, u8 reg, u8 *dest)
> +{
> + int ret;
> +
> + ret = i2c_smbus_read_byte_data(client, reg);
> + if (ret < 0)
> + return -EIO;
If you've got an error code back you should return it directly rather
than replacing it with -EIO.
> +static int max8952_read_reg(struct max8952_data *max8952, u8 reg)
> +{
> + u8 value = 0;
> + int ret;
> +
> + mutex_lock(&max8952->mutex);
> + ret = max8952_i2c_read(max8952->client, reg, &value);
> + mutex_unlock(&max8952->mutex);
> + if (!ret)
> + ret = value & 0xff;
I don't see any need for the lock here - you're doing simple SMBus
transactions which should already be atomic. Locks are needed when
you're doing multiple transactions in your driver but that's not the
case at this level.
> +static int max8952_is_enabled(struct regulator_dev *rdev)
> +{
> + struct max8952_data *max8952 = rdev_get_drvdata(rdev);
> +
> + if (gpio_is_valid(max8952->pdata->gpio_en))
> + return gpio_get_value(max8952->pdata->gpio_en);
You're not allowed to read the status of output GPIOs by the gpiolib
API, you need to remember what you set it to.
> +
> + return -ENXIO;
> +}
If there's no GPIO I'd expect the driver to report that the regulator is
always enabled since the most likely configuration is that the enable is
latched high. Otherwise users will get confused.
> +static int max8952_get_voltage(struct regulator_dev *rdev)
> +{
> + struct max8952_data *max8952 = rdev_get_drvdata(rdev);
> + u8 vid = 0;
> +
> + if (gpio_is_valid(max8952->pdata->gpio_vid0) &&
> + gpio_is_valid(max8952->pdata->gpio_vid1)) {
> + if (gpio_get_value(max8952->pdata->gpio_vid0))
> + vid += 1;
> + if (gpio_get_value(max8952->pdata->gpio_vid1))
> + vid += 2;
Again, you can't read GPIOs that you're using for output.
> +static int max8952_set_voltage(struct regulator_dev *rdev,
> + int min_uV, int max_uV)
> +{
> + struct max8952_data *max8952 = rdev_get_drvdata(rdev);
> + u8 vid = -1, i;
> +
> + for (i = 0; i < MAX8952_NUM_DVS_MODE; i++) {
> + int volt = max8952_voltage(max8952, i);
> +
> + /* Set the voltage as low as possible within the range */
> + if ((volt <= max_uV) && (volt >= min_uV))
> + if ((vid == -1) ||
> + (max8952_voltage(max8952, vid) > volt))
> + vid = i;
The indentation here is badly confused - the second branch of the or is
massively indented.
> +static int max8952_do_nothing(struct regulator_dev *rdev)
> +{
> + return 0;
> +}
Why have you done this?
> + .set_suspend_enable = max8952_do_nothing,
> + .set_suspend_disable = max8952_disable,
If the chip has no explicit suspend mode control then remove these.
> + pr_info("MAX8952 Probing...\n");
Remove this.
> + if (pdata->gpio_en_writable == false) {
> + max8952_ops.enable = NULL;
> + max8952_ops.disable = NULL;
> + max8952_ops.set_suspend_disable = max8952_do_nothing;
> + }
This is going to break if you have more than one of these regulators in
the system.
> + ret = IS_ERR(max8952->rdev);
> + if (ret)
> + dev_err(max8952->dev, "regulator init failed\n");
Print the error code too.
> + } else {
> + pr_err("MAX8952 Initilization Failed: Wrong GPIO setting.\n");
> + return -EINVAL;
dev_err().
> + max8952_write_reg(max8952, MAX8952_REG_SYNC,
> + (max8952_read_reg(max8952, MAX8952_REG_SYNC) & 0x3F) |
> + ((pdata->sync_freq & 0x3) << 6));
> + max8952_write_reg(max8952, MAX8952_REG_RAMP,
> + (max8952_read_reg(max8952, MAX8952_REG_RAMP) & 0x1F) |
> + ((pdata->ramp_speed & 0x7) << 5));
This looks like it should be platform data.
> + i2c_set_clientdata(client, NULL);
Not needed.
> +#ifdef CONFIG_REGULATOR_RESUME
> +/* becasue alway_power_on, add this feature,
> + * To do this at bootloader is better */
> +beforeresume_initcall(max8952_pmic_init);
> +#else
> +subsys_initcall(max8952_pmic_init);
> +#endif
There's no CONFIG_REGULATOR_RESUME in mainline.
> +struct max8952_platform_data {
> + int gpio_vid0;
> + int gpio_vid1;
> + int gpio_en;
> +
> + /*
> + * In C210 Universal Board, EN is connected to PWR_EN, which can also
> + * turn off the whole system. In such a case, disable en_writable.
> + */
> + bool gpio_en_writable;
This should not be in the driver - any regulator could be used in a
fashion that's critical to system operation and the regulator API
always_on constraint will do this for you.
More information about the linux-arm-kernel
mailing list