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