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 -EINVAL; 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 -ENOTSUPP; 38 39 if (on) 40 val |= out; 41 else 42 val &= ~out; 43 44 if (pmic_reg_write(p, reg, val)) 45 return -ENOTSUPP; 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 -ENODEV; 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 if (argc < 3) 144 return CMD_RET_USAGE; 145 146 name = argv[1]; 147 cmd = argv[2]; 148 149 debug("%s: name: %s cmd: %s\n", __func__, name, cmd); 150 p = pmic_get(name); 151 if (!p) 152 return CMD_RET_FAILURE; 153 154 if (strcmp(cmd, "dump") == 0) { 155 if (pmic_dump(p)) 156 return CMD_RET_FAILURE; 157 return CMD_RET_SUCCESS; 158 } 159 160 if (strcmp(cmd, "read") == 0) { 161 if (argc < 4) 162 return CMD_RET_USAGE; 163 164 reg = simple_strtoul(argv[3], NULL, 16); 165 ret = pmic_reg_read(p, reg, &val); 166 167 if (ret) 168 puts("PMIC: Register read failed\n"); 169 170 printf("\n0x%02x: 0x%08x\n", reg, val); 171 172 return CMD_RET_SUCCESS; 173 } 174 175 if (strcmp(cmd, "write") == 0) { 176 if (argc < 5) 177 return CMD_RET_USAGE; 178 179 reg = simple_strtoul(argv[3], NULL, 16); 180 val = simple_strtoul(argv[4], NULL, 16); 181 pmic_reg_write(p, reg, val); 182 183 return CMD_RET_SUCCESS; 184 } 185 186 if (strcmp(cmd, "bat") == 0) { 187 if (argc < 4) 188 return CMD_RET_USAGE; 189 190 if (!p->pbat) { 191 printf("%s is not a battery\n", p->name); 192 return CMD_RET_FAILURE; 193 } 194 195 if (strcmp(argv[3], "state") == 0) 196 p->fg->fg_battery_check(p->pbat->fg, p); 197 198 if (strcmp(argv[3], "charge") == 0) { 199 printf("BAT: %s charging (ctrl+c to break)\n", 200 p->name); 201 if (p->low_power_mode) 202 p->low_power_mode(); 203 if (p->pbat->battery_charge) 204 p->pbat->battery_charge(p); 205 } 206 207 return CMD_RET_SUCCESS; 208 } 209 210 /* No subcommand found */ 211 return CMD_RET_SUCCESS; 212 } 213 214 U_BOOT_CMD( 215 pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, 216 "PMIC", 217 "list - list available PMICs\n" 218 "pmic name dump - dump named PMIC registers\n" 219 "pmic name read <reg> - read register\n" 220 "pmic name write <reg> <value> - write register\n" 221 "pmic name bat state - write register\n" 222 "pmic name bat charge - write register\n" 223 ); 224