blob: 368d9163b8f275eed18ff249e3831f4b5e567cd1 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/io.h>
#include <linux/of_device.h>
#include <linux/pm_domain.h>
#include <linux/platform_device.h>
#include <linux/amlogic/pwr_ctrl.h>
static unsigned int power_domain;
struct generic_pm_domain **power_domains;
static unsigned int pdid_start, pdid_max;
static void pd_snprintf(char *buf, unsigned int cnt, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(buf, cnt, fmt, args);
va_end(args);
}
static ssize_t power_on_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
ret = kstrtouint(buf, 0, &power_domain);
if (ret)
return -EINVAL;
pwr_ctrl_psci_smc(power_domain, PWR_ON);
return count;
}
static DEVICE_ATTR_WO(power_on);
static ssize_t power_off_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
ret = kstrtouint(buf, 0, &power_domain);
if (ret)
return -EINVAL;
pwr_ctrl_psci_smc(power_domain, PWR_OFF);
return count;
}
static DEVICE_ATTR_WO(power_off);
static ssize_t power_status_show(struct device *_dev,
struct device_attribute *attr, char *buf)
{
int power_status, i;
unsigned int len = 0, cnt = 20;
for (i = pdid_start; i < pdid_max; i++) {
power_status = pwr_ctrl_status_psci_smc(i);
pd_snprintf(buf, cnt, "%s[%d] :%d\n",
(*(power_domains + i))->name, i, power_status);
buf = buf + cnt;
len = len + cnt;
}
return len;
}
static ssize_t power_status_store(struct device *_dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
ret = kstrtouint(buf, 0, &power_domain);
if (ret)
return -EINVAL;
return count;
}
static DEVICE_ATTR_RW(power_status);
void pd_dev_create_file(struct device *dev, int cnt_start, int cnt_end,
struct generic_pm_domain **domains)
{
power_domains = domains;
pdid_start = cnt_start;
pdid_max = cnt_end;
device_create_file(dev, &dev_attr_power_status);
device_create_file(dev, &dev_attr_power_on);
device_create_file(dev, &dev_attr_power_off);
}
void pd_dev_remove_file(struct device *dev)
{
device_remove_file(dev, &dev_attr_power_status);
device_remove_file(dev, &dev_attr_power_on);
device_remove_file(dev, &dev_attr_power_off);
}