This commit adds new PMIC core driver PMIC IC devices connected via I2C or SPI can be used.
Signed-off-by: Lukasz Majewski <l.majew...@samsung.com> --- arch/arm/lib/board.c | 5 + drivers/misc/Makefile | 1 + drivers/misc/pmic_core.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++ include/pmic.h | 60 ++++++++++++ 4 files changed, 302 insertions(+), 0 deletions(-) create mode 100644 drivers/misc/pmic_core.c create mode 100644 include/pmic.h diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index c899839..bd2c619 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -48,6 +48,7 @@ #include <nand.h> #include <onenand_uboot.h> #include <mmc.h> +#include <pmic.h> #ifdef CONFIG_BITBANGMII #include <miiphy.h> @@ -580,6 +581,10 @@ void board_init_r(gd_t *id, ulong dest_addr) copy_filename(BootFile, s, sizeof(BootFile)); #endif +#if defined(CONFIG_PMIC) + pmic_init(); +#endif + #ifdef BOARD_LATE_INIT board_late_init(); #endif diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b152486..f710a29 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -35,6 +35,7 @@ COBJS-$(CONFIG_NS87308) += ns87308.o COBJS-$(CONFIG_PDSP188x) += pdsp188x.o COBJS-$(CONFIG_STATUS_LED) += status_led.o COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o +COBJS-$(CONFIG_PMIC) += pmic_core.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/misc/pmic_core.c b/drivers/misc/pmic_core.c new file mode 100644 index 0000000..d96bb87 --- /dev/null +++ b/drivers/misc/pmic_core.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * Lukasz Majewski <l.majew...@samsung.com> + * + * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. + * + * 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 <linux/types.h> +#include <pmic.h> + +static struct pmic pmic; + +#ifdef CONFIG_PMIC_I2C +#include <i2c.h> +#define pmic_set_reg(r) (p->hw.i2c.reg = r) +#define pmic_set_addr(a) (p->hw.i2c.addr = a) +#define pmic_i2c_addr (p->hw.i2c.addr) +#define pmic_i2c_reg (p->hw.i2c.reg) +#define pmic_tx_num (p->hw.i2c.tx_num) +#define pmic_i2c_bus (p->hw.i2c.bus_num) + +int pmic_reg_write(struct pmic *p, u32 *val) +{ + unsigned char buf[4] = { 0 }; + + switch (pmic_tx_num) { + case 3: + buf[0] = (*val >> 16) & 0xff; + buf[1] = (*val >> 8) & 0xff; + buf[2] = (*val) & 0xff; + break; + case 1: + buf[0] = (*val) & 0xff; + break; + } + + if (i2c_write(pmic_i2c_addr, pmic_i2c_reg, 1, buf, pmic_tx_num)) + return -1; + + return 0; +} + +int pmic_reg_read(struct pmic *p, u32 *val) +{ + unsigned char buf[4] = { 0 }; + u32 ret_val = 0; + + if (i2c_read(pmic_i2c_addr, pmic_i2c_reg, 1, buf, pmic_tx_num)) + return -1; + + switch (pmic_tx_num) { + case 3: + ret_val = buf[0] << 16 | buf[1] << 8 | buf[2]; + break; + case 1: + ret_val = buf[0]; + break; + } + memcpy(val, &ret_val, sizeof(ret_val)); + /* printf("val 0x%x:", *val); */ + + return 0; +} + +int pmic_probe(struct pmic *p) +{ + i2c_set_bus_num(pmic_i2c_bus); + printf("PMIC:%s probed!\n", p->name); + if (i2c_probe(pmic_i2c_addr)) { + puts("Can't find max8998\n"); + return -1; + } + + return 0; +} +#else /* SPI interface */ +#include <spi.h> +static struct spi_slave *slave; + +#define pmic_set_reg(r) +#define pmic_set_addr(a) + +void pmic_spi_free(struct spi_slave *slave) +{ + if (slave) + spi_free_slave(slave); +} + + +int pmic_reg_write(struct pmic *p, u32 *val) +{ + return 0; +} + +int pmic_reg_read(struct pmic *p, u32 *val) +{ + return 0; +} +#endif + +int __attribute__((weak)) board_pmic_init(struct pmic *p) +{ + puts("weak function"); + return 0; +} + +int pmic_set_output(struct pmic *p, int out, int on) +{ + u32 val; + + if (pmic_reg_read(p, &val)) + return -1; + + if (on) + val |= out; + else + val &= ~out; + + if (pmic_reg_write(p, &val)) + return -1; + + return 0; +} + +static void pmic_show_info(struct pmic *p) +{ + printf("PMIC: %s\n", p->name); +} + +static void pmic_dump(struct pmic *p) +{ + int i, ret; + u32 val; + + pmic_show_info(p); + for (i = 0; i < p->number_of_regs; i++) { + pmic_set_reg(i); + ret = pmic_reg_read(p, &val); + if (ret) + puts("PMIC: Registers dump failed\n"); + + if (!(i % 8)) + printf ("\n0x%02x: ", i); + + printf("%08x ", val); + } + puts("\n"); +} + + +int pmic_init(void) +{ + return board_pmic_init(&pmic); +} + +struct pmic* get_pmic(void) { + return &pmic; +} + +int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + u32 ret, reg, val; + char *cmd; + + struct pmic *p = &pmic; + + /* at least two arguments please */ + if (argc < 2) + return cmd_usage(cmdtp); + + cmd = argv[1]; + if (strcmp(cmd, "dump") == 0) { + pmic_dump(p); + return 0; + } + + if (strcmp(cmd, "read") == 0) { + if (argc < 3) + return cmd_usage(cmdtp); + + reg = simple_strtoul(argv[2], NULL, 16); + + pmic_set_reg(reg); + ret = pmic_reg_read(p, &val); + + if (ret) + puts("PMIC: Register read failed\n"); + + printf("\n0x%02x: 0x%08x \n", reg, val); + + return 0; + } + + if (strcmp(cmd, "write") == 0) { + if (argc < 4) + return cmd_usage(cmdtp); + + reg = simple_strtoul(argv[2], NULL, 16); + val = simple_strtoul(argv[3], NULL, 16); + + pmic_set_reg(reg); + pmic_reg_write(p, &val); + + return 0; + } + + /* No subcommand found */ + return 1; +} + +U_BOOT_CMD( + pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, + "PMIC", + "dump - dump PMIC registers\n" + "pmic read <reg> - read register" + "pmic write <reg> <value> - write register" +); diff --git a/include/pmic.h b/include/pmic.h new file mode 100644 index 0000000..a048ec7 --- /dev/null +++ b/include/pmic.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * Lukasz Majewski <l.majew...@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 __CORE_PMIC_H_ +#define __CORE_PMIC_H_ + +enum { PMIC_I2C, PMIC_SPI, }; +enum { I2C_PMIC, I2C_NUM, }; +enum { PMIC_READ, PMIC_WRITE, }; + +struct p_i2c { + unsigned char addr; + unsigned char reg; + unsigned char *buf; + unsigned char tx_num; + unsigned char bus_num; +}; + +struct p_spi { + unsigned int flags; +}; + +struct pmic { + char *name; + unsigned char interface; + unsigned char number_of_regs; + union hw { + struct p_i2c i2c; + struct p_spi spi; + } hw; +}; + +int pmic_init(void); +struct pmic *get_pmic(void); +int pmic_probe(struct pmic *p); +int pmic_read_reg(struct pmic *p, u32 *val); +int pmic_write_reg(struct pmic *p, u32 *val); +int pmic_set_output(struct pmic *p, int ldo, int on); + +#endif /* __CORE_PMIC_H_ */ -- 1.7.2.3 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot