[U-Boot] [PATCH] PMIC: MAX77686: Add support for MAX77686
Lukasz Majewski
l.majewski at samsung.com
Tue May 22 08:50:44 CEST 2012
Hi Rajeshwari,
> This patch adds driver and register definitions for PMIC chip
> MAX77686.
Why don't use the PMIC framework? Please look into drivers/misc/pmic_*
for examples.
For now there is a support for MAX899{7|8} chips for Samsung platforms.
>
> Signed-off-by: Alim Akhtar <alim.akhtar at samsung.com>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s at samsung.com>
> ---
> drivers/power/Makefile | 1 +
> drivers/power/max77686.c | 225
> ++++++++++++++++++++++++++++++++++++++++++++++
> include/max77686.h | 115 +++++++++++++++++++++++ 3 files
> changed, 341 insertions(+), 0 deletions(-) create mode 100644
> drivers/power/max77686.c create mode 100644 include/max77686.h
>
> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> index 6bf388c..b4ffc1d 100644
> --- a/drivers/power/Makefile
> +++ b/drivers/power/Makefile
> @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
> LIB := $(obj)libpower.o
>
> COBJS-$(CONFIG_FTPMU010_POWER) += ftpmu010.o
> +COBJS-$(CONFIG_MAX77686_POWER) += max77686.o
> COBJS-$(CONFIG_TPS6586X_POWER) += tps6586x.o
> COBJS-$(CONFIG_TWL4030_POWER) += twl4030.o
> COBJS-$(CONFIG_TWL6030_POWER) += twl6030.o
> diff --git a/drivers/power/max77686.c b/drivers/power/max77686.c
> new file mode 100644
> index 0000000..cf58611
> --- /dev/null
> +++ b/drivers/power/max77686.c
> @@ -0,0 +1,225 @@
> +/*
> + * Copyright (C) 2012 Samsung Electronics
> + * Alim Akhtar <alim.akhtar at samsung.com>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <common.h>
> +#include <i2c.h>
> +#include <max77686.h>
> +
> +/*
> + * Max77686 parameters values
> + * see max77686.h for parameters details
> + */
> +struct max77686_para max77686_param[] = {/*{regnum, vol_addr,
> vol_bitpos,
> + vol_bitmask, reg_enaddr, reg_enbitpos, reg_enbitmask,
> reg_enbiton,
> + reg_enbitoff, vol_min, vol_div}*/
> + {PMIC_BUCK1, 0x11, 0x0, 0x3F, 0x10, 0x0, 0x3, 0x3, 0x0, 750,
> 50000},
> + {PMIC_BUCK2, 0x14, 0x0, 0xFF, 0x12, 0x4, 0x3, 0x1, 0x0, 600,
> 12500},
> + {PMIC_BUCK3, 0x1E, 0x0, 0xFF, 0x1C, 0x4, 0x3, 0x1, 0x0, 600,
> 12500},
> + {PMIC_BUCK4, 0x28, 0x0, 0xFF, 0x26, 0x4, 0x3, 0x1, 0x0, 600,
> 12500},
> + {PMIC_BUCK5, 0x31, 0x0, 0x3F, 0x30, 0x0, 0x3, 0x3, 0x0, 750,
> 50000},
> + {PMIC_BUCK6, 0x33, 0x0, 0x3F, 0x32, 0x0, 0x3, 0x3, 0x0, 750,
> 50000},
> + {PMIC_BUCK7, 0x35, 0x0, 0x3F, 0x34, 0x0, 0x3, 0x3, 0x0, 750,
> 50000},
> + {PMIC_BUCK8, 0x37, 0x0, 0x3F, 0x36, 0x0, 0x3, 0x3, 0x0, 750,
> 50000},
> + {PMIC_BUCK9, 0x39, 0x0, 0x3F, 0x38, 0x0, 0x3, 0x3, 0x0, 750,
> 50000},
> + {PMIC_LDO1, 0x40, 0x0, 0x3F, 0x40, 0x6, 0x3, 0x3, 0x0, 800,
> 25000},
> + {PMIC_LDO2, 0x41, 0x0, 0x3F, 0x41, 0x6, 0x3, 0x1, 0x0, 800,
> 25000},
> + {PMIC_LDO3, 0x42, 0x0, 0x3F, 0x42, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO4, 0x43, 0x0, 0x3F, 0x43, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO5, 0x44, 0x0, 0x3F, 0x44, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO6, 0x45, 0x0, 0x3F, 0x45, 0x6, 0x3, 0x1, 0x0, 800,
> 25000},
> + {PMIC_LDO7, 0x46, 0x0, 0x3F, 0x46, 0x6, 0x3, 0x1, 0x0, 800,
> 25000},
> + {PMIC_LDO8, 0x47, 0x0, 0x3F, 0x47, 0x6, 0x3, 0x1, 0x0, 800,
> 25000},
> + {PMIC_LDO9, 0x48, 0x0, 0x3F, 0x48, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO10, 0x49, 0x0, 0x3F, 0x49, 0x6, 0x3, 0x1, 0x0, 800,
> 50000},
> + {PMIC_LDO11, 0x4A, 0x0, 0x3F, 0x4A, 0x6, 0x3, 0x1, 0x0, 800,
> 50000},
> + {PMIC_LDO12, 0x4B, 0x0, 0x3F, 0x4B, 0x6, 0x3, 0x1, 0x0, 800,
> 50000},
> + {PMIC_LDO13, 0x4C, 0x0, 0x3F, 0x4C, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO14, 0x4D, 0x0, 0x3F, 0x4D, 0x6, 0x3, 0x1, 0x0, 800,
> 50000},
> + {PMIC_LDO15, 0x4E, 0x0, 0x3F, 0x4E, 0x6, 0x3, 0x1, 0x0, 800,
> 25000},
> + {PMIC_LDO16, 0x4F, 0x0, 0x3F, 0x4F, 0x6, 0x3, 0x1, 0x0, 800,
> 50000},
> + {PMIC_LDO17, 0x50, 0x0, 0x3F, 0x50, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO18, 0x51, 0x0, 0x3F, 0x51, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO19, 0x52, 0x0, 0x3F, 0x52, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO20, 0x53, 0x0, 0x3F, 0x53, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO21, 0x54, 0x0, 0x3F, 0x54, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO22, 0x55, 0x0, 0x3F, 0x55, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO23, 0x56, 0x0, 0x3F, 0x56, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO24, 0x57, 0x0, 0x3F, 0x57, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO25, 0x58, 0x0, 0x3F, 0x58, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_LDO26, 0x59, 0x0, 0x3F, 0x59, 0x6, 0x3, 0x3, 0x0, 800,
> 50000},
> + {PMIC_EN32KHZ_CP, 0x0, 0x0, 0x0, 0x7F, 0x1, 0x1, 0x1, 0x0,
> 0x0, 0x0}, +};
Frankly speaking it looks a bit unreadable (especially without specs
attached).
> +
> +/*
> + * Write a value to a register
> + *
> + * @param chip_addr i2c addr for max77686
> + * @param reg reg number to write
> + * @param val value to be written
> + *
> + */
> +static inline int max77686_i2c_write(unsigned char chip_addr,
> + unsigned int reg, unsigned
> char val) +{
> + return i2c_write(chip_addr, reg, 1, &val, 1);
> +}
This "write register" is also available in the PMIC framework.
> +
> +/*
> + * Read a value from a register
> + *
> + * @param chip_addr i2c addr for max77686
> + * @param reg reg number to write
> + * @param val value to be written
> + *
> + */
> +static inline int max77686_i2c_read(unsigned char chip_addr,
> + unsigned int reg, unsigned
It is also available on the PMIC framework.
> char *val) +{
> + return i2c_read(chip_addr, reg, 1, val, 1);
> +}
> +
> +/*
> + * Enable the max77686 register
> + *
> + * @param reg register number of buck/ldo to be
> enabled
> + * @param enable enable or disable bit
> + *
> + * REG_DISABLE = 0,
> + needed to set the buck/ldo enable bit OFF
> + * @return Return 0 if ok, else -1
> + */
> +static int max77686_enablereg(enum max77686_regnum reg, int enable)
> +{
> + struct max77686_para *pmic;
> + unsigned char read_data;
> + int ret;
> +
> + pmic = &max77686_param[reg];
> +
> + ret = max77686_i2c_read(MAX77686_I2C_ADDR, pmic->vol_addr,
> &read_data);
> + if (ret != 0) {
> + debug("max77686 i2c read failed.\n");
> + return -1;
> + }
> +
> + if (enable == REG_DISABLE) {
> + clrbits_8(&read_data,
> + pmic->reg_enbitmask <<
> pmic->reg_enbitpos);
> + } else {
> + clrsetbits_8(&read_data,
> + pmic->reg_enbitmask <<
> pmic->reg_enbitpos,
> + pmic->reg_enbiton <<
> pmic->reg_enbitpos);
> + }
> +
> + ret = max77686_i2c_write(MAX77686_I2C_ADDR,
> + pmic->reg_enaddr, read_data);
> + if (ret != 0) {
> + debug("max77686 i2c write failed.\n");
> + return -1;
> + }
> +
> + return 0;
> +}
Please look into the PMIC section of ./board/samsung/trats/trats.c for
reference. Moreover changing/enabling regulator function is already
available at pmic_core.c
> +
> +/* Set the required voltage level of pmic
> + *
> + * @param reg register number of buck/ldo to be set
> + * @param volt voltage level to be set
> + * @param enable enable or disable bit
> + *
> + * @return Return 0 if ok, else -1
> + */
> +static int max77686_volsetting(enum max77686_regnum reg, unsigned
> int volt,
> + int enable)
> +{
> + struct max77686_para *pmic;
> + unsigned char read_data;
> + unsigned int vol_level = 0;
> + int ret;
> +
> + pmic = &max77686_param[reg];
> +
> + if (pmic->vol_addr == 0) {
> + debug("not a voltage register.\n");
> + return -1;
> + }
> +
> + ret = max77686_i2c_read(MAX77686_I2C_ADDR, pmic->vol_addr,
> &read_data);
> + if (ret != 0) {
> + debug("max77686 i2c read failed.\n");
> + return -1;
> + }
> +
> + if (volt - pmic->vol_min > 0)
> + vol_level = ((volt - pmic->vol_min) * 1000) /
> pmic->vol_div; +
> + clrsetbits_8(&read_data, pmic->vol_bitmask <<
> pmic->vol_bitpos,
> + vol_level << pmic->vol_bitpos);
> +
> + ret = max77686_i2c_write(MAX77686_I2C_ADDR, pmic->vol_addr,
> read_data);
> + if (ret != 0) {
> + debug("max77686 i2c write failed.\n");
> + return -1;
> + }
> +
> + ret = max77686_enablereg(reg, enable);
> + if (ret != 0) {
> + debug("Failed to enable buck/ldo.\n");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
I believe,that it would be better to further develop PMIC
framework, than writing your own "special" driver.
> +int max77686_enable_32khz_cp(void)
> +{
> + return max77686_enablereg(PMIC_EN32KHZ_CP, REG_ENABLE);
> +}
> +
> +/**
> + * Initialize the pmic voltages to power up the system
> + * This also calls i2c_init so that we can program the pmic
> + *
> + * REG_ENABLE = 0, needed to set the buck/ldo enable bit ON
> + *
> + * @return Return 0 if ok, else -1
> + */
> +int power_init(void)
> +{
> + int error = 0;
> +
> + /* init the i2c so that we can program pmic chip */
> + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
> +
> + error = max77686_volsetting(PMIC_BUCK2, CONFIG_VDD_ARM,
> REG_ENABLE);
> + error |= max77686_volsetting(PMIC_BUCK3, CONFIG_VDD_INT,
> REG_ENABLE);
> + error |= max77686_volsetting(PMIC_BUCK1, CONFIG_VDD_MIF,
> REG_ENABLE);
> + error |= max77686_volsetting(PMIC_LDO2, CONFIG_VDD_LDO2,
> REG_ENABLE);
> + error |= max77686_volsetting(PMIC_LDO3, CONFIG_VDD_LDO3,
> REG_ENABLE);
> + error |= max77686_volsetting(PMIC_LDO5, CONFIG_VDD_LDO5,
> REG_ENABLE);
> + error |= max77686_volsetting(PMIC_LDO10, CONFIG_VDD_LDO10,
> REG_ENABLE);
> + if (error != 0)
> + debug("power init failed\n");
> +
> + return error;
> +}
> diff --git a/include/max77686.h b/include/max77686.h
> new file mode 100644
> index 0000000..e630ed8
> --- /dev/null
> +++ b/include/max77686.h
> @@ -0,0 +1,115 @@
> +/*
> + * Copyright (C) 2012 Samsung Electronics
> + * Alim Akhtar <alim.akhtar at samsung.com>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#ifndef __MAX77686_H_
> +#define __MAX77686_H_
> +
> +enum max77686_regnum {
> + PMIC_BUCK1 = 0,
> + PMIC_BUCK2,
> + PMIC_BUCK3,
> + PMIC_BUCK4,
> + PMIC_BUCK5,
> + PMIC_BUCK6,
> + PMIC_BUCK7,
> + PMIC_BUCK8,
> + PMIC_BUCK9,
> + PMIC_LDO1,
> + PMIC_LDO2,
> + PMIC_LDO3,
> + PMIC_LDO4,
> + PMIC_LDO5,
> + PMIC_LDO6,
> + PMIC_LDO7,
> + PMIC_LDO8,
> + PMIC_LDO9,
> + PMIC_LDO10,
> + PMIC_LDO11,
> + PMIC_LDO12,
> + PMIC_LDO13,
> + PMIC_LDO14,
> + PMIC_LDO15,
> + PMIC_LDO16,
> + PMIC_LDO17,
> + PMIC_LDO18,
> + PMIC_LDO19,
> + PMIC_LDO20,
> + PMIC_LDO21,
> + PMIC_LDO22,
> + PMIC_LDO23,
> + PMIC_LDO24,
> + PMIC_LDO25,
> + PMIC_LDO26,
> + PMIC_EN32KHZ_CP
> +};
> +
> +/**
> + * struct max77686_para - max77686 register parameters
> + * @param vol_addr i2c address of the given buck/ldo register
> + * @param vol_bitpos bit position to be set or clear within
> register
> + * @param vol_bitmask bit mask value
> + * @param reg_enaddr control register address, which enable
> the given
> + * given buck/ldo.
> + * @param reg_enbitpos bit position to be enabled
> + * @param reg_enbiton value to be written to buck/ldo to make
> it ON
> + * @param reg_enbitoff value to be written to buck/ldo to
> make it OFF
> + * @param vol_min minimum voltage level supported by given
> buck/ldo
> + * @param vol_div voltage division value of given buck/ldo
> + */
> +struct max77686_para {
> + enum max77686_regnum regnum;
> + u8 vol_addr;
> + u8 vol_bitpos;
> + u8 vol_bitmask;
> + u8 reg_enaddr;
> + u8 reg_enbitpos;
> + u8 reg_enbitmask;
> + u8 reg_enbiton;
> + u8 reg_enbitoff;
> + u32 vol_min;
> + u32 vol_div;
> +};
> +
> +/* I2C device address for pmic max77686 */
> +#define MAX77686_I2C_ADDR (0x12 >> 1)
> +
> +enum {
> + REG_DISABLE = 0,
> + REG_ENABLE
> +};
> +
> +/**
> + * This function enables the 32KHz coprocessor clock.
> + *
> + * Return 0 if ok, else -1
> + */
> +int max77686_enable_32khz_cp(void);
> +
> +/**
> + * This function sets the BUCK's/LDO's voltages of pmic
> + *
> + * Return 0 if ok, else -1
> + */
> +int power_init(void);
> +
> +#endif /* __MAX77686_PMIC_H_ */
It looks like the max77686.h file is already written in a similar way
to e.g. max8998.h file and stick to the PMIC framework.
I'd really encourage you to look into the PMIC driver and adjust your
driver to the PMIC framework.
--
Best regards,
Lukasz Majewski
Samsung Poland R&D Center | Linux Platform Group
More information about the U-Boot
mailing list