diff options
Diffstat (limited to 'firmware/target/arm/tms320dm320/dsp-dm320.c')
-rw-r--r-- | firmware/target/arm/tms320dm320/dsp-dm320.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/firmware/target/arm/tms320dm320/dsp-dm320.c b/firmware/target/arm/tms320dm320/dsp-dm320.c new file mode 100644 index 0000000000..673182f3fc --- /dev/null +++ b/firmware/target/arm/tms320dm320/dsp-dm320.c | |||
@@ -0,0 +1,146 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Catalin Patulea <cat@vv.carleton.ca> | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "config.h" | ||
20 | #include "cpu.h" | ||
21 | #include "system.h" | ||
22 | #include "debug.h" | ||
23 | #include "dsp-target.h" | ||
24 | |||
25 | /* A "DSP image" is an array of these, terminated by raw_data_size_half = 0. */ | ||
26 | struct dsp_section { | ||
27 | const unsigned short *raw_data; | ||
28 | unsigned short physical_addr; | ||
29 | unsigned short raw_data_size_half; | ||
30 | }; | ||
31 | |||
32 | /* Must define struct dsp_section before including the image. */ | ||
33 | #include "dsp_image_helloworld.h" | ||
34 | |||
35 | #ifdef DEBUG | ||
36 | static void dsp_status(void) { | ||
37 | unsigned short addr_7fff = DSP_(0x7fff); | ||
38 | unsigned short hpib_ctl = IO_DSPC_HPIB_CONTROL; | ||
39 | unsigned short hpib_stat = IO_DSPC_HPIB_STATUS; | ||
40 | char buffer1[80], buffer2[80]; | ||
41 | |||
42 | DEBUGF("dsp_status(): clkc_hpib=%u clkc_dsp=%u", | ||
43 | !!(IO_CLK_MOD0 & (1 << 11)), !!(IO_CLK_MOD0 & (1 << 10))); | ||
44 | |||
45 | DEBUGF("dsp_status(): irq_dsphint=%u scratch_status=0x%04x" | ||
46 | " acked=%04x", | ||
47 | (IO_INTC_IRQ0 >> IRQ_DSPHINT) & 1, DSP_(_status), DSP_(_acked)); | ||
48 | #define B(f,w,b,m) if ((w & (1 << b)) == 0) \ | ||
49 | strcat(f, "!"); \ | ||
50 | strcat(f, #m "|"); | ||
51 | strcpy(buffer1, ""); | ||
52 | B(buffer1, hpib_ctl, 0, EN); | ||
53 | B(buffer1, hpib_ctl, 3, NMI); | ||
54 | B(buffer1, hpib_ctl, 5, EXCHG); | ||
55 | B(buffer1, hpib_ctl, 7, DINT0); | ||
56 | B(buffer1, hpib_ctl, 8, DRST); | ||
57 | B(buffer1, hpib_ctl, 9, DHOLD); | ||
58 | B(buffer1, hpib_ctl, 10, BIO); | ||
59 | |||
60 | strcpy(buffer2, ""); | ||
61 | B(buffer2, hpib_stat, 8, HOLDA); | ||
62 | B(buffer2, hpib_stat, 12, DXF); | ||
63 | |||
64 | DEBUGF("dsp_status(): hpib: ctl=%s stat=%s", buffer1, buffer2); | ||
65 | #undef B | ||
66 | } | ||
67 | #endif | ||
68 | |||
69 | static void dsp_reset(void) { | ||
70 | DSP_(0x7fff) = 0xdead; | ||
71 | |||
72 | IO_DSPC_HPIB_CONTROL &= ~(1 << 8); | ||
73 | /* HPIB bus cycles will lock up the ARM in here. Don't touch DSP RAM. */ | ||
74 | nop; nop; | ||
75 | IO_DSPC_HPIB_CONTROL |= 1 << 8; | ||
76 | |||
77 | /* TODO: Timeout. */ | ||
78 | while (DSP_(0x7fff) != 0); | ||
79 | } | ||
80 | |||
81 | void dsp_wake(void) { | ||
82 | /* If this is called concurrently, we may overlap setting and resetting the | ||
83 | bit, which causes lost interrupts to the DSP. */ | ||
84 | int old_level = set_irq_level(IRQ_DISABLED); | ||
85 | |||
86 | /* The first time you INT0 the DSP, the ROM loader will branch to your RST | ||
87 | handler. Subsequent times, your INT0 handler will get executed. */ | ||
88 | IO_DSPC_HPIB_CONTROL &= ~(1 << 7); | ||
89 | nop; nop; | ||
90 | IO_DSPC_HPIB_CONTROL |= 1 << 7; | ||
91 | |||
92 | set_irq_level(old_level); | ||
93 | } | ||
94 | |||
95 | static void dsp_load(const struct dsp_section *im) { | ||
96 | while (im->raw_data_size_half) { | ||
97 | volatile unsigned short *data_ptr = &DSP_(im->physical_addr); | ||
98 | unsigned int i; | ||
99 | |||
100 | /* Use 16-bit writes. */ | ||
101 | if (im->raw_data) { | ||
102 | DEBUGF("dsp_load(): loading %u words at 0x%04x (0x%08lx)", | ||
103 | im->raw_data_size_half, im->physical_addr, | ||
104 | (unsigned long)data_ptr); | ||
105 | |||
106 | for (i = 0; i < im->raw_data_size_half; i++) { | ||
107 | data_ptr[i] = im->raw_data[i]; | ||
108 | } | ||
109 | } else { | ||
110 | DEBUGF("dsp_load(): clearing %u words at 0x%04x (0x%08lx)", | ||
111 | im->raw_data_size_half, im->physical_addr, | ||
112 | (unsigned long)data_ptr); | ||
113 | |||
114 | for (i = 0; i < im->raw_data_size_half; i++) { | ||
115 | data_ptr[i] = 0; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | im++; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | void dsp_init(void) { | ||
124 | IO_INTC_IRQ0 = 1 << 11; | ||
125 | IO_INTC_EINT0 |= 1 << 11; | ||
126 | |||
127 | dsp_reset(); | ||
128 | dsp_load(dsp_image_helloworld); | ||
129 | } | ||
130 | |||
131 | void DSPHINT(void) { | ||
132 | unsigned int i; | ||
133 | char buffer[80]; | ||
134 | |||
135 | IO_INTC_IRQ0 = 1 << 11; | ||
136 | |||
137 | /* DSP stores one character per word. */ | ||
138 | for (i = 0; i < sizeof(buffer); i++) { | ||
139 | buffer[i] = (&DSP_(_status))[i]; | ||
140 | } | ||
141 | |||
142 | /* Release shared area to DSP. */ | ||
143 | dsp_wake(); | ||
144 | |||
145 | DEBUGF("DSP: %s", buffer); | ||
146 | } | ||