mfd: backport khadas mcu driver changes from armbian rockchip-rk3588-edge kernel
This commit is contained in:
parent
2c87757969
commit
cdfac8115a
4 changed files with 110 additions and 20 deletions
|
|
@ -11,7 +11,7 @@ maintainers:
|
|||
|
||||
description: |
|
||||
Khadas embeds a microcontroller on their VIM and Edge boards adding some
|
||||
system feature as PWM Fan control (for VIM2 rev14 or VIM3), User memory
|
||||
system feature as PWM Fan control (for VIM2 rev14, VIM3, Edge2), User memory
|
||||
storage, IR/Key resume control, system power LED control and more.
|
||||
|
||||
properties:
|
||||
|
|
@ -22,6 +22,11 @@ properties:
|
|||
"#cooling-cells": # Only needed for boards having FAN control feature
|
||||
const: 2
|
||||
|
||||
cooling-levels:
|
||||
description: Max speed of PWM fan. This property is necessary for Khadas Edge 2.
|
||||
items:
|
||||
maximum: 100
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg)
|
|||
case KHADAS_MCU_CHECK_USER_PASSWD_REG:
|
||||
case KHADAS_MCU_WOL_INIT_START_REG:
|
||||
case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG:
|
||||
case KHADAS_MCU_LED_ON_RAM_REG:
|
||||
case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2:
|
||||
case KHADAS_MCU_WDT_EN_REG:
|
||||
case KHADAS_MCU_SYS_RST_REG:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
@ -69,23 +73,18 @@ static const struct regmap_config khadas_mcu_regmap_config = {
|
|||
.reg_bits = 8,
|
||||
.reg_stride = 1,
|
||||
.val_bits = 8,
|
||||
.max_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
|
||||
.max_register = KHADAS_MCU_SYS_RST_REG,
|
||||
.volatile_reg = khadas_mcu_reg_volatile,
|
||||
.writeable_reg = khadas_mcu_reg_writeable,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static struct mfd_cell khadas_mcu_fan_cells[] = {
|
||||
/* VIM1/2 Rev13+ and VIM3 only */
|
||||
/* VIM1/2 Rev13+, VIM3 and Edge2 only */
|
||||
{ .name = "khadas-mcu-fan-ctrl", },
|
||||
};
|
||||
|
||||
static struct mfd_cell khadas_mcu_cells[] = {
|
||||
{ .name = "khadas-mcu-user-mem", },
|
||||
};
|
||||
|
||||
static int khadas_mcu_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int khadas_mcu_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct khadas_mcu *ddata;
|
||||
|
|
@ -106,13 +105,6 @@ static int khadas_mcu_probe(struct i2c_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
|
||||
khadas_mcu_cells,
|
||||
ARRAY_SIZE(khadas_mcu_cells),
|
||||
NULL, 0, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (of_find_property(dev->of_node, "#cooling-cells", NULL))
|
||||
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
|
||||
khadas_mcu_fan_cells,
|
||||
|
|
|
|||
|
|
@ -15,10 +15,16 @@
|
|||
#include <linux/thermal.h>
|
||||
|
||||
#define MAX_LEVEL 3
|
||||
#define MAX_SPEED 0x64
|
||||
|
||||
struct khadas_mcu_fan_ctx {
|
||||
struct khadas_mcu *mcu;
|
||||
unsigned int level;
|
||||
|
||||
unsigned int fan_max_level;
|
||||
unsigned int fan_register;
|
||||
unsigned int *fan_cooling_levels;
|
||||
|
||||
struct thermal_cooling_device *cdev;
|
||||
};
|
||||
|
||||
|
|
@ -26,9 +32,21 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
|
|||
unsigned int level)
|
||||
{
|
||||
int ret;
|
||||
unsigned int write_level = level;
|
||||
|
||||
if (level > ctx->fan_max_level)
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->fan_cooling_levels != NULL) {
|
||||
write_level = ctx->fan_cooling_levels[level];
|
||||
|
||||
if (write_level > MAX_SPEED)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_write(ctx->mcu->regmap, ctx->fan_register,
|
||||
write_level);
|
||||
|
||||
ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
|
||||
level);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -40,7 +58,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
|
|||
static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
|
||||
unsigned long *state)
|
||||
{
|
||||
*state = MAX_LEVEL;
|
||||
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
|
||||
|
||||
*state = ctx->fan_max_level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -61,7 +81,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
|||
{
|
||||
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
|
||||
|
||||
if (state > MAX_LEVEL)
|
||||
if (state > ctx->fan_max_level)
|
||||
return -EINVAL;
|
||||
|
||||
if (state == ctx->level)
|
||||
|
|
@ -76,6 +96,48 @@ static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = {
|
|||
.set_cur_state = khadas_mcu_fan_set_cur_state,
|
||||
};
|
||||
|
||||
// Khadas Edge 2 sets fan level by passing fan speed(0-100). So we need different logic here like pwm-fan cooling-levels.
|
||||
// This is optional and just necessary for Edge 2.
|
||||
static int khadas_mcu_fan_get_cooling_data_edge2(struct khadas_mcu_fan_ctx *ctx, struct device *dev) {
|
||||
struct device_node *np = ctx->mcu->dev->of_node;
|
||||
int num, i, ret;
|
||||
|
||||
if (!of_find_property(np, "cooling-levels", NULL))
|
||||
return 0;
|
||||
|
||||
ret = of_property_count_u32_elems(np, "cooling-levels");
|
||||
if (ret <= 0) {
|
||||
dev_err(dev, "Wrong data!\n");
|
||||
return ret ? : -EINVAL;
|
||||
}
|
||||
|
||||
num = ret;
|
||||
ctx->fan_cooling_levels = devm_kcalloc(dev, num, sizeof(u32),
|
||||
GFP_KERNEL);
|
||||
if (!ctx->fan_cooling_levels)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_property_read_u32_array(np, "cooling-levels",
|
||||
ctx->fan_cooling_levels, num);
|
||||
if (ret) {
|
||||
dev_err(dev, "Property 'cooling-levels' cannot be read!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (ctx->fan_cooling_levels[i] > MAX_SPEED) {
|
||||
dev_err(dev, "PWM fan state[%d]:%d > %d\n", i,
|
||||
ctx->fan_cooling_levels[i], MAX_SPEED);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->fan_max_level = num - 1;
|
||||
ctx->fan_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int khadas_mcu_fan_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent);
|
||||
|
|
@ -90,6 +152,13 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
|
|||
ctx->mcu = mcu;
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
|
||||
ctx->fan_max_level = MAX_LEVEL;
|
||||
ctx->fan_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG;
|
||||
|
||||
ret = khadas_mcu_fan_get_cooling_data_edge2(ctx, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cdev = devm_thermal_of_cooling_device_register(dev->parent,
|
||||
dev->parent->of_node, "khadas-mcu-fan", ctx,
|
||||
&khadas_mcu_fan_cooling_ops);
|
||||
|
|
|
|||
|
|
@ -35,26 +35,45 @@
|
|||
#define KHADAS_MCU_FACTORY_TEST_REG 0x16 /* R */
|
||||
#define KHADAS_MCU_BOOT_MODE_REG 0x20 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_WOL_REG 0x21 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_DCIN_REG_V2 0x21 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_RTC_REG 0x22 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_EXP_REG 0x23 /* RW */
|
||||
#define KHADAS_MCU_LED_MODE_ON_REG_V2 0x23 /* RW */
|
||||
#define KHADAS_MCU_LED_MODE_OFF_REG_V2 0x24 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_IR_REG 0x24 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_DCIN_REG 0x25 /* RW */
|
||||
#define KHADAS_MCU_RGB_ON_R_REG 0x25 /* RW */
|
||||
#define KHADAS_MCU_RGB_ON_G_REG 0x26 /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_KEY_REG 0x26 /* RW */
|
||||
#define KHADAS_MCU_RGB_ON_B_REG 0x27 /* RW */
|
||||
#define KHADAS_MCU_KEY_MODE_REG 0x27 /* RW */
|
||||
#define KHADAS_MCU_RGB_OFF_R_REG 0x28 /* RW */
|
||||
#define KHADAS_MCU_LED_MODE_ON_REG 0x28 /* RW */
|
||||
#define KHADAS_MCU_RGB_OFF_G_REG 0x29 /* RW */
|
||||
#define KHADAS_MCU_LED_MODE_OFF_REG 0x29 /* RW */
|
||||
#define KHADAS_MCU_RGB_OFF_B_REG 0x2a /* RW */
|
||||
#define KHADAS_MCU_SHUTDOWN_NORMAL_REG 0x2c /* RW */
|
||||
#define KHADAS_MCU_MAC_SWITCH_REG 0x2d /* RW */
|
||||
#define KHADAS_MCU_REST_CONF_REG 0x2e /* RW */
|
||||
#define KHADAS_MCU_MCU_SLEEP_MODE_REG 0x2e /* RW */
|
||||
#define KHADAS_MCU_BOOT_EN_IR_REG_V2 0x2f /* RW */
|
||||
#define KHADAS_MCU_IR_CODE1_0_REG 0x2f /* RW */
|
||||
#define KHADAS_MCU_IR_CODE1_1_REG 0x30 /* RW */
|
||||
#define KHADAS_MCU_IR1_CUST1_REG 0x30 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE1_2_REG 0x31 /* RW */
|
||||
#define KHADAS_MCU_IR1_CUST2_REG 0x31 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE1_3_REG 0x32 /* RW */
|
||||
#define KHADAS_MCU_IR1_ORDER1_REG 0x32 /* RW */
|
||||
#define KHADAS_MCU_USB_PCIE_SWITCH_REG 0x33 /* RW */
|
||||
#define KHADAS_MCU_IR1_ORDER2_REG 0x33 /* RW */
|
||||
#define KHADAS_MCU_IR2_CUST1_REG 0x34 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE2_0_REG 0x34 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE2_1_REG 0x35 /* RW */
|
||||
#define KHADAS_MCU_IR2_CUST2_REG 0x35 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE2_2_REG 0x36 /* RW */
|
||||
#define KHADAS_MCU_IR2_ORDER1_REG 0x36 /* RW */
|
||||
#define KHADAS_MCU_IR_CODE2_3_REG 0x37 /* RW */
|
||||
#define KHADAS_MCU_IR2_ORDER2_REG 0x36 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_0_REG 0x40 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_1_REG 0x41 /* RW */
|
||||
#define KHADAS_MCU_PASSWD_USER_2_REG 0x42 /* RW */
|
||||
|
|
@ -69,6 +88,10 @@
|
|||
#define KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG 0x86 /* RO */
|
||||
#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */
|
||||
#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */
|
||||
#define KHADAS_MCU_LED_ON_RAM_REG 0x89 /* WO */
|
||||
#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2 0x8A /* WO */
|
||||
#define KHADAS_MCU_WDT_EN_REG 0x8B /* WO */
|
||||
#define KHADAS_MCU_SYS_RST_REG 0x91 /* WO */
|
||||
|
||||
enum {
|
||||
KHADAS_BOARD_VIM1 = 0x1,
|
||||
|
|
@ -76,6 +99,7 @@ enum {
|
|||
KHADAS_BOARD_VIM3,
|
||||
KHADAS_BOARD_EDGE = 0x11,
|
||||
KHADAS_BOARD_EDGE_V,
|
||||
KHADAS_BOARD_EDGE2,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue