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