265 lines
7.0 KiB
C
Executable File
265 lines
7.0 KiB
C
Executable File
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
/******************************************************************************
|
|
* pmic_wrapper.c - Linux pmic_wrapper Driver
|
|
*
|
|
*
|
|
* DESCRIPTION:
|
|
* This file provid the other drivers PMIC wrapper relative functions
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/types.h>
|
|
#include <linux/device.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/module.h>
|
|
/*#include <mach/mt_typedefs.h>*/
|
|
#include <linux/timer.h>
|
|
#include <mach/mtk_pmic_wrap.h>
|
|
#include <linux/syscore_ops.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/soc/mediatek/pmic_wrap.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_fdt.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/spinlock.h>
|
|
|
|
#define PMIC_WRAP_DEVICE "pmic_wrap"
|
|
#define VERSION "Revision"
|
|
|
|
|
|
|
|
|
|
#if !defined CONFIG_MTK_PMIC_WRAP || defined(CONFIG_MACH_MT6739)
|
|
static struct mt_pmic_wrap_driver mt_wrp = {
|
|
.driver = {
|
|
.name = "pmic_wrap",
|
|
.bus = &platform_bus_type,
|
|
.owner = THIS_MODULE,
|
|
},
|
|
};
|
|
|
|
struct mt_pmic_wrap_driver *get_mt_pmic_wrap_drv(void)
|
|
{
|
|
return &mt_wrp;
|
|
}
|
|
#endif
|
|
#if !defined CONFIG_MTK_PMIC_WRAP
|
|
/*this function only used for ROME plus*/
|
|
int check_pmic_wrap_init(void)
|
|
{
|
|
if (mt_wrp.wacs2_hal == NULL)
|
|
return -1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
/* --external API for pmic_wrap user---------------------------------------- */
|
|
/* ************************************************************************* */
|
|
s32 pwrap_wacs2(u32 write, u32 adr, u32 wdata, u32 *rdata)
|
|
{
|
|
if (mt_wrp.wacs2_hal != NULL)
|
|
return mt_wrp.wacs2_hal(write, adr, wdata, rdata);
|
|
|
|
pr_notice("[WRAP] driver need registered!!");
|
|
return -5;
|
|
|
|
}
|
|
EXPORT_SYMBOL(pwrap_wacs2);
|
|
s32 pwrap_read(u32 adr, u32 *rdata)
|
|
{
|
|
return pwrap_wacs2(PWRAP_READ, adr, 0, rdata);
|
|
}
|
|
EXPORT_SYMBOL(pwrap_read);
|
|
|
|
s32 pwrap_write(u32 adr, u32 wdata)
|
|
{
|
|
/*
|
|
*#if defined PWRAP_TRACE
|
|
* tracepwrap(adr, wdata);
|
|
*#endif
|
|
*/
|
|
return pwrap_wacs2(PWRAP_WRITE, adr, wdata, 0);
|
|
}
|
|
EXPORT_SYMBOL(pwrap_write);
|
|
/********************************************************************/
|
|
/********************************************************************/
|
|
/* return value : EINT_STA: [0]: CPU IRQ status in PMIC1 */
|
|
/* [1]: MD32 IRQ status in PMIC1 */
|
|
/* [2]: CPU IRQ status in PMIC2 */
|
|
/* [3]: RESERVED */
|
|
/********************************************************************/
|
|
u32 pmic_wrap_eint_status(void)
|
|
{
|
|
return mt_pmic_wrap_eint_status();
|
|
}
|
|
EXPORT_SYMBOL(pmic_wrap_eint_status);
|
|
|
|
/********************************************************************/
|
|
/* set value(W1C) : EINT_CLR: [0]: CPU IRQ status in PMIC1 */
|
|
/* [1]: MD32 IRQ status in PMIC1 */
|
|
/* [2]: CPU IRQ status in PMIC2 */
|
|
/* [3]: RESERVED */
|
|
/* para: offset is shift of clear bit which needs to clear */
|
|
/********************************************************************/
|
|
void pmic_wrap_eint_clr(int offset)
|
|
{
|
|
mt_pmic_wrap_eint_clr(offset);
|
|
}
|
|
EXPORT_SYMBOL(pmic_wrap_eint_clr);
|
|
/************************************************************************/
|
|
static ssize_t mt_pwrap_show(struct device_driver *driver, char *buf)
|
|
{
|
|
if (mt_wrp.show_hal != NULL)
|
|
return mt_wrp.show_hal(buf);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", "[WRAP]driver need register!!");
|
|
}
|
|
|
|
static ssize_t mt_pwrap_store(struct device_driver *driver,
|
|
const char *buf, size_t count)
|
|
{
|
|
if (mt_wrp.store_hal != NULL)
|
|
return mt_wrp.store_hal(buf, count);
|
|
|
|
pr_notice("[WRAP]driver need registered!!");
|
|
return count;
|
|
}
|
|
|
|
DRIVER_ATTR(pwrap, 0664, mt_pwrap_show, mt_pwrap_store);
|
|
/*-----suspend/resume for pmic_wrap-------------------------------------------*/
|
|
/* infra power down while suspend,pmic_wrap will gate clock after suspend. */
|
|
/* so,need to init PPB when resume. */
|
|
/* only affect PWM and I2C */
|
|
static int pwrap_suspend(void)
|
|
{
|
|
/* PWRAPLOG("pwrap_suspend\n"); */
|
|
if (mt_wrp.suspend != NULL)
|
|
return mt_wrp.suspend();
|
|
return 0;
|
|
}
|
|
|
|
static void pwrap_resume(void)
|
|
{
|
|
if (mt_wrp.resume != NULL)
|
|
mt_wrp.resume();
|
|
}
|
|
|
|
static struct syscore_ops pwrap_syscore_ops = {
|
|
.resume = pwrap_resume,
|
|
.suspend = pwrap_suspend,
|
|
};
|
|
|
|
static int __init mt_pwrap_init(void)
|
|
{
|
|
u32 ret = 0;
|
|
|
|
ret = driver_register(&mt_wrp.driver);
|
|
if (ret)
|
|
pr_notice("[WRAP]Fail to register mt_wrp");
|
|
ret = driver_create_file(&mt_wrp.driver, &driver_attr_pwrap);
|
|
if (ret)
|
|
pr_notice("[WRAP]Fail to create mt_wrp sysfs files");
|
|
/* PWRAPLOG("pwrap_init_ops\n"); */
|
|
register_syscore_ops(&pwrap_syscore_ops);
|
|
return ret;
|
|
|
|
}
|
|
postcore_initcall(mt_pwrap_init);
|
|
/* device_initcall(mt_pwrap_init); */
|
|
/* ---------------------------------------------------------------------*/
|
|
/* static void __exit mt_pwrap_exit(void) */
|
|
/* { */
|
|
/* platform_driver_unregister(&mt_pwrap_driver); */
|
|
/* return; */
|
|
/* } */
|
|
/* ---------------------------------------------------------------------*/
|
|
/* postcore_initcall(mt_pwrap_init); */
|
|
/* module_exit(mt_pwrap_exit); */
|
|
/* #define PWRAP_EARLY_PORTING */
|
|
/*-----suspend/resume for pmic_wrap-------------------------------------------*/
|
|
/* infra power down while suspend,pmic_wrap will gate clock after suspend. */
|
|
/* so,need to init PPB when resume. */
|
|
/* only affect PWM and I2C */
|
|
|
|
/* static struct syscore_ops pwrap_syscore_ops = { */
|
|
/* .resume = pwrap_resume, */
|
|
/* .suspend = pwrap_suspend, */
|
|
/* }; */
|
|
/* */
|
|
/* static int __init pwrap_init_ops(void) */
|
|
/* { */
|
|
/* PWRAPLOG("pwrap_init_ops\n"); */
|
|
/* register_syscore_ops(&pwrap_syscore_ops); */
|
|
/* return 0; */
|
|
/* } */
|
|
/* device_initcall(pwrap_init_ops); */
|
|
#else
|
|
|
|
static struct regmap *pmic_regmap;
|
|
static spinlock_t wrp_lock = __SPIN_LOCK_UNLOCKED(lock);
|
|
|
|
s32 pwrap_read(u32 adr, u32 *rdata)
|
|
{
|
|
int ret = 0;
|
|
unsigned long flags = 0;
|
|
|
|
if (pmic_regmap) {
|
|
spin_lock_irqsave(&wrp_lock, flags);
|
|
ret = regmap_read(pmic_regmap, adr, rdata);
|
|
spin_unlock_irqrestore(&wrp_lock, flags);
|
|
} else
|
|
pr_notice("%s %d Error.\n", __func__, __LINE__);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(pwrap_read);
|
|
|
|
s32 pwrap_write(u32 adr, u32 wdata)
|
|
{
|
|
int ret = 0;
|
|
unsigned long flags = 0;
|
|
|
|
if (pmic_regmap) {
|
|
spin_lock_irqsave(&wrp_lock, flags);
|
|
ret = regmap_write(pmic_regmap, adr, wdata);
|
|
spin_unlock_irqrestore(&wrp_lock, flags);
|
|
} else
|
|
pr_notice("%s %d Error.\n", __func__, __LINE__);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(pwrap_write);
|
|
|
|
static int __init mt_pwrap_init(void)
|
|
{
|
|
struct device_node *node, *pwrap_node;
|
|
|
|
pr_info("%s\n", __func__);
|
|
node = of_find_compatible_node(NULL, NULL, "mediatek,pwraph");
|
|
pwrap_node = of_parse_phandle(node, "mediatek,pwrap-regmap", 0);
|
|
if (pwrap_node) {
|
|
pmic_regmap = pwrap_node_to_regmap(pwrap_node);
|
|
if (IS_ERR(pmic_regmap)) {
|
|
pr_notice("%s %d Error.\n", __func__, __LINE__);
|
|
return PTR_ERR(pmic_regmap);
|
|
}
|
|
} else {
|
|
pr_notice("%s %d Error.\n", __func__, __LINE__);
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
subsys_initcall(mt_pwrap_init);
|
|
#endif
|
|
|
|
MODULE_AUTHOR("Brian-py Chen, mediatek");
|
|
MODULE_DESCRIPTION("pmic_wrapper Driver Revision");
|
|
MODULE_LICENSE("GPL");
|