Linux Audio

Check our new training course

Loading...
  1/*
  2 * Common INTC2 register accessors
  3 *
  4 * Copyright (C) 2007, 2008 Magnus Damm
  5 * Copyright (C) 2009, 2010 Paul Mundt
  6 *
  7 * This file is subject to the terms and conditions of the GNU General Public
  8 * License.  See the file "COPYING" in the main directory of this archive
  9 * 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};
  1/*
  2 * Common INTC2 register accessors
  3 *
  4 * Copyright (C) 2007, 2008 Magnus Damm
  5 * Copyright (C) 2009, 2010 Paul Mundt
  6 *
  7 * This file is subject to the terms and conditions of the GNU General Public
  8 * License.  See the file "COPYING" in the main directory of this archive
  9 * 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};