Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 2 | /* |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 3 | * Copyright (C) 2014-2015 Samsung Electronics |
| 4 | * Przemyslaw Marczak <p.marczak@samsung.com> |
| 5 | * |
Łukasz Majewski | 1c6dba1 | 2012-11-13 03:21:55 +0000 | [diff] [blame] | 6 | * Copyright (C) 2011-2012 Samsung Electronics |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 7 | * Lukasz Majewski <l.majewski@samsung.com> |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 8 | */ |
| 9 | |
| 10 | #ifndef __CORE_PMIC_H_ |
| 11 | #define __CORE_PMIC_H_ |
| 12 | |
Peng Fan | 6c6d647 | 2017-12-04 12:31:20 +0800 | [diff] [blame] | 13 | #include <dm/ofnode.h> |
Łukasz Majewski | 1c6dba1 | 2012-11-13 03:21:55 +0000 | [diff] [blame] | 14 | #include <i2c.h> |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 15 | #include <linux/list.h> |
Łukasz Majewski | 62ecae9 | 2012-11-13 03:22:00 +0000 | [diff] [blame] | 16 | #include <power/power_chrg.h> |
Łukasz Majewski | 1c6dba1 | 2012-11-13 03:21:55 +0000 | [diff] [blame] | 17 | |
Łukasz Majewski | 62ecae9 | 2012-11-13 03:22:00 +0000 | [diff] [blame] | 18 | enum { PMIC_I2C, PMIC_SPI, PMIC_NONE}; |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 19 | |
Simon Glass | 44da595 | 2021-08-08 12:20:26 -0600 | [diff] [blame] | 20 | /* TODO: Change to !CONFIG_IS_ENABLED(DM_PMIC) when SPL_DM_PMIC exists */ |
Simon Glass | 3133941 | 2021-08-08 12:20:27 -0600 | [diff] [blame] | 21 | #if CONFIG_IS_ENABLED(POWER_LEGACY) |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 22 | enum { I2C_PMIC, I2C_NUM, }; |
| 23 | enum { PMIC_READ, PMIC_WRITE, }; |
Łukasz Majewski | 40f5ca0 | 2012-11-13 03:21:53 +0000 | [diff] [blame] | 24 | enum { PMIC_SENSOR_BYTE_ORDER_LITTLE, PMIC_SENSOR_BYTE_ORDER_BIG, }; |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 25 | |
Simon Glass | 05400a6 | 2014-05-20 06:01:35 -0600 | [diff] [blame] | 26 | enum { |
| 27 | PMIC_CHARGER_DISABLE, |
| 28 | PMIC_CHARGER_ENABLE, |
| 29 | }; |
| 30 | |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 31 | struct p_i2c { |
| 32 | unsigned char addr; |
| 33 | unsigned char *buf; |
| 34 | unsigned char tx_num; |
| 35 | }; |
| 36 | |
| 37 | struct p_spi { |
| 38 | unsigned int cs; |
| 39 | unsigned int mode; |
| 40 | unsigned int bitlen; |
| 41 | unsigned int clk; |
| 42 | unsigned int flags; |
| 43 | u32 (*prepare_tx)(u32 reg, u32 *val, u32 write); |
| 44 | }; |
| 45 | |
Łukasz Majewski | 62ecae9 | 2012-11-13 03:22:00 +0000 | [diff] [blame] | 46 | struct pmic; |
| 47 | struct power_fg { |
| 48 | int (*fg_battery_check) (struct pmic *p, struct pmic *bat); |
| 49 | int (*fg_battery_update) (struct pmic *p, struct pmic *bat); |
| 50 | }; |
| 51 | |
| 52 | struct power_chrg { |
| 53 | int (*chrg_type) (struct pmic *p); |
| 54 | int (*chrg_bat_present) (struct pmic *p); |
| 55 | int (*chrg_state) (struct pmic *p, int state, int current); |
| 56 | }; |
| 57 | |
| 58 | struct power_battery { |
| 59 | struct battery *bat; |
| 60 | int (*battery_init) (struct pmic *bat, struct pmic *p1, |
| 61 | struct pmic *p2, struct pmic *p3); |
| 62 | int (*battery_charge) (struct pmic *bat); |
| 63 | /* Keep info about power devices involved with battery operation */ |
| 64 | struct pmic *chrg, *fg, *muic; |
| 65 | }; |
| 66 | |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 67 | struct pmic { |
| 68 | const char *name; |
| 69 | unsigned char bus; |
| 70 | unsigned char interface; |
Łukasz Majewski | 40f5ca0 | 2012-11-13 03:21:53 +0000 | [diff] [blame] | 71 | unsigned char sensor_byte_order; |
Łukasz Majewski | 1c6dba1 | 2012-11-13 03:21:55 +0000 | [diff] [blame] | 72 | unsigned int number_of_regs; |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 73 | union hw { |
| 74 | struct p_i2c i2c; |
| 75 | struct p_spi spi; |
| 76 | } hw; |
Łukasz Majewski | 1c6dba1 | 2012-11-13 03:21:55 +0000 | [diff] [blame] | 77 | |
Łukasz Majewski | 62ecae9 | 2012-11-13 03:22:00 +0000 | [diff] [blame] | 78 | void (*low_power_mode) (void); |
| 79 | struct power_battery *pbat; |
| 80 | struct power_chrg *chrg; |
| 81 | struct power_fg *fg; |
| 82 | |
| 83 | struct pmic *parent; |
Łukasz Majewski | 1c6dba1 | 2012-11-13 03:21:55 +0000 | [diff] [blame] | 84 | struct list_head list; |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 85 | }; |
Simon Glass | 3133941 | 2021-08-08 12:20:27 -0600 | [diff] [blame] | 86 | #endif /* CONFIG_IS_ENABLED(POWER_LEGACY) */ |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 87 | |
Simon Glass | 44da595 | 2021-08-08 12:20:26 -0600 | [diff] [blame] | 88 | /* TODO: Change to CONFIG_IS_ENABLED(DM_PMIC) when SPL_DM_PMIC exists */ |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 89 | #ifdef CONFIG_DM_PMIC |
| 90 | /** |
| 91 | * U-Boot PMIC Framework |
| 92 | * ===================== |
| 93 | * |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 94 | * UCLASS_PMIC - This is designed to provide an I/O interface for PMIC devices. |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 95 | * |
| 96 | * For the multi-function PMIC devices, this can be used as parent I/O device |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 97 | * for each IC's interface. Then, each child uses its parent for read/write. |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 98 | * |
| 99 | * The driver model tree could look like this: |
| 100 | * |
| 101 | *_ root device |
| 102 | * |_ BUS 0 device (e.g. I2C0) - UCLASS_I2C/SPI/... |
| 103 | * | |_ PMIC device (READ/WRITE ops) - UCLASS_PMIC |
| 104 | * | |_ REGULATOR device (ldo/buck/... ops) - UCLASS_REGULATOR |
| 105 | * | |_ CHARGER device (charger ops) - UCLASS_CHARGER (in the future) |
| 106 | * | |_ MUIC device (microUSB connector ops) - UCLASS_MUIC (in the future) |
| 107 | * | |_ ... |
| 108 | * | |
| 109 | * |_ BUS 1 device (e.g. I2C1) - UCLASS_I2C/SPI/... |
| 110 | * |_ PMIC device (READ/WRITE ops) - UCLASS_PMIC |
| 111 | * |_ RTC device (rtc ops) - UCLASS_RTC (in the future) |
| 112 | * |
| 113 | * We can find two PMIC cases in boards design: |
| 114 | * - single I/O interface |
| 115 | * - multiple I/O interfaces |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 116 | * We bind a single PMIC device for each interface, to provide an I/O for |
| 117 | * its child devices. And each child usually implements a different function, |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 118 | * controlled by the same interface. |
| 119 | * |
| 120 | * The binding should be done automatically. If device tree nodes/subnodes are |
| 121 | * proper defined, then: |
| 122 | * |
| 123 | * |_ the ROOT driver will bind the device for I2C/SPI node: |
| 124 | * |_ the I2C/SPI driver should bind a device for pmic node: |
| 125 | * |_ the PMIC driver should bind devices for its childs: |
| 126 | * |_ regulator (child) |
| 127 | * |_ charger (child) |
| 128 | * |_ other (child) |
| 129 | * |
| 130 | * The same for other device nodes, for multi-interface PMIC. |
| 131 | * |
| 132 | * Note: |
| 133 | * Each PMIC interface driver should use a different compatible string. |
| 134 | * |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 135 | * If a PMIC child device driver needs access the PMIC-specific registers, |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 136 | * it need know only the register address and the access can be done through |
| 137 | * the parent pmic driver. Like in the example: |
| 138 | * |
| 139 | *_ root driver |
| 140 | * |_ dev: bus I2C0 - UCLASS_I2C |
| 141 | * | |_ dev: my_pmic (read/write) (is parent) - UCLASS_PMIC |
| 142 | * | |_ dev: my_regulator (set value/etc..) (is child) - UCLASS_REGULATOR |
| 143 | * |
| 144 | * To ensure such device relationship, the pmic device driver should also bind |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 145 | * all its child devices, like in the example below. It can be done by calling |
| 146 | * the 'pmic_bind_children()' - please refer to the function description, which |
| 147 | * can be found in this header file. This function, should be called inside the |
| 148 | * driver's bind() method. |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 149 | * |
| 150 | * For the example driver, please refer the MAX77686 driver: |
| 151 | * - 'drivers/power/pmic/max77686.c' |
| 152 | */ |
| 153 | |
| 154 | /** |
| 155 | * struct dm_pmic_ops - PMIC device I/O interface |
| 156 | * |
| 157 | * Should be implemented by UCLASS_PMIC device drivers. The standard |
| 158 | * device operations provides the I/O interface for it's childs. |
| 159 | * |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 160 | * @reg_count: device's register count |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 161 | * @read: read 'len' bytes at "reg" and store it into the 'buffer' |
| 162 | * @write: write 'len' bytes from the 'buffer' to the register at 'reg' address |
| 163 | */ |
| 164 | struct dm_pmic_ops { |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 165 | int (*reg_count)(struct udevice *dev); |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 166 | int (*read)(struct udevice *dev, uint reg, uint8_t *buffer, int len); |
| 167 | int (*write)(struct udevice *dev, uint reg, const uint8_t *buffer, |
| 168 | int len); |
| 169 | }; |
| 170 | |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 171 | /** |
| 172 | * enum pmic_op_type - used for various pmic devices operation calls, |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 173 | * for reduce a number of lines with the same code for read/write or get/set. |
| 174 | * |
| 175 | * @PMIC_OP_GET - get operation |
| 176 | * @PMIC_OP_SET - set operation |
| 177 | */ |
| 178 | enum pmic_op_type { |
| 179 | PMIC_OP_GET, |
| 180 | PMIC_OP_SET, |
| 181 | }; |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 182 | |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 183 | /** |
| 184 | * struct pmic_child_info - basic device's child info for bind child nodes with |
| 185 | * the driver by the node name prefix and driver name. This is a helper struct |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 186 | * for function: pmic_bind_children(). |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 187 | * |
| 188 | * @prefix - child node name prefix (or its name if is unique or single) |
| 189 | * @driver - driver name for the sub-node with prefix |
| 190 | */ |
| 191 | struct pmic_child_info { |
| 192 | const char *prefix; |
| 193 | const char *driver; |
| 194 | }; |
| 195 | |
| 196 | /* drivers/power/pmic-uclass.c */ |
| 197 | |
| 198 | /** |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 199 | * pmic_bind_children() - bind drivers for given parent pmic, using child info |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 200 | * found in 'child_info' array. |
| 201 | * |
| 202 | * @pmic - pmic device - the parent of found child's |
| 203 | * @child_info - N-childs info array |
| 204 | * @return a positive number of childs, or 0 if no child found (error) |
| 205 | * |
| 206 | * Note: For N-childs the child_info array should have N+1 entries and the last |
| 207 | * entry prefix should be NULL - the same as for drivers compatible. |
| 208 | * |
| 209 | * For example, a single prefix info (N=1): |
| 210 | * static const struct pmic_child_info bind_info[] = { |
| 211 | * { .prefix = "ldo", .driver = "ldo_driver" }, |
| 212 | * { }, |
| 213 | * }; |
| 214 | * |
| 215 | * This function is useful for regulator sub-nodes: |
| 216 | * my_regulator@0xa { |
| 217 | * reg = <0xa>; |
| 218 | * (pmic - bind automatically by compatible) |
| 219 | * compatible = "my_pmic"; |
| 220 | * ... |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 221 | * (pmic's childs - bind by pmic_bind_children()) |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 222 | * (nodes prefix: "ldo", driver: "my_regulator_ldo") |
| 223 | * ldo1 { ... }; |
| 224 | * ldo2 { ... }; |
| 225 | * |
| 226 | * (nodes prefix: "buck", driver: "my_regulator_buck") |
| 227 | * buck1 { ... }; |
| 228 | * buck2 { ... }; |
| 229 | * }; |
| 230 | */ |
Simon Glass | 2c2d2c2 | 2017-05-18 20:09:32 -0600 | [diff] [blame] | 231 | int pmic_bind_children(struct udevice *pmic, ofnode parent, |
Przemyslaw Marczak | 1031498 | 2015-05-13 13:38:26 +0200 | [diff] [blame] | 232 | const struct pmic_child_info *child_info); |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 233 | |
| 234 | /** |
| 235 | * pmic_get: get the pmic device using its name |
| 236 | * |
| 237 | * @name - device name |
| 238 | * @devp - returned pointer to the pmic device |
| 239 | * @return 0 on success or negative value of errno. |
| 240 | * |
| 241 | * The returned devp device can be used with pmic_read/write calls |
| 242 | */ |
| 243 | int pmic_get(const char *name, struct udevice **devp); |
| 244 | |
| 245 | /** |
| 246 | * pmic_reg_count: get the pmic register count |
| 247 | * |
| 248 | * The required pmic device can be obtained by 'pmic_get()' |
| 249 | * |
| 250 | * @dev - pointer to the UCLASS_PMIC device |
| 251 | * @return register count value on success or negative value of errno. |
| 252 | */ |
| 253 | int pmic_reg_count(struct udevice *dev); |
| 254 | |
| 255 | /** |
| 256 | * pmic_read/write: read/write to the UCLASS_PMIC device |
| 257 | * |
| 258 | * The required pmic device can be obtained by 'pmic_get()' |
| 259 | * |
| 260 | * @pmic - pointer to the UCLASS_PMIC device |
| 261 | * @reg - device register offset |
| 262 | * @buffer - pointer to read/write buffer |
| 263 | * @len - byte count for read/write |
| 264 | * @return 0 on success or negative value of errno. |
| 265 | */ |
| 266 | int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len); |
| 267 | int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len); |
Simon Glass | c3f21c3 | 2015-06-23 15:39:01 -0600 | [diff] [blame] | 268 | |
| 269 | /** |
| 270 | * pmic_reg_read() - read a PMIC register value |
| 271 | * |
| 272 | * @dev: PMIC device to read |
| 273 | * @reg: Register to read |
| 274 | * @return value read on success or negative value of errno. |
| 275 | */ |
| 276 | int pmic_reg_read(struct udevice *dev, uint reg); |
| 277 | |
| 278 | /** |
| 279 | * pmic_reg_write() - write a PMIC register value |
| 280 | * |
| 281 | * @dev: PMIC device to write |
| 282 | * @reg: Register to write |
| 283 | * @value: Value to write |
| 284 | * @return 0 on success or negative value of errno. |
| 285 | */ |
| 286 | int pmic_reg_write(struct udevice *dev, uint reg, uint value); |
| 287 | |
| 288 | /** |
| 289 | * pmic_clrsetbits() - clear and set bits in a PMIC register |
| 290 | * |
| 291 | * This reads a register, optionally clears some bits, optionally sets some |
| 292 | * bits, then writes the register. |
| 293 | * |
| 294 | * @dev: PMIC device to update |
| 295 | * @reg: Register to update |
| 296 | * @clr: Bit mask to clear (set those bits that you want cleared) |
| 297 | * @set: Bit mask to set (set those bits that you want set) |
| 298 | * @return 0 on success or negative value of errno. |
| 299 | */ |
| 300 | int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set); |
| 301 | |
Lukasz Majewski | 767a10a | 2018-05-15 16:26:35 +0200 | [diff] [blame] | 302 | /* |
| 303 | * This structure holds the private data for PMIC uclass |
| 304 | * For now we store information about the number of bytes |
| 305 | * being sent at once to the device. |
| 306 | */ |
| 307 | struct uc_pmic_priv { |
| 308 | uint trans_len; |
| 309 | }; |
| 310 | |
Simon Glass | 44da595 | 2021-08-08 12:20:26 -0600 | [diff] [blame] | 311 | #endif /* DM_PMIC */ |
Przemyslaw Marczak | 9a8bc95 | 2015-04-20 20:07:41 +0200 | [diff] [blame] | 312 | |
Simon Glass | 44da595 | 2021-08-08 12:20:26 -0600 | [diff] [blame] | 313 | /* TODO: Change to CONFIG_IS_ENABLED(DM_PMIC) when SPL_DM_PMIC exists */ |
Simon Glass | 3133941 | 2021-08-08 12:20:27 -0600 | [diff] [blame] | 314 | #if CONFIG_IS_ENABLED(POWER_LEGACY) |
Simon Glass | 44da595 | 2021-08-08 12:20:26 -0600 | [diff] [blame] | 315 | |
| 316 | /* Legacy API, do not use */ |
Łukasz Majewski | 1c6dba1 | 2012-11-13 03:21:55 +0000 | [diff] [blame] | 317 | int pmic_init(unsigned char bus); |
Tom Rini | 85ca252 | 2014-06-23 16:06:28 -0400 | [diff] [blame] | 318 | int power_init_board(void); |
Łukasz Majewski | 1c6dba1 | 2012-11-13 03:21:55 +0000 | [diff] [blame] | 319 | int pmic_dialog_init(unsigned char bus); |
| 320 | int check_reg(struct pmic *p, u32 reg); |
| 321 | struct pmic *pmic_alloc(void); |
| 322 | struct pmic *pmic_get(const char *s); |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 323 | int pmic_probe(struct pmic *p); |
| 324 | int pmic_reg_read(struct pmic *p, u32 reg, u32 *val); |
| 325 | int pmic_reg_write(struct pmic *p, u32 reg, u32 val); |
| 326 | int pmic_set_output(struct pmic *p, u32 reg, int ldo, int on); |
Simon Glass | 3133941 | 2021-08-08 12:20:27 -0600 | [diff] [blame] | 327 | #endif /* CONFIG_IS_ENABLED(POWER_LEGACY) */ |
Łukasz Majewski | 16db062 | 2011-10-06 02:37:34 +0000 | [diff] [blame] | 328 | |
| 329 | #define pmic_i2c_addr (p->hw.i2c.addr) |
| 330 | #define pmic_i2c_tx_num (p->hw.i2c.tx_num) |
| 331 | |
| 332 | #define pmic_spi_bitlen (p->hw.spi.bitlen) |
| 333 | #define pmic_spi_flags (p->hw.spi.flags) |
| 334 | |
| 335 | #endif /* __CORE_PMIC_H_ */ |