• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/arm/mach-stmp378x/
1/*
2 * Freescale STMP378X platform support
3 *
4 * Embedded Alley Solutions, Inc <source@embeddedalley.com>
5 *
6 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
7 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
8 */
9
10/*
11 * The code contained herein is licensed under the GNU General Public
12 * License. You may obtain a copy of the GNU General Public License
13 * Version 2 or later at the following locations:
14 *
15 * http://www.opensource.org/licenses/gpl-license.html
16 * http://www.gnu.org/copyleft/gpl.html
17 */
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/platform_device.h>
21#include <linux/irq.h>
22#include <linux/dma-mapping.h>
23
24#include <asm/dma.h>
25#include <asm/setup.h>
26#include <asm/mach-types.h>
27
28#include <asm/mach/arch.h>
29#include <asm/mach/irq.h>
30#include <asm/mach/map.h>
31#include <asm/mach/time.h>
32
33#include <mach/pins.h>
34#include <mach/pinmux.h>
35#include <mach/dma.h>
36#include <mach/hardware.h>
37#include <mach/system.h>
38#include <mach/platform.h>
39#include <mach/stmp3xxx.h>
40#include <mach/regs-icoll.h>
41#include <mach/regs-apbh.h>
42#include <mach/regs-apbx.h>
43#include <mach/regs-pxp.h>
44#include <mach/regs-i2c.h>
45
46#include "stmp378x.h"
47/*
48 * IRQ handling
49 */
50static void stmp378x_ack_irq(unsigned int irq)
51{
52	/* Tell ICOLL to release IRQ line */
53	__raw_writel(0, REGS_ICOLL_BASE + HW_ICOLL_VECTOR);
54
55	/* ACK current interrupt */
56	__raw_writel(0x01 /* BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 */,
57			REGS_ICOLL_BASE + HW_ICOLL_LEVELACK);
58
59	/* Barrier */
60	(void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT);
61}
62
63static void stmp378x_mask_irq(unsigned int irq)
64{
65	/* IRQ disable */
66	stmp3xxx_clearl(BM_ICOLL_INTERRUPTn_ENABLE,
67			REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + irq * 0x10);
68}
69
70static void stmp378x_unmask_irq(unsigned int irq)
71{
72	/* IRQ enable */
73	stmp3xxx_setl(BM_ICOLL_INTERRUPTn_ENABLE,
74		      REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + irq * 0x10);
75}
76
77static struct irq_chip stmp378x_chip = {
78	.ack	= stmp378x_ack_irq,
79	.mask	= stmp378x_mask_irq,
80	.unmask = stmp378x_unmask_irq,
81};
82
83void __init stmp378x_init_irq(void)
84{
85	stmp3xxx_init_irq(&stmp378x_chip);
86}
87
88/*
89 * DMA interrupt handling
90 */
91void stmp3xxx_arch_dma_enable_interrupt(int channel)
92{
93	void __iomem *c1, *c2;
94
95	switch (STMP3XXX_DMA_BUS(channel)) {
96	case STMP3XXX_BUS_APBH:
97		c1 = REGS_APBH_BASE + HW_APBH_CTRL1;
98		c2 = REGS_APBH_BASE + HW_APBH_CTRL2;
99		break;
100
101	case STMP3XXX_BUS_APBX:
102		c1 = REGS_APBX_BASE + HW_APBX_CTRL1;
103		c2 = REGS_APBX_BASE + HW_APBX_CTRL2;
104		break;
105
106	default:
107		return;
108	}
109	stmp3xxx_setl(1 << (16 + STMP3XXX_DMA_CHANNEL(channel)), c1);
110	stmp3xxx_setl(1 << (16 + STMP3XXX_DMA_CHANNEL(channel)), c2);
111}
112EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt);
113
114void stmp3xxx_arch_dma_clear_interrupt(int channel)
115{
116	void __iomem *c1, *c2;
117
118	switch (STMP3XXX_DMA_BUS(channel)) {
119	case STMP3XXX_BUS_APBH:
120		c1 = REGS_APBH_BASE + HW_APBH_CTRL1;
121		c2 = REGS_APBH_BASE + HW_APBH_CTRL2;
122		break;
123
124	case STMP3XXX_BUS_APBX:
125		c1 = REGS_APBX_BASE + HW_APBX_CTRL1;
126		c2 = REGS_APBX_BASE + HW_APBX_CTRL2;
127		break;
128
129	default:
130		return;
131	}
132	stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), c1);
133	stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), c2);
134}
135EXPORT_SYMBOL(stmp3xxx_arch_dma_clear_interrupt);
136
137int stmp3xxx_arch_dma_is_interrupt(int channel)
138{
139	int r = 0;
140
141	switch (STMP3XXX_DMA_BUS(channel)) {
142	case STMP3XXX_BUS_APBH:
143		r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) &
144			(1 << STMP3XXX_DMA_CHANNEL(channel));
145		break;
146
147	case STMP3XXX_BUS_APBX:
148		r = __raw_readl(REGS_APBX_BASE + HW_APBX_CTRL1) &
149			(1 << STMP3XXX_DMA_CHANNEL(channel));
150		break;
151	}
152	return r;
153}
154EXPORT_SYMBOL(stmp3xxx_arch_dma_is_interrupt);
155
156void stmp3xxx_arch_dma_reset_channel(int channel)
157{
158	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
159	void __iomem *c0;
160	u32 mask;
161
162	switch (STMP3XXX_DMA_BUS(channel)) {
163	case STMP3XXX_BUS_APBH:
164		c0 = REGS_APBH_BASE + HW_APBH_CTRL0;
165		mask = chbit << BP_APBH_CTRL0_RESET_CHANNEL;
166		break;
167	case STMP3XXX_BUS_APBX:
168		c0 = REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL;
169		mask = chbit << BP_APBX_CHANNEL_CTRL_RESET_CHANNEL;
170		break;
171	default:
172		return;
173	}
174
175	/* Reset channel and wait for it to complete */
176	stmp3xxx_setl(mask, c0);
177	while (__raw_readl(c0) & mask)
178		cpu_relax();
179}
180EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel);
181
182void stmp3xxx_arch_dma_freeze(int channel)
183{
184	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
185	u32 mask = 1 << chbit;
186
187	switch (STMP3XXX_DMA_BUS(channel)) {
188	case STMP3XXX_BUS_APBH:
189		stmp3xxx_setl(mask, REGS_APBH_BASE + HW_APBH_CTRL0);
190		break;
191	case STMP3XXX_BUS_APBX:
192		stmp3xxx_setl(mask, REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL);
193		break;
194	}
195}
196EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze);
197
198void stmp3xxx_arch_dma_unfreeze(int channel)
199{
200	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
201	u32 mask = 1 << chbit;
202
203	switch (STMP3XXX_DMA_BUS(channel)) {
204	case STMP3XXX_BUS_APBH:
205		stmp3xxx_clearl(mask, REGS_APBH_BASE + HW_APBH_CTRL0);
206		break;
207	case STMP3XXX_BUS_APBX:
208		stmp3xxx_clearl(mask, REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL);
209		break;
210	}
211}
212EXPORT_SYMBOL(stmp3xxx_arch_dma_unfreeze);
213
214/*
215 * The registers are all very closely mapped, so we might as well map them all
216 * with a single mapping
217 *
218 * Logical      Physical
219 * f0000000	80000000	On-chip registers
220 * f1000000	00000000	32k on-chip SRAM
221 */
222
223static struct map_desc stmp378x_io_desc[] __initdata = {
224	{
225		.virtual	= (u32)STMP3XXX_REGS_BASE,
226		.pfn		= __phys_to_pfn(STMP3XXX_REGS_PHBASE),
227		.length		= STMP3XXX_REGS_SIZE,
228		.type		= MT_DEVICE,
229	},
230	{
231		.virtual	= (u32)STMP3XXX_OCRAM_BASE,
232		.pfn		= __phys_to_pfn(STMP3XXX_OCRAM_PHBASE),
233		.length		= STMP3XXX_OCRAM_SIZE,
234		.type		= MT_DEVICE,
235	},
236};
237
238
239static u64 common_dmamask = DMA_BIT_MASK(32);
240
241/*
242 * devices that are present only on stmp378x, not on all 3xxx boards:
243 * 	PxP
244 * 	I2C
245 */
246static struct resource pxp_resource[] = {
247	{
248		.flags	= IORESOURCE_MEM,
249		.start	= REGS_PXP_PHYS,
250		.end	= REGS_PXP_PHYS + REGS_PXP_SIZE,
251	}, {
252		.flags	= IORESOURCE_IRQ,
253		.start	= IRQ_PXP,
254		.end	= IRQ_PXP,
255	},
256};
257
258struct platform_device stmp378x_pxp = {
259	.name		= "stmp3xxx-pxp",
260	.id		= -1,
261	.dev		= {
262		.dma_mask		= &common_dmamask,
263		.coherent_dma_mask	= DMA_BIT_MASK(32),
264	},
265	.num_resources	= ARRAY_SIZE(pxp_resource),
266	.resource	= pxp_resource,
267};
268
269static struct resource i2c_resources[] = {
270	{
271		.flags = IORESOURCE_IRQ,
272		.start = IRQ_I2C_ERROR,
273		.end = IRQ_I2C_ERROR,
274	}, {
275		.flags = IORESOURCE_MEM,
276		.start = REGS_I2C_PHYS,
277		.end = REGS_I2C_PHYS + REGS_I2C_SIZE,
278	}, {
279		.flags = IORESOURCE_DMA,
280		.start = STMP3XXX_DMA(3, STMP3XXX_BUS_APBX),
281		.end = STMP3XXX_DMA(3, STMP3XXX_BUS_APBX),
282	},
283};
284
285struct platform_device stmp378x_i2c = {
286	.name = "i2c_stmp3xxx",
287	.id = 0,
288	.dev	= {
289		.dma_mask	= &common_dmamask,
290		.coherent_dma_mask = DMA_BIT_MASK(32),
291	},
292	.resource = i2c_resources,
293	.num_resources = ARRAY_SIZE(i2c_resources),
294};
295
296void __init stmp378x_map_io(void)
297{
298	iotable_init(stmp378x_io_desc, ARRAY_SIZE(stmp378x_io_desc));
299}
300