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 #include <irq-generic.h> 14 #include <asm/arch/periph.h> 15 #include <dm/pinctrl.h> 16 17 #define RK816_INT_STS_REG1 0x49 18 #define RK816_INT_MSK_REG1 0x4a 19 #define RK816_INT_STS_REG2 0x4c 20 #define RK816_INT_MSK_REG2 0x4d 21 #define RK816_INT_STS_REG3 0x4e 22 #define RK816_INT_MSK_REG3 0x4f 23 #define RK816_PWRON_RISE_INT (1 << 6) 24 #define RK816_PWRON_FALL_INT (1 << 5) 25 26 #define RK805_INT_STS_REG 0x4c 27 #define RK805_INT_MSK_REG 0x4d 28 #define RK805_PWRON_RISE_INT (1 << 0) 29 #define RK805_PWRON_FALL_INT (1 << 7) 30 31 struct reg_data { 32 u8 reg; 33 u8 val; 34 }; 35 36 struct rk8xx_key_priv { 37 u8 int_sts_reg; 38 u8 int_msk_reg; 39 u8 pwron_rise_int; 40 u8 pwron_fall_int; 41 struct reg_data *init_reg; 42 u32 init_reg_num; 43 struct reg_data *irq_reg; 44 u32 irq_reg_num; 45 }; 46 47 static struct reg_data rk816_init_reg[] = { 48 /* only enable rise/fall interrupt */ 49 { RK816_INT_MSK_REG1, 0x9f }, 50 { RK816_INT_MSK_REG2, 0xff }, 51 { RK816_INT_MSK_REG3, 0xff }, 52 /* clear all interrupt states */ 53 { RK816_INT_STS_REG1, 0xff }, 54 { RK816_INT_STS_REG2, 0xff }, 55 { RK816_INT_STS_REG3, 0xff }, 56 }; 57 58 static struct reg_data rk816_irq_reg[] = { 59 /* clear all interrupt states */ 60 { RK816_INT_STS_REG1, 0xff }, 61 { RK816_INT_STS_REG2, 0xff }, 62 { RK816_INT_STS_REG3, 0xff }, 63 }; 64 65 static struct reg_data rk805_irq_reg[] = { 66 /* clear all interrupt states */ 67 { RK805_INT_STS_REG, 0xff }, 68 }; 69 70 static struct reg_data rk805_init_reg[] = { 71 /* only enable rise/fall interrupt */ 72 { RK805_INT_MSK_REG, 0x7e }, 73 /* clear all interrupt states */ 74 { RK805_INT_STS_REG, 0xff }, 75 }; 76 77 static int rk8xx_pwrkey_read(struct udevice *dev, int code) 78 { 79 struct input_key *key = dev_get_platdata(dev); 80 u32 report = KEY_NOT_EXIST; 81 82 if (key->code != code) 83 goto out; 84 85 debug("%s: long key ms: %llu\n", 86 __func__, key->up_t - key->down_t); 87 88 if ((key->up_t > key->down_t) && 89 (key->up_t - key->down_t) >= KEY_LONG_DOWN_MS) { 90 key->up_t = 0; 91 key->down_t = 0; 92 report = KEY_PRESS_LONG_DOWN; 93 printf("'%s' key long pressed down\n", key->name); 94 } else if (key->down_t && 95 key_get_timer(key->down_t) >= KEY_LONG_DOWN_MS) { 96 key->up_t = 0; 97 key->down_t = 0; 98 report = KEY_PRESS_LONG_DOWN; 99 printf("'%s' key long pressed down(hold)\n", key->name); 100 } else if ((key->up_t > key->down_t) && 101 (key->up_t - key->down_t) < KEY_LONG_DOWN_MS) { 102 key->up_t = 0; 103 key->down_t = 0; 104 report = KEY_PRESS_DOWN; 105 printf("'%s' key pressed down\n", key->name); 106 } else { 107 report = KEY_PRESS_NONE; 108 } 109 110 out: 111 return report; 112 } 113 114 static void pwrkey_irq_handler(int irq, void *data) 115 { 116 struct udevice *dev = data; 117 struct rk8xx_key_priv *priv = dev_get_priv(dev); 118 struct input_key *key = dev_get_platdata(dev); 119 int ret, val, i; 120 121 /* read status */ 122 val = pmic_reg_read(dev->parent, priv->int_sts_reg); 123 if (val < 0) { 124 printf("%s: i2c read failed, ret=%d\n", __func__, val); 125 return; 126 } 127 128 /* fall event */ 129 if (val & priv->pwron_fall_int) { 130 key->down_t = key_get_timer(0); 131 debug("%s: key down: %llu ms\n", __func__, key->down_t); 132 } 133 134 /* rise event */ 135 if (val & priv->pwron_rise_int) { 136 key->up_t = key_get_timer(0); 137 debug("%s: key up: %llu ms\n", __func__, key->up_t); 138 } 139 140 /* clear intertup */ 141 for (i = 0; i < priv->irq_reg_num; i++) { 142 ret = pmic_reg_write(dev->parent, 143 priv->irq_reg[i].reg, 144 priv->irq_reg[i].val); 145 if (ret < 0) { 146 printf("%s: i2c write reg 0x%x failed, ret=%d\n", 147 __func__, priv->irq_reg[i].reg, ret); 148 } 149 } 150 } 151 152 static int pwrkey_interrupt_init(struct udevice *dev) 153 { 154 struct input_key *key = dev_get_platdata(dev); 155 u32 interrupt[2], phandle; 156 int irq, ret; 157 158 phandle = dev_read_u32_default(dev->parent, "interrupt-parent", -1); 159 if (phandle < 0) { 160 printf("failed get 'interrupt-parent', ret=%d\n", phandle); 161 return phandle; 162 } 163 164 ret = dev_read_u32_array(dev->parent, "interrupts", interrupt, 2); 165 if (ret) { 166 printf("failed get 'interrupt', ret=%d\n", ret); 167 return ret; 168 } 169 170 key->name = "pwrkey"; 171 key->code = KEY_POWER; 172 irq = phandle_gpio_to_irq(phandle, interrupt[0]); 173 irq_install_handler(irq, pwrkey_irq_handler, dev); 174 irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); 175 irq_handler_enable(irq); 176 177 return 0; 178 } 179 180 static const struct dm_key_ops key_ops = { 181 .name = "rk8xx-pwrkey", 182 .read = rk8xx_pwrkey_read, 183 }; 184 185 static int rk8xx_pwrkey_probe(struct udevice *dev) 186 { 187 struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent); 188 struct rk8xx_key_priv *priv = dev_get_priv(dev); 189 int ret, i; 190 191 switch (rk8xx->variant) { 192 case RK805_ID: 193 priv->int_sts_reg = RK805_INT_STS_REG; 194 priv->int_msk_reg = RK805_INT_MSK_REG; 195 priv->pwron_rise_int = RK805_PWRON_RISE_INT; 196 priv->pwron_fall_int = RK805_PWRON_FALL_INT; 197 priv->init_reg = rk805_init_reg; 198 priv->init_reg_num = ARRAY_SIZE(rk805_init_reg); 199 priv->irq_reg = rk805_irq_reg; 200 priv->irq_reg_num = ARRAY_SIZE(rk805_irq_reg); 201 break; 202 203 case RK816_ID: 204 priv->int_sts_reg = RK816_INT_STS_REG1; 205 priv->int_msk_reg = RK816_INT_MSK_REG1; 206 priv->pwron_rise_int = RK816_PWRON_RISE_INT; 207 priv->pwron_fall_int = RK816_PWRON_FALL_INT; 208 priv->init_reg = rk816_init_reg; 209 priv->init_reg_num = ARRAY_SIZE(rk816_init_reg); 210 priv->irq_reg = rk816_irq_reg; 211 priv->irq_reg_num = ARRAY_SIZE(rk816_irq_reg); 212 break; 213 214 default: 215 return -EINVAL; 216 } 217 218 /* mask and clear intertup */ 219 for (i = 0; i < priv->init_reg_num; i++) { 220 ret = pmic_reg_write(dev->parent, 221 priv->init_reg[i].reg, 222 priv->init_reg[i].val); 223 if (ret < 0) { 224 printf("%s: i2c write reg 0x%x failed, ret=%d\n", 225 __func__, priv->init_reg[i].reg, ret); 226 return ret; 227 } 228 } 229 230 return pwrkey_interrupt_init(dev); 231 } 232 233 U_BOOT_DRIVER(rk8xx_pwrkey) = { 234 .name = "rk8xx_pwrkey", 235 .id = UCLASS_KEY, 236 .ops = &key_ops, 237 .probe = rk8xx_pwrkey_probe, 238 .platdata_auto_alloc_size = sizeof(struct input_key), 239 .priv_auto_alloc_size = sizeof(struct rk8xx_key_priv), 240 }; 241