1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2011 Samsung Electronics 4 * Lukasz Majewski <l.majewski@samsung.com> 5 * 6 * (C) Copyright 2010 7 * Stefano Babic, DENX Software Engineering, sbabic@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