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