/*! * This function returns the PMIC version in system. * * @param ver pointer to the pmic_version_t structure * * @return This function returns PMIC version. */ void pmic_get_revision(pmic_version_t * ver) { int rev_id = 0; int rev1 = 0; int rev2 = 0; int finid = 0; int icid = 0; ver->id = PMIC_MC13783; pmic_read(REG_REVISION, &rev_id); rev1 = (rev_id & 0x018) >> 3; rev2 = (rev_id & 0x007); icid = (rev_id & 0x01C0) >> 6; finid = (rev_id & 0x01E00) >> 9; /* Ver 0.2 is actually 3.2a. Report as 3.2 */ if ((rev1 == 0) && (rev2 == 2)) { rev1 = 3; } if (rev1 == 0 || icid != 2) { ver->revision = -1; printk(KERN_NOTICE "mc13783: Not detected.\tAccess failed\t!!!\n"); } else { ver->revision = ((rev1 * 10) + rev2); printk(KERN_INFO "mc13783 Rev %d.%d FinVer %x detected\n", rev1, rev2, finid); } return; }
/* Test PMIC I/O */ static int dm_test_power_pmic_io(struct unit_test_state *uts) { const char *name = "sandbox_pmic"; uint8_t out_buffer, in_buffer; struct udevice *dev; int reg_count, i; ut_assertok(pmic_get(name, &dev)); reg_count = pmic_reg_count(dev); ut_asserteq(reg_count, SANDBOX_PMIC_REG_COUNT); /* * Test PMIC I/O - write and read a loop counter. * usually we can't write to all PMIC's registers in the real hardware, * but we can to the sandbox pmic. */ for (i = 0; i < reg_count; i++) { out_buffer = i; ut_assertok(pmic_write(dev, i, &out_buffer, 1)); ut_assertok(pmic_read(dev, i, &in_buffer, 1)); ut_asserteq(out_buffer, in_buffer); } return 0; }
static ssize_t mc13892_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int reg, value, ret; char *p; reg = simple_strtoul(buf, NULL, 10); p = NULL; p = memchr(buf, ' ', count); if (p == NULL) { pmic_read(reg, &value); pr_debug("reg%02d: %06x\n", reg, value); return count; } p += 1; value = simple_strtoul(p, NULL, 16); ret = pmic_write(reg, value); if (ret == 0) pr_debug("write reg%02d: %06x\n", reg, value); else pr_debug("register update failed\n"); return count; }
unsigned int pmic_get_active_events(unsigned int *active_events) { unsigned int count = 0; unsigned int faults; int bit_set; /* Check for any relevant PMIC faults */ pmic_read(REG_MC34704_FAULTS, &faults); faults &= events_enabled; /* * Mask all active events, because there is no way to acknowledge * or dismiss them in the PMIC -- they're sticky. */ events_enabled &= ~faults; /* Account for all unmasked faults */ while (faults) { bit_set = ffs(faults) - 1; *(active_events + count) = bit_set; count++; faults ^= (1 << bit_set); } return count; }
static int s2mps11_buck_mode(struct udevice *dev, int op, int *opmode) { unsigned int addr, mode; unsigned char val; int buck, ret; buck = dev->driver_data; if (buck < 1 || buck > S2MPS11_BUCK_NUM) { pr_err("Wrong buck number: %d\n", buck); return -EINVAL; } addr = s2mps11_buck_ctrl[buck]; ret = pmic_read(dev->parent, addr, &val, 1); if (ret) return ret; if (op == PMIC_OP_GET) { val &= (S2MPS11_BUCK_MODE_MASK << S2MPS11_BUCK_MODE_SHIFT); switch (val) { case S2MPS11_BUCK_MODE_OFF: *opmode = OP_OFF; break; case S2MPS11_BUCK_MODE_STANDBY: *opmode = OP_STANDBY; break; case S2MPS11_BUCK_MODE_ON: *opmode = OP_ON; break; default: return -EINVAL; } return 0; } switch (*opmode) { case OP_OFF: mode = S2MPS11_BUCK_MODE_OFF; break; case OP_STANDBY: mode = S2MPS11_BUCK_MODE_STANDBY; break; case OP_ON: mode = S2MPS11_BUCK_MODE_ON; break; default: pr_err("Wrong mode: %d for buck: %d\n", *opmode, buck); return -EINVAL; } val &= ~(S2MPS11_BUCK_MODE_MASK << S2MPS11_BUCK_MODE_SHIFT); val |= mode; ret = pmic_write(dev->parent, addr, &val, 1); return ret; }
static ssize_t pmic_show(struct device *dev, struct device_attribute *attr, char *buf) { int i, value; int offset = (REG_TEST4 + 1) / 4; for (i = 0; i < offset; i++) { pmic_read(i, &value); pr_info("reg%02d: %06x\t\t", i, value); pmic_read(i + offset, &value); pr_info("reg%02d: %06x\t\t", i + offset, value); pmic_read(i + offset * 2, &value); pr_info("reg%02d: %06x\t\t", i + offset * 2, value); pmic_read(i + offset * 3, &value); pr_info("reg%02d: %06x\n", i + offset * 3, value); } return 0; }
/*! * Get the current version of the Altas part */ int get_pmic_revision(void) { int rev_id = 0; int finid = 0; pmic_read(REG_IDENTIFICATION, &rev_id); finid = (rev_id & 0x01E00) >> 9; return finid; }
static int axp192_usb_online(void) { int ret; uint8_t val; struct pmic_charger *charger = &pmic_charger; ret = pmic_read(charger->master, AXP192_POWER_STATE, &val); if (ret < 0) return ret; return (val >> 5) & 0x01; }
static int max77686_buck_val(struct udevice *dev, int op, int *uV) { unsigned int hex, ret, mask, adr; unsigned char val; int buck; buck = dev->driver_data; if (buck < 1 || buck > MAX77686_BUCK_NUM) { error("Wrong buck number: %d", buck); return -EINVAL; } if (op == PMIC_OP_GET) *uV = 0; /* &buck_out = ctrl + 1 */ adr = max77686_buck_addr[buck] + 1; /* mask */ switch (buck) { case 2: case 3: case 4: /* Those use voltage scallers - will support in the future */ mask = MAX77686_BUCK234_VOLT_MASK; return -ENOSYS; default: mask = MAX77686_BUCK_VOLT_MASK; } ret = pmic_read(dev->parent, adr, &val, 1); if (ret) return ret; if (op == PMIC_OP_GET) { val &= mask; ret = max77686_buck_hex2volt(buck, val); if (ret < 0) return ret; *uV = ret; return 0; } hex = max77686_buck_volt2hex(buck, *uV); if (hex < 0) return hex; val &= ~mask; val |= hex; ret = pmic_write(dev->parent, adr, &val, 1); return ret; }
static int s2mps11_buck_val(struct udevice *dev, int op, int *uV) { int hex, buck, ret; u32 mask, addr; u8 val; buck = dev->driver_data; if (buck < 1 || buck > S2MPS11_BUCK_NUM) { pr_err("Wrong buck number: %d\n", buck); return -EINVAL; } if (op == PMIC_OP_GET) *uV = 0; addr = s2mps11_buck_out[buck]; switch (buck) { case 9: mask = S2MPS11_BUCK9_VOLT_MASK; break; default: mask = S2MPS11_BUCK_VOLT_MASK; break; } ret = pmic_read(dev->parent, addr, &val, 1); if (ret) return ret; if (op == PMIC_OP_GET) { val &= mask; ret = s2mps11_buck_hex2volt(buck, val); if (ret < 0) return ret; *uV = ret; return 0; } hex = s2mps11_buck_volt2hex(buck, *uV); if (hex < 0) return hex; val &= ~mask; val |= hex; ret = pmic_write(dev->parent, addr, &val, 1); return ret; }
/*! * This function is called by PMIC clients to read a register on PMIC. * * @param reg number of register * @param reg_value return value of register * @param reg_mask Bitmap mask indicating which bits to modify * * @return This function returns PMIC_SUCCESS if successful. */ PMIC_STATUS pmic_read_reg(int reg, unsigned int *reg_value, unsigned int reg_mask) { int ret = 0; unsigned int temp = 0; ret = pmic_read(reg, &temp); if (ret != PMIC_SUCCESS) { return PMIC_ERROR; } *reg_value = (temp & reg_mask); pr_debug("Read REG[ %d ] = 0x%x\n", reg, *reg_value); return ret; }
/*! * This function returns the PMIC version in system. * * @param ver pointer to the pmic_version_t structure * * @return This function returns PMIC version. */ void mc13892_get_revision(pmic_version_t *ver) { int rev_id = 0; int rev1 = 0; int rev2 = 0; int finid = 0; int icid = 0; ver->id = PMIC_MC13892; pmic_read(REG_IDENTIFICATION, &rev_id); rev1 = (rev_id & 0x018) >> 3; rev2 = (rev_id & 0x007); icid = (rev_id & 0x01C0) >> 6; finid = (rev_id & 0x01E00) >> 9; ver->revision = ((rev1 * 10) + rev2); printk(KERN_INFO "mc13892 Rev %d.%d FinVer %x detected\n", rev1, rev2, finid); }
static int max77686_ldo_val(struct udevice *dev, int op, int *uV) { unsigned int ret, hex, adr; unsigned char val; int ldo; if (op == PMIC_OP_GET) *uV = 0; ldo = dev->driver_data; if (ldo < 1 || ldo > MAX77686_LDO_NUM) { error("Wrong ldo number: %d", ldo); return -EINVAL; } adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1; ret = pmic_read(dev->parent, adr, &val, 1); if (ret) return ret; if (op == PMIC_OP_GET) { val &= MAX77686_LDO_VOLT_MASK; ret = max77686_ldo_hex2volt(ldo, val); if (ret < 0) return ret; *uV = ret; return 0; } hex = max77686_ldo_volt2hex(ldo, *uV); if (hex < 0) return hex; val &= ~MAX77686_LDO_VOLT_MASK; val |= hex; ret = pmic_write(dev->parent, adr, &val, 1); return ret; }
static int max77686_buck_mode(struct udevice *dev, int op, int *opmode) { unsigned int ret, mask, adr, mode, mode_shift; unsigned char val; int buck; buck = dev->driver_data; if (buck < 1 || buck > MAX77686_BUCK_NUM) { error("Wrong buck number: %d", buck); return -EINVAL; } adr = max77686_buck_addr[buck]; /* mask */ switch (buck) { case 2: case 3: case 4: mode_shift = MAX77686_BUCK_MODE_SHIFT_2; break; default: mode_shift = MAX77686_BUCK_MODE_SHIFT_1; } mask = MAX77686_BUCK_MODE_MASK << mode_shift; ret = pmic_read(dev->parent, adr, &val, 1); if (ret) return ret; if (op == PMIC_OP_GET) { val &= mask; val >>= mode_shift; ret = max77686_buck_hex2mode(buck, val); if (ret < 0) return ret; *opmode = ret; return 0; }
static int s2mps11_ldo_val(struct udevice *dev, int op, int *uV) { unsigned int addr; unsigned char val; int hex, ldo, ret; ldo = dev->driver_data; if (ldo < 1 || ldo > S2MPS11_LDO_NUM) { pr_err("Wrong ldo number: %d\n", ldo); return -EINVAL; } addr = S2MPS11_REG_L1CTRL + ldo - 1; ret = pmic_read(dev->parent, addr, &val, 1); if (ret) return ret; if (op == PMIC_OP_GET) { *uV = 0; val &= S2MPS11_LDO_VOLT_MASK; ret = s2mps11_ldo_hex2volt(ldo, val); if (ret < 0) return ret; *uV = ret; return 0; } hex = s2mps11_ldo_volt2hex(ldo, *uV); if (hex < 0) return hex; val &= ~S2MPS11_LDO_VOLT_MASK; val |= hex; ret = pmic_write(dev->parent, addr, &val, 1); return ret; }
/*! * This function is called by PMIC clients to write a register on PMIC. * * @param reg number of register * @param reg_value New value of register * @param reg_mask Bitmap mask indicating which bits to modify * * @return This function returns PMIC_SUCCESS if successful. */ PMIC_STATUS pmic_write_reg(int reg, unsigned int reg_value, unsigned int reg_mask) { int ret = 0; unsigned int temp = 0; ret = pmic_read(reg, &temp); if (ret != PMIC_SUCCESS) { return PMIC_ERROR; } temp = (temp & (~reg_mask)) | reg_value; #ifdef CONFIG_MXC_PMIC_MC13783 if (reg == REG_POWER_MISCELLANEOUS) temp &= 0xFFFE7FFF; #endif ret = pmic_write(reg, temp); if (ret != PMIC_SUCCESS) { return PMIC_ERROR; } pr_debug("Write REG[ %d ] = 0x%x\n", reg, reg_value); return ret; }
static int s2mps11_ldo_mode(struct udevice *dev, int op, int *opmode) { unsigned int addr, mode; unsigned char val; int ldo, ret; ldo = dev->driver_data; if (ldo < 1 || ldo > S2MPS11_LDO_NUM) { pr_err("Wrong ldo number: %d\n", ldo); return -EINVAL; } addr = S2MPS11_REG_L1CTRL + ldo - 1; ret = pmic_read(dev->parent, addr, &val, 1); if (ret) return ret; if (op == PMIC_OP_GET) { val &= (S2MPS11_LDO_MODE_MASK << S2MPS11_LDO_MODE_SHIFT); switch (val) { case S2MPS11_LDO_MODE_OFF: *opmode = OP_OFF; break; case S2MPS11_LDO_MODE_STANDBY: *opmode = OP_STANDBY; break; case S2MPS11_LDO_MODE_STANDBY_LPM: *opmode = OP_STANDBY_LPM; break; case S2MPS11_LDO_MODE_ON: *opmode = OP_ON; break; default: return -EINVAL; } return 0; } switch (*opmode) { case OP_OFF: mode = S2MPS11_LDO_MODE_OFF; break; case OP_STANDBY: mode = S2MPS11_LDO_MODE_STANDBY; break; case OP_STANDBY_LPM: mode = S2MPS11_LDO_MODE_STANDBY_LPM; break; case OP_ON: mode = S2MPS11_LDO_MODE_ON; break; default: pr_err("Wrong mode: %d for ldo: %d\n", *opmode, ldo); return -EINVAL; } val &= ~(S2MPS11_LDO_MODE_MASK << S2MPS11_LDO_MODE_SHIFT); val |= mode; ret = pmic_write(dev->parent, addr, &val, 1); return ret; }
static int max77686_ldo_mode(struct udevice *dev, int op, int *opmode) { unsigned int ret, adr, mode; unsigned char val; int ldo; if (op == PMIC_OP_GET) *opmode = -EINVAL; ldo = dev->driver_data; if (ldo < 1 || ldo > MAX77686_LDO_NUM) { error("Wrong ldo number: %d", ldo); return -EINVAL; } adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1; ret = pmic_read(dev->parent, adr, &val, 1); if (ret) return ret; if (op == PMIC_OP_GET) { val &= MAX77686_LDO_MODE_MASK; ret = max77686_ldo_hex2mode(ldo, val); if (ret < 0) return ret; *opmode = ret; return 0; } /* mode */ switch (*opmode) { case OPMODE_OFF: mode = MAX77686_LDO_MODE_OFF; break; case OPMODE_LPM: switch (ldo) { case 2: case 6: case 7: case 8: case 10: case 11: case 12: case 14: case 15: case 16: return -EINVAL; default: mode = MAX77686_LDO_MODE_LPM; } break; case OPMODE_STANDBY: switch (ldo) { case 2: case 6: case 7: case 8: case 10: case 11: case 12: case 14: case 15: case 16: mode = MAX77686_LDO_MODE_STANDBY; break; default: return -EINVAL; } break; case OPMODE_STANDBY_LPM: mode = MAX77686_LDO_MODE_STANDBY_LPM; break; case OPMODE_ON: mode = MAX77686_LDO_MODE_ON; break; default: mode = 0xff; } if (mode == 0xff) { error("Wrong mode: %d for ldo%d", *opmode, ldo); return -EINVAL; } val &= ~MAX77686_LDO_MODE_MASK; val |= mode; ret = pmic_write(dev->parent, adr, &val, 1); return ret; }