1 /* 2 * Copyright (c) 2015 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <cros_ec.h> 11 #include <errno.h> 12 #include <i2c.h> 13 #include <power/tps65090.h> 14 15 static int cros_ec_ldo_set_bus_speed(struct udevice *dev, unsigned int speed) 16 { 17 return 0; 18 } 19 20 static int cros_ec_ldo_xfer(struct udevice *dev, struct i2c_msg *msg, 21 int nmsgs) 22 { 23 bool is_read = nmsgs > 1; 24 int fet_id, ret; 25 26 /* 27 * Look for reads and writes of the LDO registers. In either case the 28 * first message is a write with the register number as the first byte. 29 */ 30 if (!nmsgs || !msg->len || (msg->flags & I2C_M_RD)) { 31 debug("%s: Invalid message\n", __func__); 32 goto err; 33 } 34 35 fet_id = msg->buf[0] - REG_FET_BASE; 36 if (fet_id < 1 || fet_id > MAX_FET_NUM) { 37 debug("%s: Invalid FET %d\n", __func__, fet_id); 38 goto err; 39 } 40 41 if (is_read) { 42 uint8_t state; 43 44 ret = cros_ec_get_ldo(dev->parent, fet_id, &state); 45 if (!ret) 46 msg[1].buf[0] = state ? 47 FET_CTRL_ENFET | FET_CTRL_PGFET : 0; 48 } else { 49 bool on = msg->buf[1] & FET_CTRL_ENFET; 50 51 ret = cros_ec_set_ldo(dev->parent, fet_id, on); 52 } 53 54 return ret; 55 56 err: 57 /* Indicate that the message is unimplemented */ 58 return -ENOSYS; 59 } 60 61 static const struct dm_i2c_ops cros_ec_i2c_ops = { 62 .xfer = cros_ec_ldo_xfer, 63 .set_bus_speed = cros_ec_ldo_set_bus_speed, 64 }; 65 66 static const struct udevice_id cros_ec_i2c_ids[] = { 67 { .compatible = "google,cros-ec-ldo-tunnel" }, 68 { } 69 }; 70 71 U_BOOT_DRIVER(cros_ec_ldo) = { 72 .name = "cros_ec_ldo_tunnel", 73 .id = UCLASS_I2C, 74 .of_match = cros_ec_i2c_ids, 75 .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip), 76 .ops = &cros_ec_i2c_ops, 77 }; 78