1316a51beSŁukasz Majewski /* 2316a51beSŁukasz Majewski * Copyright (C) 2011 Samsung Electronics 3316a51beSŁukasz Majewski * Lukasz Majewski <l.majewski@samsung.com> 4316a51beSŁukasz Majewski * 5316a51beSŁukasz Majewski * (C) Copyright 2010 6316a51beSŁukasz Majewski * Stefano Babic, DENX Software Engineering, sbabic@denx.de 7316a51beSŁukasz Majewski * 8316a51beSŁukasz Majewski * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. 9316a51beSŁukasz Majewski * 101a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 11316a51beSŁukasz Majewski */ 12316a51beSŁukasz Majewski 13316a51beSŁukasz Majewski #include <common.h> 14316a51beSŁukasz Majewski #include <malloc.h> 15316a51beSŁukasz Majewski #include <linux/types.h> 16316a51beSŁukasz Majewski #include <linux/list.h> 17316a51beSŁukasz Majewski #include <power/pmic.h> 18316a51beSŁukasz Majewski 19316a51beSŁukasz Majewski static LIST_HEAD(pmic_list); 20316a51beSŁukasz Majewski 21316a51beSŁukasz Majewski int check_reg(struct pmic *p, u32 reg) 22316a51beSŁukasz Majewski { 23316a51beSŁukasz Majewski if (reg >= p->number_of_regs) { 24316a51beSŁukasz Majewski printf("<reg num> = %d is invalid. Should be less than %d\n", 25316a51beSŁukasz Majewski reg, p->number_of_regs); 26316a51beSŁukasz Majewski return -1; 27316a51beSŁukasz Majewski } 28316a51beSŁukasz Majewski 29316a51beSŁukasz Majewski return 0; 30316a51beSŁukasz Majewski } 31316a51beSŁukasz Majewski 32316a51beSŁukasz Majewski int pmic_set_output(struct pmic *p, u32 reg, int out, int on) 33316a51beSŁukasz Majewski { 34316a51beSŁukasz Majewski u32 val; 35316a51beSŁukasz Majewski 36316a51beSŁukasz Majewski if (pmic_reg_read(p, reg, &val)) 37316a51beSŁukasz Majewski return -1; 38316a51beSŁukasz Majewski 39316a51beSŁukasz Majewski if (on) 40316a51beSŁukasz Majewski val |= out; 41316a51beSŁukasz Majewski else 42316a51beSŁukasz Majewski val &= ~out; 43316a51beSŁukasz Majewski 44316a51beSŁukasz Majewski if (pmic_reg_write(p, reg, val)) 45316a51beSŁukasz Majewski return -1; 46316a51beSŁukasz Majewski 47316a51beSŁukasz Majewski return 0; 48316a51beSŁukasz Majewski } 49316a51beSŁukasz Majewski 50316a51beSŁukasz Majewski static void pmic_show_info(struct pmic *p) 51316a51beSŁukasz Majewski { 52316a51beSŁukasz Majewski printf("PMIC: %s\n", p->name); 53316a51beSŁukasz Majewski } 54316a51beSŁukasz Majewski 55316a51beSŁukasz Majewski static int pmic_dump(struct pmic *p) 56316a51beSŁukasz Majewski { 57316a51beSŁukasz Majewski int i, ret; 58316a51beSŁukasz Majewski u32 val; 59316a51beSŁukasz Majewski 60316a51beSŁukasz Majewski if (!p) { 61316a51beSŁukasz Majewski puts("Wrong PMIC name!\n"); 62316a51beSŁukasz Majewski return -1; 63316a51beSŁukasz Majewski } 64316a51beSŁukasz Majewski 65316a51beSŁukasz Majewski pmic_show_info(p); 66316a51beSŁukasz Majewski for (i = 0; i < p->number_of_regs; i++) { 67316a51beSŁukasz Majewski ret = pmic_reg_read(p, i, &val); 68316a51beSŁukasz Majewski if (ret) 69316a51beSŁukasz Majewski puts("PMIC: Registers dump failed\n"); 70316a51beSŁukasz Majewski 71316a51beSŁukasz Majewski if (!(i % 8)) 72316a51beSŁukasz Majewski printf("\n0x%02x: ", i); 73316a51beSŁukasz Majewski 74316a51beSŁukasz Majewski printf("%08x ", val); 75316a51beSŁukasz Majewski } 76316a51beSŁukasz Majewski puts("\n"); 77316a51beSŁukasz Majewski return 0; 78316a51beSŁukasz Majewski } 79316a51beSŁukasz Majewski 80316a51beSŁukasz Majewski struct pmic *pmic_alloc(void) 81316a51beSŁukasz Majewski { 82316a51beSŁukasz Majewski struct pmic *p; 83316a51beSŁukasz Majewski 84316a51beSŁukasz Majewski p = calloc(sizeof(*p), 1); 85316a51beSŁukasz Majewski if (!p) { 86316a51beSŁukasz Majewski printf("%s: No available memory for allocation!\n", __func__); 87316a51beSŁukasz Majewski return NULL; 88316a51beSŁukasz Majewski } 89316a51beSŁukasz Majewski 90316a51beSŁukasz Majewski list_add_tail(&p->list, &pmic_list); 91316a51beSŁukasz Majewski 92316a51beSŁukasz Majewski debug("%s: new pmic struct: 0x%p\n", __func__, p); 93316a51beSŁukasz Majewski 94316a51beSŁukasz Majewski return p; 95316a51beSŁukasz Majewski } 96316a51beSŁukasz Majewski 97316a51beSŁukasz Majewski struct pmic *pmic_get(const char *s) 98316a51beSŁukasz Majewski { 99316a51beSŁukasz Majewski struct pmic *p; 100316a51beSŁukasz Majewski 101316a51beSŁukasz Majewski list_for_each_entry(p, &pmic_list, list) { 102316a51beSŁukasz Majewski if (strcmp(p->name, s) == 0) { 103316a51beSŁukasz Majewski debug("%s: pmic %s -> 0x%p\n", __func__, p->name, p); 104316a51beSŁukasz Majewski return p; 105316a51beSŁukasz Majewski } 106316a51beSŁukasz Majewski } 107316a51beSŁukasz Majewski 108316a51beSŁukasz Majewski return NULL; 109316a51beSŁukasz Majewski } 110316a51beSŁukasz Majewski 111316a51beSŁukasz Majewski const char *power_get_interface(int interface) 112316a51beSŁukasz Majewski { 113316a51beSŁukasz Majewski const char *power_interface[] = {"I2C", "SPI", "|+|-|"}; 114316a51beSŁukasz Majewski return power_interface[interface]; 115316a51beSŁukasz Majewski } 116316a51beSŁukasz Majewski 117316a51beSŁukasz Majewski static void pmic_list_names(void) 118316a51beSŁukasz Majewski { 119316a51beSŁukasz Majewski struct pmic *p; 120316a51beSŁukasz Majewski 121316a51beSŁukasz Majewski puts("PMIC devices:\n"); 122316a51beSŁukasz Majewski list_for_each_entry(p, &pmic_list, list) { 123316a51beSŁukasz Majewski printf("name: %s bus: %s_%d\n", p->name, 124316a51beSŁukasz Majewski power_get_interface(p->interface), p->bus); 125316a51beSŁukasz Majewski } 126316a51beSŁukasz Majewski } 127316a51beSŁukasz Majewski 128316a51beSŁukasz Majewski int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 129316a51beSŁukasz Majewski { 130316a51beSŁukasz Majewski u32 ret, reg, val; 131316a51beSŁukasz Majewski char *cmd, *name; 132316a51beSŁukasz Majewski struct pmic *p; 133316a51beSŁukasz Majewski 134316a51beSŁukasz Majewski /* at least two arguments please */ 135316a51beSŁukasz Majewski if (argc < 2) 136316a51beSŁukasz Majewski return CMD_RET_USAGE; 137316a51beSŁukasz Majewski 138316a51beSŁukasz Majewski if (strcmp(argv[1], "list") == 0) { 139316a51beSŁukasz Majewski pmic_list_names(); 140316a51beSŁukasz Majewski return CMD_RET_SUCCESS; 141316a51beSŁukasz Majewski } 142316a51beSŁukasz Majewski 143316a51beSŁukasz Majewski name = argv[1]; 144316a51beSŁukasz Majewski cmd = argv[2]; 145316a51beSŁukasz Majewski 146316a51beSŁukasz Majewski debug("%s: name: %s cmd: %s\n", __func__, name, cmd); 147316a51beSŁukasz Majewski p = pmic_get(name); 148316a51beSŁukasz Majewski if (!p) 149316a51beSŁukasz Majewski return CMD_RET_FAILURE; 150316a51beSŁukasz Majewski 151316a51beSŁukasz Majewski if (strcmp(cmd, "dump") == 0) { 152316a51beSŁukasz Majewski if (pmic_dump(p)) 153316a51beSŁukasz Majewski return CMD_RET_FAILURE; 154316a51beSŁukasz Majewski return CMD_RET_SUCCESS; 155316a51beSŁukasz Majewski } 156316a51beSŁukasz Majewski 157316a51beSŁukasz Majewski if (strcmp(cmd, "read") == 0) { 158316a51beSŁukasz Majewski if (argc < 4) 159316a51beSŁukasz Majewski return CMD_RET_USAGE; 160316a51beSŁukasz Majewski 161316a51beSŁukasz Majewski reg = simple_strtoul(argv[3], NULL, 16); 162316a51beSŁukasz Majewski ret = pmic_reg_read(p, reg, &val); 163316a51beSŁukasz Majewski 164316a51beSŁukasz Majewski if (ret) 165316a51beSŁukasz Majewski puts("PMIC: Register read failed\n"); 166316a51beSŁukasz Majewski 167316a51beSŁukasz Majewski printf("\n0x%02x: 0x%08x\n", reg, val); 168316a51beSŁukasz Majewski 169316a51beSŁukasz Majewski return CMD_RET_SUCCESS; 170316a51beSŁukasz Majewski } 171316a51beSŁukasz Majewski 172316a51beSŁukasz Majewski if (strcmp(cmd, "write") == 0) { 173316a51beSŁukasz Majewski if (argc < 5) 174316a51beSŁukasz Majewski return CMD_RET_USAGE; 175316a51beSŁukasz Majewski 176316a51beSŁukasz Majewski reg = simple_strtoul(argv[3], NULL, 16); 177316a51beSŁukasz Majewski val = simple_strtoul(argv[4], NULL, 16); 178316a51beSŁukasz Majewski pmic_reg_write(p, reg, val); 179316a51beSŁukasz Majewski 180316a51beSŁukasz Majewski return CMD_RET_SUCCESS; 181316a51beSŁukasz Majewski } 182316a51beSŁukasz Majewski 183316a51beSŁukasz Majewski if (strcmp(cmd, "bat") == 0) { 184316a51beSŁukasz Majewski if (argc < 4) 185316a51beSŁukasz Majewski return CMD_RET_USAGE; 186316a51beSŁukasz Majewski 187*a6abaadcSPiotr Wilczek if (!p->pbat) { 188*a6abaadcSPiotr Wilczek printf("%s is not a battery\n", p->name); 189*a6abaadcSPiotr Wilczek return CMD_RET_FAILURE; 190*a6abaadcSPiotr Wilczek } 191*a6abaadcSPiotr Wilczek 192316a51beSŁukasz Majewski if (strcmp(argv[3], "state") == 0) 193316a51beSŁukasz Majewski p->fg->fg_battery_check(p->pbat->fg, p); 194316a51beSŁukasz Majewski 195316a51beSŁukasz Majewski if (strcmp(argv[3], "charge") == 0) { 1969dfa3d07SŁukasz Majewski printf("BAT: %s charging (ctrl+c to break)\n", 1979dfa3d07SŁukasz Majewski p->name); 198316a51beSŁukasz Majewski if (p->low_power_mode) 199316a51beSŁukasz Majewski p->low_power_mode(); 200316a51beSŁukasz Majewski if (p->pbat->battery_charge) 201316a51beSŁukasz Majewski p->pbat->battery_charge(p); 202316a51beSŁukasz Majewski } 203316a51beSŁukasz Majewski 204316a51beSŁukasz Majewski return CMD_RET_SUCCESS; 205316a51beSŁukasz Majewski } 206316a51beSŁukasz Majewski 207316a51beSŁukasz Majewski /* No subcommand found */ 208316a51beSŁukasz Majewski return CMD_RET_SUCCESS; 209316a51beSŁukasz Majewski } 210316a51beSŁukasz Majewski 211316a51beSŁukasz Majewski U_BOOT_CMD( 212316a51beSŁukasz Majewski pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, 213316a51beSŁukasz Majewski "PMIC", 214316a51beSŁukasz Majewski "list - list available PMICs\n" 215316a51beSŁukasz Majewski "pmic name dump - dump named PMIC registers\n" 216316a51beSŁukasz Majewski "pmic name read <reg> - read register\n" 217316a51beSŁukasz Majewski "pmic name write <reg> <value> - write register\n" 218316a51beSŁukasz Majewski "pmic name bat state - write register\n" 219316a51beSŁukasz Majewski "pmic name bat charge - write register\n" 220316a51beSŁukasz Majewski ); 221