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

fsl_mpic_timer_wakeup.c (3255B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * MPIC timer wakeup driver
      4 *
      5 * Copyright 2013 Freescale Semiconductor, Inc.
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/slab.h>
     10#include <linux/errno.h>
     11#include <linux/module.h>
     12#include <linux/interrupt.h>
     13#include <linux/device.h>
     14
     15#include <asm/mpic_timer.h>
     16#include <asm/mpic.h>
     17
     18struct fsl_mpic_timer_wakeup {
     19	struct mpic_timer *timer;
     20	struct work_struct free_work;
     21};
     22
     23static struct fsl_mpic_timer_wakeup *fsl_wakeup;
     24static DEFINE_MUTEX(sysfs_lock);
     25
     26static void fsl_free_resource(struct work_struct *ws)
     27{
     28	struct fsl_mpic_timer_wakeup *wakeup =
     29		container_of(ws, struct fsl_mpic_timer_wakeup, free_work);
     30
     31	mutex_lock(&sysfs_lock);
     32
     33	if (wakeup->timer) {
     34		disable_irq_wake(wakeup->timer->irq);
     35		mpic_free_timer(wakeup->timer);
     36	}
     37
     38	wakeup->timer = NULL;
     39	mutex_unlock(&sysfs_lock);
     40}
     41
     42static irqreturn_t fsl_mpic_timer_irq(int irq, void *dev_id)
     43{
     44	struct fsl_mpic_timer_wakeup *wakeup = dev_id;
     45
     46	schedule_work(&wakeup->free_work);
     47
     48	return wakeup->timer ? IRQ_HANDLED : IRQ_NONE;
     49}
     50
     51static ssize_t fsl_timer_wakeup_show(struct device *dev,
     52				struct device_attribute *attr,
     53				char *buf)
     54{
     55	time64_t interval = 0;
     56
     57	mutex_lock(&sysfs_lock);
     58	if (fsl_wakeup->timer) {
     59		mpic_get_remain_time(fsl_wakeup->timer, &interval);
     60		interval++;
     61	}
     62	mutex_unlock(&sysfs_lock);
     63
     64	return sprintf(buf, "%lld\n", interval);
     65}
     66
     67static ssize_t fsl_timer_wakeup_store(struct device *dev,
     68				struct device_attribute *attr,
     69				const char *buf,
     70				size_t count)
     71{
     72	time64_t interval;
     73	int ret;
     74
     75	if (kstrtoll(buf, 0, &interval))
     76		return -EINVAL;
     77
     78	mutex_lock(&sysfs_lock);
     79
     80	if (fsl_wakeup->timer) {
     81		disable_irq_wake(fsl_wakeup->timer->irq);
     82		mpic_free_timer(fsl_wakeup->timer);
     83		fsl_wakeup->timer = NULL;
     84	}
     85
     86	if (!interval) {
     87		mutex_unlock(&sysfs_lock);
     88		return count;
     89	}
     90
     91	fsl_wakeup->timer = mpic_request_timer(fsl_mpic_timer_irq,
     92						fsl_wakeup, interval);
     93	if (!fsl_wakeup->timer) {
     94		mutex_unlock(&sysfs_lock);
     95		return -EINVAL;
     96	}
     97
     98	ret = enable_irq_wake(fsl_wakeup->timer->irq);
     99	if (ret) {
    100		mpic_free_timer(fsl_wakeup->timer);
    101		fsl_wakeup->timer = NULL;
    102		mutex_unlock(&sysfs_lock);
    103
    104		return ret;
    105	}
    106
    107	mpic_start_timer(fsl_wakeup->timer);
    108
    109	mutex_unlock(&sysfs_lock);
    110
    111	return count;
    112}
    113
    114static struct device_attribute mpic_attributes = __ATTR(timer_wakeup, 0644,
    115			fsl_timer_wakeup_show, fsl_timer_wakeup_store);
    116
    117static int __init fsl_wakeup_sys_init(void)
    118{
    119	int ret;
    120
    121	fsl_wakeup = kzalloc(sizeof(struct fsl_mpic_timer_wakeup), GFP_KERNEL);
    122	if (!fsl_wakeup)
    123		return -ENOMEM;
    124
    125	INIT_WORK(&fsl_wakeup->free_work, fsl_free_resource);
    126
    127	ret = device_create_file(mpic_subsys.dev_root, &mpic_attributes);
    128	if (ret)
    129		kfree(fsl_wakeup);
    130
    131	return ret;
    132}
    133
    134static void __exit fsl_wakeup_sys_exit(void)
    135{
    136	device_remove_file(mpic_subsys.dev_root, &mpic_attributes);
    137
    138	mutex_lock(&sysfs_lock);
    139
    140	if (fsl_wakeup->timer) {
    141		disable_irq_wake(fsl_wakeup->timer->irq);
    142		mpic_free_timer(fsl_wakeup->timer);
    143	}
    144
    145	kfree(fsl_wakeup);
    146
    147	mutex_unlock(&sysfs_lock);
    148}
    149
    150module_init(fsl_wakeup_sys_init);
    151module_exit(fsl_wakeup_sys_exit);
    152
    153MODULE_DESCRIPTION("Freescale MPIC global timer wakeup driver");
    154MODULE_LICENSE("GPL v2");
    155MODULE_AUTHOR("Wang Dongsheng <dongsheng.wang@freescale.com>");