1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2014-2015 Samsung Electronics 4 * Przemyslaw Marczak <p.marczak@samsung.com> 5 */ 6#include <common.h> 7#include <command.h> 8#include <errno.h> 9#include <dm.h> 10#include <dm/uclass-internal.h> 11#include <power/pmic.h> 12 13#define LIMIT_DEV 32 14#define LIMIT_PARENT 20 15 16static struct udevice *currdev; 17 18static int failure(int ret) 19{ 20 printf("Error: %d (%s)\n", ret, errno_str(ret)); 21 22 return CMD_RET_FAILURE; 23} 24 25static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 26{ 27 char *name; 28 int ret = -ENODEV; 29 30 switch (argc) { 31 case 2: 32 name = argv[1]; 33 ret = pmic_get(name, &currdev); 34 if (ret) { 35 printf("Can't get PMIC: %s!\n", name); 36 return failure(ret); 37 } 38 case 1: 39 if (!currdev) { 40 printf("PMIC device is not set!\n\n"); 41 return CMD_RET_USAGE; 42 } 43 44 printf("dev: %d @ %s\n", dev_seq(currdev), currdev->name); 45 } 46 47 return CMD_RET_SUCCESS; 48} 49 50static int do_list(struct cmd_tbl *cmdtp, int flag, int argc, 51 char *const argv[]) 52{ 53 struct udevice *dev; 54 int ret, err = 0; 55 56 printf("| %-*.*s| %-*.*s| %s @ %s\n", 57 LIMIT_DEV, LIMIT_DEV, "Name", 58 LIMIT_PARENT, LIMIT_PARENT, "Parent name", 59 "Parent uclass", "seq"); 60 61 for (ret = uclass_first_device_check(UCLASS_PMIC, &dev); dev; 62 ret = uclass_next_device_check(&dev)) { 63 if (ret) 64 err = ret; 65 66 printf("| %-*.*s| %-*.*s| %s @ %d | status: %i\n", 67 LIMIT_DEV, LIMIT_DEV, dev->name, 68 LIMIT_PARENT, LIMIT_PARENT, dev->parent->name, 69 dev_get_uclass_name(dev->parent), dev_seq(dev->parent), 70 ret); 71 } 72 73 if (err) 74 return CMD_RET_FAILURE; 75 76 return CMD_RET_SUCCESS; 77} 78 79static int do_dump(struct cmd_tbl *cmdtp, int flag, int argc, 80 char *const argv[]) 81{ 82 struct uc_pmic_priv *priv; 83 struct udevice *dev; 84 char fmt[16]; 85 uint reg; 86 int ret; 87 88 if (!currdev) { 89 printf("First, set the PMIC device!\n"); 90 return CMD_RET_USAGE; 91 } 92 93 dev = currdev; 94 priv = dev_get_uclass_priv(dev); 95 printf("Dump pmic: %s registers\n", dev->name); 96 97 sprintf(fmt, "%%%d.%dx ", priv->trans_len * 2, 98 priv->trans_len * 2); 99 100 for (reg = 0; reg < pmic_reg_count(dev); reg++) { 101 ret = pmic_reg_read(dev, reg); 102 if (ret < 0 && ret != -ENODATA) { 103 printf("Can't read register: %d\n", reg); 104 return failure(ret); 105 } 106 107 if (!(reg % 16)) 108 printf("\n0x%02x: ", reg); 109 110 if (ret == -ENODATA) { 111 int i; 112 113 for (i = 0; i < priv->trans_len; i++) 114 puts("--"); 115 puts(" "); 116 } else { 117 printf(fmt, ret); 118 } 119 } 120 printf("\n"); 121 122 return CMD_RET_SUCCESS; 123} 124 125static int do_read(struct cmd_tbl *cmdtp, int flag, int argc, 126 char *const argv[]) 127{ 128 struct uc_pmic_priv *priv; 129 struct udevice *dev; 130 int regs, ret; 131 char fmt[24]; 132 uint reg; 133 134 if (!currdev) { 135 printf("First, set the PMIC device!\n"); 136 return CMD_RET_USAGE; 137 } 138 139 dev = currdev; 140 priv = dev_get_uclass_priv(dev); 141 142 if (argc != 2) 143 return CMD_RET_USAGE; 144 145 reg = simple_strtoul(argv[1], NULL, 0); 146 regs = pmic_reg_count(dev); 147 if (reg > regs) { 148 printf("PMIC max reg: %d\n", regs); 149 return failure(-EFAULT); 150 } 151 152 ret = pmic_reg_read(dev, reg); 153 if (ret < 0) { 154 printf("Can't read PMIC register: %d!\n", reg); 155 return failure(ret); 156 } 157 158 sprintf(fmt, "0x%%02x: 0x%%%d.%dx\n", priv->trans_len * 2, 159 priv->trans_len * 2); 160 printf(fmt, reg, ret); 161 162 return CMD_RET_SUCCESS; 163} 164 165static int do_write(struct cmd_tbl *cmdtp, int flag, int argc, 166 char *const argv[]) 167{ 168 struct udevice *dev; 169 uint reg, value; 170 int regs, ret; 171 172 if (!currdev) { 173 printf("First, set the PMIC device!\n"); 174 return CMD_RET_USAGE; 175 } 176 177 dev = currdev; 178 179 if (argc != 3) 180 return CMD_RET_USAGE; 181 182 reg = simple_strtoul(argv[1], NULL, 0); 183 regs = pmic_reg_count(dev); 184 if (reg > regs) { 185 printf("PMIC max reg: %d\n", regs); 186 return failure(-EFAULT); 187 } 188 189 value = simple_strtoul(argv[2], NULL, 0); 190 191 ret = pmic_reg_write(dev, reg, value); 192 if (ret) { 193 printf("Can't write PMIC register: %d!\n", reg); 194 return failure(ret); 195 } 196 197 return CMD_RET_SUCCESS; 198} 199 200static struct cmd_tbl subcmd[] = { 201 U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""), 202 U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""), 203 U_BOOT_CMD_MKENT(dump, 1, 1, do_dump, "", ""), 204 U_BOOT_CMD_MKENT(read, 2, 1, do_read, "", ""), 205 U_BOOT_CMD_MKENT(write, 3, 1, do_write, "", ""), 206}; 207 208static int do_pmic(struct cmd_tbl *cmdtp, int flag, int argc, 209 char *const argv[]) 210{ 211 struct cmd_tbl *cmd; 212 213 argc--; 214 argv++; 215 216 cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd)); 217 if (cmd == NULL || argc > cmd->maxargs) 218 return CMD_RET_USAGE; 219 220 return cmd->cmd(cmdtp, flag, argc, argv); 221} 222 223U_BOOT_CMD(pmic, CONFIG_SYS_MAXARGS, 1, do_pmic, 224 "PMIC sub-system", 225 "list - list pmic devices\n" 226 "pmic dev [name] - show or [set] operating PMIC device\n" 227 "pmic dump - dump registers\n" 228 "pmic read <reg> - read byte of 'reg' register\n" 229 "pmic write <reg> <byte> - write 'byte' byte to 'reg' register\n" 230); 231