cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

img-ir-raw.c (3917B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * ImgTec IR Raw Decoder found in PowerDown Controller.
      4 *
      5 * Copyright 2010-2014 Imagination Technologies Ltd.
      6 *
      7 * This ties into the input subsystem using the RC-core in raw mode. Raw IR
      8 * signal edges are reported and decoded by generic software decoders.
      9 */
     10
     11#include <linux/spinlock.h>
     12#include <media/rc-core.h>
     13#include "img-ir.h"
     14
     15#define ECHO_TIMEOUT_MS 150	/* ms between echos */
     16
     17/* must be called with priv->lock held */
     18static void img_ir_refresh_raw(struct img_ir_priv *priv, u32 irq_status)
     19{
     20	struct img_ir_priv_raw *raw = &priv->raw;
     21	struct rc_dev *rc_dev = priv->raw.rdev;
     22	int multiple;
     23	u32 ir_status;
     24
     25	/* find whether both rise and fall was detected */
     26	multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE);
     27	/*
     28	 * If so, we need to see if the level has actually changed.
     29	 * If it's just noise that we didn't have time to process,
     30	 * there's no point reporting it.
     31	 */
     32	ir_status = img_ir_read(priv, IMG_IR_STATUS) & IMG_IR_IRRXD;
     33	if (multiple && ir_status == raw->last_status)
     34		return;
     35	raw->last_status = ir_status;
     36
     37	/* report the edge to the IR raw decoders */
     38	if (ir_status) /* low */
     39		ir_raw_event_store_edge(rc_dev, false);
     40	else /* high */
     41		ir_raw_event_store_edge(rc_dev, true);
     42	ir_raw_event_handle(rc_dev);
     43}
     44
     45/* called with priv->lock held */
     46void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
     47{
     48	struct img_ir_priv_raw *raw = &priv->raw;
     49
     50	/* check not removing */
     51	if (!raw->rdev)
     52		return;
     53
     54	img_ir_refresh_raw(priv, irq_status);
     55
     56	/* start / push back the echo timer */
     57	mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS));
     58}
     59
     60/*
     61 * Echo timer callback function.
     62 * The raw decoders expect to get a final sample even if there are no edges, in
     63 * order to be assured of the final space. If there are no edges for a certain
     64 * time we use this timer to emit a final sample to satisfy them.
     65 */
     66static void img_ir_echo_timer(struct timer_list *t)
     67{
     68	struct img_ir_priv *priv = from_timer(priv, t, raw.timer);
     69
     70	spin_lock_irq(&priv->lock);
     71
     72	/* check not removing */
     73	if (priv->raw.rdev)
     74		/*
     75		 * It's safe to pass irq_status=0 since it's only used to check
     76		 * for double edges.
     77		 */
     78		img_ir_refresh_raw(priv, 0);
     79
     80	spin_unlock_irq(&priv->lock);
     81}
     82
     83void img_ir_setup_raw(struct img_ir_priv *priv)
     84{
     85	u32 irq_en;
     86
     87	if (!priv->raw.rdev)
     88		return;
     89
     90	/* clear and enable edge interrupts */
     91	spin_lock_irq(&priv->lock);
     92	irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
     93	irq_en |= IMG_IR_IRQ_EDGE;
     94	img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
     95	img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
     96	spin_unlock_irq(&priv->lock);
     97}
     98
     99int img_ir_probe_raw(struct img_ir_priv *priv)
    100{
    101	struct img_ir_priv_raw *raw = &priv->raw;
    102	struct rc_dev *rdev;
    103	int error;
    104
    105	/* Set up the echo timer */
    106	timer_setup(&raw->timer, img_ir_echo_timer, 0);
    107
    108	/* Allocate raw decoder */
    109	raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
    110	if (!rdev) {
    111		dev_err(priv->dev, "cannot allocate raw input device\n");
    112		return -ENOMEM;
    113	}
    114	rdev->priv = priv;
    115	rdev->map_name = RC_MAP_EMPTY;
    116	rdev->device_name = "IMG Infrared Decoder Raw";
    117
    118	/* Register raw decoder */
    119	error = rc_register_device(rdev);
    120	if (error) {
    121		dev_err(priv->dev, "failed to register raw IR input device\n");
    122		rc_free_device(rdev);
    123		raw->rdev = NULL;
    124		return error;
    125	}
    126
    127	return 0;
    128}
    129
    130void img_ir_remove_raw(struct img_ir_priv *priv)
    131{
    132	struct img_ir_priv_raw *raw = &priv->raw;
    133	struct rc_dev *rdev = raw->rdev;
    134	u32 irq_en;
    135
    136	if (!rdev)
    137		return;
    138
    139	/* switch off and disable raw (edge) interrupts */
    140	spin_lock_irq(&priv->lock);
    141	raw->rdev = NULL;
    142	irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
    143	irq_en &= ~IMG_IR_IRQ_EDGE;
    144	img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
    145	img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
    146	spin_unlock_irq(&priv->lock);
    147
    148	rc_unregister_device(rdev);
    149
    150	del_timer_sync(&raw->timer);
    151}