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

st_rc.c (11302B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2013 STMicroelectronics Limited
      4 * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
      5 */
      6#include <linux/kernel.h>
      7#include <linux/clk.h>
      8#include <linux/interrupt.h>
      9#include <linux/module.h>
     10#include <linux/of.h>
     11#include <linux/platform_device.h>
     12#include <linux/reset.h>
     13#include <media/rc-core.h>
     14#include <linux/pinctrl/consumer.h>
     15#include <linux/pm_wakeirq.h>
     16
     17struct st_rc_device {
     18	struct device			*dev;
     19	int				irq;
     20	int				irq_wake;
     21	struct clk			*sys_clock;
     22	void __iomem			*base;	/* Register base address */
     23	void __iomem			*rx_base;/* RX Register base address */
     24	struct rc_dev			*rdev;
     25	bool				overclocking;
     26	int				sample_mult;
     27	int				sample_div;
     28	bool				rxuhfmode;
     29	struct	reset_control		*rstc;
     30};
     31
     32/* Registers */
     33#define IRB_SAMPLE_RATE_COMM	0x64	/* sample freq divisor*/
     34#define IRB_CLOCK_SEL		0x70	/* clock select       */
     35#define IRB_CLOCK_SEL_STATUS	0x74	/* clock status       */
     36/* IRB IR/UHF receiver registers */
     37#define IRB_RX_ON               0x40	/* pulse time capture */
     38#define IRB_RX_SYS              0X44	/* sym period capture */
     39#define IRB_RX_INT_EN           0x48	/* IRQ enable (R/W)   */
     40#define IRB_RX_INT_STATUS       0x4c	/* IRQ status (R/W)   */
     41#define IRB_RX_EN               0x50	/* Receive enable     */
     42#define IRB_MAX_SYM_PERIOD      0x54	/* max sym value      */
     43#define IRB_RX_INT_CLEAR        0x58	/* overrun status     */
     44#define IRB_RX_STATUS           0x6c	/* receive status     */
     45#define IRB_RX_NOISE_SUPPR      0x5c	/* noise suppression  */
     46#define IRB_RX_POLARITY_INV     0x68	/* polarity inverter  */
     47
     48/*
     49 * IRQ set: Enable full FIFO                 1  -> bit  3;
     50 *          Enable overrun IRQ               1  -> bit  2;
     51 *          Enable last symbol IRQ           1  -> bit  1:
     52 *          Enable RX interrupt              1  -> bit  0;
     53 */
     54#define IRB_RX_INTS		0x0f
     55#define IRB_RX_OVERRUN_INT	0x04
     56 /* maximum symbol period (microsecs),timeout to detect end of symbol train */
     57#define MAX_SYMB_TIME		0x5000
     58#define IRB_SAMPLE_FREQ		10000000
     59#define	IRB_FIFO_NOT_EMPTY	0xff00
     60#define IRB_OVERFLOW		0x4
     61#define IRB_TIMEOUT		0xffff
     62#define IR_ST_NAME "st-rc"
     63
     64static void st_rc_send_lirc_timeout(struct rc_dev *rdev)
     65{
     66	struct ir_raw_event ev = { .timeout = true, .duration = rdev->timeout };
     67	ir_raw_event_store(rdev, &ev);
     68}
     69
     70/*
     71 * RX graphical example to better understand the difference between ST IR block
     72 * output and standard definition used by LIRC (and most of the world!)
     73 *
     74 *           mark                                     mark
     75 *      |-IRB_RX_ON-|                            |-IRB_RX_ON-|
     76 *      ___  ___  ___                            ___  ___  ___             _
     77 *      | |  | |  | |                            | |  | |  | |             |
     78 *      | |  | |  | |         space 0            | |  | |  | |   space 1   |
     79 * _____| |__| |__| |____________________________| |__| |__| |_____________|
     80 *
     81 *      |--------------- IRB_RX_SYS -------------|------ IRB_RX_SYS -------|
     82 *
     83 *      |------------- encoding bit 0 -----------|---- encoding bit 1 -----|
     84 *
     85 * ST hardware returns mark (IRB_RX_ON) and total symbol time (IRB_RX_SYS), so
     86 * convert to standard mark/space we have to calculate space=(IRB_RX_SYS-mark)
     87 * The mark time represents the amount of time the carrier (usually 36-40kHz)
     88 * is detected.The above examples shows Pulse Width Modulation encoding where
     89 * bit 0 is represented by space>mark.
     90 */
     91
     92static irqreturn_t st_rc_rx_interrupt(int irq, void *data)
     93{
     94	unsigned long timeout;
     95	unsigned int symbol, mark = 0;
     96	struct st_rc_device *dev = data;
     97	int last_symbol = 0;
     98	u32 status, int_status;
     99	struct ir_raw_event ev = {};
    100
    101	if (dev->irq_wake)
    102		pm_wakeup_event(dev->dev, 0);
    103
    104	/* FIXME: is 10ms good enough ? */
    105	timeout = jiffies +  msecs_to_jiffies(10);
    106	do {
    107		status  = readl(dev->rx_base + IRB_RX_STATUS);
    108		if (!(status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW)))
    109			break;
    110
    111		int_status = readl(dev->rx_base + IRB_RX_INT_STATUS);
    112		if (unlikely(int_status & IRB_RX_OVERRUN_INT)) {
    113			/* discard the entire collection in case of errors!  */
    114			ir_raw_event_overflow(dev->rdev);
    115			dev_info(dev->dev, "IR RX overrun\n");
    116			writel(IRB_RX_OVERRUN_INT,
    117					dev->rx_base + IRB_RX_INT_CLEAR);
    118			continue;
    119		}
    120
    121		symbol = readl(dev->rx_base + IRB_RX_SYS);
    122		mark = readl(dev->rx_base + IRB_RX_ON);
    123
    124		if (symbol == IRB_TIMEOUT)
    125			last_symbol = 1;
    126
    127		 /* Ignore any noise */
    128		if ((mark > 2) && (symbol > 1)) {
    129			symbol -= mark;
    130			if (dev->overclocking) { /* adjustments to timings */
    131				symbol *= dev->sample_mult;
    132				symbol /= dev->sample_div;
    133				mark *= dev->sample_mult;
    134				mark /= dev->sample_div;
    135			}
    136
    137			ev.duration = mark;
    138			ev.pulse = true;
    139			ir_raw_event_store(dev->rdev, &ev);
    140
    141			if (!last_symbol) {
    142				ev.duration = symbol;
    143				ev.pulse = false;
    144				ir_raw_event_store(dev->rdev, &ev);
    145			} else  {
    146				st_rc_send_lirc_timeout(dev->rdev);
    147			}
    148
    149		}
    150		last_symbol = 0;
    151	} while (time_is_after_jiffies(timeout));
    152
    153	writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_CLEAR);
    154
    155	/* Empty software fifo */
    156	ir_raw_event_handle(dev->rdev);
    157	return IRQ_HANDLED;
    158}
    159
    160static int st_rc_hardware_init(struct st_rc_device *dev)
    161{
    162	int ret;
    163	int baseclock, freqdiff;
    164	unsigned int rx_max_symbol_per = MAX_SYMB_TIME;
    165	unsigned int rx_sampling_freq_div;
    166
    167	/* Enable the IP */
    168	reset_control_deassert(dev->rstc);
    169
    170	ret = clk_prepare_enable(dev->sys_clock);
    171	if (ret) {
    172		dev_err(dev->dev, "Failed to prepare/enable system clock\n");
    173		return ret;
    174	}
    175
    176	baseclock = clk_get_rate(dev->sys_clock);
    177
    178	/* IRB input pins are inverted internally from high to low. */
    179	writel(1, dev->rx_base + IRB_RX_POLARITY_INV);
    180
    181	rx_sampling_freq_div = baseclock / IRB_SAMPLE_FREQ;
    182	writel(rx_sampling_freq_div, dev->base + IRB_SAMPLE_RATE_COMM);
    183
    184	freqdiff = baseclock - (rx_sampling_freq_div * IRB_SAMPLE_FREQ);
    185	if (freqdiff) { /* over clocking, workout the adjustment factors */
    186		dev->overclocking = true;
    187		dev->sample_mult = 1000;
    188		dev->sample_div = baseclock / (10000 * rx_sampling_freq_div);
    189		rx_max_symbol_per = (rx_max_symbol_per * 1000)/dev->sample_div;
    190	}
    191
    192	writel(rx_max_symbol_per, dev->rx_base + IRB_MAX_SYM_PERIOD);
    193
    194	return 0;
    195}
    196
    197static int st_rc_remove(struct platform_device *pdev)
    198{
    199	struct st_rc_device *rc_dev = platform_get_drvdata(pdev);
    200
    201	dev_pm_clear_wake_irq(&pdev->dev);
    202	device_init_wakeup(&pdev->dev, false);
    203	clk_disable_unprepare(rc_dev->sys_clock);
    204	rc_unregister_device(rc_dev->rdev);
    205	return 0;
    206}
    207
    208static int st_rc_open(struct rc_dev *rdev)
    209{
    210	struct st_rc_device *dev = rdev->priv;
    211	unsigned long flags;
    212	local_irq_save(flags);
    213	/* enable interrupts and receiver */
    214	writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_EN);
    215	writel(0x01, dev->rx_base + IRB_RX_EN);
    216	local_irq_restore(flags);
    217
    218	return 0;
    219}
    220
    221static void st_rc_close(struct rc_dev *rdev)
    222{
    223	struct st_rc_device *dev = rdev->priv;
    224	/* disable interrupts and receiver */
    225	writel(0x00, dev->rx_base + IRB_RX_EN);
    226	writel(0x00, dev->rx_base + IRB_RX_INT_EN);
    227}
    228
    229static int st_rc_probe(struct platform_device *pdev)
    230{
    231	int ret = -EINVAL;
    232	struct rc_dev *rdev;
    233	struct device *dev = &pdev->dev;
    234	struct st_rc_device *rc_dev;
    235	struct device_node *np = pdev->dev.of_node;
    236	const char *rx_mode;
    237
    238	rc_dev = devm_kzalloc(dev, sizeof(struct st_rc_device), GFP_KERNEL);
    239
    240	if (!rc_dev)
    241		return -ENOMEM;
    242
    243	rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
    244
    245	if (!rdev)
    246		return -ENOMEM;
    247
    248	if (np && !of_property_read_string(np, "rx-mode", &rx_mode)) {
    249
    250		if (!strcmp(rx_mode, "uhf")) {
    251			rc_dev->rxuhfmode = true;
    252		} else if (!strcmp(rx_mode, "infrared")) {
    253			rc_dev->rxuhfmode = false;
    254		} else {
    255			dev_err(dev, "Unsupported rx mode [%s]\n", rx_mode);
    256			goto err;
    257		}
    258
    259	} else {
    260		goto err;
    261	}
    262
    263	rc_dev->sys_clock = devm_clk_get(dev, NULL);
    264	if (IS_ERR(rc_dev->sys_clock)) {
    265		dev_err(dev, "System clock not found\n");
    266		ret = PTR_ERR(rc_dev->sys_clock);
    267		goto err;
    268	}
    269
    270	rc_dev->irq = platform_get_irq(pdev, 0);
    271	if (rc_dev->irq < 0) {
    272		ret = rc_dev->irq;
    273		goto err;
    274	}
    275
    276	rc_dev->base = devm_platform_ioremap_resource(pdev, 0);
    277	if (IS_ERR(rc_dev->base)) {
    278		ret = PTR_ERR(rc_dev->base);
    279		goto err;
    280	}
    281
    282	if (rc_dev->rxuhfmode)
    283		rc_dev->rx_base = rc_dev->base + 0x40;
    284	else
    285		rc_dev->rx_base = rc_dev->base;
    286
    287	rc_dev->rstc = reset_control_get_optional_exclusive(dev, NULL);
    288	if (IS_ERR(rc_dev->rstc)) {
    289		ret = PTR_ERR(rc_dev->rstc);
    290		goto err;
    291	}
    292
    293	rc_dev->dev = dev;
    294	platform_set_drvdata(pdev, rc_dev);
    295	ret = st_rc_hardware_init(rc_dev);
    296	if (ret)
    297		goto err;
    298
    299	rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
    300	/* rx sampling rate is 10Mhz */
    301	rdev->rx_resolution = 100;
    302	rdev->timeout = MAX_SYMB_TIME;
    303	rdev->priv = rc_dev;
    304	rdev->open = st_rc_open;
    305	rdev->close = st_rc_close;
    306	rdev->driver_name = IR_ST_NAME;
    307	rdev->map_name = RC_MAP_EMPTY;
    308	rdev->device_name = "ST Remote Control Receiver";
    309
    310	ret = rc_register_device(rdev);
    311	if (ret < 0)
    312		goto clkerr;
    313
    314	rc_dev->rdev = rdev;
    315	if (devm_request_irq(dev, rc_dev->irq, st_rc_rx_interrupt,
    316			     0, IR_ST_NAME, rc_dev) < 0) {
    317		dev_err(dev, "IRQ %d register failed\n", rc_dev->irq);
    318		ret = -EINVAL;
    319		goto rcerr;
    320	}
    321
    322	/* enable wake via this device */
    323	device_init_wakeup(dev, true);
    324	dev_pm_set_wake_irq(dev, rc_dev->irq);
    325
    326	/*
    327	 * for LIRC_MODE_MODE2 or LIRC_MODE_PULSE or LIRC_MODE_RAW
    328	 * lircd expects a long space first before a signal train to sync.
    329	 */
    330	st_rc_send_lirc_timeout(rdev);
    331
    332	dev_info(dev, "setup in %s mode\n", rc_dev->rxuhfmode ? "UHF" : "IR");
    333
    334	return ret;
    335rcerr:
    336	rc_unregister_device(rdev);
    337	rdev = NULL;
    338clkerr:
    339	clk_disable_unprepare(rc_dev->sys_clock);
    340err:
    341	rc_free_device(rdev);
    342	dev_err(dev, "Unable to register device (%d)\n", ret);
    343	return ret;
    344}
    345
    346#ifdef CONFIG_PM_SLEEP
    347static int st_rc_suspend(struct device *dev)
    348{
    349	struct st_rc_device *rc_dev = dev_get_drvdata(dev);
    350
    351	if (device_may_wakeup(dev)) {
    352		if (!enable_irq_wake(rc_dev->irq))
    353			rc_dev->irq_wake = 1;
    354		else
    355			return -EINVAL;
    356	} else {
    357		pinctrl_pm_select_sleep_state(dev);
    358		writel(0x00, rc_dev->rx_base + IRB_RX_EN);
    359		writel(0x00, rc_dev->rx_base + IRB_RX_INT_EN);
    360		clk_disable_unprepare(rc_dev->sys_clock);
    361		reset_control_assert(rc_dev->rstc);
    362	}
    363
    364	return 0;
    365}
    366
    367static int st_rc_resume(struct device *dev)
    368{
    369	int ret;
    370	struct st_rc_device *rc_dev = dev_get_drvdata(dev);
    371	struct rc_dev	*rdev = rc_dev->rdev;
    372
    373	if (rc_dev->irq_wake) {
    374		disable_irq_wake(rc_dev->irq);
    375		rc_dev->irq_wake = 0;
    376	} else {
    377		pinctrl_pm_select_default_state(dev);
    378		ret = st_rc_hardware_init(rc_dev);
    379		if (ret)
    380			return ret;
    381
    382		if (rdev->users) {
    383			writel(IRB_RX_INTS, rc_dev->rx_base + IRB_RX_INT_EN);
    384			writel(0x01, rc_dev->rx_base + IRB_RX_EN);
    385		}
    386	}
    387
    388	return 0;
    389}
    390
    391#endif
    392
    393static SIMPLE_DEV_PM_OPS(st_rc_pm_ops, st_rc_suspend, st_rc_resume);
    394
    395#ifdef CONFIG_OF
    396static const struct of_device_id st_rc_match[] = {
    397	{ .compatible = "st,comms-irb", },
    398	{},
    399};
    400
    401MODULE_DEVICE_TABLE(of, st_rc_match);
    402#endif
    403
    404static struct platform_driver st_rc_driver = {
    405	.driver = {
    406		.name = IR_ST_NAME,
    407		.of_match_table = of_match_ptr(st_rc_match),
    408		.pm     = &st_rc_pm_ops,
    409	},
    410	.probe = st_rc_probe,
    411	.remove = st_rc_remove,
    412};
    413
    414module_platform_driver(st_rc_driver);
    415
    416MODULE_DESCRIPTION("RC Transceiver driver for STMicroelectronics platforms");
    417MODULE_AUTHOR("STMicroelectronics (R&D) Ltd");
    418MODULE_LICENSE("GPL");