diff options
author | Stefano Babic <sbabic@denx.de> | 2010-04-04 23:08:03 +0200 |
---|---|---|
committer | Stefano Babic <sbabic@denx.de> | 2010-05-05 09:48:41 +0200 |
commit | 28bb6d34d3f431b7b00444e2f829b2c04f5daf4d (patch) | |
tree | 884811fb66472a3bf7c4f3ba400c797856d2c006 /drivers/misc/fsl_pmic.c | |
parent | ba6adeb48e71f7f1b791b6e98999a5680d919b26 (diff) |
MX: Added Freescale Power Management Driver
The patch add supports for the Freescale's Power
Management Controller (known as Atlas) used together with i.MX31/51
processors. It was tested with a MC13783 (MX31) and
MC13892 (MX51).
Signed-off-by: Stefano Babic <sbabic@denx.de>
Diffstat (limited to 'drivers/misc/fsl_pmic.c')
-rw-r--r-- | drivers/misc/fsl_pmic.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/drivers/misc/fsl_pmic.c b/drivers/misc/fsl_pmic.c new file mode 100644 index 0000000000..87f0aedeb6 --- /dev/null +++ b/drivers/misc/fsl_pmic.c @@ -0,0 +1,200 @@ +/* + * (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 <config.h> +#include <common.h> +#include <spi.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <fsl_pmic.h> + +static struct spi_slave *slave; + +struct spi_slave *pmic_spi_probe(void) +{ + return spi_setup_slave(CONFIG_FSL_PMIC_BUS, + CONFIG_FSL_PMIC_CS, + CONFIG_FSL_PMIC_CLK, + CONFIG_FSL_PMIC_MODE); +} + +void pmic_spi_free(struct spi_slave *slave) +{ + if (slave) + spi_free_slave(slave); +} + +u32 pmic_reg(u32 reg, u32 val, u32 write) +{ + u32 pmic_tx, pmic_rx; + + if (!slave) { + slave = pmic_spi_probe(); + + if (!slave) + return -1; + } + + if (reg > 63 || write > 1) { + printf("<reg num> = %d is invalid. Should be less then 63\n", + reg); + return -1; + } + + if (spi_claim_bus(slave)) + return -1; + + pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF); + + if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx, + SPI_XFER_BEGIN | SPI_XFER_END)) { + spi_release_bus(slave); + return -1; + } + + if (write) { + pmic_tx &= ~(1 << 31); + if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx, + SPI_XFER_BEGIN | SPI_XFER_END)) { + spi_release_bus(slave); + return -1; + } + } + + spi_release_bus(slave); + return pmic_rx; +} + +void pmic_reg_write(u32 reg, u32 value) +{ + pmic_reg(reg, value, 1); +} + +u32 pmic_reg_read(u32 reg) +{ + return pmic_reg(reg, 0, 0); +} + +void pmic_show_pmic_info(void) +{ + u32 rev_id; + + rev_id = pmic_reg_read(REG_IDENTIFICATION); + printf("PMIC ID: 0x%08x [Rev: ", rev_id); + switch (rev_id & 0x1F) { + case 0x1: + puts("1.0"); + break; + case 0x9: + puts("1.1"); + break; + case 0xA: + puts("1.2"); + break; + case 0x10: + puts("2.0"); + break; + case 0x11: + puts("2.1"); + break; + case 0x18: + puts("3.0"); + break; + case 0x19: + puts("3.1"); + break; + case 0x1A: + puts("3.2"); + break; + case 0x2: + puts("3.2A"); + break; + case 0x1B: + puts("3.3"); + break; + case 0x1D: + puts("3.5"); + break; + default: + puts("unknown"); + break; + } + puts("]\n"); +} + +static void pmic_dump(int numregs) +{ + u32 val; + int i; + + pmic_show_pmic_info(); + for (i = 0; i < numregs; i++) { + val = pmic_reg_read(i); + if (!(i % 8)) + printf ("\n0x%02x: ", i); + printf("%08x ", val); + } + puts("\n"); +} + +int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *cmd; + int nregs; + u32 val; + + /* at least two arguments please */ + if (argc < 2) { + cmd_usage(cmdtp); + return 1; + } + + cmd = argv[1]; + if (strcmp(cmd, "dump") == 0) { + if (argc < 3) { + cmd_usage(cmdtp); + return 1; + } + nregs = simple_strtoul(argv[2], NULL, 16); + pmic_dump(nregs); + return 0; + } + if (strcmp(cmd, "write") == 0) { + if (argc < 4) { + cmd_usage(cmdtp); + return 1; + } + nregs = simple_strtoul(argv[2], NULL, 16); + val = simple_strtoul(argv[3], NULL, 16); + pmic_reg_write(nregs, val); + return 0; + } + /* No subcommand found */ + return 1; +} + +U_BOOT_CMD( + pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, + "Freescale PMIC (Atlas)", + "dump [numregs] dump registers\n" + "pmic write <reg> <value> - write register" +); |