/* * Copyright (C) 2014 NVIDIA Corporation * * SPDX-License-Identifier: GPL-2.0+ */ #define pr_fmt(fmt) "as3722: " fmt #include #include #include #include #include #include #define AS3722_SD_VOLTAGE(n) (0x00 + (n)) #define AS3722_GPIO_CONTROL(n) (0x08 + (n)) #define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0) #define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0) #define AS3722_GPIO_CONTROL_INVERT (1 << 7) #define AS3722_LDO_VOLTAGE(n) (0x10 + (n)) #define AS3722_GPIO_SIGNAL_OUT 0x20 #define AS3722_SD_CONTROL 0x4d #define AS3722_LDO_CONTROL 0x4e #define AS3722_ASIC_ID1 0x90 #define AS3722_DEVICE_ID 0x0c #define AS3722_ASIC_ID2 0x91 int as3722_read(struct udevice *pmic, u8 reg, u8 *value) { int err; err = dm_i2c_read(pmic, reg, value, 1); if (err < 0) return err; return 0; } int as3722_write(struct udevice *pmic, u8 reg, u8 value) { int err; err = dm_i2c_write(pmic, reg, &value, 1); if (err < 0) return err; return 0; } static int as3722_read_id(struct udevice *pmic, u8 *id, u8 *revision) { int err; err = as3722_read(pmic, AS3722_ASIC_ID1, id); if (err) { error("failed to read ID1 register: %d", err); return err; } err = as3722_read(pmic, AS3722_ASIC_ID2, revision); if (err) { error("failed to read ID2 register: %d", err); return err; } return 0; } int as3722_sd_enable(struct udevice *pmic, unsigned int sd) { u8 value; int err; if (sd > 6) return -EINVAL; err = as3722_read(pmic, AS3722_SD_CONTROL, &value); if (err) { error("failed to read SD control register: %d", err); return err; } value |= 1 << sd; err = as3722_write(pmic, AS3722_SD_CONTROL, value); if (err < 0) { error("failed to write SD control register: %d", err); return err; } return 0; } int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value) { int err; if (sd > 6) return -EINVAL; err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value); if (err < 0) { error("failed to write SD%u voltage register: %d", sd, err); return err; } return 0; } int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo) { u8 value; int err; if (ldo > 11) return -EINVAL; err = as3722_read(pmic, AS3722_LDO_CONTROL, &value); if (err) { error("failed to read LDO control register: %d", err); return err; } value |= 1 << ldo; err = as3722_write(pmic, AS3722_LDO_CONTROL, value); if (err < 0) { error("failed to write LDO control register: %d", err); return err; } return 0; } int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value) { int err; if (ldo > 11) return -EINVAL; err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value); if (err < 0) { error("failed to write LDO%u voltage register: %d", ldo, err); return err; } return 0; } int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio, unsigned long flags) { u8 value = 0; int err; if (flags & AS3722_GPIO_OUTPUT_VDDH) value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; if (flags & AS3722_GPIO_INVERT) value |= AS3722_GPIO_CONTROL_INVERT; err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value); if (err) { error("failed to configure GPIO#%u: %d", gpio, err); return err; } return 0; } static int as3722_gpio_set(struct udevice *pmic, unsigned int gpio, unsigned int level) { const char *l; u8 value; int err; if (gpio > 7) return -EINVAL; err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value); if (err < 0) { error("failed to read GPIO signal out register: %d", err); return err; } if (level == 0) { value &= ~(1 << gpio); l = "low"; } else { value |= 1 << gpio; l = "high"; } err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value); if (err) { error("failed to set GPIO#%u %s: %d", gpio, l, err); return err; } return 0; } int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio, unsigned int level) { u8 value; int err; if (gpio > 7) return -EINVAL; if (level == 0) value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL; else value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value); if (err) { error("failed to configure GPIO#%u as output: %d", gpio, err); return err; } err = as3722_gpio_set(pmic, gpio, level); if (err < 0) { error("failed to set GPIO#%u high: %d", gpio, err); return err; } return 0; } /* Temporary function until we get the pmic framework */ int as3722_get(struct udevice **devp) { int bus = 0; int address = 0x40; return i2c_get_chip_for_busnum(bus, address, 1, devp); } int as3722_init(struct udevice **devp) { struct udevice *pmic; u8 id, revision; const unsigned int bus = 0; const unsigned int address = 0x40; int err; err = i2c_get_chip_for_busnum(bus, address, 1, &pmic); if (err) return err; err = as3722_read_id(pmic, &id, &revision); if (err < 0) { error("failed to read ID: %d", err); return err; } if (id != AS3722_DEVICE_ID) { error("unknown device"); return -ENOENT; } debug("AS3722 revision %#x found on I2C bus %u, address %#x\n", revision, bus, address); if (devp) *devp = pmic; return 0; }