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 RK817_INT_STS_REG0 0xf8 18 #define RK817_INT_MSK_REG0 0xf9 19 #define RK817_INT_STS_REG1 0xfa 20 #define RK817_INT_MSK_REG1 0xfb 21 #define RK817_INT_STS_REG2 0xfc 22 #define RK817_INT_MSK_REG2 0xfd 23 #define RK817_PWRON_RISE_INT (1 << 1) 24 #define RK817_PWRON_FALL_INT (1 << 0) 25 #define RK817_PLUG_OUT_INT (1 << 1) 26 27 #define RK816_INT_STS_REG1 0x49 28 #define RK816_INT_MSK_REG1 0x4a 29 #define RK816_INT_STS_REG2 0x4c 30 #define RK816_INT_MSK_REG2 0x4d 31 #define RK816_INT_STS_REG3 0x4e 32 #define RK816_INT_MSK_REG3 0x4f 33 #define RK816_PWRON_RISE_INT (1 << 6) 34 #define RK816_PWRON_FALL_INT (1 << 5) 35 #define RK816_PLUG_OUT_INT (1 << 1) 36 37 #define RK805_INT_STS_REG 0x4c 38 #define RK805_INT_MSK_REG 0x4d 39 #define RK805_PWRON_RISE_INT (1 << 0) 40 #define RK805_PWRON_FALL_INT (1 << 7) 41 42 struct rk8xx_key_priv { 43 u8 key_int_sts_reg; 44 u8 key_int_msk_reg; 45 u8 plug_int_sts_reg; 46 u8 plug_int_msk_reg; 47 u8 pwron_rise_int; 48 u8 pwron_fall_int; 49 u8 plug_out_int; 50 struct reg_data *init_reg; 51 u32 init_reg_num; 52 struct reg_data *irq_reg; 53 u32 irq_reg_num; 54 }; 55 56 static struct reg_data rk817_init_reg[] = { 57 /* only enable rise/fall interrupt, plugout */ 58 { RK817_INT_MSK_REG0, 0xfc }, 59 { RK817_INT_MSK_REG1, 0xfd }, 60 { RK817_INT_MSK_REG2, 0xff }, 61 /* clear all interrupt states */ 62 { RK817_INT_STS_REG0, 0xff }, 63 { RK817_INT_STS_REG1, 0xff }, 64 { RK817_INT_STS_REG2, 0xff }, 65 }; 66 67 static struct reg_data rk817_irq_reg[] = { 68 /* clear all interrupt states */ 69 { RK817_INT_STS_REG0, 0xff }, 70 { RK817_INT_STS_REG1, 0xff }, 71 { RK817_INT_STS_REG2, 0xff }, 72 }; 73 74 static struct reg_data rk816_init_reg[] = { 75 /* only enable rise/fall interrupt, plugout */ 76 { RK816_INT_MSK_REG1, 0x9f }, 77 { RK816_INT_MSK_REG2, 0xff }, 78 { RK816_INT_MSK_REG3, 0xfd }, 79 /* clear all interrupt states */ 80 { RK816_INT_STS_REG1, 0xff }, 81 { RK816_INT_STS_REG2, 0xff }, 82 { RK816_INT_STS_REG3, 0xff }, 83 }; 84 85 static struct reg_data rk816_irq_reg[] = { 86 /* clear all interrupt states */ 87 { RK816_INT_STS_REG1, 0xff }, 88 { RK816_INT_STS_REG2, 0xff }, 89 { RK816_INT_STS_REG3, 0xff }, 90 }; 91 92 static struct reg_data rk805_irq_reg[] = { 93 /* clear all interrupt states */ 94 { RK805_INT_STS_REG, 0xff }, 95 }; 96 97 static struct reg_data rk805_init_reg[] = { 98 /* only enable rise/fall interrupt */ 99 { RK805_INT_MSK_REG, 0x7e }, 100 /* clear all interrupt states */ 101 { RK805_INT_STS_REG, 0xff }, 102 }; 103 104 static int rk8xx_pwrkey_read(struct udevice *dev, int code) 105 { 106 struct input_key *key = dev_get_platdata(dev); 107 108 if (key->code != code) 109 return KEY_NOT_EXIST; 110 111 return key_parse_gpio_event(key); 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 debug("%s: irq = %d\n", __func__, irq); 122 123 /* 124 * This plug out interrupt only used to wakeup cpu while U-Boot 125 * charging and system suspend. Because we need to detect charger 126 * plug out event and then shutdown system. 127 */ 128 if (priv->plug_int_sts_reg) { 129 val = pmic_reg_read(dev->parent, priv->plug_int_sts_reg); 130 if (val < 0) { 131 printf("%s: i2c read failed, ret=%d\n", __func__, val); 132 return; 133 } 134 135 if (val & priv->plug_out_int) 136 printf("Plug out interrupt\n"); 137 } 138 139 /* read key status */ 140 val = pmic_reg_read(dev->parent, priv->key_int_sts_reg); 141 if (val < 0) { 142 printf("%s: i2c read failed, ret=%d\n", __func__, val); 143 return; 144 } 145 146 /* fall event */ 147 if (val & priv->pwron_fall_int) { 148 key->down_t = key_get_timer(0); 149 debug("%s: key down: %llu ms\n", __func__, key->down_t); 150 } 151 152 /* rise event */ 153 if (val & priv->pwron_rise_int) { 154 key->up_t = key_get_timer(0); 155 debug("%s: key up: %llu ms\n", __func__, key->up_t); 156 } 157 158 /* clear intertup */ 159 for (i = 0; i < priv->irq_reg_num; i++) { 160 ret = pmic_reg_write(dev->parent, 161 priv->irq_reg[i].reg, 162 priv->irq_reg[i].val); 163 if (ret < 0) { 164 printf("%s: i2c write reg 0x%x failed, ret=%d\n", 165 __func__, priv->irq_reg[i].reg, ret); 166 } 167 168 debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->irq_reg[i].reg, 169 pmic_reg_read(dev->parent, priv->irq_reg[i].reg)); 170 } 171 } 172 173 static int pwrkey_interrupt_init(struct udevice *dev) 174 { 175 struct input_key *key = dev_get_platdata(dev); 176 u32 interrupt[2], phandle; 177 int irq, ret; 178 179 phandle = dev_read_u32_default(dev->parent, "interrupt-parent", -1); 180 if (phandle < 0) { 181 printf("failed get 'interrupt-parent', ret=%d\n", phandle); 182 return phandle; 183 } 184 185 ret = dev_read_u32_array(dev->parent, "interrupts", interrupt, 2); 186 if (ret) { 187 printf("failed get 'interrupt', ret=%d\n", ret); 188 return ret; 189 } 190 191 key->name = "power"; 192 key->code = KEY_POWER; 193 irq = phandle_gpio_to_irq(phandle, interrupt[0]); 194 irq_install_handler(irq, pwrkey_irq_handler, dev); 195 irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); 196 irq_handler_enable(irq); 197 198 return 0; 199 } 200 201 static const struct dm_key_ops key_ops = { 202 .name = "rk8xx-pwrkey", 203 .read = rk8xx_pwrkey_read, 204 }; 205 206 static int rk8xx_pwrkey_probe(struct udevice *dev) 207 { 208 struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent); 209 struct rk8xx_key_priv *priv = dev_get_priv(dev); 210 int ret, i; 211 212 switch (rk8xx->variant) { 213 case RK805_ID: 214 priv->key_int_sts_reg = RK805_INT_STS_REG; 215 priv->key_int_msk_reg = RK805_INT_MSK_REG; 216 priv->pwron_rise_int = RK805_PWRON_RISE_INT; 217 priv->pwron_fall_int = RK805_PWRON_FALL_INT; 218 priv->init_reg = rk805_init_reg; 219 priv->init_reg_num = ARRAY_SIZE(rk805_init_reg); 220 priv->irq_reg = rk805_irq_reg; 221 priv->irq_reg_num = ARRAY_SIZE(rk805_irq_reg); 222 break; 223 224 case RK816_ID: 225 priv->key_int_sts_reg = RK816_INT_STS_REG1; 226 priv->key_int_msk_reg = RK816_INT_MSK_REG1; 227 priv->plug_int_sts_reg = RK816_INT_STS_REG3; 228 priv->plug_int_msk_reg = RK816_INT_MSK_REG3; 229 priv->pwron_rise_int = RK816_PWRON_RISE_INT; 230 priv->pwron_fall_int = RK816_PWRON_FALL_INT; 231 priv->plug_out_int = RK816_PLUG_OUT_INT; 232 priv->init_reg = rk816_init_reg; 233 priv->init_reg_num = ARRAY_SIZE(rk816_init_reg); 234 priv->irq_reg = rk816_irq_reg; 235 priv->irq_reg_num = ARRAY_SIZE(rk816_irq_reg); 236 break; 237 case RK809_ID: 238 case RK817_ID: 239 priv->key_int_sts_reg = RK817_INT_STS_REG0; 240 priv->key_int_msk_reg = RK817_INT_MSK_REG0; 241 priv->plug_int_sts_reg = RK817_INT_STS_REG1; 242 priv->plug_int_msk_reg = RK817_INT_MSK_REG1; 243 priv->pwron_rise_int = RK817_PWRON_RISE_INT; 244 priv->pwron_fall_int = RK817_PWRON_FALL_INT; 245 priv->plug_out_int = RK817_PLUG_OUT_INT; 246 priv->init_reg = rk817_init_reg; 247 priv->init_reg_num = ARRAY_SIZE(rk817_init_reg); 248 priv->irq_reg = rk817_irq_reg; 249 priv->irq_reg_num = ARRAY_SIZE(rk817_irq_reg); 250 break; 251 default: 252 return -EINVAL; 253 } 254 255 /* mask and clear interrupt */ 256 for (i = 0; i < priv->init_reg_num; i++) { 257 ret = pmic_reg_write(dev->parent, 258 priv->init_reg[i].reg, 259 priv->init_reg[i].val); 260 if (ret < 0) { 261 printf("%s: i2c write reg 0x%x failed, ret=%d\n", 262 __func__, priv->init_reg[i].reg, ret); 263 return ret; 264 } 265 266 debug("%s: reg[%x] = 0x%x\n", __func__, priv->init_reg[i].reg, 267 pmic_reg_read(dev->parent, priv->init_reg[i].reg)); 268 } 269 270 return pwrkey_interrupt_init(dev); 271 } 272 273 U_BOOT_DRIVER(rk8xx_pwrkey) = { 274 .name = "rk8xx_pwrkey", 275 .id = UCLASS_KEY, 276 .ops = &key_ops, 277 .probe = rk8xx_pwrkey_probe, 278 .platdata_auto_alloc_size = sizeof(struct input_key), 279 .priv_auto_alloc_size = sizeof(struct rk8xx_key_priv), 280 }; 281