aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-05-08 21:29:27 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-05-08 21:29:27 -0400
commitd585a021c0b10b0477d6b608c53e1feb8cde0507 (patch)
tree5ca059da1db7f15d4b29427644ad9c08270c885c /arch/arm/mach-ep93xx
parent84e5b0d00f8f84c4ae226be131d4bebbcee88bd3 (diff)
parent091bf7624d1c90cec9e578a18529f615213ff847 (diff)
Merge commit 'v2.6.30-rc5' into next
Diffstat (limited to 'arch/arm/mach-ep93xx')
-rw-r--r--arch/arm/mach-ep93xx/Makefile2
-rw-r--r--arch/arm/mach-ep93xx/clock.c79
-rw-r--r--arch/arm/mach-ep93xx/core.c2
-rw-r--r--arch/arm/mach-ep93xx/dma-m2p.c408
-rw-r--r--arch/arm/mach-ep93xx/edb9307a.c12
-rw-r--r--arch/arm/mach-ep93xx/include/mach/dma.h52
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h3
-rw-r--r--arch/arm/mach-ep93xx/include/mach/platform.h2
-rw-r--r--arch/arm/mach-ep93xx/include/mach/system.h2
9 files changed, 558 insertions, 4 deletions
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 944e42d5164..9522e205b73 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -1,7 +1,7 @@
1# 1#
2# Makefile for the linux kernel. 2# Makefile for the linux kernel.
3# 3#
4obj-y := core.o clock.o gpio.o 4obj-y := core.o clock.o dma-m2p.o gpio.o
5obj-m := 5obj-m :=
6obj-n := 6obj-n :=
7obj- := 7obj- :=
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index 96049283a10..e8ebeaea6c4 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -41,6 +41,56 @@ static struct clk clk_usb_host = {
41 .enable_mask = EP93XX_SYSCON_CLOCK_USH_EN, 41 .enable_mask = EP93XX_SYSCON_CLOCK_USH_EN,
42}; 42};
43 43
44/* DMA Clocks */
45static struct clk clk_m2p0 = {
46 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
47 .enable_mask = 0x00020000,
48};
49static struct clk clk_m2p1 = {
50 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
51 .enable_mask = 0x00010000,
52};
53static struct clk clk_m2p2 = {
54 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
55 .enable_mask = 0x00080000,
56};
57static struct clk clk_m2p3 = {
58 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
59 .enable_mask = 0x00040000,
60};
61static struct clk clk_m2p4 = {
62 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
63 .enable_mask = 0x00200000,
64};
65static struct clk clk_m2p5 = {
66 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
67 .enable_mask = 0x00100000,
68};
69static struct clk clk_m2p6 = {
70 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
71 .enable_mask = 0x00800000,
72};
73static struct clk clk_m2p7 = {
74 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
75 .enable_mask = 0x00400000,
76};
77static struct clk clk_m2p8 = {
78 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
79 .enable_mask = 0x02000000,
80};
81static struct clk clk_m2p9 = {
82 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
83 .enable_mask = 0x01000000,
84};
85static struct clk clk_m2m0 = {
86 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
87 .enable_mask = 0x04000000,
88};
89static struct clk clk_m2m1 = {
90 .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
91 .enable_mask = 0x08000000,
92};
93
44#define INIT_CK(dev,con,ck) \ 94#define INIT_CK(dev,con,ck) \
45 { .dev_id = dev, .con_id = con, .clk = ck } 95 { .dev_id = dev, .con_id = con, .clk = ck }
46 96
@@ -54,6 +104,18 @@ static struct clk_lookup clocks[] = {
54 INIT_CK(NULL, "pclk", &clk_p), 104 INIT_CK(NULL, "pclk", &clk_p),
55 INIT_CK(NULL, "pll2", &clk_pll2), 105 INIT_CK(NULL, "pll2", &clk_pll2),
56 INIT_CK(NULL, "usb_host", &clk_usb_host), 106 INIT_CK(NULL, "usb_host", &clk_usb_host),
107 INIT_CK(NULL, "m2p0", &clk_m2p0),
108 INIT_CK(NULL, "m2p1", &clk_m2p1),
109 INIT_CK(NULL, "m2p2", &clk_m2p2),
110 INIT_CK(NULL, "m2p3", &clk_m2p3),
111 INIT_CK(NULL, "m2p4", &clk_m2p4),
112 INIT_CK(NULL, "m2p5", &clk_m2p5),
113 INIT_CK(NULL, "m2p6", &clk_m2p6),
114 INIT_CK(NULL, "m2p7", &clk_m2p7),
115 INIT_CK(NULL, "m2p8", &clk_m2p8),
116 INIT_CK(NULL, "m2p9", &clk_m2p9),
117 INIT_CK(NULL, "m2m0", &clk_m2m0),
118 INIT_CK(NULL, "m2m1", &clk_m2m1),
57}; 119};
58 120
59 121
@@ -110,6 +172,22 @@ static unsigned long calc_pll_rate(u32 config_word)
110 return (unsigned long)rate; 172 return (unsigned long)rate;
111} 173}
112 174
175static void __init ep93xx_dma_clock_init(void)
176{
177 clk_m2p0.rate = clk_h.rate;
178 clk_m2p1.rate = clk_h.rate;
179 clk_m2p2.rate = clk_h.rate;
180 clk_m2p3.rate = clk_h.rate;
181 clk_m2p4.rate = clk_h.rate;
182 clk_m2p5.rate = clk_h.rate;
183 clk_m2p6.rate = clk_h.rate;
184 clk_m2p7.rate = clk_h.rate;
185 clk_m2p8.rate = clk_h.rate;
186 clk_m2p9.rate = clk_h.rate;
187 clk_m2m0.rate = clk_h.rate;
188 clk_m2m1.rate = clk_h.rate;
189}
190
113static int __init ep93xx_clock_init(void) 191static int __init ep93xx_clock_init(void)
114{ 192{
115 u32 value; 193 u32 value;
@@ -124,6 +202,7 @@ static int __init ep93xx_clock_init(void)
124 clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7]; 202 clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
125 clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7]; 203 clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
126 clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3]; 204 clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
205 ep93xx_dma_clock_init();
127 206
128 value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2); 207 value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
129 if (!(value & 0x00080000)) { /* PLL2 bypassed? */ 208 if (!(value & 0x00080000)) { /* PLL2 bypassed? */
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 6d9152de607..ae24486f858 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -100,7 +100,7 @@ static unsigned int last_jiffy_time;
100 100
101#define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) 101#define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
102 102
103static int ep93xx_timer_interrupt(int irq, void *dev_id) 103static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
104{ 104{
105 __raw_writel(1, EP93XX_TIMER1_CLEAR); 105 __raw_writel(1, EP93XX_TIMER1_CLEAR);
106 while ((signed long) 106 while ((signed long)
diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c
new file mode 100644
index 00000000000..a2df5bb7dff
--- /dev/null
+++ b/arch/arm/mach-ep93xx/dma-m2p.c
@@ -0,0 +1,408 @@
1/*
2 * arch/arm/mach-ep93xx/dma-m2p.c
3 * M2P DMA handling for Cirrus EP93xx chips.
4 *
5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
6 * Copyright (C) 2006 Applied Data Systems
7 *
8 * Copyright (C) 2009 Ryan Mallon <ryan@bluewatersys.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 */
15
16/*
17 * On the EP93xx chip the following peripherals my be allocated to the 10
18 * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
19 *
20 * I2S contains 3 Tx and 3 Rx DMA Channels
21 * AAC contains 3 Tx and 3 Rx DMA Channels
22 * UART1 contains 1 Tx and 1 Rx DMA Channels
23 * UART2 contains 1 Tx and 1 Rx DMA Channels
24 * UART3 contains 1 Tx and 1 Rx DMA Channels
25 * IrDA contains 1 Tx and 1 Rx DMA Channels
26 *
27 * SSP and IDE use the Memory to Memory (M2M) channels and are not covered
28 * with this implementation.
29 */
30
31#include <linux/kernel.h>
32#include <linux/clk.h>
33#include <linux/err.h>
34#include <linux/interrupt.h>
35#include <linux/module.h>
36
37#include <mach/dma.h>
38#include <mach/hardware.h>
39
40#define M2P_CONTROL 0x00
41#define M2P_CONTROL_STALL_IRQ_EN (1 << 0)
42#define M2P_CONTROL_NFB_IRQ_EN (1 << 1)
43#define M2P_CONTROL_ERROR_IRQ_EN (1 << 3)
44#define M2P_CONTROL_ENABLE (1 << 4)
45#define M2P_INTERRUPT 0x04
46#define M2P_INTERRUPT_STALL (1 << 0)
47#define M2P_INTERRUPT_NFB (1 << 1)
48#define M2P_INTERRUPT_ERROR (1 << 3)
49#define M2P_PPALLOC 0x08
50#define M2P_STATUS 0x0c
51#define M2P_REMAIN 0x14
52#define M2P_MAXCNT0 0x20
53#define M2P_BASE0 0x24
54#define M2P_MAXCNT1 0x30
55#define M2P_BASE1 0x34
56
57#define STATE_IDLE 0 /* Channel is inactive. */
58#define STATE_STALL 1 /* Channel is active, no buffers pending. */
59#define STATE_ON 2 /* Channel is active, one buffer pending. */
60#define STATE_NEXT 3 /* Channel is active, two buffers pending. */
61
62struct m2p_channel {
63 char *name;
64 void __iomem *base;
65 int irq;
66
67 struct clk *clk;
68 spinlock_t lock;
69
70 void *client;
71 unsigned next_slot:1;
72 struct ep93xx_dma_buffer *buffer_xfer;
73 struct ep93xx_dma_buffer *buffer_next;
74 struct list_head buffers_pending;
75};
76
77static struct m2p_channel m2p_rx[] = {
78 {"m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1},
79 {"m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3},
80 {"m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5},
81 {"m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7},
82 {"m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9},
83 {NULL},
84};
85
86static struct m2p_channel m2p_tx[] = {
87 {"m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0},
88 {"m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2},
89 {"m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4},
90 {"m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6},
91 {"m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8},
92 {NULL},
93};
94
95static void feed_buf(struct m2p_channel *ch, struct ep93xx_dma_buffer *buf)
96{
97 if (ch->next_slot == 0) {
98 writel(buf->size, ch->base + M2P_MAXCNT0);
99 writel(buf->bus_addr, ch->base + M2P_BASE0);
100 } else {
101 writel(buf->size, ch->base + M2P_MAXCNT1);
102 writel(buf->bus_addr, ch->base + M2P_BASE1);
103 }
104 ch->next_slot ^= 1;
105}
106
107static void choose_buffer_xfer(struct m2p_channel *ch)
108{
109 struct ep93xx_dma_buffer *buf;
110
111 ch->buffer_xfer = NULL;
112 if (!list_empty(&ch->buffers_pending)) {
113 buf = list_entry(ch->buffers_pending.next,
114 struct ep93xx_dma_buffer, list);
115 list_del(&buf->list);
116 feed_buf(ch, buf);
117 ch->buffer_xfer = buf;
118 }
119}
120
121static void choose_buffer_next(struct m2p_channel *ch)
122{
123 struct ep93xx_dma_buffer *buf;
124
125 ch->buffer_next = NULL;
126 if (!list_empty(&ch->buffers_pending)) {
127 buf = list_entry(ch->buffers_pending.next,
128 struct ep93xx_dma_buffer, list);
129 list_del(&buf->list);
130 feed_buf(ch, buf);
131 ch->buffer_next = buf;
132 }
133}
134
135static inline void m2p_set_control(struct m2p_channel *ch, u32 v)
136{
137 /*
138 * The control register must be read immediately after being written so
139 * that the internal state machine is correctly updated. See the ep93xx
140 * users' guide for details.
141 */
142 writel(v, ch->base + M2P_CONTROL);
143 readl(ch->base + M2P_CONTROL);
144}
145
146static inline int m2p_channel_state(struct m2p_channel *ch)
147{
148 return (readl(ch->base + M2P_STATUS) >> 4) & 0x3;
149}
150
151static irqreturn_t m2p_irq(int irq, void *dev_id)
152{
153 struct m2p_channel *ch = dev_id;
154 struct ep93xx_dma_m2p_client *cl;
155 u32 irq_status, v;
156 int error = 0;
157
158 cl = ch->client;
159
160 spin_lock(&ch->lock);
161 irq_status = readl(ch->base + M2P_INTERRUPT);
162
163 if (irq_status & M2P_INTERRUPT_ERROR) {
164 writel(M2P_INTERRUPT_ERROR, ch->base + M2P_INTERRUPT);
165 error = 1;
166 }
167
168 if ((irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) == 0) {
169 spin_unlock(&ch->lock);
170 return IRQ_NONE;
171 }
172
173 switch (m2p_channel_state(ch)) {
174 case STATE_IDLE:
175 pr_crit("m2p_irq: dma interrupt without a dma buffer\n");
176 BUG();
177 break;
178
179 case STATE_STALL:
180 cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
181 if (ch->buffer_next != NULL) {
182 cl->buffer_finished(cl->cookie, ch->buffer_next,
183 0, error);
184 }
185 choose_buffer_xfer(ch);
186 choose_buffer_next(ch);
187 if (ch->buffer_xfer != NULL)
188 cl->buffer_started(cl->cookie, ch->buffer_xfer);
189 break;
190
191 case STATE_ON:
192 cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
193 ch->buffer_xfer = ch->buffer_next;
194 choose_buffer_next(ch);
195 cl->buffer_started(cl->cookie, ch->buffer_xfer);
196 break;
197
198 case STATE_NEXT:
199 pr_crit("m2p_irq: dma interrupt while next\n");
200 BUG();
201 break;
202 }
203
204 v = readl(ch->base + M2P_CONTROL) & ~(M2P_CONTROL_STALL_IRQ_EN |
205 M2P_CONTROL_NFB_IRQ_EN);
206 if (ch->buffer_xfer != NULL)
207 v |= M2P_CONTROL_STALL_IRQ_EN;
208 if (ch->buffer_next != NULL)
209 v |= M2P_CONTROL_NFB_IRQ_EN;
210 m2p_set_control(ch, v);
211
212 spin_unlock(&ch->lock);
213 return IRQ_HANDLED;
214}
215
216static struct m2p_channel *find_free_channel(struct ep93xx_dma_m2p_client *cl)
217{
218 struct m2p_channel *ch;
219 int i;
220
221 if (cl->flags & EP93XX_DMA_M2P_RX)
222 ch = m2p_rx;
223 else
224 ch = m2p_tx;
225
226 for (i = 0; ch[i].base; i++) {
227 struct ep93xx_dma_m2p_client *client;
228
229 client = ch[i].client;
230 if (client != NULL) {
231 int port;
232
233 port = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
234 if (port == (client->flags &
235 EP93XX_DMA_M2P_PORT_MASK)) {
236 pr_warning("DMA channel already used by %s\n",
237 cl->name ? : "unknown client");
238 return ERR_PTR(-EBUSY);
239 }
240 }
241 }
242
243 for (i = 0; ch[i].base; i++) {
244 if (ch[i].client == NULL)
245 return ch + i;
246 }
247
248 pr_warning("No free DMA channel for %s\n",
249 cl->name ? : "unknown client");
250 return ERR_PTR(-ENODEV);
251}
252
253static void channel_enable(struct m2p_channel *ch)
254{
255 struct ep93xx_dma_m2p_client *cl = ch->client;
256 u32 v;
257
258 clk_enable(ch->clk);
259
260 v = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
261 writel(v, ch->base + M2P_PPALLOC);
262
263 v = cl->flags & EP93XX_DMA_M2P_ERROR_MASK;
264 v |= M2P_CONTROL_ENABLE | M2P_CONTROL_ERROR_IRQ_EN;
265 m2p_set_control(ch, v);
266}
267
268static void channel_disable(struct m2p_channel *ch)
269{
270 u32 v;
271
272 v = readl(ch->base + M2P_CONTROL);
273 v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
274 m2p_set_control(ch, v);
275
276 while (m2p_channel_state(ch) == STATE_ON)
277 cpu_relax();
278
279 m2p_set_control(ch, 0x0);
280
281 while (m2p_channel_state(ch) == STATE_STALL)
282 cpu_relax();
283
284 clk_disable(ch->clk);
285}
286
287int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *cl)
288{
289 struct m2p_channel *ch;
290 int err;
291
292 ch = find_free_channel(cl);
293 if (IS_ERR(ch))
294 return PTR_ERR(ch);
295
296 err = request_irq(ch->irq, m2p_irq, 0, cl->name ? : "dma-m2p", ch);
297 if (err)
298 return err;
299
300 ch->client = cl;
301 ch->next_slot = 0;
302 ch->buffer_xfer = NULL;
303 ch->buffer_next = NULL;
304 INIT_LIST_HEAD(&ch->buffers_pending);
305
306 cl->channel = ch;
307
308 channel_enable(ch);
309
310 return 0;
311}
312EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_register);
313
314void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *cl)
315{
316 struct m2p_channel *ch = cl->channel;
317
318 channel_disable(ch);
319 free_irq(ch->irq, ch);
320 ch->client = NULL;
321}
322EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_unregister);
323
324void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *cl,
325 struct ep93xx_dma_buffer *buf)
326{
327 struct m2p_channel *ch = cl->channel;
328 unsigned long flags;
329 u32 v;
330
331 spin_lock_irqsave(&ch->lock, flags);
332 v = readl(ch->base + M2P_CONTROL);
333 if (ch->buffer_xfer == NULL) {
334 ch->buffer_xfer = buf;
335 feed_buf(ch, buf);
336 cl->buffer_started(cl->cookie, buf);
337
338 v |= M2P_CONTROL_STALL_IRQ_EN;
339 m2p_set_control(ch, v);
340
341 } else if (ch->buffer_next == NULL) {
342 ch->buffer_next = buf;
343 feed_buf(ch, buf);
344
345 v |= M2P_CONTROL_NFB_IRQ_EN;
346 m2p_set_control(ch, v);
347 } else {
348 list_add_tail(&buf->list, &ch->buffers_pending);
349 }
350 spin_unlock_irqrestore(&ch->lock, flags);
351}
352EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit);
353
354void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *cl,
355 struct ep93xx_dma_buffer *buf)
356{
357 struct m2p_channel *ch = cl->channel;
358
359 list_add_tail(&buf->list, &ch->buffers_pending);
360}
361EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit_recursive);
362
363void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *cl)
364{
365 struct m2p_channel *ch = cl->channel;
366
367 channel_disable(ch);
368 ch->next_slot = 0;
369 ch->buffer_xfer = NULL;
370 ch->buffer_next = NULL;
371 INIT_LIST_HEAD(&ch->buffers_pending);
372 channel_enable(ch);
373}
374EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_flush);
375
376static int init_channel(struct m2p_channel *ch)
377{
378 ch->clk = clk_get(NULL, ch->name);
379 if (IS_ERR(ch->clk))
380 return PTR_ERR(ch->clk);
381
382 spin_lock_init(&ch->lock);
383 ch->client = NULL;
384
385 return 0;
386}
387
388static int __init ep93xx_dma_m2p_init(void)
389{
390 int i;
391 int ret;
392
393 for (i = 0; m2p_rx[i].base; i++) {
394 ret = init_channel(m2p_rx + i);
395 if (ret)
396 return ret;
397 }
398
399 for (i = 0; m2p_tx[i].base; i++) {
400 ret = init_channel(m2p_tx + i);
401 if (ret)
402 return ret;
403 }
404
405 pr_info("M2P DMA subsystem initialized\n");
406 return 0;
407}
408arch_initcall(ep93xx_dma_m2p_init);
diff --git a/arch/arm/mach-ep93xx/edb9307a.c b/arch/arm/mach-ep93xx/edb9307a.c
index 5b5c22b681b..6171167d331 100644
--- a/arch/arm/mach-ep93xx/edb9307a.c
+++ b/arch/arm/mach-ep93xx/edb9307a.c
@@ -48,12 +48,24 @@ static struct ep93xx_eth_data edb9307a_eth_data = {
48 .phy_id = 1, 48 .phy_id = 1,
49}; 49};
50 50
51static struct i2c_board_info __initdata edb9307a_i2c_data[] = {
52 {
53 /* On-board battery backed RTC */
54 I2C_BOARD_INFO("isl1208", 0x6f),
55 },
56 /*
57 * The I2C signals are also routed to the Expansion Connector (J4)
58 */
59};
60
51static void __init edb9307a_init_machine(void) 61static void __init edb9307a_init_machine(void)
52{ 62{
53 ep93xx_init_devices(); 63 ep93xx_init_devices();
54 platform_device_register(&edb9307a_flash); 64 platform_device_register(&edb9307a_flash);
55 65
56 ep93xx_register_eth(&edb9307a_eth_data, 1); 66 ep93xx_register_eth(&edb9307a_eth_data, 1);
67
68 ep93xx_init_i2c(edb9307a_i2c_data, ARRAY_SIZE(edb9307a_i2c_data));
57} 69}
58 70
59MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") 71MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
new file mode 100644
index 00000000000..ef6bd9d1314
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/dma.h
@@ -0,0 +1,52 @@
1#ifndef __ASM_ARCH_DMA_H
2#define __ASM_ARCH_DMA_H
3
4#include <linux/list.h>
5#include <linux/types.h>
6
7struct ep93xx_dma_buffer {
8 struct list_head list;
9 u32 bus_addr;
10 u16 size;
11};
12
13struct ep93xx_dma_m2p_client {
14 char *name;
15 u8 flags;
16 void *cookie;
17 void (*buffer_started)(void *cookie,
18 struct ep93xx_dma_buffer *buf);
19 void (*buffer_finished)(void *cookie,
20 struct ep93xx_dma_buffer *buf,
21 int bytes, int error);
22
23 /* Internal to the DMA code. */
24 void *channel;
25};
26
27#define EP93XX_DMA_M2P_PORT_I2S1 0x00
28#define EP93XX_DMA_M2P_PORT_I2S2 0x01
29#define EP93XX_DMA_M2P_PORT_AAC1 0x02
30#define EP93XX_DMA_M2P_PORT_AAC2 0x03
31#define EP93XX_DMA_M2P_PORT_AAC3 0x04
32#define EP93XX_DMA_M2P_PORT_I2S3 0x05
33#define EP93XX_DMA_M2P_PORT_UART1 0x06
34#define EP93XX_DMA_M2P_PORT_UART2 0x07
35#define EP93XX_DMA_M2P_PORT_UART3 0x08
36#define EP93XX_DMA_M2P_PORT_IRDA 0x09
37#define EP93XX_DMA_M2P_PORT_MASK 0x0f
38#define EP93XX_DMA_M2P_TX 0x00
39#define EP93XX_DMA_M2P_RX 0x10
40#define EP93XX_DMA_M2P_ABORT_ON_ERROR 0x20
41#define EP93XX_DMA_M2P_IGNORE_ERROR 0x40
42#define EP93XX_DMA_M2P_ERROR_MASK 0x60
43
44int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *m2p);
45void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *m2p);
46void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *m2p,
47 struct ep93xx_dma_buffer *buf);
48void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *m2p,
49 struct ep93xx_dma_buffer *buf);
50void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *m2p);
51
52#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index 22d6c9a6e4c..f66be12b856 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -58,7 +58,8 @@
58 58
59 59
60/* AHB peripherals */ 60/* AHB peripherals */
61#define EP93XX_DMA_BASE (EP93XX_AHB_VIRT_BASE + 0x00000000) 61#define EP93XX_DMA_BASE ((void __iomem *) \
62 (EP93XX_AHB_VIRT_BASE + 0x00000000))
62 63
63#define EP93XX_ETHERNET_BASE (EP93XX_AHB_VIRT_BASE + 0x00010000) 64#define EP93XX_ETHERNET_BASE (EP93XX_AHB_VIRT_BASE + 0x00010000)
64#define EP93XX_ETHERNET_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00010000) 65#define EP93XX_ETHERNET_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00010000)
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 88f7e88f152..05f0f4f2f3c 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -4,6 +4,8 @@
4 4
5#ifndef __ASSEMBLY__ 5#ifndef __ASSEMBLY__
6 6
7struct i2c_board_info;
8
7struct ep93xx_eth_data 9struct ep93xx_eth_data
8{ 10{
9 unsigned char dev_addr[6]; 11 unsigned char dev_addr[6];
diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h
index 67789d0f329..ed8f35e4f06 100644
--- a/arch/arm/mach-ep93xx/include/mach/system.h
+++ b/arch/arm/mach-ep93xx/include/mach/system.h
@@ -9,7 +9,7 @@ static inline void arch_idle(void)
9 cpu_do_idle(); 9 cpu_do_idle();
10} 10}
11 11
12static inline void arch_reset(char mode) 12static inline void arch_reset(char mode, const char *cmd)
13{ 13{
14 u32 devicecfg; 14 u32 devicecfg;
15 15