1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <key.h> 10 #include <linux/input.h> 11 #include <power/pmic.h> 12 #include <power/rk8xx_pmic.h> 13 14 #define RK816_INT_STS_REG1 0x49 15 #define RK816_INT_MSK_REG1 0x4a 16 #define RK816_PWRON_RISE_INT (1 << 6) 17 #define RK816_PWRON_FALL_INT (1 << 5) 18 19 #define RK805_INT_STS_REG 0x4c 20 #define RK805_INT_MSK_REG 0x4d 21 #define RK805_PWRON_RISE_INT (1 << 0) 22 #define RK805_PWRON_FALL_INT (1 << 7) 23 24 struct key_data { 25 u8 int_sts_reg; 26 u8 int_msk_reg; 27 u8 pwron_rise_int; 28 u8 pwron_fall_int; 29 }; 30 31 static int rk8xx_pwrkey_read(struct udevice *dev) 32 { 33 struct key_data *key = dev_get_priv(dev); 34 int status = KEY_PRESS_NONE; 35 int ret, val; 36 37 val = pmic_reg_read(dev->parent, key->int_sts_reg); 38 if (val < 0) { 39 printf("%s: i2c read failed, ret=%d\n", __func__, val); 40 return val; 41 } 42 43 if (val & key->pwron_fall_int) 44 status = KEY_PRESS_DOWN; 45 46 /* Must check pwron rise behind of fall !! */ 47 if (val & key->pwron_rise_int) { 48 /* Clear fall when detect rise */ 49 ret = pmic_reg_write(dev->parent, key->int_sts_reg, 50 key->pwron_fall_int | key->pwron_rise_int); 51 if (ret < 0) { 52 printf("%s: i2c write failed, ret=%d\n", __func__, val); 53 return ret; 54 } 55 56 status = KEY_PRESS_UP; 57 } 58 59 debug("%s: int sts = 0x%x msk = 0x%x\n", 60 __func__, pmic_reg_read(dev->parent, key->int_sts_reg), 61 pmic_reg_read(dev->parent, key->int_msk_reg)); 62 63 return status; 64 } 65 66 static const struct dm_key_ops key_ops = { 67 .type = KEY_POWER, 68 .name = "pmic-pwrkey", 69 .read = rk8xx_pwrkey_read, 70 }; 71 72 static int rk8xx_pwrkey_probe(struct udevice *dev) 73 { 74 struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent); 75 struct key_data *key = dev_get_priv(dev); 76 int ret, val; 77 78 switch (rk8xx->variant) { 79 case RK805_ID: 80 key->int_sts_reg = RK805_INT_STS_REG; 81 key->int_msk_reg = RK805_INT_MSK_REG; 82 key->pwron_rise_int = RK805_PWRON_RISE_INT; 83 key->pwron_fall_int = RK805_PWRON_FALL_INT; 84 break; 85 86 case RK816_ID: 87 key->int_sts_reg = RK816_INT_STS_REG1; 88 key->int_msk_reg = RK816_INT_MSK_REG1; 89 key->pwron_rise_int = RK816_PWRON_RISE_INT; 90 key->pwron_fall_int = RK816_PWRON_FALL_INT; 91 break; 92 93 default: 94 return -EINVAL; 95 } 96 97 /* Clear states */ 98 ret = pmic_reg_write(dev->parent, key->int_sts_reg, 99 key->pwron_rise_int | key->pwron_fall_int); 100 if (ret < 0) { 101 printf("%s: i2c write failed, ret=%d\n", __func__, ret); 102 return ret; 103 } 104 105 val = pmic_reg_read(dev->parent, key->int_msk_reg); 106 if (val < 0) { 107 printf("%s: i2c read failed, ret=%d\n", __func__, val); 108 return val; 109 } 110 111 /* enable fall and rise interrupt */ 112 val = 0xff; 113 val &= ~(key->pwron_rise_int | key->pwron_fall_int); 114 ret = pmic_reg_write(dev->parent, key->int_msk_reg, val); 115 if (ret < 0) { 116 printf("%s: i2c write failed, ret=%d\n", __func__, val); 117 return ret; 118 } 119 120 return 0; 121 } 122 123 U_BOOT_DRIVER(rk8xx_pwrkey) = { 124 .name = "rk8xx_pwrkey", 125 .id = UCLASS_KEY, 126 .probe = rk8xx_pwrkey_probe, 127 .ops = &key_ops, 128 .priv_auto_alloc_size = sizeof(struct key_data), 129 }; 130