OSHW-DEIMOS/SOFTWARE/A64-TERES/linux-a64/drivers/power/axp_power/axp-depend-set.c
Dimitar Gamishev f9b0e7a283 linux
2017-10-13 14:07:04 +03:00

329 lines
7.2 KiB
C
Executable File

/*
* Regulators dependence driver for allwinnertech AXP
*
* Copyright (C) 2014 allwinnertech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/async.h>
#include <linux/err.h>
#include <linux/ctype.h>
#include <linux/regulator/consumer.h>
#include <linux/power/axp_depend.h>
/*
* function: add the pwr_dm specified by input id to sys_pwr_dm;
*
* */
s32 add_sys_pwr_dm(const char *id)
{
s32 ret = 0, sys_id_conut = 0;
char ldo_name[20] = {0};
u32 sys_pwr_mask = 0;
sys_id_conut = axp_check_sys_id(id);
if (0 > sys_id_conut) {
printk(KERN_ERR "%s: %s not sys id.\n", __func__, id);
return -1;
} else {
sys_pwr_mask = get_sys_pwr_dm_mask();
if (sys_pwr_mask & (0x1 << sys_id_conut)) {
printk(KERN_INFO "%s: sys_pwr_mask = 0x%x, sys_mask already set.\n", __func__, sys_pwr_mask);
return 1;
}
}
ret = get_ldo_name(id, (char *)&ldo_name);
if (ret < 0) {
printk(KERN_ERR "%s: get ldo name for id: %s failed\n", __func__, id);
return -1;
}
ret = check_ldo_alwayson((const char *)&ldo_name);
if (ret == 0) {
if (set_ldo_alwayson((const char *)&ldo_name, 1)) {
printk(KERN_ERR "%s: %s set_ldo_alwayson failed.\n", __func__, ldo_name);
return -1;
}
} else if (ret == 1) {
printk(KERN_ERR "%s: %s ldo already alwayson.\n", __func__, ldo_name);
} else {
printk(KERN_ERR "%s: %s set err.\n", __func__, ldo_name);
return -1;
}
set_sys_pwr_dm_mask(sys_id_conut, 1);
return 0;
}
s32 del_sys_pwr_dm(const char *id)
{
s32 ret = 0, sys_id_conut = 0, i = 0;
char ldo_name[20] = {0};
char sys_ldo_name[20] = {0};
u32 sys_pwr_mask = 0;
char * sys_id;
sys_id_conut = axp_check_sys_id(id);
if (0 > sys_id_conut) {
printk(KERN_ERR "%s: %s not sys id.\n", __func__, id);
return -1;
} else {
sys_pwr_mask = get_sys_pwr_dm_mask();
if (!(sys_pwr_mask & (0x1 << sys_id_conut)))
return 1;
}
ret = get_ldo_name(id, (char *)&ldo_name);
if (ret < 0) {
printk(KERN_ERR "%s: get ldo name for id: %s failed\n", __func__, id);
return -1;
}
ret = check_ldo_alwayson((const char *)&ldo_name);
if (ret == 0) {
printk(KERN_ERR "%s: %s ldo is already not alwayson.\n", __func__, ldo_name);
} else if (ret == 1) {
for (i=0; i <VCC_MAX_INDEX; i++) {
if (sys_id_conut == i)
continue;
if(is_sys_pwr_dm_active(i)) {
sys_id = get_sys_pwr_dm_id(i);
ret = get_ldo_name(sys_id, (char *)&sys_ldo_name);
if (ret < 0) {
printk(KERN_ERR "%s: get sys_ldo_name failed\n", __func__);
return -1;
}
if (strcmp(sys_ldo_name, ldo_name) == 0) {
set_sys_pwr_dm_mask(sys_id_conut, 0);
return 0;
}
}
}
if (set_ldo_alwayson((const char *)&ldo_name, 0)) {
printk(KERN_ERR "%s: %s set_ldo_alwayson failed.\n", __func__, ldo_name);
return -1;
}
} else {
printk(KERN_ERR "%s: %s set err.\n", __func__, ldo_name);
return -1;
}
set_sys_pwr_dm_mask(sys_id_conut, 0);
return 0;
}
/*
* function: judge whether pwr_dm is part of sys_pwr_domain.
* input: pwr_dm name, such as: "vdd_sys".
* return:
* nonnegative number: the sys_pwr_domain bitmap.
* -1: the input pwr_dm is not belong to sys_pwr_domain.
*
* */
s32 is_sys_pwr_dm_id(const char *id)
{
s32 sys_id_conut = 0;
sys_id_conut = axp_check_sys_id(id);
if (0 <= sys_id_conut) {
return sys_id_conut;
} else {
return -1;
}
}
/*
* function: judge whether sys_pwr_domain is active.
* input: sys_pwr_domain bitmap.
* return:
* 1: the input sys_pwr_domain is active.
* 0: the input sys_pwr_domain is not active.
*
* */
s32 is_sys_pwr_dm_active(u32 bitmap)
{
u32 sys_pwr_mask = 0;
sys_pwr_mask = get_sys_pwr_dm_mask();
if (sys_pwr_mask & (0x1 << bitmap))
return 1;
else
return 0;
}
/*
* function: get sys_pwr_dm_id name.
* input: sys_pwr_domain bitmap.
* return:
* failed: NULL.
* success: sys_pwr_dm_id.
* */
char *get_sys_pwr_dm_id(u32 bitmap)
{
return axp_get_sys_id(bitmap);
}
static ssize_t add_sys_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
int name_len;
const char *arg;
char sys_name[20] = {0};
/* Find length of lock name */
arg = buf;
while (*arg && !isspace(*arg))
arg++;
name_len = arg - buf;
if ((!name_len)&&(name_len>20))
goto bad_arg;
strncpy(sys_name, buf, name_len);
add_sys_pwr_dm(sys_name);
return count;
bad_arg:
printk(KERN_ERR "%s para error.\n", __func__);
return count;
}
static ssize_t del_sys_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
int name_len;
const char *arg;
char sys_name[20] = {0};
/* Find length of lock name */
arg = buf;
while (*arg && !isspace(*arg))
arg++;
name_len = arg - buf;
if ((!name_len)&&(name_len>20))
goto bad_arg;
strncpy(sys_name, buf, name_len);
del_sys_pwr_dm(sys_name);
return count;
bad_arg:
printk(KERN_ERR "%s para error.\n", __func__);
return count;
}
static ssize_t get_sys_dump_show(struct class *class,
struct class_attribute *attr, char *buf)
{
ssize_t count = 0;
count += sprintf(buf+count, "0x%x", get_sys_pwr_dm_mask());
return count;
}
char check_sys_name[20] = {0};
static ssize_t check_sys_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
int name_len;
const char *arg;
/* Find length of lock name */
arg = buf;
while (*arg && !isspace(*arg))
arg++;
name_len = arg - buf;
if ((!name_len)&&(name_len>20))
goto bad_arg;
strncpy(check_sys_name, buf, name_len);
return count;
bad_arg:
printk(KERN_ERR "%s para error.\n", __func__);
return count;
}
static ssize_t check_sys_show(struct class *class,
struct class_attribute *attr, char *buf)
{
s32 sys_id_conut = 0,ret = 0;
ssize_t count = 0;
char ldo_name[20] = {0};
sys_id_conut = axp_check_sys_id(check_sys_name);
if (0 > sys_id_conut) {
printk(KERN_ERR "%s: %s not sys id.\n", __func__, check_sys_name);
return -1;
}
ret = get_ldo_name(check_sys_name, (char *)&ldo_name);
if (ret < 0) {
printk(KERN_ERR "%s: get ldo name for id: %s failed\n", __func__, check_sys_name);
return -1;
}
ret = is_sys_pwr_dm_active(sys_id_conut);
count += sprintf(buf+count, "%d", ret);
return count;
}
struct class_attribute axp_depend_class_attrs[] = {
__ATTR(add_sys,S_IRUGO|S_IWUSR,NULL,add_sys_store),
__ATTR(del_sys,S_IRUGO|S_IWUSR,NULL,del_sys_store),
__ATTR(get_sys,S_IRUGO|S_IWUSR,get_sys_dump_show,NULL),
__ATTR(check_sys,S_IRUGO|S_IWUSR,check_sys_show,check_sys_store),
__ATTR_NULL,
};
static struct class depend_class = {
.name = "axp_depend",
.owner = THIS_MODULE,
.class_attrs = axp_depend_class_attrs,
};
static int __init depend_module_init(void)
{
int status;
status = class_register(&depend_class);
if(status < 0)
pr_err("%s,%d err, status:%d\n", __func__, __LINE__, status);
return status;
}
static void __exit depend_module_exit(void)
{
class_unregister(&depend_class);
}
module_init(depend_module_init);
module_exit(depend_module_exit);
MODULE_AUTHOR("Ming Li");
MODULE_DESCRIPTION("axp depend driver");
MODULE_LICENSE("GPL");