aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/ata/pata_mpc52xx.c6
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/bestcomm/Kconfig36
-rw-r--r--drivers/dma/bestcomm/Makefile14
-rw-r--r--drivers/dma/bestcomm/ata.c157
-rw-r--r--drivers/dma/bestcomm/bcom_ata_task.c67
-rw-r--r--drivers/dma/bestcomm/bcom_fec_rx_task.c78
-rw-r--r--drivers/dma/bestcomm/bcom_fec_tx_task.c91
-rw-r--r--drivers/dma/bestcomm/bcom_gen_bd_rx_task.c63
-rw-r--r--drivers/dma/bestcomm/bcom_gen_bd_tx_task.c69
-rw-r--r--drivers/dma/bestcomm/bestcomm.c531
-rw-r--r--drivers/dma/bestcomm/fec.c270
-rw-r--r--drivers/dma/bestcomm/gen_bd.c354
-rw-r--r--drivers/dma/bestcomm/sram.c178
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c4
-rw-r--r--drivers/video/fsl-diu-fb.c64
18 files changed, 1953 insertions, 34 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 7863b9fee50b..d8372ab2e4cf 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -29,7 +29,7 @@ obj-$(CONFIG_PNP) += pnp/
29obj-y += amba/ 29obj-y += amba/
30# Many drivers will want to use DMA so this has to be made available 30# Many drivers will want to use DMA so this has to be made available
31# really early. 31# really early.
32obj-$(CONFIG_DMA_ENGINE) += dma/ 32obj-$(CONFIG_DMADEVICES) += dma/
33 33
34obj-$(CONFIG_VIRTIO) += virtio/ 34obj-$(CONFIG_VIRTIO) += virtio/
35obj-$(CONFIG_XEN) += xen/ 35obj-$(CONFIG_XEN) += xen/
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 652f57e83484..3a8fb28b71f2 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -26,9 +26,9 @@
26#include <asm/prom.h> 26#include <asm/prom.h>
27#include <asm/mpc52xx.h> 27#include <asm/mpc52xx.h>
28 28
29#include <sysdev/bestcomm/bestcomm.h> 29#include <linux/fsl/bestcomm/bestcomm.h>
30#include <sysdev/bestcomm/bestcomm_priv.h> 30#include <linux/fsl/bestcomm/bestcomm_priv.h>
31#include <sysdev/bestcomm/ata.h> 31#include <linux/fsl/bestcomm/ata.h>
32 32
33#define DRV_NAME "mpc52xx_ata" 33#define DRV_NAME "mpc52xx_ata"
34 34
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d4c12180c654..40179e749f08 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -125,6 +125,8 @@ config MPC512X_DMA
125 ---help--- 125 ---help---
126 Enable support for the Freescale MPC512x built-in DMA engine. 126 Enable support for the Freescale MPC512x built-in DMA engine.
127 127
128source "drivers/dma/bestcomm/Kconfig"
129
128config MV_XOR 130config MV_XOR
129 bool "Marvell XOR engine support" 131 bool "Marvell XOR engine support"
130 depends on PLAT_ORION 132 depends on PLAT_ORION
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 7428feaa8705..642d96736cf5 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/
10obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o 10obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
11obj-$(CONFIG_FSL_DMA) += fsldma.o 11obj-$(CONFIG_FSL_DMA) += fsldma.o
12obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o 12obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
13obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
13obj-$(CONFIG_MV_XOR) += mv_xor.o 14obj-$(CONFIG_MV_XOR) += mv_xor.o
14obj-$(CONFIG_DW_DMAC) += dw_dmac.o 15obj-$(CONFIG_DW_DMAC) += dw_dmac.o
15obj-$(CONFIG_AT_HDMAC) += at_hdmac.o 16obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
diff --git a/drivers/dma/bestcomm/Kconfig b/drivers/dma/bestcomm/Kconfig
new file mode 100644
index 000000000000..29e427085efb
--- /dev/null
+++ b/drivers/dma/bestcomm/Kconfig
@@ -0,0 +1,36 @@
1#
2# Kconfig options for Bestcomm
3#
4
5config PPC_BESTCOMM
6 tristate "Bestcomm DMA engine support"
7 depends on PPC_MPC52xx
8 default n
9 select PPC_LIB_RHEAP
10 help
11 BestComm is the name of the communication coprocessor found
12 on the Freescale MPC5200 family of processor. Its usage is
13 optional for some drivers (like ATA), but required for
14 others (like FEC).
15
16 If you want to use drivers that require DMA operations,
17 answer Y or M. Otherwise say N.
18
19config PPC_BESTCOMM_ATA
20 tristate
21 depends on PPC_BESTCOMM
22 help
23 This option enables the support for the ATA task.
24
25config PPC_BESTCOMM_FEC
26 tristate
27 depends on PPC_BESTCOMM
28 help
29 This option enables the support for the FEC tasks.
30
31config PPC_BESTCOMM_GEN_BD
32 tristate
33 depends on PPC_BESTCOMM
34 help
35 This option enables the support for the GenBD tasks.
36
diff --git a/drivers/dma/bestcomm/Makefile b/drivers/dma/bestcomm/Makefile
new file mode 100644
index 000000000000..aed2df2a6580
--- /dev/null
+++ b/drivers/dma/bestcomm/Makefile
@@ -0,0 +1,14 @@
1#
2# Makefile for BestComm & co
3#
4
5bestcomm-core-objs := bestcomm.o sram.o
6bestcomm-ata-objs := ata.o bcom_ata_task.o
7bestcomm-fec-objs := fec.o bcom_fec_rx_task.o bcom_fec_tx_task.o
8bestcomm-gen-bd-objs := gen_bd.o bcom_gen_bd_rx_task.o bcom_gen_bd_tx_task.o
9
10obj-$(CONFIG_PPC_BESTCOMM) += bestcomm-core.o
11obj-$(CONFIG_PPC_BESTCOMM_ATA) += bestcomm-ata.o
12obj-$(CONFIG_PPC_BESTCOMM_FEC) += bestcomm-fec.o
13obj-$(CONFIG_PPC_BESTCOMM_GEN_BD) += bestcomm-gen-bd.o
14
diff --git a/drivers/dma/bestcomm/ata.c b/drivers/dma/bestcomm/ata.c
new file mode 100644
index 000000000000..2fd87f83cf90
--- /dev/null
+++ b/drivers/dma/bestcomm/ata.c
@@ -0,0 +1,157 @@
1/*
2 * Bestcomm ATA task driver
3 *
4 *
5 * Patterned after bestcomm/fec.c by Dale Farnsworth <dfarnsworth@mvista.com>
6 * 2003-2004 (c) MontaVista, Software, Inc.
7 *
8 * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
9 * Copyright (C) 2006 Freescale - John Rigby
10 *
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/types.h>
19#include <asm/io.h>
20
21#include <linux/fsl/bestcomm/bestcomm.h>
22#include <linux/fsl/bestcomm/bestcomm_priv.h>
23#include <linux/fsl/bestcomm/ata.h>
24
25
26/* ======================================================================== */
27/* Task image/var/inc */
28/* ======================================================================== */
29
30/* ata task image */
31extern u32 bcom_ata_task[];
32
33/* ata task vars that need to be set before enabling the task */
34struct bcom_ata_var {
35 u32 enable; /* (u16*) address of task's control register */
36 u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
37 u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
38 u32 bd_start; /* (struct bcom_bd*) current bd */
39 u32 buffer_size; /* size of receive buffer */
40};
41
42/* ata task incs that need to be set before enabling the task */
43struct bcom_ata_inc {
44 u16 pad0;
45 s16 incr_bytes;
46 u16 pad1;
47 s16 incr_dst;
48 u16 pad2;
49 s16 incr_src;
50};
51
52
53/* ======================================================================== */
54/* Task support code */
55/* ======================================================================== */
56
57struct bcom_task *
58bcom_ata_init(int queue_len, int maxbufsize)
59{
60 struct bcom_task *tsk;
61 struct bcom_ata_var *var;
62 struct bcom_ata_inc *inc;
63
64 /* Prefetch breaks ATA DMA. Turn it off for ATA DMA */
65 bcom_disable_prefetch();
66
67 tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0);
68 if (!tsk)
69 return NULL;
70
71 tsk->flags = BCOM_FLAGS_NONE;
72
73 bcom_ata_reset_bd(tsk);
74
75 var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
76 inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
77
78 if (bcom_load_image(tsk->tasknum, bcom_ata_task)) {
79 bcom_task_free(tsk);
80 return NULL;
81 }
82
83 var->enable = bcom_eng->regs_base +
84 offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
85 var->bd_base = tsk->bd_pa;
86 var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
87 var->bd_start = tsk->bd_pa;
88 var->buffer_size = maxbufsize;
89
90 /* Configure some stuff */
91 bcom_set_task_pragma(tsk->tasknum, BCOM_ATA_PRAGMA);
92 bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
93
94 out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_RX], BCOM_IPR_ATA_RX);
95 out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ATA_TX], BCOM_IPR_ATA_TX);
96
97 out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
98
99 return tsk;
100}
101EXPORT_SYMBOL_GPL(bcom_ata_init);
102
103void bcom_ata_rx_prepare(struct bcom_task *tsk)
104{
105 struct bcom_ata_inc *inc;
106
107 inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
108
109 inc->incr_bytes = -(s16)sizeof(u32);
110 inc->incr_src = 0;
111 inc->incr_dst = sizeof(u32);
112
113 bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_RX);
114}
115EXPORT_SYMBOL_GPL(bcom_ata_rx_prepare);
116
117void bcom_ata_tx_prepare(struct bcom_task *tsk)
118{
119 struct bcom_ata_inc *inc;
120
121 inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum);
122
123 inc->incr_bytes = -(s16)sizeof(u32);
124 inc->incr_src = sizeof(u32);
125 inc->incr_dst = 0;
126
127 bcom_set_initiator(tsk->tasknum, BCOM_INITIATOR_ATA_TX);
128}
129EXPORT_SYMBOL_GPL(bcom_ata_tx_prepare);
130
131void bcom_ata_reset_bd(struct bcom_task *tsk)
132{
133 struct bcom_ata_var *var;
134
135 /* Reset all BD */
136 memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
137
138 tsk->index = 0;
139 tsk->outdex = 0;
140
141 var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum);
142 var->bd_start = var->bd_base;
143}
144EXPORT_SYMBOL_GPL(bcom_ata_reset_bd);
145
146void bcom_ata_release(struct bcom_task *tsk)
147{
148 /* Nothing special for the ATA tasks */
149 bcom_task_free(tsk);
150}
151EXPORT_SYMBOL_GPL(bcom_ata_release);
152
153
154MODULE_DESCRIPTION("BestComm ATA task driver");
155MODULE_AUTHOR("John Rigby");
156MODULE_LICENSE("GPL v2");
157
diff --git a/drivers/dma/bestcomm/bcom_ata_task.c b/drivers/dma/bestcomm/bcom_ata_task.c
new file mode 100644
index 000000000000..cc6049a4e469
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_ata_task.c
@@ -0,0 +1,67 @@
1/*
2 * Bestcomm ATA task microcode
3 *
4 * Copyright (c) 2004 Freescale Semiconductor, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 *
10 * Created based on bestcom/code_dma/image_rtos1/dma_image.hex
11 */
12
13#include <asm/types.h>
14
15/*
16 * The header consists of the following fields:
17 * u32 magic;
18 * u8 desc_size;
19 * u8 var_size;
20 * u8 inc_size;
21 * u8 first_var;
22 * u8 reserved[8];
23 *
24 * The size fields contain the number of 32-bit words.
25 */
26
27u32 bcom_ata_task[] = {
28 /* header */
29 0x4243544b,
30 0x0e060709,
31 0x00000000,
32 0x00000000,
33
34 /* Task descriptors */
35 0x8198009b, /* LCD: idx0 = var3; idx0 <= var2; idx0 += inc3 */
36 0x13e00c08, /* DRD1A: var3 = var1; FN=0 MORE init=31 WS=0 RS=0 */
37 0xb8000264, /* LCD: idx1 = *idx0, idx2 = var0; idx1 < var9; idx1 += inc4, idx2 += inc4 */
38 0x10000f00, /* DRD1A: var3 = idx0; FN=0 MORE init=0 WS=0 RS=0 */
39 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
40 0x0c8cfc8a, /* DRD2B1: *idx2 = EU3(); EU3(*idx2,var10) */
41 0xd8988240, /* LCDEXT: idx1 = idx1; idx1 > var9; idx1 += inc0 */
42 0xf845e011, /* LCDEXT: idx2 = *(idx0 + var00000015); ; idx2 += inc2 */
43 0xb845e00a, /* LCD: idx3 = *(idx0 + var00000019); ; idx3 += inc1 */
44 0x0bfecf90, /* DRD1A: *idx3 = *idx2; FN=0 TFD init=31 WS=3 RS=3 */
45 0x9898802d, /* LCD: idx1 = idx1; idx1 once var0; idx1 += inc5 */
46 0x64000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 INT EXT init=0 WS=0 RS=0 */
47 0x0c0cf849, /* DRD2B1: *idx0 = EU3(); EU3(idx1,var9) */
48 0x000001f8, /* NOP */
49
50 /* VAR[9]-VAR[14] */
51 0x40000000,
52 0x7fff7fff,
53 0x00000000,
54 0x00000000,
55 0x00000000,
56 0x00000000,
57
58 /* INC[0]-INC[6] */
59 0x40000000,
60 0xe0000000,
61 0xe0000000,
62 0xa000000c,
63 0x20000000,
64 0x00000000,
65 0x00000000,
66};
67
diff --git a/drivers/dma/bestcomm/bcom_fec_rx_task.c b/drivers/dma/bestcomm/bcom_fec_rx_task.c
new file mode 100644
index 000000000000..a1ad6a02fcef
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_fec_rx_task.c
@@ -0,0 +1,78 @@
1/*
2 * Bestcomm FEC RX task microcode
3 *
4 * Copyright (c) 2004 Freescale Semiconductor, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 *
10 * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
11 * on Tue Mar 22 11:19:38 2005 GMT
12 */
13
14#include <asm/types.h>
15
16/*
17 * The header consists of the following fields:
18 * u32 magic;
19 * u8 desc_size;
20 * u8 var_size;
21 * u8 inc_size;
22 * u8 first_var;
23 * u8 reserved[8];
24 *
25 * The size fields contain the number of 32-bit words.
26 */
27
28u32 bcom_fec_rx_task[] = {
29 /* header */
30 0x4243544b,
31 0x18060709,
32 0x00000000,
33 0x00000000,
34
35 /* Task descriptors */
36 0x808220e3, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
37 0x10601010, /* DRD1A: var4 = var2; FN=0 MORE init=3 WS=0 RS=0 */
38 0xb8800264, /* LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc4, idx3 += inc4 */
39 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
40 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
41 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
42 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
43 0xb8c58029, /* LCD: idx3 = *(idx1 + var00000015); idx3 once var0; idx3 += inc5 */
44 0x60000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
45 0x088cf8cc, /* DRD2B1: idx2 = EU3(); EU3(idx3,var12) */
46 0x991982f2, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var11; idx2 += inc6, idx3 += inc2 */
47 0x006acf80, /* DRD1A: *idx3 = *idx0; FN=0 init=3 WS=1 RS=1 */
48 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
49 0x9999802d, /* LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
50 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
51 0x034cfc4e, /* DRD2B1: var13 = EU3(); EU3(*idx1,var14) */
52 0x00008868, /* DRD1A: idx2 = var13; FN=0 init=0 WS=0 RS=0 */
53 0x99198341, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var13; idx2 += inc0, idx3 += inc1 */
54 0x007ecf80, /* DRD1A: *idx3 = *idx0; FN=0 init=3 WS=3 RS=3 */
55 0x99198272, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc6, idx3 += inc2 */
56 0x046acf80, /* DRD1A: *idx3 = *idx0; FN=0 INT init=3 WS=1 RS=1 */
57 0x9819002d, /* LCD: idx2 = idx0; idx2 once var0; idx2 += inc5 */
58 0x0060c790, /* DRD1A: *idx1 = *idx2; FN=0 init=3 WS=0 RS=0 */
59 0x000001f8, /* NOP */
60
61 /* VAR[9]-VAR[14] */
62 0x40000000,
63 0x7fff7fff,
64 0x00000000,
65 0x00000003,
66 0x40000008,
67 0x43ffffff,
68
69 /* INC[0]-INC[6] */
70 0x40000000,
71 0xe0000000,
72 0xe0000000,
73 0xa0000008,
74 0x20000000,
75 0x00000000,
76 0x4000ffff,
77};
78
diff --git a/drivers/dma/bestcomm/bcom_fec_tx_task.c b/drivers/dma/bestcomm/bcom_fec_tx_task.c
new file mode 100644
index 000000000000..b1c495c3a65a
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_fec_tx_task.c
@@ -0,0 +1,91 @@
1/*
2 * Bestcomm FEC TX task microcode
3 *
4 * Copyright (c) 2004 Freescale Semiconductor, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 *
10 * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
11 * on Tue Mar 22 11:19:29 2005 GMT
12 */
13
14#include <asm/types.h>
15
16/*
17 * The header consists of the following fields:
18 * u32 magic;
19 * u8 desc_size;
20 * u8 var_size;
21 * u8 inc_size;
22 * u8 first_var;
23 * u8 reserved[8];
24 *
25 * The size fields contain the number of 32-bit words.
26 */
27
28u32 bcom_fec_tx_task[] = {
29 /* header */
30 0x4243544b,
31 0x2407070d,
32 0x00000000,
33 0x00000000,
34
35 /* Task descriptors */
36 0x8018001b, /* LCD: idx0 = var0; idx0 <= var0; idx0 += inc3 */
37 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
38 0x01ccfc0d, /* DRD2B1: var7 = EU3(); EU3(*idx0,var13) */
39 0x8082a123, /* LCD: idx0 = var1, idx1 = var5; idx1 <= var4; idx0 += inc4, idx1 += inc3 */
40 0x10801418, /* DRD1A: var5 = var3; FN=0 MORE init=4 WS=0 RS=0 */
41 0xf88103a4, /* LCDEXT: idx2 = *idx1, idx3 = var2; idx2 < var14; idx2 += inc4, idx3 += inc4 */
42 0x801a6024, /* LCD: idx4 = var0; ; idx4 += inc4 */
43 0x10001708, /* DRD1A: var5 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
44 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
45 0x0cccfccf, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var15) */
46 0x991a002c, /* LCD: idx2 = idx2, idx3 = idx4; idx2 once var0; idx2 += inc5, idx3 += inc4 */
47 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
48 0x024cfc4d, /* DRD2B1: var9 = EU3(); EU3(*idx1,var13) */
49 0x60000003, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */
50 0x0cccf247, /* DRD2B1: *idx3 = EU3(); EU3(var9,var7) */
51 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
52 0xb8c80029, /* LCD: idx3 = *(idx1 + var0000001a); idx3 once var0; idx3 += inc5 */
53 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
54 0x088cf8d1, /* DRD2B1: idx2 = EU3(); EU3(idx3,var17) */
55 0x00002f10, /* DRD1A: var11 = idx2; FN=0 init=0 WS=0 RS=0 */
56 0x99198432, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var16; idx2 += inc6, idx3 += inc2 */
57 0x008ac398, /* DRD1A: *idx0 = *idx3; FN=0 init=4 WS=1 RS=1 */
58 0x80004000, /* LCDEXT: idx2 = 0x00000000; ; */
59 0x9999802d, /* LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
60 0x70000002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
61 0x048cfc53, /* DRD2B1: var18 = EU3(); EU3(*idx1,var19) */
62 0x60000008, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=8 EXT init=0 WS=0 RS=0 */
63 0x088cf48b, /* DRD2B1: idx2 = EU3(); EU3(var18,var11) */
64 0x99198481, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var18; idx2 += inc0, idx3 += inc1 */
65 0x009ec398, /* DRD1A: *idx0 = *idx3; FN=0 init=4 WS=3 RS=3 */
66 0x991983b2, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var14; idx2 += inc6, idx3 += inc2 */
67 0x088ac398, /* DRD1A: *idx0 = *idx3; FN=0 TFD init=4 WS=1 RS=1 */
68 0x9919002d, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc5 */
69 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
70 0x0c4cf88e, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var14) */
71 0x000001f8, /* NOP */
72
73 /* VAR[13]-VAR[19] */
74 0x0c000000,
75 0x40000000,
76 0x7fff7fff,
77 0x00000000,
78 0x00000003,
79 0x40000004,
80 0x43ffffff,
81
82 /* INC[0]-INC[6] */
83 0x40000000,
84 0xe0000000,
85 0xe0000000,
86 0xa0000008,
87 0x20000000,
88 0x00000000,
89 0x4000ffff,
90};
91
diff --git a/drivers/dma/bestcomm/bcom_gen_bd_rx_task.c b/drivers/dma/bestcomm/bcom_gen_bd_rx_task.c
new file mode 100644
index 000000000000..efee022b0256
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_gen_bd_rx_task.c
@@ -0,0 +1,63 @@
1/*
2 * Bestcomm GenBD RX task microcode
3 *
4 * Copyright (C) 2006 AppSpec Computer Technologies Corp.
5 * Jeff Gibbons <jeff.gibbons@appspec.com>
6 * Copyright (c) 2004 Freescale Semiconductor, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
13 * on Tue Mar 4 10:14:12 2006 GMT
14 *
15 */
16
17#include <asm/types.h>
18
19/*
20 * The header consists of the following fields:
21 * u32 magic;
22 * u8 desc_size;
23 * u8 var_size;
24 * u8 inc_size;
25 * u8 first_var;
26 * u8 reserved[8];
27 *
28 * The size fields contain the number of 32-bit words.
29 */
30
31u32 bcom_gen_bd_rx_task[] = {
32 /* header */
33 0x4243544b,
34 0x0d020409,
35 0x00000000,
36 0x00000000,
37
38 /* Task descriptors */
39 0x808220da, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc3, idx1 += inc2 */
40 0x13e01010, /* DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
41 0xb880025b, /* LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc3, idx3 += inc3 */
42 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
43 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
44 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
45 0xd9190240, /* LCDEXT: idx2 = idx2; idx2 > var9; idx2 += inc0 */
46 0xb8c5e009, /* LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
47 0x07fecf80, /* DRD1A: *idx3 = *idx0; FN=0 INT init=31 WS=3 RS=3 */
48 0x99190024, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc4 */
49 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
50 0x0c4cf889, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var9) */
51 0x000001f8, /* NOP */
52
53 /* VAR[9]-VAR[10] */
54 0x40000000,
55 0x7fff7fff,
56
57 /* INC[0]-INC[3] */
58 0x40000000,
59 0xe0000000,
60 0xa0000008,
61 0x20000000,
62};
63
diff --git a/drivers/dma/bestcomm/bcom_gen_bd_tx_task.c b/drivers/dma/bestcomm/bcom_gen_bd_tx_task.c
new file mode 100644
index 000000000000..c605aa42ecbb
--- /dev/null
+++ b/drivers/dma/bestcomm/bcom_gen_bd_tx_task.c
@@ -0,0 +1,69 @@
1/*
2 * Bestcomm GenBD TX task microcode
3 *
4 * Copyright (C) 2006 AppSpec Computer Technologies Corp.
5 * Jeff Gibbons <jeff.gibbons@appspec.com>
6 * Copyright (c) 2004 Freescale Semiconductor, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 * Based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
13 * on Tue Mar 4 10:14:12 2006 GMT
14 *
15 */
16
17#include <asm/types.h>
18
19/*
20 * The header consists of the following fields:
21 * u32 magic;
22 * u8 desc_size;
23 * u8 var_size;
24 * u8 inc_size;
25 * u8 first_var;
26 * u8 reserved[8];
27 *
28 * The size fields contain the number of 32-bit words.
29 */
30
31u32 bcom_gen_bd_tx_task[] = {
32 /* header */
33 0x4243544b,
34 0x0f040609,
35 0x00000000,
36 0x00000000,
37
38 /* Task descriptors */
39 0x800220e3, /* LCD: idx0 = var0, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
40 0x13e01010, /* DRD1A: var4 = var2; FN=0 MORE init=31 WS=0 RS=0 */
41 0xb8808264, /* LCD: idx2 = *idx1, idx3 = var1; idx2 < var9; idx2 += inc4, idx3 += inc4 */
42 0x10001308, /* DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
43 0x60140002, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
44 0x0cccfcca, /* DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
45 0xd9190300, /* LCDEXT: idx2 = idx2; idx2 > var12; idx2 += inc0 */
46 0xb8c5e009, /* LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
47 0x03fec398, /* DRD1A: *idx0 = *idx3; FN=0 init=31 WS=3 RS=3 */
48 0x9919826a, /* LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc5, idx3 += inc2 */
49 0x0feac398, /* DRD1A: *idx0 = *idx3; FN=0 TFD INT init=31 WS=1 RS=1 */
50 0x99190036, /* LCD: idx2 = idx2; idx2 once var0; idx2 += inc6 */
51 0x60000005, /* DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
52 0x0c4cf889, /* DRD2B1: *idx1 = EU3(); EU3(idx2,var9) */
53 0x000001f8, /* NOP */
54
55 /* VAR[9]-VAR[12] */
56 0x40000000,
57 0x7fff7fff,
58 0x00000000,
59 0x40000004,
60
61 /* INC[0]-INC[5] */
62 0x40000000,
63 0xe0000000,
64 0xe0000000,
65 0xa0000008,
66 0x20000000,
67 0x4000ffff,
68};
69
diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
new file mode 100644
index 000000000000..3a1894603282
--- /dev/null
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -0,0 +1,531 @@
1/*
2 * Driver for MPC52xx processor BestComm peripheral controller
3 *
4 *
5 * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
6 * Copyright (C) 2005 Varma Electronics Oy,
7 * ( by Andrey Volkov <avolkov@varma-el.com> )
8 * Copyright (C) 2003-2004 MontaVista, Software, Inc.
9 * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
10 *
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
14 */
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <linux/of.h>
20#include <linux/of_device.h>
21#include <linux/of_platform.h>
22#include <asm/io.h>
23#include <asm/irq.h>
24#include <asm/mpc52xx.h>
25
26#include <linux/fsl/bestcomm/sram.h>
27#include <linux/fsl/bestcomm/bestcomm_priv.h>
28#include "linux/fsl/bestcomm/bestcomm.h"
29
30#define DRIVER_NAME "bestcomm-core"
31
32/* MPC5200 device tree match tables */
33static struct of_device_id mpc52xx_sram_ids[] = {
34 { .compatible = "fsl,mpc5200-sram", },
35 { .compatible = "mpc5200-sram", },
36 {}
37};
38
39
40struct bcom_engine *bcom_eng = NULL;
41EXPORT_SYMBOL_GPL(bcom_eng); /* needed for inline functions */
42
43/* ======================================================================== */
44/* Public and private API */
45/* ======================================================================== */
46
47/* Private API */
48
49struct bcom_task *
50bcom_task_alloc(int bd_count, int bd_size, int priv_size)
51{
52 int i, tasknum = -1;
53 struct bcom_task *tsk;
54
55 /* Don't try to do anything if bestcomm init failed */
56 if (!bcom_eng)
57 return NULL;
58
59 /* Get and reserve a task num */
60 spin_lock(&bcom_eng->lock);
61
62 for (i=0; i<BCOM_MAX_TASKS; i++)
63 if (!bcom_eng->tdt[i].stop) { /* we use stop as a marker */
64 bcom_eng->tdt[i].stop = 0xfffffffful; /* dummy addr */
65 tasknum = i;
66 break;
67 }
68
69 spin_unlock(&bcom_eng->lock);
70
71 if (tasknum < 0)
72 return NULL;
73
74 /* Allocate our structure */
75 tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
76 if (!tsk)
77 goto error;
78
79 tsk->tasknum = tasknum;
80 if (priv_size)
81 tsk->priv = (void*)tsk + sizeof(struct bcom_task);
82
83 /* Get IRQ of that task */
84 tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
85 if (tsk->irq == NO_IRQ)
86 goto error;
87
88 /* Init the BDs, if needed */
89 if (bd_count) {
90 tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL);
91 if (!tsk->cookie)
92 goto error;
93
94 tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
95 if (!tsk->bd)
96 goto error;
97 memset(tsk->bd, 0x00, bd_count * bd_size);
98
99 tsk->num_bd = bd_count;
100 tsk->bd_size = bd_size;
101 }
102
103 return tsk;
104
105error:
106 if (tsk) {
107 if (tsk->irq != NO_IRQ)
108 irq_dispose_mapping(tsk->irq);
109 bcom_sram_free(tsk->bd);
110 kfree(tsk->cookie);
111 kfree(tsk);
112 }
113
114 bcom_eng->tdt[tasknum].stop = 0;
115
116 return NULL;
117}
118EXPORT_SYMBOL_GPL(bcom_task_alloc);
119
120void
121bcom_task_free(struct bcom_task *tsk)
122{
123 /* Stop the task */
124 bcom_disable_task(tsk->tasknum);
125
126 /* Clear TDT */
127 bcom_eng->tdt[tsk->tasknum].start = 0;
128 bcom_eng->tdt[tsk->tasknum].stop = 0;
129
130 /* Free everything */
131 irq_dispose_mapping(tsk->irq);
132 bcom_sram_free(tsk->bd);
133 kfree(tsk->cookie);
134 kfree(tsk);
135}
136EXPORT_SYMBOL_GPL(bcom_task_free);
137
138int
139bcom_load_image(int task, u32 *task_image)
140{
141 struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
142 struct bcom_tdt *tdt;
143 u32 *desc, *var, *inc;
144 u32 *desc_src, *var_src, *inc_src;
145
146 /* Safety checks */
147 if (hdr->magic != BCOM_TASK_MAGIC) {
148 printk(KERN_ERR DRIVER_NAME
149 ": Trying to load invalid microcode\n");
150 return -EINVAL;
151 }
152
153 if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
154 printk(KERN_ERR DRIVER_NAME
155 ": Trying to load invalid task %d\n", task);
156 return -EINVAL;
157 }
158
159 /* Initial load or reload */
160 tdt = &bcom_eng->tdt[task];
161
162 if (tdt->start) {
163 desc = bcom_task_desc(task);
164 if (hdr->desc_size != bcom_task_num_descs(task)) {
165 printk(KERN_ERR DRIVER_NAME
166 ": Trying to reload wrong task image "
167 "(%d size %d/%d)!\n",
168 task,
169 hdr->desc_size,
170 bcom_task_num_descs(task));
171 return -EINVAL;
172 }
173 } else {
174 phys_addr_t start_pa;
175
176 desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
177 if (!desc)
178 return -ENOMEM;
179
180 tdt->start = start_pa;
181 tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
182 }
183
184 var = bcom_task_var(task);
185 inc = bcom_task_inc(task);
186
187 /* Clear & copy */
188 memset(var, 0x00, BCOM_VAR_SIZE);
189 memset(inc, 0x00, BCOM_INC_SIZE);
190
191 desc_src = (u32 *)(hdr + 1);
192 var_src = desc_src + hdr->desc_size;
193 inc_src = var_src + hdr->var_size;
194
195 memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
196 memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
197 memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
198
199 return 0;
200}
201EXPORT_SYMBOL_GPL(bcom_load_image);
202
203void
204bcom_set_initiator(int task, int initiator)
205{
206 int i;
207 int num_descs;
208 u32 *desc;
209 int next_drd_has_initiator;
210
211 bcom_set_tcr_initiator(task, initiator);
212
213 /* Just setting tcr is apparently not enough due to some problem */
214 /* with it. So we just go thru all the microcode and replace in */
215 /* the DRD directly */
216
217 desc = bcom_task_desc(task);
218 next_drd_has_initiator = 1;
219 num_descs = bcom_task_num_descs(task);
220
221 for (i=0; i<num_descs; i++, desc++) {
222 if (!bcom_desc_is_drd(*desc))
223 continue;
224 if (next_drd_has_initiator)
225 if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
226 bcom_set_desc_initiator(desc, initiator);
227 next_drd_has_initiator = !bcom_drd_is_extended(*desc);
228 }
229}
230EXPORT_SYMBOL_GPL(bcom_set_initiator);
231
232
233/* Public API */
234
235void
236bcom_enable(struct bcom_task *tsk)
237{
238 bcom_enable_task(tsk->tasknum);
239}
240EXPORT_SYMBOL_GPL(bcom_enable);
241
242void
243bcom_disable(struct bcom_task *tsk)
244{
245 bcom_disable_task(tsk->tasknum);
246}
247EXPORT_SYMBOL_GPL(bcom_disable);
248
249
250/* ======================================================================== */
251/* Engine init/cleanup */
252/* ======================================================================== */
253
254/* Function Descriptor table */
255/* this will need to be updated if Freescale changes their task code FDT */
256static u32 fdt_ops[] = {
257 0xa0045670, /* FDT[48] - load_acc() */
258 0x80045670, /* FDT[49] - unload_acc() */
259 0x21800000, /* FDT[50] - and() */
260 0x21e00000, /* FDT[51] - or() */
261 0x21500000, /* FDT[52] - xor() */
262 0x21400000, /* FDT[53] - andn() */
263 0x21500000, /* FDT[54] - not() */
264 0x20400000, /* FDT[55] - add() */
265 0x20500000, /* FDT[56] - sub() */
266 0x20800000, /* FDT[57] - lsh() */
267 0x20a00000, /* FDT[58] - rsh() */
268 0xc0170000, /* FDT[59] - crc8() */
269 0xc0145670, /* FDT[60] - crc16() */
270 0xc0345670, /* FDT[61] - crc32() */
271 0xa0076540, /* FDT[62] - endian32() */
272 0xa0000760, /* FDT[63] - endian16() */
273};
274
275
276static int bcom_engine_init(void)
277{
278 int task;
279 phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
280 unsigned int tdt_size, ctx_size, var_size, fdt_size;
281
282 /* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
283 tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
284 ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
285 var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
286 fdt_size = BCOM_FDT_SIZE;
287
288 bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
289 bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
290 bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
291 bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
292
293 if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
294 printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
295
296 bcom_sram_free(bcom_eng->tdt);
297 bcom_sram_free(bcom_eng->ctx);
298 bcom_sram_free(bcom_eng->var);
299 bcom_sram_free(bcom_eng->fdt);
300
301 return -ENOMEM;
302 }
303
304 memset(bcom_eng->tdt, 0x00, tdt_size);
305 memset(bcom_eng->ctx, 0x00, ctx_size);
306 memset(bcom_eng->var, 0x00, var_size);
307 memset(bcom_eng->fdt, 0x00, fdt_size);
308
309 /* Copy the FDT for the EU#3 */
310 memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
311
312 /* Initialize Task base structure */
313 for (task=0; task<BCOM_MAX_TASKS; task++)
314 {
315 out_be16(&bcom_eng->regs->tcr[task], 0);
316 out_8(&bcom_eng->regs->ipr[task], 0);
317
318 bcom_eng->tdt[task].context = ctx_pa;
319 bcom_eng->tdt[task].var = var_pa;
320 bcom_eng->tdt[task].fdt = fdt_pa;
321
322 var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
323 ctx_pa += BCOM_CTX_SIZE;
324 }
325
326 out_be32(&bcom_eng->regs->taskBar, tdt_pa);
327
328 /* Init 'always' initiator */
329 out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
330
331 /* Disable COMM Bus Prefetch on the original 5200; it's broken */
332 if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
333 bcom_disable_prefetch();
334
335 /* Init lock */
336 spin_lock_init(&bcom_eng->lock);
337
338 return 0;
339}
340
341static void
342bcom_engine_cleanup(void)
343{
344 int task;
345
346 /* Stop all tasks */
347 for (task=0; task<BCOM_MAX_TASKS; task++)
348 {
349 out_be16(&bcom_eng->regs->tcr[task], 0);
350 out_8(&bcom_eng->regs->ipr[task], 0);
351 }
352
353 out_be32(&bcom_eng->regs->taskBar, 0ul);
354
355 /* Release the SRAM zones */
356 bcom_sram_free(bcom_eng->tdt);
357 bcom_sram_free(bcom_eng->ctx);
358 bcom_sram_free(bcom_eng->var);
359 bcom_sram_free(bcom_eng->fdt);
360}
361
362
363/* ======================================================================== */
364/* OF platform driver */
365/* ======================================================================== */
366
367static int mpc52xx_bcom_probe(struct platform_device *op)
368{
369 struct device_node *ofn_sram;
370 struct resource res_bcom;
371
372 int rv;
373
374 /* Inform user we're ok so far */
375 printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
376
377 /* Get the bestcomm node */
378 of_node_get(op->dev.of_node);
379
380 /* Prepare SRAM */
381 ofn_sram = of_find_matching_node(NULL, mpc52xx_sram_ids);
382 if (!ofn_sram) {
383 printk(KERN_ERR DRIVER_NAME ": "
384 "No SRAM found in device tree\n");
385 rv = -ENODEV;
386 goto error_ofput;
387 }
388 rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
389 of_node_put(ofn_sram);
390
391 if (rv) {
392 printk(KERN_ERR DRIVER_NAME ": "
393 "Error in SRAM init\n");
394 goto error_ofput;
395 }
396
397 /* Get a clean struct */
398 bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
399 if (!bcom_eng) {
400 printk(KERN_ERR DRIVER_NAME ": "
401 "Can't allocate state structure\n");
402 rv = -ENOMEM;
403 goto error_sramclean;
404 }
405
406 /* Save the node */
407 bcom_eng->ofnode = op->dev.of_node;
408
409 /* Get, reserve & map io */
410 if (of_address_to_resource(op->dev.of_node, 0, &res_bcom)) {
411 printk(KERN_ERR DRIVER_NAME ": "
412 "Can't get resource\n");
413 rv = -EINVAL;
414 goto error_sramclean;
415 }
416
417 if (!request_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma),
418 DRIVER_NAME)) {
419 printk(KERN_ERR DRIVER_NAME ": "
420 "Can't request registers region\n");
421 rv = -EBUSY;
422 goto error_sramclean;
423 }
424
425 bcom_eng->regs_base = res_bcom.start;
426 bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
427 if (!bcom_eng->regs) {
428 printk(KERN_ERR DRIVER_NAME ": "
429 "Can't map registers\n");
430 rv = -ENOMEM;
431 goto error_release;
432 }
433
434 /* Now, do the real init */
435 rv = bcom_engine_init();
436 if (rv)
437 goto error_unmap;
438
439 /* Done ! */
440 printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
441 (long)bcom_eng->regs_base);
442
443 return 0;
444
445 /* Error path */
446error_unmap:
447 iounmap(bcom_eng->regs);
448error_release:
449 release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
450error_sramclean:
451 kfree(bcom_eng);
452 bcom_sram_cleanup();
453error_ofput:
454 of_node_put(op->dev.of_node);
455
456 printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
457
458 return rv;
459}
460
461
462static int mpc52xx_bcom_remove(struct platform_device *op)
463{
464 /* Clean up the engine */
465 bcom_engine_cleanup();
466
467 /* Cleanup SRAM */
468 bcom_sram_cleanup();
469
470 /* Release regs */
471 iounmap(bcom_eng->regs);
472 release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
473
474 /* Release the node */
475 of_node_put(bcom_eng->ofnode);
476
477 /* Release memory */
478 kfree(bcom_eng);
479 bcom_eng = NULL;
480
481 return 0;
482}
483
484static struct of_device_id mpc52xx_bcom_of_match[] = {
485 { .compatible = "fsl,mpc5200-bestcomm", },
486 { .compatible = "mpc5200-bestcomm", },
487 {},
488};
489
490MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
491
492
493static struct platform_driver mpc52xx_bcom_of_platform_driver = {
494 .probe = mpc52xx_bcom_probe,
495 .remove = mpc52xx_bcom_remove,
496 .driver = {
497 .name = DRIVER_NAME,
498 .owner = THIS_MODULE,
499 .of_match_table = mpc52xx_bcom_of_match,
500 },
501};
502
503
504/* ======================================================================== */
505/* Module */
506/* ======================================================================== */
507
508static int __init
509mpc52xx_bcom_init(void)
510{
511 return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
512}
513
514static void __exit
515mpc52xx_bcom_exit(void)
516{
517 platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
518}
519
520/* If we're not a module, we must make sure everything is setup before */
521/* anyone tries to use us ... that's why we use subsys_initcall instead */
522/* of module_init. */
523subsys_initcall(mpc52xx_bcom_init);
524module_exit(mpc52xx_bcom_exit);
525
526MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
527MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
528MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
529MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
530MODULE_LICENSE("GPL v2");
531
diff --git a/drivers/dma/bestcomm/fec.c b/drivers/dma/bestcomm/fec.c
new file mode 100644
index 000000000000..7f1fb1c999e4
--- /dev/null
+++ b/drivers/dma/bestcomm/fec.c
@@ -0,0 +1,270 @@
1/*
2 * Bestcomm FEC tasks driver
3 *
4 *
5 * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
6 * Copyright (C) 2003-2004 MontaVista, Software, Inc.
7 * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
8 *
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied.
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/types.h>
17#include <asm/io.h>
18
19#include <linux/fsl/bestcomm/bestcomm.h>
20#include <linux/fsl/bestcomm/bestcomm_priv.h>
21#include <linux/fsl/bestcomm/fec.h>
22
23
24/* ======================================================================== */
25/* Task image/var/inc */
26/* ======================================================================== */
27
28/* fec tasks images */
29extern u32 bcom_fec_rx_task[];
30extern u32 bcom_fec_tx_task[];
31
32/* rx task vars that need to be set before enabling the task */
33struct bcom_fec_rx_var {
34 u32 enable; /* (u16*) address of task's control register */
35 u32 fifo; /* (u32*) address of fec's fifo */
36 u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
37 u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
38 u32 bd_start; /* (struct bcom_bd*) current bd */
39 u32 buffer_size; /* size of receive buffer */
40};
41
42/* rx task incs that need to be set before enabling the task */
43struct bcom_fec_rx_inc {
44 u16 pad0;
45 s16 incr_bytes;
46 u16 pad1;
47 s16 incr_dst;
48 u16 pad2;
49 s16 incr_dst_ma;
50};
51
52/* tx task vars that need to be set before enabling the task */
53struct bcom_fec_tx_var {
54 u32 DRD; /* (u32*) address of self-modified DRD */
55 u32 fifo; /* (u32*) address of fec's fifo */
56 u32 enable; /* (u16*) address of task's control register */
57 u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
58 u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
59 u32 bd_start; /* (struct bcom_bd*) current bd */
60 u32 buffer_size; /* set by uCode for each packet */
61};
62
63/* tx task incs that need to be set before enabling the task */
64struct bcom_fec_tx_inc {
65 u16 pad0;
66 s16 incr_bytes;
67 u16 pad1;
68 s16 incr_src;
69 u16 pad2;
70 s16 incr_src_ma;
71};
72
73/* private structure in the task */
74struct bcom_fec_priv {
75 phys_addr_t fifo;
76 int maxbufsize;
77};
78
79
80/* ======================================================================== */
81/* Task support code */
82/* ======================================================================== */
83
84struct bcom_task *
85bcom_fec_rx_init(int queue_len, phys_addr_t fifo, int maxbufsize)
86{
87 struct bcom_task *tsk;
88 struct bcom_fec_priv *priv;
89
90 tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
91 sizeof(struct bcom_fec_priv));
92 if (!tsk)
93 return NULL;
94
95 tsk->flags = BCOM_FLAGS_NONE;
96
97 priv = tsk->priv;
98 priv->fifo = fifo;
99 priv->maxbufsize = maxbufsize;
100
101 if (bcom_fec_rx_reset(tsk)) {
102 bcom_task_free(tsk);
103 return NULL;
104 }
105
106 return tsk;
107}
108EXPORT_SYMBOL_GPL(bcom_fec_rx_init);
109
110int
111bcom_fec_rx_reset(struct bcom_task *tsk)
112{
113 struct bcom_fec_priv *priv = tsk->priv;
114 struct bcom_fec_rx_var *var;
115 struct bcom_fec_rx_inc *inc;
116
117 /* Shutdown the task */
118 bcom_disable_task(tsk->tasknum);
119
120 /* Reset the microcode */
121 var = (struct bcom_fec_rx_var *) bcom_task_var(tsk->tasknum);
122 inc = (struct bcom_fec_rx_inc *) bcom_task_inc(tsk->tasknum);
123
124 if (bcom_load_image(tsk->tasknum, bcom_fec_rx_task))
125 return -1;
126
127 var->enable = bcom_eng->regs_base +
128 offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
129 var->fifo = (u32) priv->fifo;
130 var->bd_base = tsk->bd_pa;
131 var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
132 var->bd_start = tsk->bd_pa;
133 var->buffer_size = priv->maxbufsize;
134
135 inc->incr_bytes = -(s16)sizeof(u32); /* These should be in the */
136 inc->incr_dst = sizeof(u32); /* task image, but we stick */
137 inc->incr_dst_ma= sizeof(u8); /* to the official ones */
138
139 /* Reset the BDs */
140 tsk->index = 0;
141 tsk->outdex = 0;
142
143 memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
144
145 /* Configure some stuff */
146 bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA);
147 bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
148
149 out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_RX], BCOM_IPR_FEC_RX);
150
151 out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
152
153 return 0;
154}
155EXPORT_SYMBOL_GPL(bcom_fec_rx_reset);
156
157void
158bcom_fec_rx_release(struct bcom_task *tsk)
159{
160 /* Nothing special for the FEC tasks */
161 bcom_task_free(tsk);
162}
163EXPORT_SYMBOL_GPL(bcom_fec_rx_release);
164
165
166
167 /* Return 2nd to last DRD */
168 /* This is an ugly hack, but at least it's only done
169 once at initialization */
170static u32 *self_modified_drd(int tasknum)
171{
172 u32 *desc;
173 int num_descs;
174 int drd_count;
175 int i;
176
177 num_descs = bcom_task_num_descs(tasknum);
178 desc = bcom_task_desc(tasknum) + num_descs - 1;
179 drd_count = 0;
180 for (i=0; i<num_descs; i++, desc--)
181 if (bcom_desc_is_drd(*desc) && ++drd_count == 3)
182 break;
183 return desc;
184}
185
186struct bcom_task *
187bcom_fec_tx_init(int queue_len, phys_addr_t fifo)
188{
189 struct bcom_task *tsk;
190 struct bcom_fec_priv *priv;
191
192 tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_fec_bd),
193 sizeof(struct bcom_fec_priv));
194 if (!tsk)
195 return NULL;
196
197 tsk->flags = BCOM_FLAGS_ENABLE_TASK;
198
199 priv = tsk->priv;
200 priv->fifo = fifo;
201
202 if (bcom_fec_tx_reset(tsk)) {
203 bcom_task_free(tsk);
204 return NULL;
205 }
206
207 return tsk;
208}
209EXPORT_SYMBOL_GPL(bcom_fec_tx_init);
210
211int
212bcom_fec_tx_reset(struct bcom_task *tsk)
213{
214 struct bcom_fec_priv *priv = tsk->priv;
215 struct bcom_fec_tx_var *var;
216 struct bcom_fec_tx_inc *inc;
217
218 /* Shutdown the task */
219 bcom_disable_task(tsk->tasknum);
220
221 /* Reset the microcode */
222 var = (struct bcom_fec_tx_var *) bcom_task_var(tsk->tasknum);
223 inc = (struct bcom_fec_tx_inc *) bcom_task_inc(tsk->tasknum);
224
225 if (bcom_load_image(tsk->tasknum, bcom_fec_tx_task))
226 return -1;
227
228 var->enable = bcom_eng->regs_base +
229 offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
230 var->fifo = (u32) priv->fifo;
231 var->DRD = bcom_sram_va2pa(self_modified_drd(tsk->tasknum));
232 var->bd_base = tsk->bd_pa;
233 var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
234 var->bd_start = tsk->bd_pa;
235
236 inc->incr_bytes = -(s16)sizeof(u32); /* These should be in the */
237 inc->incr_src = sizeof(u32); /* task image, but we stick */
238 inc->incr_src_ma= sizeof(u8); /* to the official ones */
239
240 /* Reset the BDs */
241 tsk->index = 0;
242 tsk->outdex = 0;
243
244 memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
245
246 /* Configure some stuff */
247 bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA);
248 bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
249
250 out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_FEC_TX], BCOM_IPR_FEC_TX);
251
252 out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
253
254 return 0;
255}
256EXPORT_SYMBOL_GPL(bcom_fec_tx_reset);
257
258void
259bcom_fec_tx_release(struct bcom_task *tsk)
260{
261 /* Nothing special for the FEC tasks */
262 bcom_task_free(tsk);
263}
264EXPORT_SYMBOL_GPL(bcom_fec_tx_release);
265
266
267MODULE_DESCRIPTION("BestComm FEC tasks driver");
268MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
269MODULE_LICENSE("GPL v2");
270
diff --git a/drivers/dma/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c
new file mode 100644
index 000000000000..1a5b22d88127
--- /dev/null
+++ b/drivers/dma/bestcomm/gen_bd.c
@@ -0,0 +1,354 @@
1/*
2 * Driver for MPC52xx processor BestComm General Buffer Descriptor
3 *
4 * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
5 * Copyright (C) 2006 AppSpec Computer Technologies Corp.
6 * Jeff Gibbons <jeff.gibbons@appspec.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/types.h>
18#include <asm/errno.h>
19#include <asm/io.h>
20
21#include <asm/mpc52xx.h>
22#include <asm/mpc52xx_psc.h>
23
24#include <linux/fsl/bestcomm/bestcomm.h>
25#include <linux/fsl/bestcomm/bestcomm_priv.h>
26#include <linux/fsl/bestcomm/gen_bd.h>
27
28
29/* ======================================================================== */
30/* Task image/var/inc */
31/* ======================================================================== */
32
33/* gen_bd tasks images */
34extern u32 bcom_gen_bd_rx_task[];
35extern u32 bcom_gen_bd_tx_task[];
36
37/* rx task vars that need to be set before enabling the task */
38struct bcom_gen_bd_rx_var {
39 u32 enable; /* (u16*) address of task's control register */
40 u32 fifo; /* (u32*) address of gen_bd's fifo */
41 u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
42 u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
43 u32 bd_start; /* (struct bcom_bd*) current bd */
44 u32 buffer_size; /* size of receive buffer */
45};
46
47/* rx task incs that need to be set before enabling the task */
48struct bcom_gen_bd_rx_inc {
49 u16 pad0;
50 s16 incr_bytes;
51 u16 pad1;
52 s16 incr_dst;
53};
54
55/* tx task vars that need to be set before enabling the task */
56struct bcom_gen_bd_tx_var {
57 u32 fifo; /* (u32*) address of gen_bd's fifo */
58 u32 enable; /* (u16*) address of task's control register */
59 u32 bd_base; /* (struct bcom_bd*) beginning of ring buffer */
60 u32 bd_last; /* (struct bcom_bd*) end of ring buffer */
61 u32 bd_start; /* (struct bcom_bd*) current bd */
62 u32 buffer_size; /* set by uCode for each packet */
63};
64
65/* tx task incs that need to be set before enabling the task */
66struct bcom_gen_bd_tx_inc {
67 u16 pad0;
68 s16 incr_bytes;
69 u16 pad1;
70 s16 incr_src;
71 u16 pad2;
72 s16 incr_src_ma;
73};
74
75/* private structure */
76struct bcom_gen_bd_priv {
77 phys_addr_t fifo;
78 int initiator;
79 int ipr;
80 int maxbufsize;
81};
82
83
84/* ======================================================================== */
85/* Task support code */
86/* ======================================================================== */
87
88struct bcom_task *
89bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
90 int initiator, int ipr, int maxbufsize)
91{
92 struct bcom_task *tsk;
93 struct bcom_gen_bd_priv *priv;
94
95 tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
96 sizeof(struct bcom_gen_bd_priv));
97 if (!tsk)
98 return NULL;
99
100 tsk->flags = BCOM_FLAGS_NONE;
101
102 priv = tsk->priv;
103 priv->fifo = fifo;
104 priv->initiator = initiator;
105 priv->ipr = ipr;
106 priv->maxbufsize = maxbufsize;
107
108 if (bcom_gen_bd_rx_reset(tsk)) {
109 bcom_task_free(tsk);
110 return NULL;
111 }
112
113 return tsk;
114}
115EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
116
117int
118bcom_gen_bd_rx_reset(struct bcom_task *tsk)
119{
120 struct bcom_gen_bd_priv *priv = tsk->priv;
121 struct bcom_gen_bd_rx_var *var;
122 struct bcom_gen_bd_rx_inc *inc;
123
124 /* Shutdown the task */
125 bcom_disable_task(tsk->tasknum);
126
127 /* Reset the microcode */
128 var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
129 inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
130
131 if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
132 return -1;
133
134 var->enable = bcom_eng->regs_base +
135 offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
136 var->fifo = (u32) priv->fifo;
137 var->bd_base = tsk->bd_pa;
138 var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
139 var->bd_start = tsk->bd_pa;
140 var->buffer_size = priv->maxbufsize;
141
142 inc->incr_bytes = -(s16)sizeof(u32);
143 inc->incr_dst = sizeof(u32);
144
145 /* Reset the BDs */
146 tsk->index = 0;
147 tsk->outdex = 0;
148
149 memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
150
151 /* Configure some stuff */
152 bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
153 bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
154
155 out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
156 bcom_set_initiator(tsk->tasknum, priv->initiator);
157
158 out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
159
160 return 0;
161}
162EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
163
164void
165bcom_gen_bd_rx_release(struct bcom_task *tsk)
166{
167 /* Nothing special for the GenBD tasks */
168 bcom_task_free(tsk);
169}
170EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
171
172
173extern struct bcom_task *
174bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
175 int initiator, int ipr)
176{
177 struct bcom_task *tsk;
178 struct bcom_gen_bd_priv *priv;
179
180 tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
181 sizeof(struct bcom_gen_bd_priv));
182 if (!tsk)
183 return NULL;
184
185 tsk->flags = BCOM_FLAGS_NONE;
186
187 priv = tsk->priv;
188 priv->fifo = fifo;
189 priv->initiator = initiator;
190 priv->ipr = ipr;
191
192 if (bcom_gen_bd_tx_reset(tsk)) {
193 bcom_task_free(tsk);
194 return NULL;
195 }
196
197 return tsk;
198}
199EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
200
201int
202bcom_gen_bd_tx_reset(struct bcom_task *tsk)
203{
204 struct bcom_gen_bd_priv *priv = tsk->priv;
205 struct bcom_gen_bd_tx_var *var;
206 struct bcom_gen_bd_tx_inc *inc;
207
208 /* Shutdown the task */
209 bcom_disable_task(tsk->tasknum);
210
211 /* Reset the microcode */
212 var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
213 inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
214
215 if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
216 return -1;
217
218 var->enable = bcom_eng->regs_base +
219 offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
220 var->fifo = (u32) priv->fifo;
221 var->bd_base = tsk->bd_pa;
222 var->bd_last = tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
223 var->bd_start = tsk->bd_pa;
224
225 inc->incr_bytes = -(s16)sizeof(u32);
226 inc->incr_src = sizeof(u32);
227 inc->incr_src_ma = sizeof(u8);
228
229 /* Reset the BDs */
230 tsk->index = 0;
231 tsk->outdex = 0;
232
233 memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
234
235 /* Configure some stuff */
236 bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
237 bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
238
239 out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
240 bcom_set_initiator(tsk->tasknum, priv->initiator);
241
242 out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum); /* Clear ints */
243
244 return 0;
245}
246EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
247
248void
249bcom_gen_bd_tx_release(struct bcom_task *tsk)
250{
251 /* Nothing special for the GenBD tasks */
252 bcom_task_free(tsk);
253}
254EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
255
256/* ---------------------------------------------------------------------
257 * PSC support code
258 */
259
260/**
261 * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
262 *
263 * This structure is only used internally. It is a lookup table for PSC
264 * specific parameters to bestcomm tasks.
265 */
266static struct bcom_psc_params {
267 int rx_initiator;
268 int rx_ipr;
269 int tx_initiator;
270 int tx_ipr;
271} bcom_psc_params[] = {
272 [0] = {
273 .rx_initiator = BCOM_INITIATOR_PSC1_RX,
274 .rx_ipr = BCOM_IPR_PSC1_RX,
275 .tx_initiator = BCOM_INITIATOR_PSC1_TX,
276 .tx_ipr = BCOM_IPR_PSC1_TX,
277 },
278 [1] = {
279 .rx_initiator = BCOM_INITIATOR_PSC2_RX,
280 .rx_ipr = BCOM_IPR_PSC2_RX,
281 .tx_initiator = BCOM_INITIATOR_PSC2_TX,
282 .tx_ipr = BCOM_IPR_PSC2_TX,
283 },
284 [2] = {
285 .rx_initiator = BCOM_INITIATOR_PSC3_RX,
286 .rx_ipr = BCOM_IPR_PSC3_RX,
287 .tx_initiator = BCOM_INITIATOR_PSC3_TX,
288 .tx_ipr = BCOM_IPR_PSC3_TX,
289 },
290 [3] = {
291 .rx_initiator = BCOM_INITIATOR_PSC4_RX,
292 .rx_ipr = BCOM_IPR_PSC4_RX,
293 .tx_initiator = BCOM_INITIATOR_PSC4_TX,
294 .tx_ipr = BCOM_IPR_PSC4_TX,
295 },
296 [4] = {
297 .rx_initiator = BCOM_INITIATOR_PSC5_RX,
298 .rx_ipr = BCOM_IPR_PSC5_RX,
299 .tx_initiator = BCOM_INITIATOR_PSC5_TX,
300 .tx_ipr = BCOM_IPR_PSC5_TX,
301 },
302 [5] = {
303 .rx_initiator = BCOM_INITIATOR_PSC6_RX,
304 .rx_ipr = BCOM_IPR_PSC6_RX,
305 .tx_initiator = BCOM_INITIATOR_PSC6_TX,
306 .tx_ipr = BCOM_IPR_PSC6_TX,
307 },
308};
309
310/**
311 * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
312 * @psc_num: Number of the PSC to allocate a task for
313 * @queue_len: number of buffer descriptors to allocate for the task
314 * @fifo: physical address of FIFO register
315 * @maxbufsize: Maximum receive data size in bytes.
316 *
317 * Allocate a bestcomm task structure for receiving data from a PSC.
318 */
319struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
320 phys_addr_t fifo, int maxbufsize)
321{
322 if (psc_num >= MPC52xx_PSC_MAXNUM)
323 return NULL;
324
325 return bcom_gen_bd_rx_init(queue_len, fifo,
326 bcom_psc_params[psc_num].rx_initiator,
327 bcom_psc_params[psc_num].rx_ipr,
328 maxbufsize);
329}
330EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
331
332/**
333 * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
334 * @psc_num: Number of the PSC to allocate a task for
335 * @queue_len: number of buffer descriptors to allocate for the task
336 * @fifo: physical address of FIFO register
337 *
338 * Allocate a bestcomm task structure for transmitting data to a PSC.
339 */
340struct bcom_task *
341bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
342{
343 struct psc;
344 return bcom_gen_bd_tx_init(queue_len, fifo,
345 bcom_psc_params[psc_num].tx_initiator,
346 bcom_psc_params[psc_num].tx_ipr);
347}
348EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
349
350
351MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
352MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
353MODULE_LICENSE("GPL v2");
354
diff --git a/drivers/dma/bestcomm/sram.c b/drivers/dma/bestcomm/sram.c
new file mode 100644
index 000000000000..5e2ed30ba2c4
--- /dev/null
+++ b/drivers/dma/bestcomm/sram.c
@@ -0,0 +1,178 @@
1/*
2 * Simple memory allocator for on-board SRAM
3 *
4 *
5 * Maintainer : Sylvain Munaut <tnt@246tNt.com>
6 *
7 * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
8 *
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied.
12 */
13
14#include <linux/err.h>
15#include <linux/kernel.h>
16#include <linux/export.h>
17#include <linux/slab.h>
18#include <linux/spinlock.h>
19#include <linux/string.h>
20#include <linux/ioport.h>
21#include <linux/of.h>
22
23#include <asm/io.h>
24#include <asm/mmu.h>
25
26#include <linux/fsl/bestcomm/sram.h>
27
28
29/* Struct keeping our 'state' */
30struct bcom_sram *bcom_sram = NULL;
31EXPORT_SYMBOL_GPL(bcom_sram); /* needed for inline functions */
32
33
34/* ======================================================================== */
35/* Public API */
36/* ======================================================================== */
37/* DO NOT USE in interrupts, if needed in irq handler, we should use the
38 _irqsave version of the spin_locks */
39
40int bcom_sram_init(struct device_node *sram_node, char *owner)
41{
42 int rv;
43 const u32 *regaddr_p;
44 u64 regaddr64, size64;
45 unsigned int psize;
46
47 /* Create our state struct */
48 if (bcom_sram) {
49 printk(KERN_ERR "%s: bcom_sram_init: "
50 "Already initialized !\n", owner);
51 return -EBUSY;
52 }
53
54 bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL);
55 if (!bcom_sram) {
56 printk(KERN_ERR "%s: bcom_sram_init: "
57 "Couldn't allocate internal state !\n", owner);
58 return -ENOMEM;
59 }
60
61 /* Get address and size of the sram */
62 regaddr_p = of_get_address(sram_node, 0, &size64, NULL);
63 if (!regaddr_p) {
64 printk(KERN_ERR "%s: bcom_sram_init: "
65 "Invalid device node !\n", owner);
66 rv = -EINVAL;
67 goto error_free;
68 }
69
70 regaddr64 = of_translate_address(sram_node, regaddr_p);
71
72 bcom_sram->base_phys = (phys_addr_t) regaddr64;
73 bcom_sram->size = (unsigned int) size64;
74
75 /* Request region */
76 if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) {
77 printk(KERN_ERR "%s: bcom_sram_init: "
78 "Couldn't request region !\n", owner);
79 rv = -EBUSY;
80 goto error_free;
81 }
82
83 /* Map SRAM */
84 /* sram is not really __iomem */
85 bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size);
86
87 if (!bcom_sram->base_virt) {
88 printk(KERN_ERR "%s: bcom_sram_init: "
89 "Map error SRAM zone 0x%08lx (0x%0x)!\n",
90 owner, (long)bcom_sram->base_phys, bcom_sram->size );
91 rv = -ENOMEM;
92 goto error_release;
93 }
94
95 /* Create an rheap (defaults to 32 bits word alignment) */
96 bcom_sram->rh = rh_create(4);
97
98 /* Attach the free zones */
99#if 0
100 /* Currently disabled ... for future use only */
101 reg_addr_p = of_get_property(sram_node, "available", &psize);
102#else
103 regaddr_p = NULL;
104 psize = 0;
105#endif
106
107 if (!regaddr_p || !psize) {
108 /* Attach the whole zone */
109 rh_attach_region(bcom_sram->rh, 0, bcom_sram->size);
110 } else {
111 /* Attach each zone independently */
112 while (psize >= 2 * sizeof(u32)) {
113 phys_addr_t zbase = of_translate_address(sram_node, regaddr_p);
114 rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]);
115 regaddr_p += 2;
116 psize -= 2 * sizeof(u32);
117 }
118 }
119
120 /* Init our spinlock */
121 spin_lock_init(&bcom_sram->lock);
122
123 return 0;
124
125error_release:
126 release_mem_region(bcom_sram->base_phys, bcom_sram->size);
127error_free:
128 kfree(bcom_sram);
129 bcom_sram = NULL;
130
131 return rv;
132}
133EXPORT_SYMBOL_GPL(bcom_sram_init);
134
135void bcom_sram_cleanup(void)
136{
137 /* Free resources */
138 if (bcom_sram) {
139 rh_destroy(bcom_sram->rh);
140 iounmap((void __iomem *)bcom_sram->base_virt);
141 release_mem_region(bcom_sram->base_phys, bcom_sram->size);
142 kfree(bcom_sram);
143 bcom_sram = NULL;
144 }
145}
146EXPORT_SYMBOL_GPL(bcom_sram_cleanup);
147
148void* bcom_sram_alloc(int size, int align, phys_addr_t *phys)
149{
150 unsigned long offset;
151
152 spin_lock(&bcom_sram->lock);
153 offset = rh_alloc_align(bcom_sram->rh, size, align, NULL);
154 spin_unlock(&bcom_sram->lock);
155
156 if (IS_ERR_VALUE(offset))
157 return NULL;
158
159 *phys = bcom_sram->base_phys + offset;
160 return bcom_sram->base_virt + offset;
161}
162EXPORT_SYMBOL_GPL(bcom_sram_alloc);
163
164void bcom_sram_free(void *ptr)
165{
166 unsigned long offset;
167
168 if (!ptr)
169 return;
170
171 offset = ptr - bcom_sram->base_virt;
172
173 spin_lock(&bcom_sram->lock);
174 rh_free(bcom_sram->rh, offset);
175 spin_unlock(&bcom_sram->lock);
176}
177EXPORT_SYMBOL_GPL(bcom_sram_free);
178
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 817d081d2cd8..85e776d500a6 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -40,8 +40,8 @@
40#include <asm/delay.h> 40#include <asm/delay.h>
41#include <asm/mpc52xx.h> 41#include <asm/mpc52xx.h>
42 42
43#include <sysdev/bestcomm/bestcomm.h> 43#include <linux/fsl/bestcomm/bestcomm.h>
44#include <sysdev/bestcomm/fec.h> 44#include <linux/fsl/bestcomm/fec.h>
45 45
46#include "fec_mpc52xx.h" 46#include "fec_mpc52xx.h"
47 47
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 19cfd7a92563..41fbd9453c5f 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -944,7 +944,7 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
944#define PF_COMP_0_MASK 0x0000000F 944#define PF_COMP_0_MASK 0x0000000F
945#define PF_COMP_0_SHIFT 0 945#define PF_COMP_0_SHIFT 0
946 946
947#define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \ 947#define MAKE_PF(alpha, red, green, blue, size, c0, c1, c2, c3) \
948 cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \ 948 cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \
949 (blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \ 949 (blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \
950 (red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \ 950 (red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \
@@ -954,10 +954,10 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
954 switch (bits_per_pixel) { 954 switch (bits_per_pixel) {
955 case 32: 955 case 32:
956 /* 0x88883316 */ 956 /* 0x88883316 */
957 return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8); 957 return MAKE_PF(3, 2, 1, 0, 3, 8, 8, 8, 8);
958 case 24: 958 case 24:
959 /* 0x88082219 */ 959 /* 0x88082219 */
960 return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8); 960 return MAKE_PF(4, 0, 1, 2, 2, 8, 8, 8, 0);
961 case 16: 961 case 16:
962 /* 0x65053118 */ 962 /* 0x65053118 */
963 return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0); 963 return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0);
@@ -1232,6 +1232,16 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
1232 return 0; 1232 return 0;
1233} 1233}
1234 1234
1235static inline void fsl_diu_enable_interrupts(struct fsl_diu_data *data)
1236{
1237 u32 int_mask = INT_UNDRUN; /* enable underrun detection */
1238
1239 if (IS_ENABLED(CONFIG_NOT_COHERENT_CACHE))
1240 int_mask |= INT_VSYNC; /* enable vertical sync */
1241
1242 clrbits32(&data->diu_reg->int_mask, int_mask);
1243}
1244
1235/* turn on fb if count == 1 1245/* turn on fb if count == 1
1236 */ 1246 */
1237static int fsl_diu_open(struct fb_info *info, int user) 1247static int fsl_diu_open(struct fb_info *info, int user)
@@ -1251,19 +1261,7 @@ static int fsl_diu_open(struct fb_info *info, int user)
1251 if (res < 0) 1261 if (res < 0)
1252 mfbi->count--; 1262 mfbi->count--;
1253 else { 1263 else {
1254 struct fsl_diu_data *data = mfbi->parent; 1264 fsl_diu_enable_interrupts(mfbi->parent);
1255
1256#ifdef CONFIG_NOT_COHERENT_CACHE
1257 /*
1258 * Enable underrun detection and vertical sync
1259 * interrupts.
1260 */
1261 clrbits32(&data->diu_reg->int_mask,
1262 INT_UNDRUN | INT_VSYNC);
1263#else
1264 /* Enable underrun detection */
1265 clrbits32(&data->diu_reg->int_mask, INT_UNDRUN);
1266#endif
1267 fsl_diu_enable_panel(info); 1265 fsl_diu_enable_panel(info);
1268 } 1266 }
1269 } 1267 }
@@ -1283,9 +1281,18 @@ static int fsl_diu_release(struct fb_info *info, int user)
1283 mfbi->count--; 1281 mfbi->count--;
1284 if (mfbi->count == 0) { 1282 if (mfbi->count == 0) {
1285 struct fsl_diu_data *data = mfbi->parent; 1283 struct fsl_diu_data *data = mfbi->parent;
1284 bool disable = true;
1285 int i;
1286 1286
1287 /* Disable interrupts */ 1287 /* Disable interrupts only if all AOIs are closed */
1288 out_be32(&data->diu_reg->int_mask, 0xffffffff); 1288 for (i = 0; i < NUM_AOIS; i++) {
1289 struct mfb_info *mi = data->fsl_diu_info[i].par;
1290
1291 if (mi->count)
1292 disable = false;
1293 }
1294 if (disable)
1295 out_be32(&data->diu_reg->int_mask, 0xffffffff);
1289 fsl_diu_disable_panel(info); 1296 fsl_diu_disable_panel(info);
1290 } 1297 }
1291 1298
@@ -1614,14 +1621,6 @@ static int fsl_diu_probe(struct platform_device *pdev)
1614 out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr); 1621 out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
1615 out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr); 1622 out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
1616 1623
1617 for (i = 0; i < NUM_AOIS; i++) {
1618 ret = install_fb(&data->fsl_diu_info[i]);
1619 if (ret) {
1620 dev_err(&pdev->dev, "could not register fb %d\n", i);
1621 goto error;
1622 }
1623 }
1624
1625 /* 1624 /*
1626 * Older versions of U-Boot leave interrupts enabled, so disable 1625 * Older versions of U-Boot leave interrupts enabled, so disable
1627 * all of them and clear the status register. 1626 * all of them and clear the status register.
@@ -1630,12 +1629,21 @@ static int fsl_diu_probe(struct platform_device *pdev)
1630 in_be32(&data->diu_reg->int_status); 1629 in_be32(&data->diu_reg->int_status);
1631 1630
1632 ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", 1631 ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
1633 &data->diu_reg); 1632 data->diu_reg);
1634 if (ret) { 1633 if (ret) {
1635 dev_err(&pdev->dev, "could not claim irq\n"); 1634 dev_err(&pdev->dev, "could not claim irq\n");
1636 goto error; 1635 goto error;
1637 } 1636 }
1638 1637
1638 for (i = 0; i < NUM_AOIS; i++) {
1639 ret = install_fb(&data->fsl_diu_info[i]);
1640 if (ret) {
1641 dev_err(&pdev->dev, "could not register fb %d\n", i);
1642 free_irq(data->irq, data->diu_reg);
1643 goto error;
1644 }
1645 }
1646
1639 sysfs_attr_init(&data->dev_attr.attr); 1647 sysfs_attr_init(&data->dev_attr.attr);
1640 data->dev_attr.attr.name = "monitor"; 1648 data->dev_attr.attr.name = "monitor";
1641 data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; 1649 data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
@@ -1667,7 +1675,7 @@ static int fsl_diu_remove(struct platform_device *pdev)
1667 data = dev_get_drvdata(&pdev->dev); 1675 data = dev_get_drvdata(&pdev->dev);
1668 disable_lcdc(&data->fsl_diu_info[0]); 1676 disable_lcdc(&data->fsl_diu_info[0]);
1669 1677
1670 free_irq(data->irq, &data->diu_reg); 1678 free_irq(data->irq, data->diu_reg);
1671 1679
1672 for (i = 0; i < NUM_AOIS; i++) 1680 for (i = 0; i < NUM_AOIS; i++)
1673 uninstall_fb(&data->fsl_diu_info[i]); 1681 uninstall_fb(&data->fsl_diu_info[i]);