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 struct pmic *pmic_alloc(void) 51 { 52 struct pmic *p; 53 54 p = calloc(sizeof(*p), 1); 55 if (!p) { 56 printf("%s: No available memory for allocation!\n", __func__); 57 return NULL; 58 } 59 60 list_add_tail(&p->list, &pmic_list); 61 62 debug("%s: new pmic struct: 0x%p\n", __func__, p); 63 64 return p; 65 } 66 67 struct pmic *pmic_get(const char *s) 68 { 69 struct pmic *p; 70 71 list_for_each_entry(p, &pmic_list, list) { 72 if (strcmp(p->name, s) == 0) { 73 debug("%s: pmic %s -> 0x%p\n", __func__, p->name, p); 74 return p; 75 } 76 } 77 78 return NULL; 79 } 80 81 #ifndef CONFIG_SPL_BUILD 82 static int pmic_dump(struct pmic *p) 83 { 84 int i, ret; 85 u32 val; 86 87 if (!p) { 88 puts("Wrong PMIC name!\n"); 89 return -ENODEV; 90 } 91 92 printf("PMIC: %s\n", p->name); 93 for (i = 0; i < p->number_of_regs; i++) { 94 ret = pmic_reg_read(p, i, &val); 95 if (ret) 96 puts("PMIC: Registers dump failed\n"); 97 98 if (!(i % 8)) 99 printf("\n0x%02x: ", i); 100 101 printf("%08x ", val); 102 } 103 puts("\n"); 104 return 0; 105 } 106 107 static const char *power_get_interface(int interface) 108 { 109 const char *power_interface[] = {"I2C", "SPI", "|+|-|"}; 110 return power_interface[interface]; 111 } 112 113 static void pmic_list_names(void) 114 { 115 struct pmic *p; 116 117 puts("PMIC devices:\n"); 118 list_for_each_entry(p, &pmic_list, list) { 119 printf("name: %s bus: %s_%d\n", p->name, 120 power_get_interface(p->interface), p->bus); 121 } 122 } 123 124 static int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 125 { 126 u32 ret, reg, val; 127 char *cmd, *name; 128 struct pmic *p; 129 130 /* at least two arguments please */ 131 if (argc < 2) 132 return CMD_RET_USAGE; 133 134 if (strcmp(argv[1], "list") == 0) { 135 pmic_list_names(); 136 return CMD_RET_SUCCESS; 137 } 138 139 if (argc < 3) 140 return CMD_RET_USAGE; 141 142 name = argv[1]; 143 cmd = argv[2]; 144 145 debug("%s: name: %s cmd: %s\n", __func__, name, cmd); 146 p = pmic_get(name); 147 if (!p) 148 return CMD_RET_FAILURE; 149 150 if (strcmp(cmd, "dump") == 0) { 151 if (pmic_dump(p)) 152 return CMD_RET_FAILURE; 153 return CMD_RET_SUCCESS; 154 } 155 156 if (strcmp(cmd, "read") == 0) { 157 if (argc < 4) 158 return CMD_RET_USAGE; 159 160 reg = simple_strtoul(argv[3], NULL, 16); 161 ret = pmic_reg_read(p, reg, &val); 162 163 if (ret) 164 puts("PMIC: Register read failed\n"); 165 166 printf("\n0x%02x: 0x%08x\n", reg, val); 167 168 return CMD_RET_SUCCESS; 169 } 170 171 if (strcmp(cmd, "write") == 0) { 172 if (argc < 5) 173 return CMD_RET_USAGE; 174 175 reg = simple_strtoul(argv[3], NULL, 16); 176 val = simple_strtoul(argv[4], NULL, 16); 177 pmic_reg_write(p, reg, val); 178 179 return CMD_RET_SUCCESS; 180 } 181 182 if (strcmp(cmd, "bat") == 0) { 183 if (argc < 4) 184 return CMD_RET_USAGE; 185 186 if (!p->pbat) { 187 printf("%s is not a battery\n", p->name); 188 return CMD_RET_FAILURE; 189 } 190 191 if (strcmp(argv[3], "state") == 0) 192 p->fg->fg_battery_check(p->pbat->fg, p); 193 194 if (strcmp(argv[3], "charge") == 0) { 195 printf("BAT: %s charging (ctrl+c to break)\n", 196 p->name); 197 if (p->low_power_mode) 198 p->low_power_mode(); 199 if (p->pbat->battery_charge) 200 p->pbat->battery_charge(p); 201 } 202 203 return CMD_RET_SUCCESS; 204 } 205 206 /* No subcommand found */ 207 return CMD_RET_SUCCESS; 208 } 209 210 U_BOOT_CMD( 211 pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, 212 "PMIC", 213 "list - list available PMICs\n" 214 "pmic name dump - dump named PMIC registers\n" 215 "pmic name read <reg> - read register\n" 216 "pmic name write <reg> <value> - write register\n" 217 "pmic name bat state - write register\n" 218 "pmic name bat charge - write register\n" 219 ); 220 #endif 221