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 * See file CREDITS for list of people who contributed to this 11 * project. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License as 15 * published by the Free Software Foundation; either version 2 of 16 * the License, or (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 26 * MA 02111-1307 USA 27 */ 28 29 #include <common.h> 30 #include <malloc.h> 31 #include <linux/types.h> 32 #include <linux/list.h> 33 #include <power/pmic.h> 34 35 static LIST_HEAD(pmic_list); 36 37 int check_reg(struct pmic *p, u32 reg) 38 { 39 if (reg >= p->number_of_regs) { 40 printf("<reg num> = %d is invalid. Should be less than %d\n", 41 reg, p->number_of_regs); 42 return -1; 43 } 44 45 return 0; 46 } 47 48 int pmic_set_output(struct pmic *p, u32 reg, int out, int on) 49 { 50 u32 val; 51 52 if (pmic_reg_read(p, reg, &val)) 53 return -1; 54 55 if (on) 56 val |= out; 57 else 58 val &= ~out; 59 60 if (pmic_reg_write(p, reg, val)) 61 return -1; 62 63 return 0; 64 } 65 66 static void pmic_show_info(struct pmic *p) 67 { 68 printf("PMIC: %s\n", p->name); 69 } 70 71 static int pmic_dump(struct pmic *p) 72 { 73 int i, ret; 74 u32 val; 75 76 if (!p) { 77 puts("Wrong PMIC name!\n"); 78 return -1; 79 } 80 81 pmic_show_info(p); 82 for (i = 0; i < p->number_of_regs; i++) { 83 ret = pmic_reg_read(p, i, &val); 84 if (ret) 85 puts("PMIC: Registers dump failed\n"); 86 87 if (!(i % 8)) 88 printf("\n0x%02x: ", i); 89 90 printf("%08x ", val); 91 } 92 puts("\n"); 93 return 0; 94 } 95 96 struct pmic *pmic_alloc(void) 97 { 98 struct pmic *p; 99 100 p = calloc(sizeof(*p), 1); 101 if (!p) { 102 printf("%s: No available memory for allocation!\n", __func__); 103 return NULL; 104 } 105 106 list_add_tail(&p->list, &pmic_list); 107 108 debug("%s: new pmic struct: 0x%p\n", __func__, p); 109 110 return p; 111 } 112 113 struct pmic *pmic_get(const char *s) 114 { 115 struct pmic *p; 116 117 list_for_each_entry(p, &pmic_list, list) { 118 if (strcmp(p->name, s) == 0) { 119 debug("%s: pmic %s -> 0x%p\n", __func__, p->name, p); 120 return p; 121 } 122 } 123 124 return NULL; 125 } 126 127 const char *power_get_interface(int interface) 128 { 129 const char *power_interface[] = {"I2C", "SPI", "|+|-|"}; 130 return power_interface[interface]; 131 } 132 133 static void pmic_list_names(void) 134 { 135 struct pmic *p; 136 137 puts("PMIC devices:\n"); 138 list_for_each_entry(p, &pmic_list, list) { 139 printf("name: %s bus: %s_%d\n", p->name, 140 power_get_interface(p->interface), p->bus); 141 } 142 } 143 144 int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 145 { 146 u32 ret, reg, val; 147 char *cmd, *name; 148 struct pmic *p; 149 150 /* at least two arguments please */ 151 if (argc < 2) 152 return CMD_RET_USAGE; 153 154 if (strcmp(argv[1], "list") == 0) { 155 pmic_list_names(); 156 return CMD_RET_SUCCESS; 157 } 158 159 name = argv[1]; 160 cmd = argv[2]; 161 162 debug("%s: name: %s cmd: %s\n", __func__, name, cmd); 163 p = pmic_get(name); 164 if (!p) 165 return CMD_RET_FAILURE; 166 167 if (strcmp(cmd, "dump") == 0) { 168 if (pmic_dump(p)) 169 return CMD_RET_FAILURE; 170 return CMD_RET_SUCCESS; 171 } 172 173 if (strcmp(cmd, "read") == 0) { 174 if (argc < 4) 175 return CMD_RET_USAGE; 176 177 reg = simple_strtoul(argv[3], NULL, 16); 178 ret = pmic_reg_read(p, reg, &val); 179 180 if (ret) 181 puts("PMIC: Register read failed\n"); 182 183 printf("\n0x%02x: 0x%08x\n", reg, val); 184 185 return CMD_RET_SUCCESS; 186 } 187 188 if (strcmp(cmd, "write") == 0) { 189 if (argc < 5) 190 return CMD_RET_USAGE; 191 192 reg = simple_strtoul(argv[3], NULL, 16); 193 val = simple_strtoul(argv[4], NULL, 16); 194 pmic_reg_write(p, reg, val); 195 196 return CMD_RET_SUCCESS; 197 } 198 199 if (strcmp(cmd, "bat") == 0) { 200 if (argc < 4) 201 return CMD_RET_USAGE; 202 203 if (strcmp(argv[3], "state") == 0) 204 p->fg->fg_battery_check(p->pbat->fg, p); 205 206 if (strcmp(argv[3], "charge") == 0) { 207 if (p->pbat) { 208 printf("BAT: %s charging (ctrl+c to break)\n", 209 p->name); 210 if (p->low_power_mode) 211 p->low_power_mode(); 212 if (p->pbat->battery_charge) 213 p->pbat->battery_charge(p); 214 } 215 } 216 217 return CMD_RET_SUCCESS; 218 } 219 220 /* No subcommand found */ 221 return CMD_RET_SUCCESS; 222 } 223 224 U_BOOT_CMD( 225 pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, 226 "PMIC", 227 "list - list available PMICs\n" 228 "pmic name dump - dump named PMIC registers\n" 229 "pmic name read <reg> - read register\n" 230 "pmic name write <reg> <value> - write register\n" 231 "pmic name bat state - write register\n" 232 "pmic name bat charge - write register\n" 233 ); 234