brintos

brintos / linux-shallow public Read only

0
0
Text · 2.2 KiB · a363f77 Raw
96 lines · c
1/*2 * Support for hardware-assisted userspace interrupt masking.3 *4 * Copyright (C) 2010  Paul Mundt5 *6 * This file is subject to the terms and conditions of the GNU General Public7 * License.  See the file "COPYING" in the main directory of this archive8 * for more details.9 */10#define pr_fmt(fmt) "intc: " fmt11 12#include <linux/errno.h>13#include <linux/device.h>14#include <linux/init.h>15#include <linux/io.h>16#include <linux/stat.h>17#include <linux/sizes.h>18#include "internals.h"19 20static void __iomem *uimask;21 22static ssize_t23show_intc_userimask(struct device *dev,24		    struct device_attribute *attr, char *buf)25{26	return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf);27}28 29static ssize_t30store_intc_userimask(struct device *dev,31		     struct device_attribute *attr,32		     const char *buf, size_t count)33{34	unsigned long level;35	int ret;36 37	ret = kstrtoul(buf, 10, &level);38	if (ret != 0)39		return ret;40 41	/*42	 * Minimal acceptable IRQ levels are in the 2 - 16 range, but43	 * these are chomped so as to not interfere with normal IRQs.44	 *45	 * Level 1 is a special case on some CPUs in that it's not46	 * directly settable, but given that USERIMASK cuts off below a47	 * certain level, we don't care about this limitation here.48	 * Level 0 on the other hand equates to user masking disabled.49	 *50	 * We use the default priority level as a cut off so that only51	 * special case opt-in IRQs can be mangled.52	 */53	if (level >= intc_get_dfl_prio_level())54		return -EINVAL;55 56	__raw_writel(0xa5 << 24 | level << 4, uimask);57 58	return count;59}60 61static DEVICE_ATTR(userimask, S_IRUSR | S_IWUSR,62		   show_intc_userimask, store_intc_userimask);63 64 65static int __init userimask_sysdev_init(void)66{67	struct device *dev_root;68	int ret = 0;69 70	if (unlikely(!uimask))71		return -ENXIO;72 73	dev_root = bus_get_dev_root(&intc_subsys);74	if (dev_root) {75		ret = device_create_file(dev_root, &dev_attr_userimask);76		put_device(dev_root);77	}78	return ret;79}80late_initcall(userimask_sysdev_init);81 82int register_intc_userimask(unsigned long addr)83{84	if (unlikely(uimask))85		return -EBUSY;86 87	uimask = ioremap(addr, SZ_4K);88	if (unlikely(!uimask))89		return -ENOMEM;90 91	pr_info("userimask support registered for levels 0 -> %d\n",92		intc_get_dfl_prio_level() - 1);93 94	return 0;95}96