brintos

brintos / linux-shallow public Read only

0
0
Text · 6.5 KiB · 114390f Raw
247 lines · c
1/*2 * Common INTC2 register accessors3 *4 * Copyright (C) 2007, 2008 Magnus Damm5 * Copyright (C) 2009, 2010 Paul Mundt6 *7 * This file is subject to the terms and conditions of the GNU General Public8 * License.  See the file "COPYING" in the main directory of this archive9 * for more details.10 */11#include <linux/io.h>12#include "internals.h"13 14unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address)15{16	struct intc_window *window;17	int k;18 19	/* scan through physical windows and convert address */20	for (k = 0; k < d->nr_windows; k++) {21		window = d->window + k;22 23		if (address < window->phys)24			continue;25 26		if (address >= (window->phys + window->size))27			continue;28 29		address -= window->phys;30		address += (unsigned long)window->virt;31 32		return address;33	}34 35	/* no windows defined, register must be 1:1 mapped virt:phys */36	return address;37}38 39unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address)40{41	unsigned int k;42 43	address = intc_phys_to_virt(d, address);44 45	for (k = 0; k < d->nr_reg; k++) {46		if (d->reg[k] == address)47			return k;48	}49 50	BUG();51	return 0;52}53 54unsigned int intc_set_field_from_handle(unsigned int value,55					unsigned int field_value,56					unsigned int handle)57{58	unsigned int width = _INTC_WIDTH(handle);59	unsigned int shift = _INTC_SHIFT(handle);60 61	value &= ~(((1 << width) - 1) << shift);62	value |= field_value << shift;63	return value;64}65 66unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle)67{68	unsigned int width = _INTC_WIDTH(handle);69	unsigned int shift = _INTC_SHIFT(handle);70	unsigned int mask = ((1 << width) - 1) << shift;71 72	return (value & mask) >> shift;73}74 75static unsigned long test_8(unsigned long addr, unsigned long h,76			    unsigned long ignore)77{78	void __iomem *ptr = (void __iomem *)addr;79	return intc_get_field_from_handle(__raw_readb(ptr), h);80}81 82static unsigned long test_16(unsigned long addr, unsigned long h,83			     unsigned long ignore)84{85	void __iomem *ptr = (void __iomem *)addr;86	return intc_get_field_from_handle(__raw_readw(ptr), h);87}88 89static unsigned long test_32(unsigned long addr, unsigned long h,90			     unsigned long ignore)91{92	void __iomem *ptr = (void __iomem *)addr;93	return intc_get_field_from_handle(__raw_readl(ptr), h);94}95 96static unsigned long write_8(unsigned long addr, unsigned long h,97			     unsigned long data)98{99	void __iomem *ptr = (void __iomem *)addr;100	__raw_writeb(intc_set_field_from_handle(0, data, h), ptr);101	(void)__raw_readb(ptr);	/* Defeat write posting */102	return 0;103}104 105static unsigned long write_16(unsigned long addr, unsigned long h,106			      unsigned long data)107{108	void __iomem *ptr = (void __iomem *)addr;109	__raw_writew(intc_set_field_from_handle(0, data, h), ptr);110	(void)__raw_readw(ptr);	/* Defeat write posting */111	return 0;112}113 114static unsigned long write_32(unsigned long addr, unsigned long h,115			      unsigned long data)116{117	void __iomem *ptr = (void __iomem *)addr;118	__raw_writel(intc_set_field_from_handle(0, data, h), ptr);119	(void)__raw_readl(ptr);	/* Defeat write posting */120	return 0;121}122 123static unsigned long modify_8(unsigned long addr, unsigned long h,124			      unsigned long data)125{126	void __iomem *ptr = (void __iomem *)addr;127	unsigned long flags;128	unsigned int value;129	local_irq_save(flags);130	value = intc_set_field_from_handle(__raw_readb(ptr), data, h);131	__raw_writeb(value, ptr);132	(void)__raw_readb(ptr);	/* Defeat write posting */133	local_irq_restore(flags);134	return 0;135}136 137static unsigned long modify_16(unsigned long addr, unsigned long h,138			       unsigned long data)139{140	void __iomem *ptr = (void __iomem *)addr;141	unsigned long flags;142	unsigned int value;143	local_irq_save(flags);144	value = intc_set_field_from_handle(__raw_readw(ptr), data, h);145	__raw_writew(value, ptr);146	(void)__raw_readw(ptr);	/* Defeat write posting */147	local_irq_restore(flags);148	return 0;149}150 151static unsigned long modify_32(unsigned long addr, unsigned long h,152			       unsigned long data)153{154	void __iomem *ptr = (void __iomem *)addr;155	unsigned long flags;156	unsigned int value;157	local_irq_save(flags);158	value = intc_set_field_from_handle(__raw_readl(ptr), data, h);159	__raw_writel(value, ptr);160	(void)__raw_readl(ptr);	/* Defeat write posting */161	local_irq_restore(flags);162	return 0;163}164 165static unsigned long intc_mode_field(unsigned long addr,166				     unsigned long handle,167				     unsigned long (*fn)(unsigned long,168						unsigned long,169						unsigned long),170				     unsigned int irq)171{172	return fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));173}174 175static unsigned long intc_mode_zero(unsigned long addr,176				    unsigned long handle,177				    unsigned long (*fn)(unsigned long,178					       unsigned long,179					       unsigned long),180				    unsigned int irq)181{182	return fn(addr, handle, 0);183}184 185static unsigned long intc_mode_prio(unsigned long addr,186				    unsigned long handle,187				    unsigned long (*fn)(unsigned long,188					       unsigned long,189					       unsigned long),190				    unsigned int irq)191{192	return fn(addr, handle, intc_get_prio_level(irq));193}194 195unsigned long (*intc_reg_fns[])(unsigned long addr,196				unsigned long h,197				unsigned long data) = {198	[REG_FN_TEST_BASE + 0] = test_8,199	[REG_FN_TEST_BASE + 1] = test_16,200	[REG_FN_TEST_BASE + 3] = test_32,201	[REG_FN_WRITE_BASE + 0] = write_8,202	[REG_FN_WRITE_BASE + 1] = write_16,203	[REG_FN_WRITE_BASE + 3] = write_32,204	[REG_FN_MODIFY_BASE + 0] = modify_8,205	[REG_FN_MODIFY_BASE + 1] = modify_16,206	[REG_FN_MODIFY_BASE + 3] = modify_32,207};208 209unsigned long (*intc_enable_fns[])(unsigned long addr,210				   unsigned long handle,211				   unsigned long (*fn)(unsigned long,212					    unsigned long,213					    unsigned long),214				   unsigned int irq) = {215	[MODE_ENABLE_REG] = intc_mode_field,216	[MODE_MASK_REG] = intc_mode_zero,217	[MODE_DUAL_REG] = intc_mode_field,218	[MODE_PRIO_REG] = intc_mode_prio,219	[MODE_PCLR_REG] = intc_mode_prio,220};221 222unsigned long (*intc_disable_fns[])(unsigned long addr,223				    unsigned long handle,224				    unsigned long (*fn)(unsigned long,225					     unsigned long,226					     unsigned long),227				    unsigned int irq) = {228	[MODE_ENABLE_REG] = intc_mode_zero,229	[MODE_MASK_REG] = intc_mode_field,230	[MODE_DUAL_REG] = intc_mode_field,231	[MODE_PRIO_REG] = intc_mode_zero,232	[MODE_PCLR_REG] = intc_mode_field,233};234 235unsigned long (*intc_enable_noprio_fns[])(unsigned long addr,236					  unsigned long handle,237					  unsigned long (*fn)(unsigned long,238						unsigned long,239						unsigned long),240					  unsigned int irq) = {241	[MODE_ENABLE_REG] = intc_mode_field,242	[MODE_MASK_REG] = intc_mode_zero,243	[MODE_DUAL_REG] = intc_mode_field,244	[MODE_PRIO_REG] = intc_mode_field,245	[MODE_PCLR_REG] = intc_mode_field,246};247