mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-18 18:59:44 +00:00
83d290c56f
When U-Boot started using SPDX tags we were among the early adopters and there weren't a lot of other examples to borrow from. So we picked the area of the file that usually had a full license text and replaced it with an appropriate SPDX-License-Identifier: entry. Since then, the Linux Kernel has adopted SPDX tags and they place it as the very first line in a file (except where shebangs are used, then it's second line) and with slightly different comment styles than us. In part due to community overlap, in part due to better tag visibility and in part for other minor reasons, switch over to that style. This commit changes all instances where we have a single declared license in the tag as both the before and after are identical in tag contents. There's also a few places where I found we did not have a tag and have introduced one. Signed-off-by: Tom Rini <trini@konsulko.com>
303 lines
5.5 KiB
C
303 lines
5.5 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2012 Samsung Electronics
|
|
* Rajeshwari Shinde <rajeshwari.s@samsung.com>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <fdtdec.h>
|
|
#include <i2c.h>
|
|
#include <power/pmic.h>
|
|
#include <power/max77686_pmic.h>
|
|
#include <errno.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
static const char max77686_buck_addr[] = {
|
|
0xff, 0x10, 0x12, 0x1c, 0x26, 0x30, 0x32, 0x34, 0x36, 0x38
|
|
};
|
|
|
|
static unsigned int max77686_ldo_volt2hex(int ldo, ulong uV)
|
|
{
|
|
unsigned int hex = 0;
|
|
|
|
switch (ldo) {
|
|
case 1:
|
|
case 2:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 15:
|
|
hex = (uV - 800000) / 25000;
|
|
break;
|
|
default:
|
|
hex = (uV - 800000) / 50000;
|
|
}
|
|
|
|
if (hex >= 0 && hex <= MAX77686_LDO_VOLT_MAX_HEX)
|
|
return hex;
|
|
|
|
debug("%s: %ld is wrong voltage value for LDO%d\n", __func__, uV, ldo);
|
|
return 0;
|
|
}
|
|
|
|
static int max77686_buck_volt2hex(int buck, ulong uV)
|
|
{
|
|
int hex = 0;
|
|
|
|
if (buck < 5 || buck > 9) {
|
|
debug("%s: buck %d is not supported\n", __func__, buck);
|
|
return -EINVAL;
|
|
}
|
|
|
|
hex = (uV - 750000) / 50000;
|
|
|
|
if (hex >= 0 && hex <= MAX77686_BUCK_VOLT_MAX_HEX)
|
|
return hex;
|
|
|
|
debug("%s: %ld is wrong voltage value for BUCK%d\n",
|
|
__func__, uV, buck);
|
|
return -EINVAL;
|
|
}
|
|
|
|
int max77686_set_ldo_voltage(struct pmic *p, int ldo, ulong uV)
|
|
{
|
|
unsigned int val, ret, hex, adr;
|
|
|
|
if (ldo < 1 || ldo > 26) {
|
|
printf("%s: %d is wrong ldo number\n", __func__, ldo);
|
|
return -EINVAL;
|
|
}
|
|
|
|
adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1;
|
|
hex = max77686_ldo_volt2hex(ldo, uV);
|
|
|
|
if (!hex)
|
|
return -EINVAL;
|
|
|
|
ret = pmic_reg_read(p, adr, &val);
|
|
if (ret)
|
|
return ret;
|
|
|
|
val &= ~MAX77686_LDO_VOLT_MASK;
|
|
val |= hex;
|
|
ret |= pmic_reg_write(p, adr, val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int max77686_set_buck_voltage(struct pmic *p, int buck, ulong uV)
|
|
{
|
|
unsigned int val, adr;
|
|
int hex, ret;
|
|
|
|
if (buck < 5 || buck > 9) {
|
|
printf("%s: %d is an unsupported bucket number\n",
|
|
__func__, buck);
|
|
return -EINVAL;
|
|
}
|
|
|
|
adr = max77686_buck_addr[buck] + 1;
|
|
hex = max77686_buck_volt2hex(buck, uV);
|
|
|
|
if (hex < 0)
|
|
return hex;
|
|
|
|
ret = pmic_reg_read(p, adr, &val);
|
|
if (ret)
|
|
return ret;
|
|
|
|
val &= ~MAX77686_BUCK_VOLT_MASK;
|
|
ret |= pmic_reg_write(p, adr, val | hex);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int max77686_set_ldo_mode(struct pmic *p, int ldo, char opmode)
|
|
{
|
|
unsigned int val, ret, adr, mode;
|
|
|
|
if (ldo < 1 || 26 < ldo) {
|
|
printf("%s: %d is wrong ldo number\n", __func__, ldo);
|
|
return -EINVAL;
|
|
}
|
|
|
|
adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1;
|
|
|
|
/* mode */
|
|
switch (opmode) {
|
|
case OPMODE_OFF:
|
|
mode = MAX77686_LDO_MODE_OFF;
|
|
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:
|
|
mode = 0xff;
|
|
}
|
|
break;
|
|
case OPMODE_LPM:
|
|
mode = MAX77686_LDO_MODE_LPM;
|
|
break;
|
|
case OPMODE_ON:
|
|
mode = MAX77686_LDO_MODE_ON;
|
|
break;
|
|
default:
|
|
mode = 0xff;
|
|
}
|
|
|
|
if (mode == 0xff) {
|
|
printf("%s: %d is not supported on LDO%d\n",
|
|
__func__, opmode, ldo);
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
ret = pmic_reg_read(p, adr, &val);
|
|
if (ret)
|
|
return ret;
|
|
|
|
val &= ~MAX77686_LDO_MODE_MASK;
|
|
val |= mode;
|
|
ret |= pmic_reg_write(p, adr, val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int max77686_set_buck_mode(struct pmic *p, int buck, char opmode)
|
|
{
|
|
unsigned int val, ret, mask, adr, size, mode, mode_shift;
|
|
|
|
size = ARRAY_SIZE(max77686_buck_addr);
|
|
if (buck >= size) {
|
|
printf("%s: %d is wrong buck number\n", __func__, 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;
|
|
|
|
/* mode */
|
|
switch (opmode) {
|
|
case OPMODE_OFF:
|
|
mode = MAX77686_BUCK_MODE_OFF << mode_shift;
|
|
break;
|
|
case OPMODE_STANDBY:
|
|
switch (buck) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
mode = MAX77686_BUCK_MODE_STANDBY << mode_shift;
|
|
break;
|
|
default:
|
|
mode = 0xff;
|
|
}
|
|
break;
|
|
case OPMODE_LPM:
|
|
switch (buck) {
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
mode = MAX77686_BUCK_MODE_LPM << mode_shift;
|
|
break;
|
|
default:
|
|
mode = 0xff;
|
|
}
|
|
break;
|
|
case OPMODE_ON:
|
|
mode = MAX77686_BUCK_MODE_ON << mode_shift;
|
|
break;
|
|
default:
|
|
mode = 0xff;
|
|
}
|
|
|
|
if (mode == 0xff) {
|
|
printf("%s: %d is not supported on BUCK%d\n",
|
|
__func__, opmode, buck);
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
ret = pmic_reg_read(p, adr, &val);
|
|
if (ret)
|
|
return ret;
|
|
|
|
val &= ~mask;
|
|
val |= mode;
|
|
ret |= pmic_reg_write(p, adr, val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int pmic_init(unsigned char bus)
|
|
{
|
|
static const char name[] = "MAX77686_PMIC";
|
|
struct pmic *p = pmic_alloc();
|
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
|
const void *blob = gd->fdt_blob;
|
|
int node, parent, tmp;
|
|
#endif
|
|
|
|
if (!p) {
|
|
printf("%s: POWER allocation error!\n", __func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
|
node = fdtdec_next_compatible(blob, 0, COMPAT_MAXIM_MAX77686_PMIC);
|
|
if (node < 0) {
|
|
debug("PMIC: No node for PMIC Chip in device tree\n");
|
|
debug("node = %d\n", node);
|
|
return -ENODEV;
|
|
}
|
|
|
|
parent = fdt_parent_offset(blob, node);
|
|
if (parent < 0) {
|
|
debug("%s: Cannot find node parent\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
/* tmp since p->bus is unsigned */
|
|
tmp = i2c_get_bus_num_fdt(parent);
|
|
if (tmp < 0) {
|
|
debug("%s: Cannot find I2C bus\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
p->bus = tmp;
|
|
p->hw.i2c.addr = fdtdec_get_int(blob, node, "reg", 9);
|
|
#else
|
|
p->bus = bus;
|
|
p->hw.i2c.addr = MAX77686_I2C_ADDR;
|
|
#endif
|
|
|
|
p->name = name;
|
|
p->interface = PMIC_I2C;
|
|
p->number_of_regs = MAX77686_NUM_OF_REGS;
|
|
p->hw.i2c.tx_num = 1;
|
|
|
|
puts("Board PMIC init\n");
|
|
|
|
return 0;
|
|
}
|