254 lines
6.9 KiB
C
Executable File
254 lines
6.9 KiB
C
Executable File
/*
|
|
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com
|
|
*
|
|
* 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/kernel.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/init.h>
|
|
#include <linux/platform_device.h>
|
|
#include <soc/samsung/acpm_mfd.h>
|
|
#include <soc/samsung/acpm_ipc_ctrl.h>
|
|
|
|
extern struct device_node *acpm_mfd_node;
|
|
static DEFINE_MUTEX(acpm_mfd_lock);
|
|
|
|
int exynos_acpm_read_reg(u16 type, u8 reg, u8 *dest)
|
|
{
|
|
unsigned int channel_num, size;
|
|
struct ipc_config config;
|
|
unsigned int command[4] = {0,};
|
|
int ret = 0;
|
|
|
|
mutex_lock(&acpm_mfd_lock);
|
|
if (!acpm_ipc_request_channel(acpm_mfd_node, NULL, &channel_num, &size)) {
|
|
config.cmd = command;
|
|
config.cmd[0] = set_protocol(type, TYPE) | set_protocol(reg, REG);
|
|
config.cmd[1] = set_protocol(FUNC_READ, FUNC);
|
|
config.response = true;
|
|
config.indirection = false;
|
|
|
|
ACPM_MFD_PRINT("%s - addr: 0x%03x\n",
|
|
__func__, set_protocol(type, TYPE) | set_protocol(reg, REG));
|
|
|
|
ret = acpm_ipc_send_data(channel_num, &config);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - acpm_ipc_send_data fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
*dest = read_protocol(config.cmd[1], DEST);
|
|
ret = read_protocol(config.cmd[1], RETURN);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - APM's speedy_rx fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
ACPM_MFD_PRINT("%s - data = 0x%02x ret = 0x%02x\n",
|
|
__func__, *dest, ret);
|
|
|
|
acpm_ipc_release_channel(acpm_mfd_node, channel_num);
|
|
} else {
|
|
pr_err(ACPM_MFD_PREFIX "%s ipc request_channel fail, id:%u, size:%u\n",
|
|
__func__, channel_num, size);
|
|
ret = -EBUSY;
|
|
}
|
|
err:
|
|
mutex_unlock(&acpm_mfd_lock);
|
|
return ret;
|
|
}
|
|
|
|
int exynos_acpm_bulk_read(u16 type, u8 reg, int count, u8 *buf)
|
|
{
|
|
unsigned int channel_num, size;
|
|
struct ipc_config config;
|
|
unsigned int command[4] = {0,};
|
|
int i, ret = 0;
|
|
|
|
mutex_lock(&acpm_mfd_lock);
|
|
if (!acpm_ipc_request_channel(acpm_mfd_node, NULL, &channel_num, &size)) {
|
|
config.cmd = command;
|
|
config.cmd[0] = set_protocol(type, TYPE) | set_protocol(reg, REG);
|
|
config.cmd[1] = set_protocol(FUNC_BULK_READ, FUNC) | set_protocol(count, CNT);
|
|
config.response = true;
|
|
config.indirection = false;
|
|
|
|
ACPM_MFD_PRINT("%s - addr: 0x%03x\n",
|
|
__func__, set_protocol(type, TYPE) | set_protocol(reg, REG));
|
|
|
|
ret = acpm_ipc_send_data(channel_num, &config);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - acpm_ipc_send_data fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
ret = read_protocol(config.cmd[1], RETURN);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - APM's speedy_rx fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (i < 4)
|
|
buf[i] = read_bulk_protocol(config.cmd[2], BULK_VAL, i);
|
|
else
|
|
buf[i] = read_bulk_protocol(config.cmd[3], BULK_VAL , i - 4);
|
|
}
|
|
|
|
acpm_ipc_release_channel(acpm_mfd_node, channel_num);
|
|
} else {
|
|
pr_err(ACPM_MFD_PREFIX "%s ipc request_channel fail, id:%u, size:%u\n",
|
|
__func__, channel_num, size);
|
|
ret = -EBUSY;
|
|
}
|
|
|
|
err:
|
|
mutex_unlock(&acpm_mfd_lock);
|
|
return ret;
|
|
}
|
|
|
|
int exynos_acpm_write_reg(u16 type, u8 reg, u8 value)
|
|
{
|
|
unsigned int channel_num, size;
|
|
struct ipc_config config;
|
|
unsigned int command[4] = {0,};
|
|
int ret = 0;
|
|
|
|
mutex_lock(&acpm_mfd_lock);
|
|
if (!acpm_ipc_request_channel(acpm_mfd_node, NULL, &channel_num, &size)) {
|
|
config.cmd = command;
|
|
config.cmd[0] = set_protocol(type, TYPE) | set_protocol(reg, REG);
|
|
config.cmd[1] = set_protocol(FUNC_WRITE, FUNC) | set_protocol(value, WRITE_VAL);
|
|
config.response = true;
|
|
config.indirection = false;
|
|
|
|
ACPM_MFD_PRINT("%s - addr: 0x%03x val: 0x%02x\n",
|
|
__func__, set_protocol(type, TYPE) | set_protocol(reg, REG), value);
|
|
|
|
ret = acpm_ipc_send_data(channel_num, &config);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - acpm_ipc_send_data fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
ret = read_protocol(config.cmd[1], RETURN);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - APM's speedy_tx fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
ACPM_MFD_PRINT("%s - read(ret) val: 0x%02x\n", __func__, ret);
|
|
|
|
acpm_ipc_release_channel(acpm_mfd_node, channel_num);
|
|
} else {
|
|
pr_err(ACPM_MFD_PREFIX "%s ipc request_channel fail, id:%u, size:%u\n",
|
|
__func__, channel_num, size);
|
|
ret = -EBUSY;
|
|
}
|
|
|
|
err:
|
|
mutex_unlock(&acpm_mfd_lock);
|
|
return ret;
|
|
}
|
|
|
|
int exynos_acpm_bulk_write(u16 type, u8 reg, int count, u8 *buf)
|
|
{
|
|
unsigned int channel_num, size;
|
|
struct ipc_config config;
|
|
unsigned int command[4] = {0,};
|
|
int ret = 0;
|
|
int i;
|
|
|
|
mutex_lock(&acpm_mfd_lock);
|
|
if (!acpm_ipc_request_channel(acpm_mfd_node, NULL, &channel_num, &size)) {
|
|
config.cmd = command;
|
|
config.cmd[0] = set_protocol(type, TYPE) | set_protocol(reg, REG);
|
|
config.cmd[1] = set_protocol(FUNC_BULK_WRITE, FUNC) | set_protocol(count, CNT);
|
|
config.response = true;
|
|
config.indirection = false;
|
|
|
|
ACPM_MFD_PRINT("%s - addr: 0x%03x\n cnt: 0x%02x\n",
|
|
__func__, set_protocol(type, TYPE) | set_protocol(reg, REG), count);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (i < 4)
|
|
config.cmd[2] |= set_bulk_protocol(buf[i], BULK_VAL, i);
|
|
else
|
|
config.cmd[3] |= set_bulk_protocol(buf[i], BULK_VAL, i - 4);
|
|
}
|
|
|
|
ret = acpm_ipc_send_data(channel_num, &config);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - acpm_ipc_send_data fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
ret = read_protocol(config.cmd[1], RETURN);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - APM's speedy_tx fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
acpm_ipc_release_channel(acpm_mfd_node, channel_num);
|
|
} else {
|
|
pr_err(ACPM_MFD_PREFIX "%s ipc request_channel fail, id:%u, size:%u\n",
|
|
__func__, channel_num, size);
|
|
ret = -EBUSY;
|
|
}
|
|
|
|
err:
|
|
mutex_unlock(&acpm_mfd_lock);
|
|
return ret;
|
|
}
|
|
|
|
int exynos_acpm_update_reg(u16 type, u8 reg, u8 value, u8 mask)
|
|
{
|
|
unsigned int channel_num, size;
|
|
struct ipc_config config;
|
|
unsigned int command[4] = {0,};
|
|
int ret = 0;
|
|
|
|
mutex_lock(&acpm_mfd_lock);
|
|
if (!acpm_ipc_request_channel(acpm_mfd_node, NULL, &channel_num, &size)) {
|
|
config.cmd = command;
|
|
config.cmd[0] = set_protocol(type, TYPE) | set_protocol(reg, REG);
|
|
config.cmd[1] = set_protocol(FUNC_UPDATE, FUNC)
|
|
| set_protocol(value, UPDATE_VAL)
|
|
| set_protocol(mask, UPDATE_MASK);
|
|
config.response = true;
|
|
config.indirection = false;
|
|
|
|
ACPM_MFD_PRINT("%s - addr: 0x%03x val: 0x%02x mask: 0x%02x\n",
|
|
__func__, set_protocol(type, TYPE) | set_protocol(reg, REG), value, mask);
|
|
|
|
ret = acpm_ipc_send_data(channel_num, &config);
|
|
if (ret) {
|
|
pr_err(ACPM_MFD_PREFIX "%s - acpm_ipc_send_data fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
ret = read_protocol(config.cmd[1], RETURN);
|
|
if (ret) {
|
|
if (ret == 1)
|
|
pr_err(ACPM_MFD_PREFIX "%s - APM's speedy_rx fail.\n", __func__);
|
|
else if (ret == 2)
|
|
pr_err(ACPM_MFD_PREFIX "%s - APM's speedy_tx fail.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
acpm_ipc_release_channel(acpm_mfd_node, channel_num);
|
|
} else {
|
|
pr_err(ACPM_MFD_PREFIX "%s ipc request_channel fail, id:%u, size:%u\n",
|
|
__func__, channel_num, size);
|
|
ret = -EBUSY;
|
|
}
|
|
|
|
err:
|
|
mutex_unlock(&acpm_mfd_lock);
|
|
return ret;
|
|
}
|