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 <clk.h> 9 #include <dm.h> 10 #include <dm/pinctrl.h> 11 #include <errno.h> 12 #include <rc.h> 13 #include <rockchip_ir.h> 14 #include <irq-generic.h> 15 #include <irq-platform.h> 16 17 #include <linux/bitrev.h> 18 #include <linux/input.h> 19 20 #include <asm/arch/periph.h> 21 #include <asm/io.h> 22 #include <dm/ofnode.h> 23 DECLARE_GLOBAL_DATA_PTR; 24 25 static struct nec_dec nec; 26 static struct rc_map *rc_map; 27 28 static int rockchip_ir_get_keycode(struct udevice *dev) 29 { 30 struct rockchip_ir_priv *priv = dev_get_priv(dev); 31 32 return priv->keycode; 33 } 34 35 static int rockchip_ir_get_repeat(struct udevice *dev) 36 { 37 struct rockchip_ir_priv *priv = dev_get_priv(dev); 38 39 return priv->repeat; 40 } 41 42 static int ir_lookup_by_scancode(struct rockchip_ir_priv *priv, 43 u32 usercode, 44 u32 scancode) 45 { 46 int i, j; 47 48 for (i = 0; i < priv->num; i++) { 49 if (rc_map[i].usercode == usercode) 50 break; 51 } 52 for (j = 0; i < priv->num && j < rc_map[i].nbuttons; j++) { 53 if (rc_map[i].scan[j].scancode == scancode) { 54 if (priv->keycode == rc_map[i].scan[j].keycode) 55 priv->repeat++; 56 else 57 priv->repeat = 0; 58 priv->keycode = rc_map[i].scan[j].keycode; 59 return 0; 60 } 61 } 62 63 priv->keycode = KEY_RESERVED; 64 priv->repeat = 0; 65 66 return -1; 67 } 68 69 static int ir_parse_keys(struct udevice *dev) 70 { 71 int i, j; 72 int len; 73 int ret; 74 u32 val; 75 ofnode node; 76 77 i = 0; 78 dev_for_each_subnode(node, dev) { 79 ret = ofnode_read_u32(node, "rockchip,usercode", &val); 80 if (ret) { 81 debug("unable to get usercode\n"); 82 return -1; 83 } 84 rc_map[i].usercode = val; 85 if (rc_map[i].usercode == 0) { 86 debug("missing usercode property in the dts\n"); 87 return -1; 88 } 89 debug("add new usercode:0x%x\n", rc_map[i].usercode); 90 len = ofnode_read_size(node, "rockchip,key_table"); 91 len /= sizeof(u32); 92 debug("len:%d\n", len); 93 rc_map[i].nbuttons = len / 2; 94 95 ret = ofnode_read_u32_array(node, "rockchip,key_table", 96 (u32 *)rc_map[i].scan, len); 97 if (ret) { 98 debug("missing key_table property in the dts\n"); 99 return -1; 100 } 101 for (j = 0; j < (len / 2); j++) { 102 debug("[%d],usercode=0x%x scancode=0x%x keycode=0x%x\n", 103 i, 104 rc_map[i].usercode, 105 rc_map[i].scan[j].scancode, 106 rc_map[i].scan[j].keycode); 107 } 108 i++; 109 } 110 111 return 0; 112 } 113 114 /** 115 * ir_nec_decode() - Decode one NEC pulse or space 116 * @duration: the struct ir_raw_event descriptor of the pulse/space 117 */ 118 static int ir_nec_decode(struct rockchip_ir_priv *priv, struct ir_raw_event *ev) 119 { 120 int ret; 121 u32 usercode; 122 u32 scancode; 123 u8 __maybe_unused address, not_address, command, not_command; 124 struct nec_dec *data = &nec; 125 126 switch (data->state) { 127 case STATE_INACTIVE: 128 if (!ev->pulse) 129 break; 130 131 if (!eq_margin(ev->duration, NEC_HEADER_PULSE, NEC_UNIT * 2)) 132 break; 133 134 data->count = 0; 135 data->state = STATE_HEADER_SPACE; 136 return 0; 137 138 case STATE_HEADER_SPACE: 139 if (ev->pulse) 140 break; 141 142 if (eq_margin(ev->duration, NEC_HEADER_SPACE, NEC_UNIT)) { 143 data->state = STATE_BIT_PULSE; 144 return 0; 145 } 146 147 break; 148 149 case STATE_BIT_PULSE: 150 if (!ev->pulse) 151 break; 152 153 if (!eq_margin(ev->duration, NEC_BIT_PULSE, NEC_UNIT / 2)) 154 break; 155 156 data->state = STATE_BIT_SPACE; 157 return 0; 158 159 case STATE_BIT_SPACE: 160 if (ev->pulse) 161 break; 162 163 data->bits <<= 1; 164 if (eq_margin(ev->duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) { 165 data->bits |= 1; 166 } else if (!eq_margin(ev->duration, NEC_BIT_0_SPACE, 167 NEC_UNIT / 2)) { 168 break; 169 } 170 data->count++; 171 172 if (data->count == NEC_NBITS) { 173 address = ((data->bits >> 24) & 0xff); 174 not_address = ((data->bits >> 16) & 0xff); 175 command = ((data->bits >> 8) & 0xff); 176 not_command = ((data->bits >> 0) & 0xff); 177 178 if ((command ^ not_command) != 0xff) { 179 debug("NEC checksum error: received 0x%08x\n", 180 data->bits); 181 } 182 usercode = address << 8 | not_address; 183 scancode = command << 8 | not_command; 184 185 /* change to dts format */ 186 usercode = bitrev16(usercode); 187 scancode = (bitrev16(scancode) >> 8) & 0xFF; 188 debug("usercode 0x%04x scancode 0x%04x\n", 189 usercode, scancode); 190 191 data->state = STATE_INACTIVE; 192 ret = ir_lookup_by_scancode(priv, usercode, scancode); 193 if (!ret) 194 debug("keycode 0x%02x repeat 0x%x\n", 195 priv->keycode, priv->repeat); 196 else 197 debug("ir lookup by scancode failed\n"); 198 } else { 199 data->state = STATE_BIT_PULSE; 200 } 201 202 return 0; 203 } 204 205 debug("NEC decode failed at count %d state %d (%uus %s)\n", 206 data->count, data->state, TO_US(ev->duration), TO_STR(ev->pulse)); 207 data->state = STATE_INACTIVE; 208 209 return -1; 210 } 211 212 static void rockchip_ir_irq(int irq, void *data) 213 { 214 u32 val; 215 u32 cycle_hpr, cycle_lpr, cycle; 216 struct ir_raw_event ev; 217 struct rockchip_ir_priv *priv = (struct rockchip_ir_priv *)data; 218 219 val = readl(priv->base + PWM_STA_REG(priv->id)); 220 cycle_hpr = readl(priv->base + PWM_HPR_REG); 221 cycle_lpr = readl(priv->base + PWM_LPR_REG); 222 if (val & PWM_CH_POL(priv->id)) { 223 cycle = cycle_hpr; 224 ev.pulse = 0; 225 } else { 226 cycle = cycle_lpr; 227 ev.pulse = 1; 228 } 229 writel(PWM_CH_INT(priv->id), 230 priv->base + PWM_STA_REG(priv->id)); 231 232 ev.duration = cycle * priv->period; 233 ir_nec_decode(priv, &ev); 234 } 235 236 static void rockchip_ir_hw_init(struct udevice *dev) 237 { 238 unsigned long tmp; 239 struct rockchip_ir_priv *priv = dev_get_priv(dev); 240 241 /* Enable capture mode, non-scaled clock, prescale 1 */ 242 writel(REG_CTL_MD, priv->base + PWM_CTL_REG); 243 244 /* Clear Interrupt Status */ 245 writel(PWM_CH_INT(priv->id), 246 priv->base + PWM_STA_REG(priv->id)); 247 248 /* Enable IRQ */ 249 writel(PWM_CH_INT(priv->id), 250 priv->base + PWM_INT_REG(priv->id)); 251 252 /* Enable IR Module */ 253 tmp = readl(priv->base + PWM_CTL_REG); 254 writel(tmp | REG_CTL_EN, priv->base + PWM_CTL_REG); 255 } 256 257 static int rockchip_ir_ofdata_to_platdata(struct udevice *dev) 258 { 259 ofnode node; 260 int ret; 261 int subnode_num = 0; 262 u32 val; 263 struct rockchip_ir_priv *priv = dev_get_priv(dev); 264 265 dev_for_each_subnode(node, dev) { 266 ret = ofnode_read_u32(node, "rockchip,usercode", &val); 267 if (!ret) 268 subnode_num++; 269 } 270 271 priv->num = subnode_num; 272 273 if (priv->num == 0) { 274 debug("no ir map in dts\n"); 275 return -1; 276 } 277 priv->base = dev_read_addr(dev); 278 priv->id = (priv->base >> 4) & 0xF; 279 280 return 0; 281 } 282 283 static int rockchip_ir_probe(struct udevice *dev) 284 { 285 int ret; 286 struct clk clk; 287 struct udevice *pinctrl; 288 struct rockchip_ir_priv *priv = dev_get_priv(dev); 289 290 rc_map = calloc(1, priv->num * sizeof(struct rc_map)); 291 if (!rc_map) { 292 debug("%s: failed to calloc\n", __func__); 293 return -EINVAL; 294 } 295 296 ret = ir_parse_keys(dev); 297 if (ret) { 298 debug("%s: failed to parse keys\n", __func__); 299 return -EINVAL; 300 } 301 /* 302 * The PWM does not have decicated interrupt number in dts and can 303 * not get periph_id by pinctrl framework, so let's init then here. 304 */ 305 ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 306 if (ret) { 307 debug("%s: can't find pinctrl device\n", __func__); 308 return -EINVAL; 309 } 310 311 ret = clk_get_by_index(dev, 0, &clk); 312 if (ret) { 313 debug("%s get clock fail!\n", __func__); 314 return -EINVAL; 315 } 316 priv->freq = clk_get_rate(&clk); 317 debug("%s pwm clk = %lu\n", __func__, priv->freq); 318 priv->period = 1000000000 / priv->freq; 319 320 irq_install_handler(IRQ_PWM, 321 (interrupt_handler_t *)rockchip_ir_irq, priv); 322 irq_handler_enable(IRQ_PWM); 323 324 rockchip_ir_hw_init(dev); 325 326 return ret; 327 } 328 329 static const struct dm_rc_ops rockchip_ir_ops = { 330 .get_keycode = rockchip_ir_get_keycode, 331 .get_repeat = rockchip_ir_get_repeat, 332 }; 333 334 static const struct udevice_id rockchip_ir_ids[] = { 335 { .compatible = "rockchip,remotectl-pwm" }, 336 { } 337 }; 338 339 U_BOOT_DRIVER(rockchip_ir) = { 340 .name = "rockchip_ir", 341 .id = UCLASS_RC, 342 .of_match = rockchip_ir_ids, 343 .ofdata_to_platdata = rockchip_ir_ofdata_to_platdata, 344 .probe = rockchip_ir_probe, 345 .ops = &rockchip_ir_ops, 346 .priv_auto_alloc_size = sizeof(struct rockchip_ir_priv), 347 }; 348