Home | History | Annotate | Download | only in power
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2011 Samsung Electronics
      4  * Lukasz Majewski <l.majewski (at) samsung.com>
      5  *
      6  * (C) Copyright 2010
      7  * Stefano Babic, DENX Software Engineering, sbabic (at) denx.de
      8  *
      9  * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
     10  */
     11 
     12 #include <common.h>
     13 #include <malloc.h>
     14 #include <linux/types.h>
     15 #include <linux/list.h>
     16 #include <power/pmic.h>
     17 
     18 static LIST_HEAD(pmic_list);
     19 
     20 int check_reg(struct pmic *p, u32 reg)
     21 {
     22 	if (reg >= p->number_of_regs) {
     23 		printf("<reg num> = %d is invalid. Should be less than %d\n",
     24 		       reg, p->number_of_regs);
     25 		return -EINVAL;
     26 	}
     27 
     28 	return 0;
     29 }
     30 
     31 int pmic_set_output(struct pmic *p, u32 reg, int out, int on)
     32 {
     33 	u32 val;
     34 
     35 	if (pmic_reg_read(p, reg, &val))
     36 		return -ENOTSUPP;
     37 
     38 	if (on)
     39 		val |= out;
     40 	else
     41 		val &= ~out;
     42 
     43 	if (pmic_reg_write(p, reg, val))
     44 		return -ENOTSUPP;
     45 
     46 	return 0;
     47 }
     48 
     49 struct pmic *pmic_alloc(void)
     50 {
     51 	struct pmic *p;
     52 
     53 	p = calloc(sizeof(*p), 1);
     54 	if (!p) {
     55 		printf("%s: No available memory for allocation!\n", __func__);
     56 		return NULL;
     57 	}
     58 
     59 	list_add_tail(&p->list, &pmic_list);
     60 
     61 	debug("%s: new pmic struct: 0x%p\n", __func__, p);
     62 
     63 	return p;
     64 }
     65 
     66 struct pmic *pmic_get(const char *s)
     67 {
     68 	struct pmic *p;
     69 
     70 	list_for_each_entry(p, &pmic_list, list) {
     71 		if (strcmp(p->name, s) == 0) {
     72 			debug("%s: pmic %s -> 0x%p\n", __func__, p->name, p);
     73 			return p;
     74 		}
     75 	}
     76 
     77 	return NULL;
     78 }
     79 
     80 #ifndef CONFIG_SPL_BUILD
     81 static int pmic_dump(struct pmic *p)
     82 {
     83 	int i, ret;
     84 	u32 val;
     85 
     86 	if (!p) {
     87 		puts("Wrong PMIC name!\n");
     88 		return -ENODEV;
     89 	}
     90 
     91 	printf("PMIC: %s\n", p->name);
     92 	for (i = 0; i < p->number_of_regs; i++) {
     93 		ret = pmic_reg_read(p, i, &val);
     94 		if (ret)
     95 			puts("PMIC: Registers dump failed\n");
     96 
     97 		if (!(i % 8))
     98 			printf("\n0x%02x: ", i);
     99 
    100 		printf("%08x ", val);
    101 	}
    102 	puts("\n");
    103 	return 0;
    104 }
    105 
    106 static const char *power_get_interface(int interface)
    107 {
    108 	const char *power_interface[] = {"I2C", "SPI", "|+|-|"};
    109 	return power_interface[interface];
    110 }
    111 
    112 static void pmic_list_names(void)
    113 {
    114 	struct pmic *p;
    115 
    116 	puts("PMIC devices:\n");
    117 	list_for_each_entry(p, &pmic_list, list) {
    118 		printf("name: %s bus: %s_%d\n", p->name,
    119 		       power_get_interface(p->interface), p->bus);
    120 	}
    121 }
    122 
    123 static int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    124 {
    125 	u32 ret, reg, val;
    126 	char *cmd, *name;
    127 	struct pmic *p;
    128 
    129 	/* at least two arguments please */
    130 	if (argc < 2)
    131 		return CMD_RET_USAGE;
    132 
    133 	if (strcmp(argv[1], "list") == 0) {
    134 		pmic_list_names();
    135 		return CMD_RET_SUCCESS;
    136 	}
    137 
    138 	if (argc < 3)
    139 		return CMD_RET_USAGE;
    140 
    141 	name = argv[1];
    142 	cmd = argv[2];
    143 
    144 	debug("%s: name: %s cmd: %s\n", __func__, name, cmd);
    145 	p = pmic_get(name);
    146 	if (!p)
    147 		return CMD_RET_FAILURE;
    148 
    149 	if (strcmp(cmd, "dump") == 0) {
    150 		if (pmic_dump(p))
    151 			return CMD_RET_FAILURE;
    152 		return CMD_RET_SUCCESS;
    153 	}
    154 
    155 	if (strcmp(cmd, "read") == 0) {
    156 		if (argc < 4)
    157 			return CMD_RET_USAGE;
    158 
    159 		reg = simple_strtoul(argv[3], NULL, 16);
    160 		ret = pmic_reg_read(p, reg, &val);
    161 
    162 		if (ret)
    163 			puts("PMIC: Register read failed\n");
    164 
    165 		printf("\n0x%02x: 0x%08x\n", reg, val);
    166 
    167 		return CMD_RET_SUCCESS;
    168 	}
    169 
    170 	if (strcmp(cmd, "write") == 0) {
    171 		if (argc < 5)
    172 			return CMD_RET_USAGE;
    173 
    174 		reg = simple_strtoul(argv[3], NULL, 16);
    175 		val = simple_strtoul(argv[4], NULL, 16);
    176 		pmic_reg_write(p, reg, val);
    177 
    178 		return CMD_RET_SUCCESS;
    179 	}
    180 
    181 	if (strcmp(cmd, "bat") == 0) {
    182 		if (argc < 4)
    183 			return CMD_RET_USAGE;
    184 
    185 		if (!p->pbat) {
    186 			printf("%s is not a battery\n", p->name);
    187 			return CMD_RET_FAILURE;
    188 		}
    189 
    190 		if (strcmp(argv[3], "state") == 0)
    191 			p->fg->fg_battery_check(p->pbat->fg, p);
    192 
    193 		if (strcmp(argv[3], "charge") == 0) {
    194 			printf("BAT: %s charging (ctrl+c to break)\n",
    195 			       p->name);
    196 			if (p->low_power_mode)
    197 				p->low_power_mode();
    198 			if (p->pbat->battery_charge)
    199 				p->pbat->battery_charge(p);
    200 		}
    201 
    202 		return CMD_RET_SUCCESS;
    203 	}
    204 
    205 	/* No subcommand found */
    206 	return CMD_RET_SUCCESS;
    207 }
    208 
    209 U_BOOT_CMD(
    210 	pmic,	CONFIG_SYS_MAXARGS, 1, do_pmic,
    211 	"PMIC",
    212 	"list - list available PMICs\n"
    213 	"pmic name dump - dump named PMIC registers\n"
    214 	"pmic name read <reg> - read register\n"
    215 	"pmic name write <reg> <value> - write register\n"
    216 	"pmic name bat state - write register\n"
    217 	"pmic name bat charge - write register\n"
    218 );
    219 #endif
    220