aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/8xx_io/Kconfig4
-rw-r--r--arch/ppc/8xx_io/Makefile1
-rw-r--r--arch/ppc/8xx_io/cs4218.h166
-rw-r--r--arch/ppc/8xx_io/cs4218_tdm.c2833
-rw-r--r--arch/ppc/boot/common/misc-common.c15
-rw-r--r--arch/ppc/boot/simple/Makefile1
-rw-r--r--arch/ppc/boot/simple/uartlite_tty.c37
-rw-r--r--arch/ppc/kernel/asm-offsets.c1
-rw-r--r--arch/ppc/kernel/entry.S1
-rw-r--r--arch/ppc/platforms/4xx/Kconfig15
-rw-r--r--arch/ppc/platforms/4xx/Makefile1
-rw-r--r--arch/ppc/platforms/4xx/ocotea.c4
-rw-r--r--arch/ppc/platforms/4xx/taishan.c2
-rw-r--r--arch/ppc/platforms/4xx/virtex.c56
-rw-r--r--arch/ppc/platforms/4xx/virtex.h34
-rw-r--r--arch/ppc/platforms/4xx/xilinx_ml300.c65
-rw-r--r--arch/ppc/platforms/4xx/xilinx_ml300.h45
-rw-r--r--arch/ppc/platforms/4xx/xilinx_ml403.c66
-rw-r--r--arch/ppc/platforms/4xx/xilinx_ml403.h49
-rw-r--r--arch/ppc/platforms/4xx/xparameters/xparameters.h60
-rw-r--r--arch/ppc/platforms/rpxclassic.h4
-rw-r--r--arch/ppc/platforms/rpxhiox.h41
-rw-r--r--arch/ppc/platforms/rpxlite.h4
-rw-r--r--arch/ppc/syslib/Makefile3
-rw-r--r--arch/ppc/syslib/cpc710.h81
-rw-r--r--arch/ppc/syslib/m8xx_setup.c2
-rw-r--r--arch/ppc/syslib/ppc4xx_sgdma.c1
-rw-r--r--arch/ppc/syslib/virtex_devices.c233
-rw-r--r--arch/ppc/syslib/virtex_devices.h27
29 files changed, 409 insertions, 3443 deletions
diff --git a/arch/ppc/8xx_io/Kconfig b/arch/ppc/8xx_io/Kconfig
index 57dacf978532..c623e44f01ad 100644
--- a/arch/ppc/8xx_io/Kconfig
+++ b/arch/ppc/8xx_io/Kconfig
@@ -74,10 +74,6 @@ config ENET_BIG_BUFFERS
74 Allocate large buffers for MPC8xx Ethernet. Increases throughput 74 Allocate large buffers for MPC8xx Ethernet. Increases throughput
75 and decreases the likelihood of dropped packets, but costs memory. 75 and decreases the likelihood of dropped packets, but costs memory.
76 76
77config HTDMSOUND
78 bool "Embedded Planet HIOX Audio"
79 depends on SOUND=y
80
81# This doesn't really belong here, but it is convenient to ask 77# This doesn't really belong here, but it is convenient to ask
82# 8xx specific questions. 78# 8xx specific questions.
83comment "Generic MPC8xx Options" 79comment "Generic MPC8xx Options"
diff --git a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile
index d8760181fe99..1051a06df7e0 100644
--- a/arch/ppc/8xx_io/Makefile
+++ b/arch/ppc/8xx_io/Makefile
@@ -7,4 +7,3 @@ obj-y := commproc.o
7obj-$(CONFIG_FEC_ENET) += fec.o 7obj-$(CONFIG_FEC_ENET) += fec.o
8obj-$(CONFIG_SCC_ENET) += enet.o 8obj-$(CONFIG_SCC_ENET) += enet.o
9obj-$(CONFIG_UCODE_PATCH) += micropatch.o 9obj-$(CONFIG_UCODE_PATCH) += micropatch.o
10obj-$(CONFIG_HTDMSOUND) += cs4218_tdm.o
diff --git a/arch/ppc/8xx_io/cs4218.h b/arch/ppc/8xx_io/cs4218.h
deleted file mode 100644
index e5f943045afa..000000000000
--- a/arch/ppc/8xx_io/cs4218.h
+++ /dev/null
@@ -1,166 +0,0 @@
1#ifndef _cs4218_h_
2/*
3 * Hacked version of linux/drivers/sound/dmasound/dmasound.h
4 *
5 *
6 * Minor numbers for the sound driver.
7 *
8 * Unfortunately Creative called the codec chip of SB as a DSP. For this
9 * reason the /dev/dsp is reserved for digitized audio use. There is a
10 * device for true DSP processors but it will be called something else.
11 * In v3.0 it's /dev/sndproc but this could be a temporary solution.
12 */
13#define _cs4218_h_
14
15#include <linux/types.h>
16
17#define SND_NDEVS 256 /* Number of supported devices */
18#define SND_DEV_CTL 0 /* Control port /dev/mixer */
19#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
20 synthesizer and MIDI output) */
21#define SND_DEV_MIDIN 2 /* Raw midi access */
22#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */
23#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
24#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
25#define SND_DEV_STATUS 6 /* /dev/sndstat */
26/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
27#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
28#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
29#define SND_DEV_PSS SND_DEV_SNDPROC
30
31/* switch on various prinks */
32#define DEBUG_DMASOUND 1
33
34#define MAX_AUDIO_DEV 5
35#define MAX_MIXER_DEV 4
36#define MAX_SYNTH_DEV 3
37#define MAX_MIDI_DEV 6
38#define MAX_TIMER_DEV 3
39
40#define MAX_CATCH_RADIUS 10
41
42#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
43#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
44
45#define IOCTL_IN(arg, ret) \
46 do { int error = get_user(ret, (int *)(arg)); \
47 if (error) return error; \
48 } while (0)
49#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret)
50
51static inline int ioctl_return(int *addr, int value)
52{
53 return value < 0 ? value : put_user(value, addr);
54}
55
56#define HAS_RECORD
57
58 /*
59 * Initialization
60 */
61
62/* description of the set-up applies to either hard or soft settings */
63
64typedef struct {
65 int format; /* AFMT_* */
66 int stereo; /* 0 = mono, 1 = stereo */
67 int size; /* 8/16 bit*/
68 int speed; /* speed */
69} SETTINGS;
70
71 /*
72 * Machine definitions
73 */
74
75typedef struct {
76 const char *name;
77 const char *name2;
78 void (*open)(void);
79 void (*release)(void);
80 void *(*dma_alloc)(unsigned int, gfp_t);
81 void (*dma_free)(void *, unsigned int);
82 int (*irqinit)(void);
83#ifdef MODULE
84 void (*irqcleanup)(void);
85#endif
86 void (*init)(void);
87 void (*silence)(void);
88 int (*setFormat)(int);
89 int (*setVolume)(int);
90 int (*setBass)(int);
91 int (*setTreble)(int);
92 int (*setGain)(int);
93 void (*play)(void);
94 void (*record)(void); /* optional */
95 void (*mixer_init)(void); /* optional */
96 int (*mixer_ioctl)(u_int, u_long); /* optional */
97 int (*write_sq_setup)(void); /* optional */
98 int (*read_sq_setup)(void); /* optional */
99 int (*sq_open)(mode_t); /* optional */
100 int (*state_info)(char *, size_t); /* optional */
101 void (*abort_read)(void); /* optional */
102 int min_dsp_speed;
103 int max_dsp_speed;
104 int version ;
105 int hardware_afmts ; /* OSS says we only return h'ware info */
106 /* when queried via SNDCTL_DSP_GETFMTS */
107 int capabilities ; /* low-level reply to SNDCTL_DSP_GETCAPS */
108 SETTINGS default_hard ; /* open() or init() should set something valid */
109 SETTINGS default_soft ; /* you can make it look like old OSS, if you want to */
110} MACHINE;
111
112 /*
113 * Low level stuff
114 */
115
116typedef struct {
117 ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
118 ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
119 ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
120 ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
121 ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
122 ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
123 ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
124 ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
125} TRANS;
126
127
128 /*
129 * Sound queue stuff, the heart of the driver
130 */
131
132struct sound_queue {
133 /* buffers allocated for this queue */
134 int numBufs; /* real limits on what the user can have */
135 int bufSize; /* in bytes */
136 char **buffers;
137
138 /* current parameters */
139 int locked ; /* params cannot be modified when != 0 */
140 int user_frags ; /* user requests this many */
141 int user_frag_size ; /* of this size */
142 int max_count; /* actual # fragments <= numBufs */
143 int block_size; /* internal block size in bytes */
144 int max_active; /* in-use fragments <= max_count */
145
146 /* it shouldn't be necessary to declare any of these volatile */
147 int front, rear, count;
148 int rear_size;
149 /*
150 * The use of the playing field depends on the hardware
151 *
152 * Atari, PMac: The number of frames that are loaded/playing
153 *
154 * Amiga: Bit 0 is set: a frame is loaded
155 * Bit 1 is set: a frame is playing
156 */
157 int active;
158 wait_queue_head_t action_queue, open_queue, sync_queue;
159 int open_mode;
160 int busy, syncing, xruns, died;
161};
162
163#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ)
164#define WAKE_UP(queue) (wake_up_interruptible(&queue))
165
166#endif /* _cs4218_h_ */
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
deleted file mode 100644
index a956f28ab162..000000000000
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ /dev/null
@@ -1,2833 +0,0 @@
1
2/* This is a modified version of linux/drivers/sound/dmasound.c to
3 * support the CS4218 codec on the 8xx TDM port. Thanks to everyone
4 * that contributed to the dmasound software (which includes me :-).
5 *
6 * The CS4218 is configured in Mode 4, sub-mode 0. This provides
7 * left/right data only on the TDM port, as a 32-bit word, per frame
8 * pulse. The control of the CS4218 is provided by some other means,
9 * like the SPI port.
10 * Dan Malek (dmalek@jlc.net)
11 */
12
13#include <linux/module.h>
14#include <linux/sched.h>
15#include <linux/timer.h>
16#include <linux/major.h>
17#include <linux/fcntl.h>
18#include <linux/errno.h>
19#include <linux/mm.h>
20#include <linux/slab.h>
21#include <linux/sound.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24
25#include <asm/system.h>
26#include <asm/irq.h>
27#include <asm/pgtable.h>
28#include <asm/uaccess.h>
29#include <asm/io.h>
30
31/* Should probably do something different with this path name.....
32 * Actually, I should just stop using it...
33 */
34#include "cs4218.h"
35#include <linux/soundcard.h>
36
37#include <asm/mpc8xx.h>
38#include <asm/8xx_immap.h>
39#include <asm/commproc.h>
40
41#define DMASND_CS4218 5
42
43#define MAX_CATCH_RADIUS 10
44#define MIN_BUFFERS 4
45#define MIN_BUFSIZE 4
46#define MAX_BUFSIZE 128
47
48#define HAS_8BIT_TABLES
49
50static int sq_unit = -1;
51static int mixer_unit = -1;
52static int state_unit = -1;
53static int irq_installed = 0;
54static char **sound_buffers = NULL;
55static char **sound_read_buffers = NULL;
56
57static DEFINE_SPINLOCK(cs4218_lock);
58
59/* Local copies of things we put in the control register. Output
60 * volume, like most codecs is really attenuation.
61 */
62static int cs4218_rate_index;
63
64/*
65 * Stuff for outputting a beep. The values range from -327 to +327
66 * so we can multiply by an amplitude in the range 0..100 to get a
67 * signed short value to put in the output buffer.
68 */
69static short beep_wform[256] = {
70 0, 40, 79, 117, 153, 187, 218, 245,
71 269, 288, 304, 316, 323, 327, 327, 324,
72 318, 310, 299, 288, 275, 262, 249, 236,
73 224, 213, 204, 196, 190, 186, 183, 182,
74 182, 183, 186, 189, 192, 196, 200, 203,
75 206, 208, 209, 209, 209, 207, 204, 201,
76 197, 193, 188, 183, 179, 174, 170, 166,
77 163, 161, 160, 159, 159, 160, 161, 162,
78 164, 166, 168, 169, 171, 171, 171, 170,
79 169, 167, 163, 159, 155, 150, 144, 139,
80 133, 128, 122, 117, 113, 110, 107, 105,
81 103, 103, 103, 103, 104, 104, 105, 105,
82 105, 103, 101, 97, 92, 86, 78, 68,
83 58, 45, 32, 18, 3, -11, -26, -41,
84 -55, -68, -79, -88, -95, -100, -102, -102,
85 -99, -93, -85, -75, -62, -48, -33, -16,
86 0, 16, 33, 48, 62, 75, 85, 93,
87 99, 102, 102, 100, 95, 88, 79, 68,
88 55, 41, 26, 11, -3, -18, -32, -45,
89 -58, -68, -78, -86, -92, -97, -101, -103,
90 -105, -105, -105, -104, -104, -103, -103, -103,
91 -103, -105, -107, -110, -113, -117, -122, -128,
92 -133, -139, -144, -150, -155, -159, -163, -167,
93 -169, -170, -171, -171, -171, -169, -168, -166,
94 -164, -162, -161, -160, -159, -159, -160, -161,
95 -163, -166, -170, -174, -179, -183, -188, -193,
96 -197, -201, -204, -207, -209, -209, -209, -208,
97 -206, -203, -200, -196, -192, -189, -186, -183,
98 -182, -182, -183, -186, -190, -196, -204, -213,
99 -224, -236, -249, -262, -275, -288, -299, -310,
100 -318, -324, -327, -327, -323, -316, -304, -288,
101 -269, -245, -218, -187, -153, -117, -79, -40,
102};
103
104#define BEEP_SPEED 5 /* 22050 Hz sample rate */
105#define BEEP_BUFLEN 512
106#define BEEP_VOLUME 15 /* 0 - 100 */
107
108static int beep_volume = BEEP_VOLUME;
109static int beep_playing = 0;
110static int beep_state = 0;
111static short *beep_buf;
112static void (*orig_mksound)(unsigned int, unsigned int);
113
114/* This is found someplace else......I guess in the keyboard driver
115 * we don't include.
116 */
117static void (*kd_mksound)(unsigned int, unsigned int);
118
119static int catchRadius = 0;
120static int numBufs = 4, bufSize = 32;
121static int numReadBufs = 4, readbufSize = 32;
122
123
124/* TDM/Serial transmit and receive buffer descriptors.
125*/
126static volatile cbd_t *rx_base, *rx_cur, *tx_base, *tx_cur;
127
128module_param(catchRadius, int, 0);
129module_param(numBufs, int, 0);
130module_param(bufSize, int, 0);
131module_param(numreadBufs, int, 0);
132module_param(readbufSize, int, 0);
133
134#define arraysize(x) (sizeof(x)/sizeof(*(x)))
135#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
136#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
137
138#define IOCTL_IN(arg, ret) \
139 do { int error = get_user(ret, (int *)(arg)); \
140 if (error) return error; \
141 } while (0)
142#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret)
143
144/* CS4218 serial port control in mode 4.
145*/
146#define CS_INTMASK ((uint)0x40000000)
147#define CS_DO1 ((uint)0x20000000)
148#define CS_LATTEN ((uint)0x1f000000)
149#define CS_RATTEN ((uint)0x00f80000)
150#define CS_MUTE ((uint)0x00040000)
151#define CS_ISL ((uint)0x00020000)
152#define CS_ISR ((uint)0x00010000)
153#define CS_LGAIN ((uint)0x0000f000)
154#define CS_RGAIN ((uint)0x00000f00)
155
156#define CS_LATTEN_SET(X) (((X) & 0x1f) << 24)
157#define CS_RATTEN_SET(X) (((X) & 0x1f) << 19)
158#define CS_LGAIN_SET(X) (((X) & 0x0f) << 12)
159#define CS_RGAIN_SET(X) (((X) & 0x0f) << 8)
160
161#define CS_LATTEN_GET(X) (((X) >> 24) & 0x1f)
162#define CS_RATTEN_GET(X) (((X) >> 19) & 0x1f)
163#define CS_LGAIN_GET(X) (((X) >> 12) & 0x0f)
164#define CS_RGAIN_GET(X) (((X) >> 8) & 0x0f)
165
166/* The control register is effectively write only. We have to keep a copy
167 * of what we write.
168 */
169static uint cs4218_control;
170
171/* A place to store expanding information.
172*/
173static int expand_bal;
174static int expand_data;
175
176/* Since I can't make the microcode patch work for the SPI, I just
177 * clock the bits using software.
178 */
179static void sw_spi_init(void);
180static void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt);
181static uint cs4218_ctl_write(uint ctlreg);
182
183/*** Some low level helpers **************************************************/
184
185/* 16 bit mu-law */
186
187static short ulaw2dma16[] = {
188 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
189 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
190 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
191 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
192 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
193 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
194 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
195 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
196 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
197 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
198 -876, -844, -812, -780, -748, -716, -684, -652,
199 -620, -588, -556, -524, -492, -460, -428, -396,
200 -372, -356, -340, -324, -308, -292, -276, -260,
201 -244, -228, -212, -196, -180, -164, -148, -132,
202 -120, -112, -104, -96, -88, -80, -72, -64,
203 -56, -48, -40, -32, -24, -16, -8, 0,
204 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
205 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
206 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
207 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
208 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
209 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
210 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
211 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
212 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
213 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
214 876, 844, 812, 780, 748, 716, 684, 652,
215 620, 588, 556, 524, 492, 460, 428, 396,
216 372, 356, 340, 324, 308, 292, 276, 260,
217 244, 228, 212, 196, 180, 164, 148, 132,
218 120, 112, 104, 96, 88, 80, 72, 64,
219 56, 48, 40, 32, 24, 16, 8, 0,
220};
221
222/* 16 bit A-law */
223
224static short alaw2dma16[] = {
225 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
226 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
227 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
228 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
229 -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
230 -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
231 -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
232 -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
233 -344, -328, -376, -360, -280, -264, -312, -296,
234 -472, -456, -504, -488, -408, -392, -440, -424,
235 -88, -72, -120, -104, -24, -8, -56, -40,
236 -216, -200, -248, -232, -152, -136, -184, -168,
237 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
238 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
239 -688, -656, -752, -720, -560, -528, -624, -592,
240 -944, -912, -1008, -976, -816, -784, -880, -848,
241 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
242 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
243 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
244 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
245 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
246 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
247 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
248 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
249 344, 328, 376, 360, 280, 264, 312, 296,
250 472, 456, 504, 488, 408, 392, 440, 424,
251 88, 72, 120, 104, 24, 8, 56, 40,
252 216, 200, 248, 232, 152, 136, 184, 168,
253 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
254 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
255 688, 656, 752, 720, 560, 528, 624, 592,
256 944, 912, 1008, 976, 816, 784, 880, 848,
257};
258
259
260/*** Translations ************************************************************/
261
262
263static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount,
264 u_char frame[], ssize_t *frameUsed,
265 ssize_t frameLeft);
266static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount,
267 u_char frame[], ssize_t *frameUsed,
268 ssize_t frameLeft);
269static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount,
270 u_char frame[], ssize_t *frameUsed,
271 ssize_t frameLeft);
272static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount,
273 u_char frame[], ssize_t *frameUsed,
274 ssize_t frameLeft);
275static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount,
276 u_char frame[], ssize_t *frameUsed,
277 ssize_t frameLeft);
278static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount,
279 u_char frame[], ssize_t *frameUsed,
280 ssize_t frameLeft);
281static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount,
282 u_char frame[], ssize_t *frameUsed,
283 ssize_t frameLeft);
284static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount,
285 u_char frame[], ssize_t *frameUsed,
286 ssize_t frameLeft);
287static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount,
288 u_char frame[], ssize_t *frameUsed,
289 ssize_t frameLeft);
290static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount,
291 u_char frame[], ssize_t *frameUsed,
292 ssize_t frameLeft);
293static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount,
294 u_char frame[], ssize_t *frameUsed,
295 ssize_t frameLeft);
296static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount,
297 u_char frame[], ssize_t *frameUsed,
298 ssize_t frameLeft);
299
300
301/*** Low level stuff *********************************************************/
302
303struct cs_sound_settings {
304 MACHINE mach; /* machine dependent things */
305 SETTINGS hard; /* hardware settings */
306 SETTINGS soft; /* software settings */
307 SETTINGS dsp; /* /dev/dsp default settings */
308 TRANS *trans_write; /* supported translations for playback */
309 TRANS *trans_read; /* supported translations for record */
310 int volume_left; /* volume (range is machine dependent) */
311 int volume_right;
312 int bass; /* tone (range is machine dependent) */
313 int treble;
314 int gain;
315 int minDev; /* minor device number currently open */
316};
317
318static struct cs_sound_settings sound;
319
320static void *CS_Alloc(unsigned int size, gfp_t flags);
321static void CS_Free(void *ptr, unsigned int size);
322static int CS_IrqInit(void);
323#ifdef MODULE
324static void CS_IrqCleanup(void);
325#endif /* MODULE */
326static void CS_Silence(void);
327static void CS_Init(void);
328static void CS_Play(void);
329static void CS_Record(void);
330static int CS_SetFormat(int format);
331static int CS_SetVolume(int volume);
332static void cs4218_tdm_tx_intr(void *devid);
333static void cs4218_tdm_rx_intr(void *devid);
334static void cs4218_intr(void *devid);
335static int cs_get_volume(uint reg);
336static int cs_volume_setter(int volume, int mute);
337static int cs_get_gain(uint reg);
338static int cs_set_gain(int gain);
339static void cs_mksound(unsigned int hz, unsigned int ticks);
340static void cs_nosound(unsigned long xx);
341
342/*** Mid level stuff *********************************************************/
343
344
345static void sound_silence(void);
346static void sound_init(void);
347static int sound_set_format(int format);
348static int sound_set_speed(int speed);
349static int sound_set_stereo(int stereo);
350static int sound_set_volume(int volume);
351
352static ssize_t sound_copy_translate(const u_char *userPtr,
353 size_t userCount,
354 u_char frame[], ssize_t *frameUsed,
355 ssize_t frameLeft);
356static ssize_t sound_copy_translate_read(const u_char *userPtr,
357 size_t userCount,
358 u_char frame[], ssize_t *frameUsed,
359 ssize_t frameLeft);
360
361
362/*
363 * /dev/mixer abstraction
364 */
365
366struct sound_mixer {
367 int busy;
368 int modify_counter;
369};
370
371static struct sound_mixer mixer;
372
373static struct sound_queue sq;
374static struct sound_queue read_sq;
375
376#define sq_block_address(i) (sq.buffers[i])
377#define SIGNAL_RECEIVED (signal_pending(current))
378#define NON_BLOCKING(open_mode) (open_mode & O_NONBLOCK)
379#define ONE_SECOND HZ /* in jiffies (100ths of a second) */
380#define NO_TIME_LIMIT 0xffffffff
381
382/*
383 * /dev/sndstat
384 */
385
386struct sound_state {
387 int busy;
388 char buf[512];
389 int len, ptr;
390};
391
392static struct sound_state state;
393
394/*** Common stuff ********************************************************/
395
396static long long sound_lseek(struct file *file, long long offset, int orig);
397
398/*** Config & Setup **********************************************************/
399
400void dmasound_setup(char *str, int *ints);
401
402/*** Translations ************************************************************/
403
404
405/* ++TeSche: radically changed for new expanding purposes...
406 *
407 * These two routines now deal with copying/expanding/translating the samples
408 * from user space into our buffer at the right frequency. They take care about
409 * how much data there's actually to read, how much buffer space there is and
410 * to convert samples into the right frequency/encoding. They will only work on
411 * complete samples so it may happen they leave some bytes in the input stream
412 * if the user didn't write a multiple of the current sample size. They both
413 * return the number of bytes they've used from both streams so you may detect
414 * such a situation. Luckily all programs should be able to cope with that.
415 *
416 * I think I've optimized anything as far as one can do in plain C, all
417 * variables should fit in registers and the loops are really short. There's
418 * one loop for every possible situation. Writing a more generalized and thus
419 * parameterized loop would only produce slower code. Feel free to optimize
420 * this in assembler if you like. :)
421 *
422 * I think these routines belong here because they're not yet really hardware
423 * independent, especially the fact that the Falcon can play 16bit samples
424 * only in stereo is hardcoded in both of them!
425 *
426 * ++geert: split in even more functions (one per format)
427 */
428
429static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount,
430 u_char frame[], ssize_t *frameUsed,
431 ssize_t frameLeft)
432{
433 short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16;
434 ssize_t count, used;
435 short *p = (short *) &frame[*frameUsed];
436 int val, stereo = sound.soft.stereo;
437
438 frameLeft >>= 2;
439 if (stereo)
440 userCount >>= 1;
441 used = count = min(userCount, frameLeft);
442 while (count > 0) {
443 u_char data;
444 if (get_user(data, userPtr++))
445 return -EFAULT;
446 val = table[data];
447 *p++ = val;
448 if (stereo) {
449 if (get_user(data, userPtr++))
450 return -EFAULT;
451 val = table[data];
452 }
453 *p++ = val;
454 count--;
455 }
456 *frameUsed += used * 4;
457 return stereo? used * 2: used;
458}
459
460
461static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount,
462 u_char frame[], ssize_t *frameUsed,
463 ssize_t frameLeft)
464{
465 ssize_t count, used;
466 short *p = (short *) &frame[*frameUsed];
467 int val, stereo = sound.soft.stereo;
468
469 frameLeft >>= 2;
470 if (stereo)
471 userCount >>= 1;
472 used = count = min(userCount, frameLeft);
473 while (count > 0) {
474 u_char data;
475 if (get_user(data, userPtr++))
476 return -EFAULT;
477 val = data << 8;
478 *p++ = val;
479 if (stereo) {
480 if (get_user(data, userPtr++))
481 return -EFAULT;
482 val = data << 8;
483 }
484 *p++ = val;
485 count--;
486 }
487 *frameUsed += used * 4;
488 return stereo? used * 2: used;
489}
490
491
492static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount,
493 u_char frame[], ssize_t *frameUsed,
494 ssize_t frameLeft)
495{
496 ssize_t count, used;
497 short *p = (short *) &frame[*frameUsed];
498 int val, stereo = sound.soft.stereo;
499
500 frameLeft >>= 2;
501 if (stereo)
502 userCount >>= 1;
503 used = count = min(userCount, frameLeft);
504 while (count > 0) {
505 u_char data;
506 if (get_user(data, userPtr++))
507 return -EFAULT;
508 val = (data ^ 0x80) << 8;
509 *p++ = val;
510 if (stereo) {
511 if (get_user(data, userPtr++))
512 return -EFAULT;
513 val = (data ^ 0x80) << 8;
514 }
515 *p++ = val;
516 count--;
517 }
518 *frameUsed += used * 4;
519 return stereo? used * 2: used;
520}
521
522
523/* This is the default format of the codec. Signed, 16-bit stereo
524 * generated by an application shouldn't have to be copied at all.
525 * We should just get the phsical address of the buffers and update
526 * the TDM BDs directly.
527 */
528static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount,
529 u_char frame[], ssize_t *frameUsed,
530 ssize_t frameLeft)
531{
532 ssize_t count, used;
533 int stereo = sound.soft.stereo;
534 short *fp = (short *) &frame[*frameUsed];
535
536 frameLeft >>= 2;
537 userCount >>= (stereo? 2: 1);
538 used = count = min(userCount, frameLeft);
539 if (!stereo) {
540 short *up = (short *) userPtr;
541 while (count > 0) {
542 short data;
543 if (get_user(data, up++))
544 return -EFAULT;
545 *fp++ = data;
546 *fp++ = data;
547 count--;
548 }
549 } else {
550 if (copy_from_user(fp, userPtr, count * 4))
551 return -EFAULT;
552 }
553 *frameUsed += used * 4;
554 return stereo? used * 4: used * 2;
555}
556
557static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount,
558 u_char frame[], ssize_t *frameUsed,
559 ssize_t frameLeft)
560{
561 ssize_t count, used;
562 int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
563 int stereo = sound.soft.stereo;
564 short *fp = (short *) &frame[*frameUsed];
565 short *up = (short *) userPtr;
566
567 frameLeft >>= 2;
568 userCount >>= (stereo? 2: 1);
569 used = count = min(userCount, frameLeft);
570 while (count > 0) {
571 int data;
572 if (get_user(data, up++))
573 return -EFAULT;
574 data ^= mask;
575 *fp++ = data;
576 if (stereo) {
577 if (get_user(data, up++))
578 return -EFAULT;
579 data ^= mask;
580 }
581 *fp++ = data;
582 count--;
583 }
584 *frameUsed += used * 4;
585 return stereo? used * 4: used * 2;
586}
587
588
589static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount,
590 u_char frame[], ssize_t *frameUsed,
591 ssize_t frameLeft)
592{
593 unsigned short *table = (unsigned short *)
594 (sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16);
595 unsigned int data = expand_data;
596 unsigned int *p = (unsigned int *) &frame[*frameUsed];
597 int bal = expand_bal;
598 int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
599 int utotal, ftotal;
600 int stereo = sound.soft.stereo;
601
602 frameLeft >>= 2;
603 if (stereo)
604 userCount >>= 1;
605 ftotal = frameLeft;
606 utotal = userCount;
607 while (frameLeft) {
608 u_char c;
609 if (bal < 0) {
610 if (userCount == 0)
611 break;
612 if (get_user(c, userPtr++))
613 return -EFAULT;
614 data = table[c];
615 if (stereo) {
616 if (get_user(c, userPtr++))
617 return -EFAULT;
618 data = (data << 16) + table[c];
619 } else
620 data = (data << 16) + data;
621 userCount--;
622 bal += hSpeed;
623 }
624 *p++ = data;
625 frameLeft--;
626 bal -= sSpeed;
627 }
628 expand_bal = bal;
629 expand_data = data;
630 *frameUsed += (ftotal - frameLeft) * 4;
631 utotal -= userCount;
632 return stereo? utotal * 2: utotal;
633}
634
635
636static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount,
637 u_char frame[], ssize_t *frameUsed,
638 ssize_t frameLeft)
639{
640 unsigned int *p = (unsigned int *) &frame[*frameUsed];
641 unsigned int data = expand_data;
642 int bal = expand_bal;
643 int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
644 int stereo = sound.soft.stereo;
645 int utotal, ftotal;
646
647 frameLeft >>= 2;
648 if (stereo)
649 userCount >>= 1;
650 ftotal = frameLeft;
651 utotal = userCount;
652 while (frameLeft) {
653 u_char c;
654 if (bal < 0) {
655 if (userCount == 0)
656 break;
657 if (get_user(c, userPtr++))
658 return -EFAULT;
659 data = c << 8;
660 if (stereo) {
661 if (get_user(c, userPtr++))
662 return -EFAULT;
663 data = (data << 16) + (c << 8);
664 } else
665 data = (data << 16) + data;
666 userCount--;
667 bal += hSpeed;
668 }
669 *p++ = data;
670 frameLeft--;
671 bal -= sSpeed;
672 }
673 expand_bal = bal;
674 expand_data = data;
675 *frameUsed += (ftotal - frameLeft) * 4;
676 utotal -= userCount;
677 return stereo? utotal * 2: utotal;
678}
679
680
681static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount,
682 u_char frame[], ssize_t *frameUsed,
683 ssize_t frameLeft)
684{
685 unsigned int *p = (unsigned int *) &frame[*frameUsed];
686 unsigned int data = expand_data;
687 int bal = expand_bal;
688 int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
689 int stereo = sound.soft.stereo;
690 int utotal, ftotal;
691
692 frameLeft >>= 2;
693 if (stereo)
694 userCount >>= 1;
695 ftotal = frameLeft;
696 utotal = userCount;
697 while (frameLeft) {
698 u_char c;
699 if (bal < 0) {
700 if (userCount == 0)
701 break;
702 if (get_user(c, userPtr++))
703 return -EFAULT;
704 data = (c ^ 0x80) << 8;
705 if (stereo) {
706 if (get_user(c, userPtr++))
707 return -EFAULT;
708 data = (data << 16) + ((c ^ 0x80) << 8);
709 } else
710 data = (data << 16) + data;
711 userCount--;
712 bal += hSpeed;
713 }
714 *p++ = data;
715 frameLeft--;
716 bal -= sSpeed;
717 }
718 expand_bal = bal;
719 expand_data = data;
720 *frameUsed += (ftotal - frameLeft) * 4;
721 utotal -= userCount;
722 return stereo? utotal * 2: utotal;
723}
724
725
726static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount,
727 u_char frame[], ssize_t *frameUsed,
728 ssize_t frameLeft)
729{
730 unsigned int *p = (unsigned int *) &frame[*frameUsed];
731 unsigned int data = expand_data;
732 unsigned short *up = (unsigned short *) userPtr;
733 int bal = expand_bal;
734 int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
735 int stereo = sound.soft.stereo;
736 int utotal, ftotal;
737
738 frameLeft >>= 2;
739 userCount >>= (stereo? 2: 1);
740 ftotal = frameLeft;
741 utotal = userCount;
742 while (frameLeft) {
743 unsigned short c;
744 if (bal < 0) {
745 if (userCount == 0)
746 break;
747 if (get_user(data, up++))
748 return -EFAULT;
749 if (stereo) {
750 if (get_user(c, up++))
751 return -EFAULT;
752 data = (data << 16) + c;
753 } else
754 data = (data << 16) + data;
755 userCount--;
756 bal += hSpeed;
757 }
758 *p++ = data;
759 frameLeft--;
760 bal -= sSpeed;
761 }
762 expand_bal = bal;
763 expand_data = data;
764 *frameUsed += (ftotal - frameLeft) * 4;
765 utotal -= userCount;
766 return stereo? utotal * 4: utotal * 2;
767}
768
769
770static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount,
771 u_char frame[], ssize_t *frameUsed,
772 ssize_t frameLeft)
773{
774 int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
775 unsigned int *p = (unsigned int *) &frame[*frameUsed];
776 unsigned int data = expand_data;
777 unsigned short *up = (unsigned short *) userPtr;
778 int bal = expand_bal;
779 int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
780 int stereo = sound.soft.stereo;
781 int utotal, ftotal;
782
783 frameLeft >>= 2;
784 userCount >>= (stereo? 2: 1);
785 ftotal = frameLeft;
786 utotal = userCount;
787 while (frameLeft) {
788 unsigned short c;
789 if (bal < 0) {
790 if (userCount == 0)
791 break;
792 if (get_user(data, up++))
793 return -EFAULT;
794 data ^= mask;
795 if (stereo) {
796 if (get_user(c, up++))
797 return -EFAULT;
798 data = (data << 16) + (c ^ mask);
799 } else
800 data = (data << 16) + data;
801 userCount--;
802 bal += hSpeed;
803 }
804 *p++ = data;
805 frameLeft--;
806 bal -= sSpeed;
807 }
808 expand_bal = bal;
809 expand_data = data;
810 *frameUsed += (ftotal - frameLeft) * 4;
811 utotal -= userCount;
812 return stereo? utotal * 4: utotal * 2;
813}
814
815static ssize_t cs4218_ct_s8_read(const u_char *userPtr, size_t userCount,
816 u_char frame[], ssize_t *frameUsed,
817 ssize_t frameLeft)
818{
819 ssize_t count, used;
820 short *p = (short *) &frame[*frameUsed];
821 int val, stereo = sound.soft.stereo;
822
823 frameLeft >>= 2;
824 if (stereo)
825 userCount >>= 1;
826 used = count = min(userCount, frameLeft);
827 while (count > 0) {
828 u_char data;
829
830 val = *p++;
831 data = val >> 8;
832 if (put_user(data, (u_char *)userPtr++))
833 return -EFAULT;
834 if (stereo) {
835 val = *p;
836 data = val >> 8;
837 if (put_user(data, (u_char *)userPtr++))
838 return -EFAULT;
839 }
840 p++;
841 count--;
842 }
843 *frameUsed += used * 4;
844 return stereo? used * 2: used;
845}
846
847
848static ssize_t cs4218_ct_u8_read(const u_char *userPtr, size_t userCount,
849 u_char frame[], ssize_t *frameUsed,
850 ssize_t frameLeft)
851{
852 ssize_t count, used;
853 short *p = (short *) &frame[*frameUsed];
854 int val, stereo = sound.soft.stereo;
855
856 frameLeft >>= 2;
857 if (stereo)
858 userCount >>= 1;
859 used = count = min(userCount, frameLeft);
860 while (count > 0) {
861 u_char data;
862
863 val = *p++;
864 data = (val >> 8) ^ 0x80;
865 if (put_user(data, (u_char *)userPtr++))
866 return -EFAULT;
867 if (stereo) {
868 val = *p;
869 data = (val >> 8) ^ 0x80;
870 if (put_user(data, (u_char *)userPtr++))
871 return -EFAULT;
872 }
873 p++;
874 count--;
875 }
876 *frameUsed += used * 4;
877 return stereo? used * 2: used;
878}
879
880
881static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount,
882 u_char frame[], ssize_t *frameUsed,
883 ssize_t frameLeft)
884{
885 ssize_t count, used;
886 int stereo = sound.soft.stereo;
887 short *fp = (short *) &frame[*frameUsed];
888
889 frameLeft >>= 2;
890 userCount >>= (stereo? 2: 1);
891 used = count = min(userCount, frameLeft);
892 if (!stereo) {
893 short *up = (short *) userPtr;
894 while (count > 0) {
895 short data;
896 data = *fp;
897 if (put_user(data, up++))
898 return -EFAULT;
899 fp+=2;
900 count--;
901 }
902 } else {
903 if (copy_to_user((u_char *)userPtr, fp, count * 4))
904 return -EFAULT;
905 }
906 *frameUsed += used * 4;
907 return stereo? used * 4: used * 2;
908}
909
910static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount,
911 u_char frame[], ssize_t *frameUsed,
912 ssize_t frameLeft)
913{
914 ssize_t count, used;
915 int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
916 int stereo = sound.soft.stereo;
917 short *fp = (short *) &frame[*frameUsed];
918 short *up = (short *) userPtr;
919
920 frameLeft >>= 2;
921 userCount >>= (stereo? 2: 1);
922 used = count = min(userCount, frameLeft);
923 while (count > 0) {
924 int data;
925
926 data = *fp++;
927 data ^= mask;
928 if (put_user(data, up++))
929 return -EFAULT;
930 if (stereo) {
931 data = *fp;
932 data ^= mask;
933 if (put_user(data, up++))
934 return -EFAULT;
935 }
936 fp++;
937 count--;
938 }
939 *frameUsed += used * 4;
940 return stereo? used * 4: used * 2;
941}
942
943static TRANS transCSNormal = {
944 cs4218_ct_law, cs4218_ct_law, cs4218_ct_s8, cs4218_ct_u8,
945 cs4218_ct_s16, cs4218_ct_u16, cs4218_ct_s16, cs4218_ct_u16
946};
947
948static TRANS transCSExpand = {
949 cs4218_ctx_law, cs4218_ctx_law, cs4218_ctx_s8, cs4218_ctx_u8,
950 cs4218_ctx_s16, cs4218_ctx_u16, cs4218_ctx_s16, cs4218_ctx_u16
951};
952
953static TRANS transCSNormalRead = {
954 NULL, NULL, cs4218_ct_s8_read, cs4218_ct_u8_read,
955 cs4218_ct_s16_read, cs4218_ct_u16_read,
956 cs4218_ct_s16_read, cs4218_ct_u16_read
957};
958
959/*** Low level stuff *********************************************************/
960
961static void *CS_Alloc(unsigned int size, gfp_t flags)
962{
963 int order;
964
965 size >>= 13;
966 for (order=0; order < 5; order++) {
967 if (size == 0)
968 break;
969 size >>= 1;
970 }
971 return (void *)__get_free_pages(flags, order);
972}
973
974static void CS_Free(void *ptr, unsigned int size)
975{
976 int order;
977
978 size >>= 13;
979 for (order=0; order < 5; order++) {
980 if (size == 0)
981 break;
982 size >>= 1;
983 }
984 free_pages((ulong)ptr, order);
985}
986
987static int __init CS_IrqInit(void)
988{
989 cpm_install_handler(CPMVEC_SMC2, cs4218_intr, NULL);
990 return 1;
991}
992
993#ifdef MODULE
994static void CS_IrqCleanup(void)
995{
996 volatile smc_t *sp;
997 volatile cpm8xx_t *cp;
998
999 /* First disable transmitter and receiver.
1000 */
1001 sp = &cpmp->cp_smc[1];
1002 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
1003
1004 /* And now shut down the SMC.
1005 */
1006 cp = cpmp; /* Get pointer to Communication Processor */
1007 cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
1008 CPM_CR_STOP_TX) | CPM_CR_FLG;
1009 while (cp->cp_cpcr & CPM_CR_FLG);
1010
1011 /* Release the interrupt handler.
1012 */
1013 cpm_free_handler(CPMVEC_SMC2);
1014
1015 kfree(beep_buf);
1016 kd_mksound = orig_mksound;
1017}
1018#endif /* MODULE */
1019
1020static void CS_Silence(void)
1021{
1022 volatile smc_t *sp;
1023
1024 /* Disable transmitter.
1025 */
1026 sp = &cpmp->cp_smc[1];
1027 sp->smc_smcmr &= ~SMCMR_TEN;
1028}
1029
1030/* Frequencies depend upon external oscillator. There are two
1031 * choices, 12.288 and 11.2896 MHz. The RPCG audio supports both through
1032 * and external control register selection bit.
1033 */
1034static int cs4218_freqs[] = {
1035 /* 12.288 11.2896 */
1036 48000, 44100,
1037 32000, 29400,
1038 24000, 22050,
1039 19200, 17640,
1040 16000, 14700,
1041 12000, 11025,
1042 9600, 8820,
1043 8000, 7350
1044};
1045
1046static void CS_Init(void)
1047{
1048 int i, tolerance;
1049
1050 switch (sound.soft.format) {
1051 case AFMT_S16_LE:
1052 case AFMT_U16_LE:
1053 sound.hard.format = AFMT_S16_LE;
1054 break;
1055 default:
1056 sound.hard.format = AFMT_S16_BE;
1057 break;
1058 }
1059 sound.hard.stereo = 1;
1060 sound.hard.size = 16;
1061
1062 /*
1063 * If we have a sample rate which is within catchRadius percent
1064 * of the requested value, we don't have to expand the samples.
1065 * Otherwise choose the next higher rate.
1066 */
1067 i = (sizeof(cs4218_freqs) / sizeof(int));
1068 do {
1069 tolerance = catchRadius * cs4218_freqs[--i] / 100;
1070 } while (sound.soft.speed > cs4218_freqs[i] + tolerance && i > 0);
1071 if (sound.soft.speed >= cs4218_freqs[i] - tolerance)
1072 sound.trans_write = &transCSNormal;
1073 else
1074 sound.trans_write = &transCSExpand;
1075 sound.trans_read = &transCSNormalRead;
1076 sound.hard.speed = cs4218_freqs[i];
1077 cs4218_rate_index = i;
1078
1079 /* The CS4218 has seven selectable clock dividers for the sample
1080 * clock. The HIOX then provides one of two external rates.
1081 * An even numbered frequency table index uses the high external
1082 * clock rate.
1083 */
1084 *(uint *)HIOX_CSR4_ADDR &= ~(HIOX_CSR4_AUDCLKHI | HIOX_CSR4_AUDCLKSEL);
1085 if ((i & 1) == 0)
1086 *(uint *)HIOX_CSR4_ADDR |= HIOX_CSR4_AUDCLKHI;
1087 i >>= 1;
1088 *(uint *)HIOX_CSR4_ADDR |= (i & HIOX_CSR4_AUDCLKSEL);
1089
1090 expand_bal = -sound.soft.speed;
1091}
1092
1093static int CS_SetFormat(int format)
1094{
1095 int size;
1096
1097 switch (format) {
1098 case AFMT_QUERY:
1099 return sound.soft.format;
1100 case AFMT_MU_LAW:
1101 case AFMT_A_LAW:
1102 case AFMT_U8:
1103 case AFMT_S8:
1104 size = 8;
1105 break;
1106 case AFMT_S16_BE:
1107 case AFMT_U16_BE:
1108 case AFMT_S16_LE:
1109 case AFMT_U16_LE:
1110 size = 16;
1111 break;
1112 default: /* :-) */
1113 printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n",
1114 format);
1115 size = 8;
1116 format = AFMT_U8;
1117 }
1118
1119 sound.soft.format = format;
1120 sound.soft.size = size;
1121 if (sound.minDev == SND_DEV_DSP) {
1122 sound.dsp.format = format;
1123 sound.dsp.size = size;
1124 }
1125
1126 CS_Init();
1127
1128 return format;
1129}
1130
1131/* Volume is the amount of attenuation we tell the codec to impose
1132 * on the outputs. There are 32 levels, with 0 the "loudest".
1133 */
1134#define CS_VOLUME_TO_MASK(x) (31 - ((((x) - 1) * 31) / 99))
1135#define CS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 31))
1136
1137static int cs_get_volume(uint reg)
1138{
1139 int volume;
1140
1141 volume = CS_MASK_TO_VOLUME(CS_LATTEN_GET(reg));
1142 volume |= CS_MASK_TO_VOLUME(CS_RATTEN_GET(reg)) << 8;
1143 return volume;
1144}
1145
1146static int cs_volume_setter(int volume, int mute)
1147{
1148 uint tempctl;
1149
1150 if (mute && volume == 0) {
1151 tempctl = cs4218_control | CS_MUTE;
1152 } else {
1153 tempctl = cs4218_control & ~CS_MUTE;
1154 tempctl = tempctl & ~(CS_LATTEN | CS_RATTEN);
1155 tempctl |= CS_LATTEN_SET(CS_VOLUME_TO_MASK(volume & 0xff));
1156 tempctl |= CS_RATTEN_SET(CS_VOLUME_TO_MASK((volume >> 8) & 0xff));
1157 volume = cs_get_volume(tempctl);
1158 }
1159 if (tempctl != cs4218_control) {
1160 cs4218_ctl_write(tempctl);
1161 }
1162 return volume;
1163}
1164
1165
1166/* Gain has 16 steps from 0 to 15. These are in 1.5dB increments from
1167 * 0 (no gain) to 22.5 dB.
1168 */
1169#define CS_RECLEVEL_TO_GAIN(v) \
1170 ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
1171#define CS_GAIN_TO_RECLEVEL(v) (((v) * 20 + 2) / 3)
1172
1173static int cs_get_gain(uint reg)
1174{
1175 int gain;
1176
1177 gain = CS_GAIN_TO_RECLEVEL(CS_LGAIN_GET(reg));
1178 gain |= CS_GAIN_TO_RECLEVEL(CS_RGAIN_GET(reg)) << 8;
1179 return gain;
1180}
1181
1182static int cs_set_gain(int gain)
1183{
1184 uint tempctl;
1185
1186 tempctl = cs4218_control & ~(CS_LGAIN | CS_RGAIN);
1187 tempctl |= CS_LGAIN_SET(CS_RECLEVEL_TO_GAIN(gain & 0xff));
1188 tempctl |= CS_RGAIN_SET(CS_RECLEVEL_TO_GAIN((gain >> 8) & 0xff));
1189 gain = cs_get_gain(tempctl);
1190
1191 if (tempctl != cs4218_control) {
1192 cs4218_ctl_write(tempctl);
1193 }
1194 return gain;
1195}
1196
1197static int CS_SetVolume(int volume)
1198{
1199 return cs_volume_setter(volume, CS_MUTE);
1200}
1201
1202static void CS_Play(void)
1203{
1204 int i, count;
1205 unsigned long flags;
1206 volatile cbd_t *bdp;
1207 volatile cpm8xx_t *cp;
1208
1209 /* Protect buffer */
1210 spin_lock_irqsave(&cs4218_lock, flags);
1211#if 0
1212 if (awacs_beep_state) {
1213 /* sound takes precedence over beeps */
1214 out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
1215 out_le32(&awacs->control,
1216 (in_le32(&awacs->control) & ~0x1f00)
1217 | (awacs_rate_index << 8));
1218 out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
1219 out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[(sq.front+sq.active) % sq.max_count])));
1220
1221 beep_playing = 0;
1222 awacs_beep_state = 0;
1223 }
1224#endif
1225 i = sq.front + sq.active;
1226 if (i >= sq.max_count)
1227 i -= sq.max_count;
1228 while (sq.active < 2 && sq.active < sq.count) {
1229 count = (sq.count == sq.active + 1)?sq.rear_size:sq.block_size;
1230 if (count < sq.block_size && !sq.syncing)
1231 /* last block not yet filled, and we're not syncing. */
1232 break;
1233
1234 bdp = &tx_base[i];
1235 bdp->cbd_datlen = count;
1236
1237 flush_dcache_range((ulong)sound_buffers[i],
1238 (ulong)(sound_buffers[i] + count));
1239
1240 if (++i >= sq.max_count)
1241 i = 0;
1242
1243 if (sq.active == 0) {
1244 /* The SMC does not load its fifo until the first
1245 * TDM frame pulse, so the transmit data gets shifted
1246 * by one word. To compensate for this, we incorrectly
1247 * transmit the first buffer and shorten it by one
1248 * word. Subsequent buffers are then aligned properly.
1249 */
1250 bdp->cbd_datlen -= 2;
1251
1252 /* Start up the SMC Transmitter.
1253 */
1254 cp = cpmp;
1255 cp->cp_smc[1].smc_smcmr |= SMCMR_TEN;
1256 cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
1257 CPM_CR_RESTART_TX) | CPM_CR_FLG;
1258 while (cp->cp_cpcr & CPM_CR_FLG);
1259 }
1260
1261 /* Buffer is ready now.
1262 */
1263 bdp->cbd_sc |= BD_SC_READY;
1264
1265 ++sq.active;
1266 }
1267 spin_unlock_irqrestore(&cs4218_lock, flags);
1268}
1269
1270
1271static void CS_Record(void)
1272{
1273 unsigned long flags;
1274 volatile smc_t *sp;
1275
1276 if (read_sq.active)
1277 return;
1278
1279 /* Protect buffer */
1280 spin_lock_irqsave(&cs4218_lock, flags);
1281
1282 /* This is all we have to do......Just start it up.
1283 */
1284 sp = &cpmp->cp_smc[1];
1285 sp->smc_smcmr |= SMCMR_REN;
1286
1287 read_sq.active = 1;
1288
1289 spin_unlock_irqrestore(&cs4218_lock, flags);
1290}
1291
1292
1293static void
1294cs4218_tdm_tx_intr(void *devid)
1295{
1296 int i = sq.front;
1297 volatile cbd_t *bdp;
1298
1299 while (sq.active > 0) {
1300 bdp = &tx_base[i];
1301 if (bdp->cbd_sc & BD_SC_READY)
1302 break; /* this frame is still going */
1303 --sq.count;
1304 --sq.active;
1305 if (++i >= sq.max_count)
1306 i = 0;
1307 }
1308 if (i != sq.front)
1309 WAKE_UP(sq.action_queue);
1310 sq.front = i;
1311
1312 CS_Play();
1313
1314 if (!sq.active)
1315 WAKE_UP(sq.sync_queue);
1316}
1317
1318
1319static void
1320cs4218_tdm_rx_intr(void *devid)
1321{
1322
1323 /* We want to blow 'em off when shutting down.
1324 */
1325 if (read_sq.active == 0)
1326 return;
1327
1328 /* Check multiple buffers in case we were held off from
1329 * interrupt processing for a long time. Geeze, I really hope
1330 * this doesn't happen.
1331 */
1332 while ((rx_base[read_sq.rear].cbd_sc & BD_SC_EMPTY) == 0) {
1333
1334 /* Invalidate the data cache range for this buffer.
1335 */
1336 invalidate_dcache_range(
1337 (uint)(sound_read_buffers[read_sq.rear]),
1338 (uint)(sound_read_buffers[read_sq.rear] + read_sq.block_size));
1339
1340 /* Make buffer available again and move on.
1341 */
1342 rx_base[read_sq.rear].cbd_sc |= BD_SC_EMPTY;
1343 read_sq.rear++;
1344
1345 /* Wrap the buffer ring.
1346 */
1347 if (read_sq.rear >= read_sq.max_active)
1348 read_sq.rear = 0;
1349
1350 /* If we have caught up to the front buffer, bump it.
1351 * This will cause weird (but not fatal) results if the
1352 * read loop is currently using this buffer. The user is
1353 * behind in this case anyway, so weird things are going
1354 * to happen.
1355 */
1356 if (read_sq.rear == read_sq.front) {
1357 read_sq.front++;
1358 if (read_sq.front >= read_sq.max_active)
1359 read_sq.front = 0;
1360 }
1361 }
1362
1363 WAKE_UP(read_sq.action_queue);
1364}
1365
1366static void cs_nosound(unsigned long xx)
1367{
1368 unsigned long flags;
1369
1370 /* not sure if this is needed, since hardware command is #if 0'd */
1371 spin_lock_irqsave(&cs4218_lock, flags);
1372 if (beep_playing) {
1373#if 0
1374 st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
1375#endif
1376 beep_playing = 0;
1377 }
1378 spin_unlock_irqrestore(&cs4218_lock, flags);
1379}
1380
1381static DEFINE_TIMER(beep_timer, cs_nosound, 0, 0);
1382
1383static void cs_mksound(unsigned int hz, unsigned int ticks)
1384{
1385 unsigned long flags;
1386 int beep_speed = BEEP_SPEED;
1387 int srate = cs4218_freqs[beep_speed];
1388 int period, ncycles, nsamples;
1389 int i, j, f;
1390 short *p;
1391 static int beep_hz_cache;
1392 static int beep_nsamples_cache;
1393 static int beep_volume_cache;
1394
1395 if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) {
1396#if 1
1397 /* this is a hack for broken X server code */
1398 hz = 750;
1399 ticks = 12;
1400#else
1401 /* cancel beep currently playing */
1402 awacs_nosound(0);
1403 return;
1404#endif
1405 }
1406 /* lock while modifying beep_timer */
1407 spin_lock_irqsave(&cs4218_lock, flags);
1408 del_timer(&beep_timer);
1409 if (ticks) {
1410 beep_timer.expires = jiffies + ticks;
1411 add_timer(&beep_timer);
1412 }
1413 if (beep_playing || sq.active || beep_buf == NULL) {
1414 spin_unlock_irqrestore(&cs4218_lock, flags);
1415 return; /* too hard, sorry :-( */
1416 }
1417 beep_playing = 1;
1418#if 0
1419 st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS);
1420#endif
1421 spin_unlock_irqrestore(&cs4218_lock, flags);
1422
1423 if (hz == beep_hz_cache && beep_volume == beep_volume_cache) {
1424 nsamples = beep_nsamples_cache;
1425 } else {
1426 period = srate * 256 / hz; /* fixed point */
1427 ncycles = BEEP_BUFLEN * 256 / period;
1428 nsamples = (period * ncycles) >> 8;
1429 f = ncycles * 65536 / nsamples;
1430 j = 0;
1431 p = beep_buf;
1432 for (i = 0; i < nsamples; ++i, p += 2) {
1433 p[0] = p[1] = beep_wform[j >> 8] * beep_volume;
1434 j = (j + f) & 0xffff;
1435 }
1436 beep_hz_cache = hz;
1437 beep_volume_cache = beep_volume;
1438 beep_nsamples_cache = nsamples;
1439 }
1440
1441#if 0
1442 st_le16(&beep_dbdma_cmd->req_count, nsamples*4);
1443 st_le16(&beep_dbdma_cmd->xfer_status, 0);
1444 st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd));
1445 st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf));
1446 awacs_beep_state = 1;
1447
1448 spin_lock_irqsave(&cs4218_lock, flags);
1449 if (beep_playing) { /* i.e. haven't been terminated already */
1450 out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
1451 out_le32(&awacs->control,
1452 (in_le32(&awacs->control) & ~0x1f00)
1453 | (beep_speed << 8));
1454 out_le32(&awacs->byteswap, 0);
1455 out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
1456 out_le32(&awacs_txdma->control, RUN | (RUN << 16));
1457 }
1458 spin_unlock_irqrestore(&cs4218_lock, flags);
1459#endif
1460}
1461
1462static MACHINE mach_cs4218 = {
1463 .owner = THIS_MODULE,
1464 .name = "HIOX CS4218",
1465 .name2 = "Built-in Sound",
1466 .dma_alloc = CS_Alloc,
1467 .dma_free = CS_Free,
1468 .irqinit = CS_IrqInit,
1469#ifdef MODULE
1470 .irqcleanup = CS_IrqCleanup,
1471#endif /* MODULE */
1472 .init = CS_Init,
1473 .silence = CS_Silence,
1474 .setFormat = CS_SetFormat,
1475 .setVolume = CS_SetVolume,
1476 .play = CS_Play
1477};
1478
1479
1480/*** Mid level stuff *********************************************************/
1481
1482
1483static void sound_silence(void)
1484{
1485 /* update hardware settings one more */
1486 (*sound.mach.init)();
1487
1488 (*sound.mach.silence)();
1489}
1490
1491
1492static void sound_init(void)
1493{
1494 (*sound.mach.init)();
1495}
1496
1497
1498static int sound_set_format(int format)
1499{
1500 return(*sound.mach.setFormat)(format);
1501}
1502
1503
1504static int sound_set_speed(int speed)
1505{
1506 if (speed < 0)
1507 return(sound.soft.speed);
1508
1509 sound.soft.speed = speed;
1510 (*sound.mach.init)();
1511 if (sound.minDev == SND_DEV_DSP)
1512 sound.dsp.speed = sound.soft.speed;
1513
1514 return(sound.soft.speed);
1515}
1516
1517
1518static int sound_set_stereo(int stereo)
1519{
1520 if (stereo < 0)
1521 return(sound.soft.stereo);
1522
1523 stereo = !!stereo; /* should be 0 or 1 now */
1524
1525 sound.soft.stereo = stereo;
1526 if (sound.minDev == SND_DEV_DSP)
1527 sound.dsp.stereo = stereo;
1528 (*sound.mach.init)();
1529
1530 return(stereo);
1531}
1532
1533
1534static int sound_set_volume(int volume)
1535{
1536 return(*sound.mach.setVolume)(volume);
1537}
1538
1539static ssize_t sound_copy_translate(const u_char *userPtr,
1540 size_t userCount,
1541 u_char frame[], ssize_t *frameUsed,
1542 ssize_t frameLeft)
1543{
1544 ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL;
1545
1546 switch (sound.soft.format) {
1547 case AFMT_MU_LAW:
1548 ct_func = sound.trans_write->ct_ulaw;
1549 break;
1550 case AFMT_A_LAW:
1551 ct_func = sound.trans_write->ct_alaw;
1552 break;
1553 case AFMT_S8:
1554 ct_func = sound.trans_write->ct_s8;
1555 break;
1556 case AFMT_U8:
1557 ct_func = sound.trans_write->ct_u8;
1558 break;
1559 case AFMT_S16_BE:
1560 ct_func = sound.trans_write->ct_s16be;
1561 break;
1562 case AFMT_U16_BE:
1563 ct_func = sound.trans_write->ct_u16be;
1564 break;
1565 case AFMT_S16_LE:
1566 ct_func = sound.trans_write->ct_s16le;
1567 break;
1568 case AFMT_U16_LE:
1569 ct_func = sound.trans_write->ct_u16le;
1570 break;
1571 }
1572 if (ct_func)
1573 return ct_func(userPtr, userCount, frame, frameUsed, frameLeft);
1574 else
1575 return 0;
1576}
1577
1578static ssize_t sound_copy_translate_read(const u_char *userPtr,
1579 size_t userCount,
1580 u_char frame[], ssize_t *frameUsed,
1581 ssize_t frameLeft)
1582{
1583 ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL;
1584
1585 switch (sound.soft.format) {
1586 case AFMT_MU_LAW:
1587 ct_func = sound.trans_read->ct_ulaw;
1588 break;
1589 case AFMT_A_LAW:
1590 ct_func = sound.trans_read->ct_alaw;
1591 break;
1592 case AFMT_S8:
1593 ct_func = sound.trans_read->ct_s8;
1594 break;
1595 case AFMT_U8:
1596 ct_func = sound.trans_read->ct_u8;
1597 break;
1598 case AFMT_S16_BE:
1599 ct_func = sound.trans_read->ct_s16be;
1600 break;
1601 case AFMT_U16_BE:
1602 ct_func = sound.trans_read->ct_u16be;
1603 break;
1604 case AFMT_S16_LE:
1605 ct_func = sound.trans_read->ct_s16le;
1606 break;
1607 case AFMT_U16_LE:
1608 ct_func = sound.trans_read->ct_u16le;
1609 break;
1610 }
1611 if (ct_func)
1612 return ct_func(userPtr, userCount, frame, frameUsed, frameLeft);
1613 else
1614 return 0;
1615}
1616
1617
1618/*
1619 * /dev/mixer abstraction
1620 */
1621
1622static int mixer_open(struct inode *inode, struct file *file)
1623{
1624 mixer.busy = 1;
1625 return nonseekable_open(inode, file);
1626}
1627
1628
1629static int mixer_release(struct inode *inode, struct file *file)
1630{
1631 mixer.busy = 0;
1632 return 0;
1633}
1634
1635
1636static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
1637 u_long arg)
1638{
1639 int data;
1640 uint tmpcs;
1641
1642 if (_SIOC_DIR(cmd) & _SIOC_WRITE)
1643 mixer.modify_counter++;
1644 if (cmd == OSS_GETVERSION)
1645 return IOCTL_OUT(arg, SOUND_VERSION);
1646 switch (cmd) {
1647 case SOUND_MIXER_INFO: {
1648 mixer_info info;
1649 strlcpy(info.id, "CS4218_TDM", sizeof(info.id));
1650 strlcpy(info.name, "CS4218_TDM", sizeof(info.name));
1651 info.name[sizeof(info.name)-1] = 0;
1652 info.modify_counter = mixer.modify_counter;
1653 if (copy_to_user((int *)arg, &info, sizeof(info)))
1654 return -EFAULT;
1655 return 0;
1656 }
1657 case SOUND_MIXER_READ_DEVMASK:
1658 data = SOUND_MASK_VOLUME | SOUND_MASK_LINE
1659 | SOUND_MASK_MIC | SOUND_MASK_RECLEV
1660 | SOUND_MASK_ALTPCM;
1661 return IOCTL_OUT(arg, data);
1662 case SOUND_MIXER_READ_RECMASK:
1663 data = SOUND_MASK_LINE | SOUND_MASK_MIC;
1664 return IOCTL_OUT(arg, data);
1665 case SOUND_MIXER_READ_RECSRC:
1666 if (cs4218_control & CS_DO1)
1667 data = SOUND_MASK_LINE;
1668 else
1669 data = SOUND_MASK_MIC;
1670 return IOCTL_OUT(arg, data);
1671 case SOUND_MIXER_WRITE_RECSRC:
1672 IOCTL_IN(arg, data);
1673 data &= (SOUND_MASK_LINE | SOUND_MASK_MIC);
1674 if (data & SOUND_MASK_LINE)
1675 tmpcs = cs4218_control |
1676 (CS_ISL | CS_ISR | CS_DO1);
1677 if (data & SOUND_MASK_MIC)
1678 tmpcs = cs4218_control &
1679 ~(CS_ISL | CS_ISR | CS_DO1);
1680 if (tmpcs != cs4218_control)
1681 cs4218_ctl_write(tmpcs);
1682 return IOCTL_OUT(arg, data);
1683 case SOUND_MIXER_READ_STEREODEVS:
1684 data = SOUND_MASK_VOLUME | SOUND_MASK_RECLEV;
1685 return IOCTL_OUT(arg, data);
1686 case SOUND_MIXER_READ_CAPS:
1687 return IOCTL_OUT(arg, 0);
1688 case SOUND_MIXER_READ_VOLUME:
1689 data = (cs4218_control & CS_MUTE)? 0:
1690 cs_get_volume(cs4218_control);
1691 return IOCTL_OUT(arg, data);
1692 case SOUND_MIXER_WRITE_VOLUME:
1693 IOCTL_IN(arg, data);
1694 return IOCTL_OUT(arg, sound_set_volume(data));
1695 case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
1696 IOCTL_IN(arg, data);
1697 beep_volume = data & 0xff;
1698 /* fall through */
1699 case SOUND_MIXER_READ_ALTPCM:
1700 return IOCTL_OUT(arg, beep_volume);
1701 case SOUND_MIXER_WRITE_RECLEV:
1702 IOCTL_IN(arg, data);
1703 data = cs_set_gain(data);
1704 return IOCTL_OUT(arg, data);
1705 case SOUND_MIXER_READ_RECLEV:
1706 data = cs_get_gain(cs4218_control);
1707 return IOCTL_OUT(arg, data);
1708 }
1709
1710 return -EINVAL;
1711}
1712
1713
1714static const struct file_operations mixer_fops =
1715{
1716 .owner = THIS_MODULE,
1717 .llseek = sound_lseek,
1718 .ioctl = mixer_ioctl,
1719 .open = mixer_open,
1720 .release = mixer_release,
1721};
1722
1723
1724static void __init mixer_init(void)
1725{
1726 mixer_unit = register_sound_mixer(&mixer_fops, -1);
1727 if (mixer_unit < 0)
1728 return;
1729
1730 mixer.busy = 0;
1731 sound.treble = 0;
1732 sound.bass = 0;
1733
1734 /* Set Line input, no gain, no attenuation.
1735 */
1736 cs4218_control = CS_ISL | CS_ISR | CS_DO1;
1737 cs4218_control |= CS_LGAIN_SET(0) | CS_RGAIN_SET(0);
1738 cs4218_control |= CS_LATTEN_SET(0) | CS_RATTEN_SET(0);
1739 cs4218_ctl_write(cs4218_control);
1740}
1741
1742
1743/*
1744 * Sound queue stuff, the heart of the driver
1745 */
1746
1747
1748static int sq_allocate_buffers(void)
1749{
1750 int i;
1751
1752 if (sound_buffers)
1753 return 0;
1754 sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
1755 if (!sound_buffers)
1756 return -ENOMEM;
1757 for (i = 0; i < numBufs; i++) {
1758 sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
1759 if (!sound_buffers[i]) {
1760 while (i--)
1761 sound.mach.dma_free (sound_buffers[i], bufSize << 10);
1762 kfree (sound_buffers);
1763 sound_buffers = 0;
1764 return -ENOMEM;
1765 }
1766 }
1767 return 0;
1768}
1769
1770
1771static void sq_release_buffers(void)
1772{
1773 int i;
1774
1775 if (sound_buffers) {
1776 for (i = 0; i < numBufs; i++)
1777 sound.mach.dma_free (sound_buffers[i], bufSize << 10);
1778 kfree (sound_buffers);
1779 sound_buffers = 0;
1780 }
1781}
1782
1783
1784static int sq_allocate_read_buffers(void)
1785{
1786 int i;
1787
1788 if (sound_read_buffers)
1789 return 0;
1790 sound_read_buffers = kmalloc(numReadBufs * sizeof(char *), GFP_KERNEL);
1791 if (!sound_read_buffers)
1792 return -ENOMEM;
1793 for (i = 0; i < numBufs; i++) {
1794 sound_read_buffers[i] = sound.mach.dma_alloc (readbufSize<<10,
1795 GFP_KERNEL);
1796 if (!sound_read_buffers[i]) {
1797 while (i--)
1798 sound.mach.dma_free (sound_read_buffers[i],
1799 readbufSize << 10);
1800 kfree (sound_read_buffers);
1801 sound_read_buffers = 0;
1802 return -ENOMEM;
1803 }
1804 }
1805 return 0;
1806}
1807
1808static void sq_release_read_buffers(void)
1809{
1810 int i;
1811
1812 if (sound_read_buffers) {
1813 cpmp->cp_smc[1].smc_smcmr &= ~SMCMR_REN;
1814 for (i = 0; i < numReadBufs; i++)
1815 sound.mach.dma_free (sound_read_buffers[i],
1816 bufSize << 10);
1817 kfree (sound_read_buffers);
1818 sound_read_buffers = 0;
1819 }
1820}
1821
1822
1823static void sq_setup(int numBufs, int bufSize, char **write_buffers)
1824{
1825 int i;
1826 volatile cbd_t *bdp;
1827 volatile cpm8xx_t *cp;
1828 volatile smc_t *sp;
1829
1830 /* Make sure the SMC transmit is shut down.
1831 */
1832 cp = cpmp;
1833 sp = &cpmp->cp_smc[1];
1834 sp->smc_smcmr &= ~SMCMR_TEN;
1835
1836 sq.max_count = numBufs;
1837 sq.max_active = numBufs;
1838 sq.block_size = bufSize;
1839 sq.buffers = write_buffers;
1840
1841 sq.front = sq.count = 0;
1842 sq.rear = -1;
1843 sq.syncing = 0;
1844 sq.active = 0;
1845
1846 bdp = tx_base;
1847 for (i=0; i<numBufs; i++) {
1848 bdp->cbd_bufaddr = virt_to_bus(write_buffers[i]);
1849 bdp++;
1850 }
1851
1852 /* This causes the SMC to sync up with the first buffer again.
1853 */
1854 cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_TX) | CPM_CR_FLG;
1855 while (cp->cp_cpcr & CPM_CR_FLG);
1856}
1857
1858static void read_sq_setup(int numBufs, int bufSize, char **read_buffers)
1859{
1860 int i;
1861 volatile cbd_t *bdp;
1862 volatile cpm8xx_t *cp;
1863 volatile smc_t *sp;
1864
1865 /* Make sure the SMC receive is shut down.
1866 */
1867 cp = cpmp;
1868 sp = &cpmp->cp_smc[1];
1869 sp->smc_smcmr &= ~SMCMR_REN;
1870
1871 read_sq.max_count = numBufs;
1872 read_sq.max_active = numBufs;
1873 read_sq.block_size = bufSize;
1874 read_sq.buffers = read_buffers;
1875
1876 read_sq.front = read_sq.count = 0;
1877 read_sq.rear = 0;
1878 read_sq.rear_size = 0;
1879 read_sq.syncing = 0;
1880 read_sq.active = 0;
1881
1882 bdp = rx_base;
1883 for (i=0; i<numReadBufs; i++) {
1884 bdp->cbd_bufaddr = virt_to_bus(read_buffers[i]);
1885 bdp->cbd_datlen = read_sq.block_size;
1886 bdp++;
1887 }
1888
1889 /* This causes the SMC to sync up with the first buffer again.
1890 */
1891 cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_RX) | CPM_CR_FLG;
1892 while (cp->cp_cpcr & CPM_CR_FLG);
1893}
1894
1895
1896static void sq_play(void)
1897{
1898 (*sound.mach.play)();
1899}
1900
1901
1902/* ++TeSche: radically changed this one too */
1903
1904static ssize_t sq_write(struct file *file, const char *src, size_t uLeft,
1905 loff_t *ppos)
1906{
1907 ssize_t uWritten = 0;
1908 u_char *dest;
1909 ssize_t uUsed, bUsed, bLeft;
1910
1911 /* ++TeSche: Is something like this necessary?
1912 * Hey, that's an honest question! Or does any other part of the
1913 * filesystem already checks this situation? I really don't know.
1914 */
1915 if (uLeft == 0)
1916 return 0;
1917
1918 /* The interrupt doesn't start to play the last, incomplete frame.
1919 * Thus we can append to it without disabling the interrupts! (Note
1920 * also that sq.rear isn't affected by the interrupt.)
1921 */
1922
1923 if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) {
1924 dest = sq_block_address(sq.rear);
1925 bUsed = sq.rear_size;
1926 uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
1927 if (uUsed <= 0)
1928 return uUsed;
1929 src += uUsed;
1930 uWritten += uUsed;
1931 uLeft -= uUsed;
1932 sq.rear_size = bUsed;
1933 }
1934
1935 do {
1936 while (sq.count == sq.max_active) {
1937 sq_play();
1938 if (NON_BLOCKING(sq.open_mode))
1939 return uWritten > 0 ? uWritten : -EAGAIN;
1940 SLEEP(sq.action_queue);
1941 if (SIGNAL_RECEIVED)
1942 return uWritten > 0 ? uWritten : -EINTR;
1943 }
1944
1945 /* Here, we can avoid disabling the interrupt by first
1946 * copying and translating the data, and then updating
1947 * the sq variables. Until this is done, the interrupt
1948 * won't see the new frame and we can work on it
1949 * undisturbed.
1950 */
1951
1952 dest = sq_block_address((sq.rear+1) % sq.max_count);
1953 bUsed = 0;
1954 bLeft = sq.block_size;
1955 uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
1956 if (uUsed <= 0)
1957 break;
1958 src += uUsed;
1959 uWritten += uUsed;
1960 uLeft -= uUsed;
1961 if (bUsed) {
1962 sq.rear = (sq.rear+1) % sq.max_count;
1963 sq.rear_size = bUsed;
1964 sq.count++;
1965 }
1966 } while (bUsed); /* uUsed may have been 0 */
1967
1968 sq_play();
1969
1970 return uUsed < 0? uUsed: uWritten;
1971}
1972
1973
1974/***********/
1975
1976/* Here is how the values are used for reading.
1977 * The value 'active' simply indicates the DMA is running. This is
1978 * done so the driver semantics are DMA starts when the first read is
1979 * posted. The value 'front' indicates the buffer we should next
1980 * send to the user. The value 'rear' indicates the buffer the DMA is
1981 * currently filling. When 'front' == 'rear' the buffer "ring" is
1982 * empty (we always have an empty available). The 'rear_size' is used
1983 * to track partial offsets into the current buffer. Right now, I just keep
1984 * The DMA running. If the reader can't keep up, the interrupt tosses
1985 * the oldest buffer. We could also shut down the DMA in this case.
1986 */
1987static ssize_t sq_read(struct file *file, char *dst, size_t uLeft,
1988 loff_t *ppos)
1989{
1990
1991 ssize_t uRead, bLeft, bUsed, uUsed;
1992
1993 if (uLeft == 0)
1994 return 0;
1995
1996 if (!read_sq.active)
1997 CS_Record(); /* Kick off the record process. */
1998
1999 uRead = 0;
2000
2001 /* Move what the user requests, depending upon other options.
2002 */
2003 while (uLeft > 0) {
2004
2005 /* When front == rear, the DMA is not done yet.
2006 */
2007 while (read_sq.front == read_sq.rear) {
2008 if (NON_BLOCKING(read_sq.open_mode)) {
2009 return uRead > 0 ? uRead : -EAGAIN;
2010 }
2011 SLEEP(read_sq.action_queue);
2012 if (SIGNAL_RECEIVED)
2013 return uRead > 0 ? uRead : -EINTR;
2014 }
2015
2016 /* The amount we move is either what is left in the
2017 * current buffer or what the user wants.
2018 */
2019 bLeft = read_sq.block_size - read_sq.rear_size;
2020 bUsed = read_sq.rear_size;
2021 uUsed = sound_copy_translate_read(dst, uLeft,
2022 read_sq.buffers[read_sq.front], &bUsed, bLeft);
2023 if (uUsed <= 0)
2024 return uUsed;
2025 dst += uUsed;
2026 uRead += uUsed;
2027 uLeft -= uUsed;
2028 read_sq.rear_size += bUsed;
2029 if (read_sq.rear_size >= read_sq.block_size) {
2030 read_sq.rear_size = 0;
2031 read_sq.front++;
2032 if (read_sq.front >= read_sq.max_active)
2033 read_sq.front = 0;
2034 }
2035 }
2036 return uRead;
2037}
2038
2039static int sq_open(struct inode *inode, struct file *file)
2040{
2041 int rc = 0;
2042
2043 if (file->f_mode & FMODE_WRITE) {
2044 if (sq.busy) {
2045 rc = -EBUSY;
2046 if (NON_BLOCKING(file->f_flags))
2047 goto err_out;
2048 rc = -EINTR;
2049 while (sq.busy) {
2050 SLEEP(sq.open_queue);
2051 if (SIGNAL_RECEIVED)
2052 goto err_out;
2053 }
2054 }
2055 sq.busy = 1; /* Let's play spot-the-race-condition */
2056
2057 if (sq_allocate_buffers()) goto err_out_nobusy;
2058
2059 sq_setup(numBufs, bufSize<<10,sound_buffers);
2060 sq.open_mode = file->f_mode;
2061 }
2062
2063
2064 if (file->f_mode & FMODE_READ) {
2065 if (read_sq.busy) {
2066 rc = -EBUSY;
2067 if (NON_BLOCKING(file->f_flags))
2068 goto err_out;
2069 rc = -EINTR;
2070 while (read_sq.busy) {
2071 SLEEP(read_sq.open_queue);
2072 if (SIGNAL_RECEIVED)
2073 goto err_out;
2074 }
2075 rc = 0;
2076 }
2077 read_sq.busy = 1;
2078 if (sq_allocate_read_buffers()) goto err_out_nobusy;
2079
2080 read_sq_setup(numReadBufs,readbufSize<<10, sound_read_buffers);
2081 read_sq.open_mode = file->f_mode;
2082 }
2083
2084 /* Start up the 4218 by:
2085 * Reset.
2086 * Enable, unreset.
2087 */
2088 *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_RSTAUDIO;
2089 eieio();
2090 *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_ENAUDIO;
2091 mdelay(50);
2092 *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO;
2093
2094 /* We need to send the current control word in case someone
2095 * opened /dev/mixer and changed things while we were shut
2096 * down. Chances are good the initialization that follows
2097 * would have done this, but it is still possible it wouldn't.
2098 */
2099 cs4218_ctl_write(cs4218_control);
2100
2101 sound.minDev = iminor(inode) & 0x0f;
2102 sound.soft = sound.dsp;
2103 sound.hard = sound.dsp;
2104 sound_init();
2105 if ((iminor(inode) & 0x0f) == SND_DEV_AUDIO) {
2106 sound_set_speed(8000);
2107 sound_set_stereo(0);
2108 sound_set_format(AFMT_MU_LAW);
2109 }
2110
2111 return nonseekable_open(inode, file);
2112
2113err_out_nobusy:
2114 if (file->f_mode & FMODE_WRITE) {
2115 sq.busy = 0;
2116 WAKE_UP(sq.open_queue);
2117 }
2118 if (file->f_mode & FMODE_READ) {
2119 read_sq.busy = 0;
2120 WAKE_UP(read_sq.open_queue);
2121 }
2122err_out:
2123 return rc;
2124}
2125
2126
2127static void sq_reset(void)
2128{
2129 sound_silence();
2130 sq.active = 0;
2131 sq.count = 0;
2132 sq.front = (sq.rear+1) % sq.max_count;
2133#if 0
2134 init_tdm_buffers();
2135#endif
2136}
2137
2138
2139static int sq_fsync(struct file *filp, struct dentry *dentry)
2140{
2141 int rc = 0;
2142
2143 sq.syncing = 1;
2144 sq_play(); /* there may be an incomplete frame waiting */
2145
2146 while (sq.active) {
2147 SLEEP(sq.sync_queue);
2148 if (SIGNAL_RECEIVED) {
2149 /* While waiting for audio output to drain, an
2150 * interrupt occurred. Stop audio output immediately
2151 * and clear the queue. */
2152 sq_reset();
2153 rc = -EINTR;
2154 break;
2155 }
2156 }
2157
2158 sq.syncing = 0;
2159 return rc;
2160}
2161
2162static int sq_release(struct inode *inode, struct file *file)
2163{
2164 int rc = 0;
2165
2166 if (sq.busy)
2167 rc = sq_fsync(file, file->f_path.dentry);
2168 sound.soft = sound.dsp;
2169 sound.hard = sound.dsp;
2170 sound_silence();
2171
2172 sq_release_read_buffers();
2173 sq_release_buffers();
2174
2175 if (file->f_mode & FMODE_READ) {
2176 read_sq.busy = 0;
2177 WAKE_UP(read_sq.open_queue);
2178 }
2179
2180 if (file->f_mode & FMODE_WRITE) {
2181 sq.busy = 0;
2182 WAKE_UP(sq.open_queue);
2183 }
2184
2185 /* Shut down the SMC.
2186 */
2187 cpmp->cp_smc[1].smc_smcmr &= ~(SMCMR_TEN | SMCMR_REN);
2188
2189 /* Shut down the codec.
2190 */
2191 *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO;
2192 eieio();
2193 *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_ENAUDIO;
2194
2195 /* Wake up a process waiting for the queue being released.
2196 * Note: There may be several processes waiting for a call
2197 * to open() returning. */
2198
2199 return rc;
2200}
2201
2202
2203static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
2204 u_long arg)
2205{
2206 u_long fmt;
2207 int data;
2208#if 0
2209 int size, nbufs;
2210#else
2211 int size;
2212#endif
2213
2214 switch (cmd) {
2215 case SNDCTL_DSP_RESET:
2216 sq_reset();
2217 return 0;
2218 case SNDCTL_DSP_POST:
2219 case SNDCTL_DSP_SYNC:
2220 return sq_fsync(file, file->f_path.dentry);
2221
2222 /* ++TeSche: before changing any of these it's
2223 * probably wise to wait until sound playing has
2224 * settled down. */
2225 case SNDCTL_DSP_SPEED:
2226 sq_fsync(file, file->f_path.dentry);
2227 IOCTL_IN(arg, data);
2228 return IOCTL_OUT(arg, sound_set_speed(data));
2229 case SNDCTL_DSP_STEREO:
2230 sq_fsync(file, file->f_path.dentry);
2231 IOCTL_IN(arg, data);
2232 return IOCTL_OUT(arg, sound_set_stereo(data));
2233 case SOUND_PCM_WRITE_CHANNELS:
2234 sq_fsync(file, file->f_path.dentry);
2235 IOCTL_IN(arg, data);
2236 return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);
2237 case SNDCTL_DSP_SETFMT:
2238 sq_fsync(file, file->f_path.dentry);
2239 IOCTL_IN(arg, data);
2240 return IOCTL_OUT(arg, sound_set_format(data));
2241 case SNDCTL_DSP_GETFMTS:
2242 fmt = 0;
2243 if (sound.trans_write) {
2244 if (sound.trans_write->ct_ulaw)
2245 fmt |= AFMT_MU_LAW;
2246 if (sound.trans_write->ct_alaw)
2247 fmt |= AFMT_A_LAW;
2248 if (sound.trans_write->ct_s8)
2249 fmt |= AFMT_S8;
2250 if (sound.trans_write->ct_u8)
2251 fmt |= AFMT_U8;
2252 if (sound.trans_write->ct_s16be)
2253 fmt |= AFMT_S16_BE;
2254 if (sound.trans_write->ct_u16be)
2255 fmt |= AFMT_U16_BE;
2256 if (sound.trans_write->ct_s16le)
2257 fmt |= AFMT_S16_LE;
2258 if (sound.trans_write->ct_u16le)
2259 fmt |= AFMT_U16_LE;
2260 }
2261 return IOCTL_OUT(arg, fmt);
2262 case SNDCTL_DSP_GETBLKSIZE:
2263 size = sq.block_size
2264 * sound.soft.size * (sound.soft.stereo + 1)
2265 / (sound.hard.size * (sound.hard.stereo + 1));
2266 return IOCTL_OUT(arg, size);
2267 case SNDCTL_DSP_SUBDIVIDE:
2268 break;
2269#if 0 /* Sorry can't do this at the moment. The CPM allocated buffers
2270 * long ago that can't be changed.
2271 */
2272 case SNDCTL_DSP_SETFRAGMENT:
2273 if (sq.count || sq.active || sq.syncing)
2274 return -EINVAL;
2275 IOCTL_IN(arg, size);
2276 nbufs = size >> 16;
2277 if (nbufs < 2 || nbufs > numBufs)
2278 nbufs = numBufs;
2279 size &= 0xffff;
2280 if (size >= 8 && size <= 30) {
2281 size = 1 << size;
2282 size *= sound.hard.size * (sound.hard.stereo + 1);
2283 size /= sound.soft.size * (sound.soft.stereo + 1);
2284 if (size > (bufSize << 10))
2285 size = bufSize << 10;
2286 } else
2287 size = bufSize << 10;
2288 sq_setup(numBufs, size, sound_buffers);
2289 sq.max_active = nbufs;
2290 return 0;
2291#endif
2292
2293 default:
2294 return mixer_ioctl(inode, file, cmd, arg);
2295 }
2296 return -EINVAL;
2297}
2298
2299
2300
2301static const struct file_operations sq_fops =
2302{
2303 .owner = THIS_MODULE,
2304 .llseek = sound_lseek,
2305 .read = sq_read, /* sq_read */
2306 .write = sq_write,
2307 .ioctl = sq_ioctl,
2308 .open = sq_open,
2309 .release = sq_release,
2310};
2311
2312
2313static void __init sq_init(void)
2314{
2315 sq_unit = register_sound_dsp(&sq_fops, -1);
2316 if (sq_unit < 0)
2317 return;
2318
2319 init_waitqueue_head(&sq.action_queue);
2320 init_waitqueue_head(&sq.open_queue);
2321 init_waitqueue_head(&sq.sync_queue);
2322 init_waitqueue_head(&read_sq.action_queue);
2323 init_waitqueue_head(&read_sq.open_queue);
2324 init_waitqueue_head(&read_sq.sync_queue);
2325
2326 sq.busy = 0;
2327 read_sq.busy = 0;
2328
2329 /* whatever you like as startup mode for /dev/dsp,
2330 * (/dev/audio hasn't got a startup mode). note that
2331 * once changed a new open() will *not* restore these!
2332 */
2333 sound.dsp.format = AFMT_S16_BE;
2334 sound.dsp.stereo = 1;
2335 sound.dsp.size = 16;
2336
2337 /* set minimum rate possible without expanding */
2338 sound.dsp.speed = 8000;
2339
2340 /* before the first open to /dev/dsp this wouldn't be set */
2341 sound.soft = sound.dsp;
2342 sound.hard = sound.dsp;
2343
2344 sound_silence();
2345}
2346
2347/*
2348 * /dev/sndstat
2349 */
2350
2351
2352/* state.buf should not overflow! */
2353
2354static int state_open(struct inode *inode, struct file *file)
2355{
2356 char *buffer = state.buf, *mach = "", cs4218_buf[50];
2357 int len = 0;
2358
2359 if (state.busy)
2360 return -EBUSY;
2361
2362 state.ptr = 0;
2363 state.busy = 1;
2364
2365 sprintf(cs4218_buf, "Crystal CS4218 on TDM, ");
2366 mach = cs4218_buf;
2367
2368 len += sprintf(buffer+len, "%sDMA sound driver:\n", mach);
2369
2370 len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format);
2371 switch (sound.soft.format) {
2372 case AFMT_MU_LAW:
2373 len += sprintf(buffer+len, " (mu-law)");
2374 break;
2375 case AFMT_A_LAW:
2376 len += sprintf(buffer+len, " (A-law)");
2377 break;
2378 case AFMT_U8:
2379 len += sprintf(buffer+len, " (unsigned 8 bit)");
2380 break;
2381 case AFMT_S8:
2382 len += sprintf(buffer+len, " (signed 8 bit)");
2383 break;
2384 case AFMT_S16_BE:
2385 len += sprintf(buffer+len, " (signed 16 bit big)");
2386 break;
2387 case AFMT_U16_BE:
2388 len += sprintf(buffer+len, " (unsigned 16 bit big)");
2389 break;
2390 case AFMT_S16_LE:
2391 len += sprintf(buffer+len, " (signed 16 bit little)");
2392 break;
2393 case AFMT_U16_LE:
2394 len += sprintf(buffer+len, " (unsigned 16 bit little)");
2395 break;
2396 }
2397 len += sprintf(buffer+len, "\n");
2398 len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",
2399 sound.soft.speed, sound.hard.speed);
2400 len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",
2401 sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono");
2402 len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d"
2403 " sq.max_active = %d\n",
2404 sq.block_size, sq.max_count, sq.max_active);
2405 len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count,
2406 sq.rear_size);
2407 len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n",
2408 sq.active, sq.syncing);
2409 state.len = len;
2410 return nonseekable_open(inode, file);
2411}
2412
2413
2414static int state_release(struct inode *inode, struct file *file)
2415{
2416 state.busy = 0;
2417 return 0;
2418}
2419
2420
2421static ssize_t state_read(struct file *file, char *buf, size_t count,
2422 loff_t *ppos)
2423{
2424 int n = state.len - state.ptr;
2425 if (n > count)
2426 n = count;
2427 if (n <= 0)
2428 return 0;
2429 if (copy_to_user(buf, &state.buf[state.ptr], n))
2430 return -EFAULT;
2431 state.ptr += n;
2432 return n;
2433}
2434
2435
2436static const struct file_operations state_fops =
2437{
2438 .owner = THIS_MODULE,
2439 .llseek = sound_lseek,
2440 .read = state_read,
2441 .open = state_open,
2442 .release = state_release,
2443};
2444
2445
2446static void __init state_init(void)
2447{
2448 state_unit = register_sound_special(&state_fops, SND_DEV_STATUS);
2449 if (state_unit < 0)
2450 return;
2451 state.busy = 0;
2452}
2453
2454
2455/*** Common stuff ********************************************************/
2456
2457static long long sound_lseek(struct file *file, long long offset, int orig)
2458{
2459 return -ESPIPE;
2460}
2461
2462
2463/*** Config & Setup **********************************************************/
2464
2465
2466int __init tdm8xx_sound_init(void)
2467{
2468 int i, has_sound;
2469 uint dp_offset;
2470 volatile uint *sirp;
2471 volatile cbd_t *bdp;
2472 volatile cpm8xx_t *cp;
2473 volatile smc_t *sp;
2474 volatile smc_uart_t *up;
2475 volatile immap_t *immap;
2476
2477 has_sound = 0;
2478
2479 /* Program the SI/TSA to use TDMa, connected to SMC2, for 4 bytes.
2480 */
2481 cp = cpmp; /* Get pointer to Communication Processor */
2482 immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
2483
2484 /* Set all TDMa control bits to zero. This enables most features
2485 * we want.
2486 */
2487 cp->cp_simode &= ~0x00000fff;
2488
2489 /* Enable common receive/transmit clock pins, use IDL format.
2490 * Sync on falling edge, transmit rising clock, receive falling
2491 * clock, delay 1 bit on both Tx and Rx. Common Tx/Rx clocks and
2492 * sync.
2493 * Connect SMC2 to TSA.
2494 */
2495 cp->cp_simode |= 0x80000141;
2496
2497 /* Configure port A pins for TDMa operation.
2498 * The RPX-Lite (MPC850/823) loses SMC2 when TDM is used.
2499 */
2500 immap->im_ioport.iop_papar |= 0x01c0; /* Enable TDMa functions */
2501 immap->im_ioport.iop_padir |= 0x00c0; /* Enable TDMa Tx/Rx */
2502 immap->im_ioport.iop_padir &= ~0x0100; /* Enable L1RCLKa */
2503
2504 immap->im_ioport.iop_pcpar |= 0x0800; /* Enable L1RSYNCa */
2505 immap->im_ioport.iop_pcdir &= ~0x0800;
2506
2507 /* Initialize the SI TDM routing table. We use TDMa only.
2508 * The receive table and transmit table each have only one
2509 * entry, to capture/send four bytes after each frame pulse.
2510 * The 16-bit ram entry is 0000 0001 1000 1111. (SMC2)
2511 */
2512 cp->cp_sigmr = 0;
2513 sirp = (uint *)cp->cp_siram;
2514
2515 *sirp = 0x018f0000; /* Receive entry */
2516 sirp += 64;
2517 *sirp = 0x018f0000; /* Tramsmit entry */
2518
2519 /* Enable single TDMa routing.
2520 */
2521 cp->cp_sigmr = 0x04;
2522
2523 /* Initialize the SMC for transparent operation.
2524 */
2525 sp = &cpmp->cp_smc[1];
2526 up = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC2];
2527
2528 /* We need to allocate a transmit and receive buffer
2529 * descriptors from dual port ram.
2530 */
2531 dp_addr = cpm_dpalloc(sizeof(cbd_t) * numReadBufs, 8);
2532
2533 /* Set the physical address of the host memory
2534 * buffers in the buffer descriptors, and the
2535 * virtual address for us to work with.
2536 */
2537 bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
2538 up->smc_rbase = dp_offset;
2539 rx_cur = rx_base = (cbd_t *)bdp;
2540
2541 for (i=0; i<(numReadBufs-1); i++) {
2542 bdp->cbd_bufaddr = 0;
2543 bdp->cbd_datlen = 0;
2544 bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
2545 bdp++;
2546 }
2547 bdp->cbd_bufaddr = 0;
2548 bdp->cbd_datlen = 0;
2549 bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
2550
2551 /* Now, do the same for the transmit buffers.
2552 */
2553 dp_offset = cpm_dpalloc(sizeof(cbd_t) * numBufs, 8);
2554
2555 bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
2556 up->smc_tbase = dp_offset;
2557 tx_cur = tx_base = (cbd_t *)bdp;
2558
2559 for (i=0; i<(numBufs-1); i++) {
2560 bdp->cbd_bufaddr = 0;
2561 bdp->cbd_datlen = 0;
2562 bdp->cbd_sc = BD_SC_INTRPT;
2563 bdp++;
2564 }
2565 bdp->cbd_bufaddr = 0;
2566 bdp->cbd_datlen = 0;
2567 bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
2568
2569 /* Set transparent SMC mode.
2570 * A few things are specific to our application. The codec interface
2571 * is MSB first, hence the REVD selection. The CD/CTS pulse are
2572 * used by the TSA to indicate the frame start to the SMC.
2573 */
2574 up->smc_rfcr = SCC_EB;
2575 up->smc_tfcr = SCC_EB;
2576 up->smc_mrblr = readbufSize * 1024;
2577
2578 /* Set 16-bit reversed data, transparent mode.
2579 */
2580 sp->smc_smcmr = smcr_mk_clen(15) |
2581 SMCMR_SM_TRANS | SMCMR_REVD | SMCMR_BS;
2582
2583 /* Enable and clear events.
2584 * Because of FIFO delays, all we need is the receive interrupt
2585 * and we can process both the current receive and current
2586 * transmit interrupt within a few microseconds of the transmit.
2587 */
2588 sp->smc_smce = 0xff;
2589 sp->smc_smcm = SMCM_TXE | SMCM_TX | SMCM_RX;
2590
2591 /* Send the CPM an initialize command.
2592 */
2593 cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
2594 CPM_CR_INIT_TRX) | CPM_CR_FLG;
2595 while (cp->cp_cpcr & CPM_CR_FLG);
2596
2597 sound.mach = mach_cs4218;
2598 has_sound = 1;
2599
2600 /* Initialize beep stuff */
2601 orig_mksound = kd_mksound;
2602 kd_mksound = cs_mksound;
2603 beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
2604 if (beep_buf == NULL)
2605 printk(KERN_WARNING "dmasound: no memory for "
2606 "beep buffer\n");
2607
2608 if (!has_sound)
2609 return -ENODEV;
2610
2611 /* Initialize the software SPI.
2612 */
2613 sw_spi_init();
2614
2615 /* Set up sound queue, /dev/audio and /dev/dsp. */
2616
2617 /* Set default settings. */
2618 sq_init();
2619
2620 /* Set up /dev/sndstat. */
2621 state_init();
2622
2623 /* Set up /dev/mixer. */
2624 mixer_init();
2625
2626 if (!sound.mach.irqinit()) {
2627 printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n");
2628 return -ENODEV;
2629 }
2630#ifdef MODULE
2631 irq_installed = 1;
2632#endif
2633
2634 printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n",
2635 numBufs, bufSize);
2636
2637 return 0;
2638}
2639
2640/* Due to FIFOs and bit delays, the transmit interrupt occurs a few
2641 * microseconds ahead of the receive interrupt.
2642 * When we get an interrupt, we service the transmit first, then
2643 * check for a receive to prevent the overhead of returning through
2644 * the interrupt handler only to get back here right away during
2645 * full duplex operation.
2646 */
2647static void
2648cs4218_intr(void *dev_id)
2649{
2650 volatile smc_t *sp;
2651 volatile cpm8xx_t *cp;
2652
2653 sp = &cpmp->cp_smc[1];
2654
2655 if (sp->smc_smce & SCCM_TX) {
2656 sp->smc_smce = SCCM_TX;
2657 cs4218_tdm_tx_intr((void *)sp);
2658 }
2659
2660 if (sp->smc_smce & SCCM_RX) {
2661 sp->smc_smce = SCCM_RX;
2662 cs4218_tdm_rx_intr((void *)sp);
2663 }
2664
2665 if (sp->smc_smce & SCCM_TXE) {
2666 /* Transmit underrun. This happens with the application
2667 * didn't keep up sending buffers. We tell the SMC to
2668 * restart, which will cause it to poll the current (next)
2669 * BD. If the user supplied data since this occurred,
2670 * we just start running again. If they didn't, the SMC
2671 * will poll the descriptor until data is placed there.
2672 */
2673 sp->smc_smce = SCCM_TXE;
2674 cp = cpmp; /* Get pointer to Communication Processor */
2675 cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2,
2676 CPM_CR_RESTART_TX) | CPM_CR_FLG;
2677 while (cp->cp_cpcr & CPM_CR_FLG);
2678 }
2679}
2680
2681
2682#define MAXARGS 8 /* Should be sufficient for now */
2683
2684void __init dmasound_setup(char *str, int *ints)
2685{
2686 /* check the bootstrap parameter for "dmasound=" */
2687
2688 switch (ints[0]) {
2689 case 3:
2690 if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
2691 printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius);
2692 else
2693 catchRadius = ints[3];
2694 /* fall through */
2695 case 2:
2696 if (ints[1] < MIN_BUFFERS)
2697 printk("dmasound_setup: invalid number of buffers, using default = %d\n", numBufs);
2698 else
2699 numBufs = ints[1];
2700 if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)
2701 printk("dmasound_setup: invalid buffer size, using default = %d\n", bufSize);
2702 else
2703 bufSize = ints[2];
2704 break;
2705 case 0:
2706 break;
2707 default:
2708 printk("dmasound_setup: invalid number of arguments\n");
2709 }
2710}
2711
2712/* Software SPI functions.
2713 * These are on Port B.
2714 */
2715#define PB_SPICLK ((uint)0x00000002)
2716#define PB_SPIMOSI ((uint)0x00000004)
2717#define PB_SPIMISO ((uint)0x00000008)
2718
2719static
2720void sw_spi_init(void)
2721{
2722 volatile cpm8xx_t *cp;
2723 volatile uint *hcsr4;
2724
2725 hcsr4 = (volatile uint *)HIOX_CSR4_ADDR;
2726 cp = cpmp; /* Get pointer to Communication Processor */
2727
2728 *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */
2729
2730 /* Make these Port B signals general purpose I/O.
2731 * First, make sure the clock is low.
2732 */
2733 cp->cp_pbdat &= ~PB_SPICLK;
2734 cp->cp_pbpar &= ~(PB_SPICLK | PB_SPIMOSI | PB_SPIMISO);
2735
2736 /* Clock and Master Output are outputs.
2737 */
2738 cp->cp_pbdir |= (PB_SPICLK | PB_SPIMOSI);
2739
2740 /* Master Input.
2741 */
2742 cp->cp_pbdir &= ~PB_SPIMISO;
2743
2744}
2745
2746/* Write the CS4218 control word out the SPI port. While the
2747 * the control word is going out, the status word is arriving.
2748 */
2749static
2750uint cs4218_ctl_write(uint ctlreg)
2751{
2752 uint status;
2753
2754 sw_spi_io((u_char *)&ctlreg, (u_char *)&status, 4);
2755
2756 /* Shadow the control register.....I guess we could do
2757 * the same for the status, but for now we just return it
2758 * and let the caller decide.
2759 */
2760 cs4218_control = ctlreg;
2761 return status;
2762}
2763
2764static
2765void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt)
2766{
2767 int bits, i;
2768 u_char outbyte, inbyte;
2769 volatile cpm8xx_t *cp;
2770 volatile uint *hcsr4;
2771
2772 hcsr4 = (volatile uint *)HIOX_CSR4_ADDR;
2773 cp = cpmp; /* Get pointer to Communication Processor */
2774
2775 /* The timing on the bus is pretty slow. Code inefficiency
2776 * and eieio() is our friend here :-).
2777 */
2778 cp->cp_pbdat &= ~PB_SPICLK;
2779 *hcsr4 |= HIOX_CSR4_AUDSPISEL; /* Enable SPI select */
2780 eieio();
2781
2782 /* Clock in/out the bytes. Data is valid on the falling edge
2783 * of the clock. Data is MSB first.
2784 */
2785 for (i=0; i<bcnt; i++) {
2786 outbyte = *obuf++;
2787 inbyte = 0;
2788 for (bits=0; bits<8; bits++) {
2789 eieio();
2790 cp->cp_pbdat |= PB_SPICLK;
2791 eieio();
2792 if (outbyte & 0x80)
2793 cp->cp_pbdat |= PB_SPIMOSI;
2794 else
2795 cp->cp_pbdat &= ~PB_SPIMOSI;
2796 eieio();
2797 cp->cp_pbdat &= ~PB_SPICLK;
2798 eieio();
2799 outbyte <<= 1;
2800 inbyte <<= 1;
2801 if (cp->cp_pbdat & PB_SPIMISO)
2802 inbyte |= 1;
2803 }
2804 *ibuf++ = inbyte;
2805 }
2806
2807 *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */
2808 eieio();
2809}
2810
2811void cleanup_module(void)
2812{
2813 if (irq_installed) {
2814 sound_silence();
2815#ifdef MODULE
2816 sound.mach.irqcleanup();
2817#endif
2818 }
2819
2820 sq_release_read_buffers();
2821 sq_release_buffers();
2822
2823 if (mixer_unit >= 0)
2824 unregister_sound_mixer(mixer_unit);
2825 if (state_unit >= 0)
2826 unregister_sound_special(state_unit);
2827 if (sq_unit >= 0)
2828 unregister_sound_dsp(sq_unit);
2829}
2830
2831module_init(tdm8xx_sound_init);
2832module_exit(cleanup_module);
2833
diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
index 8e1fccd96fc0..9589969cec72 100644
--- a/arch/ppc/boot/common/misc-common.c
+++ b/arch/ppc/boot/common/misc-common.c
@@ -57,7 +57,8 @@ unsigned char *ISA_io = NULL;
57 57
58#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ 58#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
59 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ 59 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
60 || defined(CONFIG_SERIAL_MPSC_CONSOLE) 60 || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
61 || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
61extern unsigned long com_port; 62extern unsigned long com_port;
62 63
63extern int serial_tstc(unsigned long com_port); 64extern int serial_tstc(unsigned long com_port);
@@ -80,7 +81,8 @@ int tstc(void)
80{ 81{
81#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ 82#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
82 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ 83 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
83 || defined(CONFIG_SERIAL_MPSC_CONSOLE) 84 || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
85 || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
84 if(keyb_present) 86 if(keyb_present)
85 return (CRT_tstc() || serial_tstc(com_port)); 87 return (CRT_tstc() || serial_tstc(com_port));
86 else 88 else
@@ -95,7 +97,8 @@ int getc(void)
95 while (1) { 97 while (1) {
96#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ 98#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
97 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ 99 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
98 || defined(CONFIG_SERIAL_MPSC_CONSOLE) 100 || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
101 || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
99 if (serial_tstc(com_port)) 102 if (serial_tstc(com_port))
100 return (serial_getc(com_port)); 103 return (serial_getc(com_port));
101#endif /* serial console */ 104#endif /* serial console */
@@ -112,7 +115,8 @@ putc(const char c)
112 115
113#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ 116#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
114 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ 117 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
115 || defined(CONFIG_SERIAL_MPSC_CONSOLE) 118 || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
119 || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
116 serial_putc(com_port, c); 120 serial_putc(com_port, c);
117 if ( c == '\n' ) 121 if ( c == '\n' )
118 serial_putc(com_port, '\r'); 122 serial_putc(com_port, '\r');
@@ -161,7 +165,8 @@ void puts(const char *s)
161 while ( ( c = *s++ ) != '\0' ) { 165 while ( ( c = *s++ ) != '\0' ) {
162#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ 166#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
163 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ 167 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
164 || defined(CONFIG_SERIAL_MPSC_CONSOLE) 168 || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
169 || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
165 serial_putc(com_port, c); 170 serial_putc(com_port, c);
166 if ( c == '\n' ) serial_putc(com_port, '\r'); 171 if ( c == '\n' ) serial_putc(com_port, '\r');
167#endif /* serial console */ 172#endif /* serial console */
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index bcfb6cde70c4..5b877792d14f 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -201,6 +201,7 @@ boot-$(CONFIG_8260) += m8260_tty.o
201endif 201endif
202boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o 202boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o
203boot-$(CONFIG_SERIAL_MPSC_CONSOLE) += mv64x60_tty.o 203boot-$(CONFIG_SERIAL_MPSC_CONSOLE) += mv64x60_tty.o
204boot-$(CONFIG_SERIAL_UARTLITE_CONSOLE) += uartlite_tty.o
204 205
205LIBS := $(common)/lib.a $(bootlib)/lib.a 206LIBS := $(common)/lib.a $(bootlib)/lib.a
206ifeq ($(CONFIG_PPC_PREP),y) 207ifeq ($(CONFIG_PPC_PREP),y)
diff --git a/arch/ppc/boot/simple/uartlite_tty.c b/arch/ppc/boot/simple/uartlite_tty.c
new file mode 100644
index 000000000000..0eae1eab38d4
--- /dev/null
+++ b/arch/ppc/boot/simple/uartlite_tty.c
@@ -0,0 +1,37 @@
1/*
2 * Xilinx UARTLITE bootloader driver
3 *
4 * Copyright (c) 2007 Secret Lab Technologies Ltd.
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 as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/types.h>
13#include <asm/serial.h>
14#include <asm/io.h>
15#include <platforms/4xx/xparameters/xparameters.h>
16
17#define UARTLITE_BASEADDR ((void*)(XPAR_UARTLITE_0_BASEADDR))
18
19void
20serial_putc(unsigned long com_port, unsigned char c)
21{
22 while ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x08) != 0); /* spin */
23 out_be32(UARTLITE_BASEADDR + 0x4, c);
24}
25
26unsigned char
27serial_getc(unsigned long com_port)
28{
29 while ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x01) == 0); /* spin */
30 return in_be32(UARTLITE_BASEADDR);
31}
32
33int
34serial_tstc(unsigned long com_port)
35{
36 return ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x01) != 0);
37}
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index 1f91eca2f3d7..c5850a272650 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -40,7 +40,6 @@ main(void)
40 DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); 40 DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
41 DEFINE(KSP, offsetof(struct thread_struct, ksp)); 41 DEFINE(KSP, offsetof(struct thread_struct, ksp));
42 DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); 42 DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
43 DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
44 DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); 43 DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
45 DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); 44 DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
46 DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); 45 DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index a9d455369dc6..ab64256110bd 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -191,7 +191,6 @@ stack_ovf:
1910: 1910:
192 192
193_GLOBAL(DoSyscall) 193_GLOBAL(DoSyscall)
194 stw r0,THREAD+LAST_SYSCALL(r2)
195 stw r3,ORIG_GPR3(r1) 194 stw r3,ORIG_GPR3(r1)
196 li r12,0 195 li r12,0
197 stw r12,RESULT(r1) 196 stw r12,RESULT(r1)
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 705ae56016f0..76551b679030 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -29,6 +29,7 @@ config CPCI405
29 29
30config EP405 30config EP405
31 bool "EP405/EP405PC" 31 bool "EP405/EP405PC"
32 select EMBEDDEDBOOT
32 help 33 help
33 This option enables support for the EP405/EP405PC boards. 34 This option enables support for the EP405/EP405PC boards.
34 35
@@ -54,11 +55,15 @@ config WALNUT
54 55
55config XILINX_ML300 56config XILINX_ML300
56 bool "Xilinx-ML300" 57 bool "Xilinx-ML300"
58 select XILINX_VIRTEX_II_PRO
59 select EMBEDDEDBOOT
57 help 60 help
58 This option enables support for the Xilinx ML300 evaluation board. 61 This option enables support for the Xilinx ML300 evaluation board.
59 62
60config XILINX_ML403 63config XILINX_ML403
61 bool "Xilinx-ML403" 64 bool "Xilinx-ML403"
65 select XILINX_VIRTEX_4_FX
66 select EMBEDDEDBOOT
62 help 67 help
63 This option enables support for the Xilinx ML403 evaluation board. 68 This option enables support for the Xilinx ML403 evaluation board.
64endchoice 69endchoice
@@ -215,18 +220,14 @@ config 405GPR
215 220
216config XILINX_VIRTEX_II_PRO 221config XILINX_VIRTEX_II_PRO
217 bool 222 bool
218 depends on XILINX_ML300 223 select XILINX_VIRTEX
219 default y
220 224
221config XILINX_VIRTEX_4_FX 225config XILINX_VIRTEX_4_FX
222 bool 226 bool
223 depends on XILINX_ML403 227 select XILINX_VIRTEX
224 default y
225 228
226config XILINX_VIRTEX 229config XILINX_VIRTEX
227 bool 230 bool
228 depends on XILINX_VIRTEX_II_PRO || XILINX_VIRTEX_4_FX
229 default y
230 231
231config STB03xxx 232config STB03xxx
232 bool 233 bool
@@ -235,8 +236,6 @@ config STB03xxx
235 236
236config EMBEDDEDBOOT 237config EMBEDDEDBOOT
237 bool 238 bool
238 depends on EP405 || XILINX_ML300 || XILINX_ML403
239 default y
240 239
241config IBM_OPENBIOS 240config IBM_OPENBIOS
242 bool 241 bool
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile
index fa6610bccaf9..723ad7985cc6 100644
--- a/arch/ppc/platforms/4xx/Makefile
+++ b/arch/ppc/platforms/4xx/Makefile
@@ -28,5 +28,4 @@ obj-$(CONFIG_440SP) += ibm440sp.o
28obj-$(CONFIG_440SPE) += ppc440spe.o 28obj-$(CONFIG_440SPE) += ppc440spe.o
29obj-$(CONFIG_405EP) += ibm405ep.o 29obj-$(CONFIG_405EP) += ibm405ep.o
30obj-$(CONFIG_405GPR) += ibm405gpr.o 30obj-$(CONFIG_405GPR) += ibm405gpr.o
31obj-$(CONFIG_XILINX_VIRTEX) += virtex.o
32 31
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index 84e999d9a7bb..5e994e146ba8 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -178,7 +178,7 @@ ocotea_setup_pcix(void)
178 /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ 178 /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
179 PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); 179 PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
180 PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); 180 PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
181 PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); 181 PCIX_WRITEL(0x80000007, PCIX0_PIM0SA);
182 182
183 eieio(); 183 eieio();
184} 184}
@@ -289,7 +289,7 @@ ocotea_setup_arch(void)
289 * from FPGA, because it can be changed by on-board switches 289 * from FPGA, because it can be changed by on-board switches
290 * --ebs 290 * --ebs
291 */ 291 */
292 ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); 292 ibm440gx_get_clocks(&clocks, 33300000, 6 * 1843200);
293 ocp_sys_info.opb_bus_freq = clocks.opb; 293 ocp_sys_info.opb_bus_freq = clocks.opb;
294 294
295 /* Setup TODC access */ 295 /* Setup TODC access */
diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c
index bb0253eef45a..5d9af8ddb155 100644
--- a/arch/ppc/platforms/4xx/taishan.c
+++ b/arch/ppc/platforms/4xx/taishan.c
@@ -235,7 +235,7 @@ taishan_setup_pcix(void)
235 /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ 235 /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
236 PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); 236 PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
237 PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); 237 PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
238 PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); 238 PCIX_WRITEL(0x80000007, PCIX0_PIM0SA);
239 PCIX_WRITEL(0xffffffff, PCIX0_PIM0SAH); 239 PCIX_WRITEL(0xffffffff, PCIX0_PIM0SAH);
240 240
241 iounmap(pcix_reg_base); 241 iounmap(pcix_reg_base);
diff --git a/arch/ppc/platforms/4xx/virtex.c b/arch/ppc/platforms/4xx/virtex.c
deleted file mode 100644
index 133a83147199..000000000000
--- a/arch/ppc/platforms/4xx/virtex.c
+++ /dev/null
@@ -1,56 +0,0 @@
1/*
2 * Virtex-II Pro & Virtex-4 FX common infrastructure
3 *
4 * Maintainer: Grant Likely <grant.likely@secretlab.ca>
5 *
6 * Copyright 2005 Secret Lab Technologies Ltd.
7 * Copyright 2005 General Dynamics Canada Ltd.
8 * Copyright 2005 Freescale Semiconductor Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/device.h>
19#include <linux/serial_8250.h>
20#include <asm/ppc_sys.h>
21#include <platforms/4xx/virtex.h>
22#include <platforms/4xx/xparameters/xparameters.h>
23
24#define XPAR_UART(num) { \
25 .mapbase = XPAR_UARTNS550_##num##_BASEADDR + 3, \
26 .irq = XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \
27 .iotype = UPIO_MEM, \
28 .uartclk = XPAR_UARTNS550_##num##_CLOCK_FREQ_HZ, \
29 .flags = UPF_BOOT_AUTOCONF, \
30 .regshift = 2, \
31 }
32
33struct plat_serial8250_port serial_platform_data[] = {
34#ifdef XPAR_UARTNS550_0_BASEADDR
35 XPAR_UART(0),
36#endif
37#ifdef XPAR_UARTNS550_1_BASEADDR
38 XPAR_UART(1),
39#endif
40#ifdef XPAR_UARTNS550_2_BASEADDR
41 XPAR_UART(2),
42#endif
43#ifdef XPAR_UARTNS550_3_BASEADDR
44 XPAR_UART(3),
45#endif
46 { }, /* terminated by empty record */
47};
48
49struct platform_device ppc_sys_platform_devices[] = {
50 [VIRTEX_UART] = {
51 .name = "serial8250",
52 .id = 0,
53 .dev.platform_data = serial_platform_data,
54 },
55};
56
diff --git a/arch/ppc/platforms/4xx/virtex.h b/arch/ppc/platforms/4xx/virtex.h
index c14325dfd7b1..738280420be5 100644
--- a/arch/ppc/platforms/4xx/virtex.h
+++ b/arch/ppc/platforms/4xx/virtex.h
@@ -1,35 +1,35 @@
1/* 1/*
2 * arch/ppc/platforms/4xx/virtex.h 2 * Basic Virtex platform defines, included by <asm/ibm4xx.h>
3 * 3 *
4 * Include file that defines the Xilinx Virtex-II Pro processor 4 * 2005-2007 (c) Secret Lab Technologies Ltd.
5 * 2002-2004 (c) MontaVista Software, Inc.
5 * 6 *
6 * Author: MontaVista Software, Inc. 7 * This file is licensed under the terms of the GNU General Public License
7 * source@mvista.com 8 * version 2. This program is licensed "as is" without any warranty of any
8 * 9 * kind, whether express or implied.
9 * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the
10 * terms of the GNU General Public License version 2. This program is licensed
11 * "as is" without any warranty of any kind, whether express or implied.
12 */ 10 */
13 11
14#ifdef __KERNEL__ 12#ifdef __KERNEL__
15#ifndef __ASM_VIRTEX_H__ 13#ifndef __ASM_VIRTEX_H__
16#define __ASM_VIRTEX_H__ 14#define __ASM_VIRTEX_H__
17 15
18/* serial defines */
19
20#include <asm/ibm405.h> 16#include <asm/ibm405.h>
17#include <asm/ppcboot.h>
21 18
22/* Ugly, ugly, ugly! BASE_BAUD defined here to keep 8250.c happy. */ 19/* Ugly, ugly, ugly! BASE_BAUD defined here to keep 8250.c happy. */
23#if !defined(BASE_BAUD) 20#if !defined(BASE_BAUD)
24 #define BASE_BAUD (0) /* dummy value; not used */ 21 #define BASE_BAUD (0) /* dummy value; not used */
25#endif 22#endif
26 23
27/* Device type enumeration for platform bus definitions */
28#ifndef __ASSEMBLY__ 24#ifndef __ASSEMBLY__
29enum ppc_sys_devices { 25extern const char* virtex_machine_name;
30 VIRTEX_UART, NUM_PPC_SYS_DEVS, 26#define PPC4xx_MACHINE_NAME (virtex_machine_name)
31}; 27#endif /* !__ASSEMBLY__ */
32#endif 28
33 29/* We don't need anything mapped. Size of zero will accomplish that. */
30#define PPC4xx_ONB_IO_PADDR 0u
31#define PPC4xx_ONB_IO_VADDR 0u
32#define PPC4xx_ONB_IO_SIZE 0u
33
34#endif /* __ASM_VIRTEX_H__ */ 34#endif /* __ASM_VIRTEX_H__ */
35#endif /* __KERNEL__ */ 35#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c
index fb5f0b5e13d1..6e522fefc26f 100644
--- a/arch/ppc/platforms/4xx/xilinx_ml300.c
+++ b/arch/ppc/platforms/4xx/xilinx_ml300.c
@@ -18,9 +18,9 @@
18#include <linux/serialP.h> 18#include <linux/serialP.h>
19#include <asm/io.h> 19#include <asm/io.h>
20#include <asm/machdep.h> 20#include <asm/machdep.h>
21#include <asm/ppc_sys.h>
22 21
23#include <syslib/gen550.h> 22#include <syslib/gen550.h>
23#include <syslib/virtex_devices.h>
24#include <platforms/4xx/xparameters/xparameters.h> 24#include <platforms/4xx/xparameters/xparameters.h>
25 25
26/* 26/*
@@ -53,24 +53,9 @@
53 * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c 53 * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c
54 */ 54 */
55 55
56/* Board specifications structures */ 56const char* virtex_machine_name = "ML300 Reference Design";
57struct ppc_sys_spec *cur_ppc_sys_spec;
58struct ppc_sys_spec ppc_sys_specs[] = {
59 {
60 /* Only one entry, always assume the same design */
61 .ppc_sys_name = "Xilinx ML300 Reference Design",
62 .mask = 0x00000000,
63 .value = 0x00000000,
64 .num_devices = 1,
65 .device_list = (enum ppc_sys_devices[])
66 {
67 VIRTEX_UART,
68 },
69 },
70};
71 57
72#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) 58#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
73
74static volatile unsigned *powerdown_base = 59static volatile unsigned *powerdown_base =
75 (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; 60 (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR;
76 61
@@ -95,52 +80,14 @@ ml300_map_io(void)
95#endif 80#endif
96} 81}
97 82
98/* Early serial support functions */
99static void __init
100ml300_early_serial_init(int num, struct plat_serial8250_port *pdata)
101{
102#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
103 struct uart_port serial_req;
104
105 memset(&serial_req, 0, sizeof(serial_req));
106 serial_req.mapbase = pdata->mapbase;
107 serial_req.membase = pdata->membase;
108 serial_req.irq = pdata->irq;
109 serial_req.uartclk = pdata->uartclk;
110 serial_req.regshift = pdata->regshift;
111 serial_req.iotype = pdata->iotype;
112 serial_req.flags = pdata->flags;
113 gen550_init(num, &serial_req);
114#endif
115}
116
117void __init
118ml300_early_serial_map(void)
119{
120#ifdef CONFIG_SERIAL_8250
121 struct plat_serial8250_port *pdata;
122 int i = 0;
123
124 pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART);
125 while(pdata && pdata->flags)
126 {
127 pdata->membase = ioremap(pdata->mapbase, 0x100);
128 ml300_early_serial_init(i, pdata);
129 pdata++;
130 i++;
131 }
132#endif /* CONFIG_SERIAL_8250 */
133}
134
135void __init 83void __init
136ml300_setup_arch(void) 84ml300_setup_arch(void)
137{ 85{
138 ml300_early_serial_map(); 86 virtex_early_serial_map();
139 ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ 87 ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */
140 88
141 /* Identify the system */ 89 /* Identify the system */
142 printk(KERN_INFO "Xilinx Virtex-II Pro port\n"); 90 printk(KERN_INFO "Xilinx ML300 Reference System (Virtex-II Pro)\n");
143 printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
144} 91}
145 92
146/* Called after board_setup_irq from ppc4xx_init_IRQ(). */ 93/* Called after board_setup_irq from ppc4xx_init_IRQ(). */
@@ -156,8 +103,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
156{ 103{
157 ppc4xx_init(r3, r4, r5, r6, r7); 104 ppc4xx_init(r3, r4, r5, r6, r7);
158 105
159 identify_ppc_sys_by_id(mfspr(SPRN_PVR));
160
161 ppc_md.setup_arch = ml300_setup_arch; 106 ppc_md.setup_arch = ml300_setup_arch;
162 ppc_md.setup_io_mappings = ml300_map_io; 107 ppc_md.setup_io_mappings = ml300_map_io;
163 ppc_md.init_IRQ = ml300_init_irq; 108 ppc_md.init_IRQ = ml300_init_irq;
@@ -167,7 +112,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
167#endif 112#endif
168 113
169#ifdef CONFIG_KGDB 114#ifdef CONFIG_KGDB
170 ppc_md.early_serial_map = ml300_early_serial_map; 115 ppc_md.early_serial_map = virtex_early_serial_map;
171#endif 116#endif
172} 117}
173 118
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h
deleted file mode 100644
index 3d57332ba820..000000000000
--- a/arch/ppc/platforms/4xx/xilinx_ml300.h
+++ /dev/null
@@ -1,45 +0,0 @@
1/*
2 * Include file that defines the Xilinx ML300 evaluation board
3 *
4 * Author: MontaVista Software, Inc.
5 * source@mvista.com
6 *
7 * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the
8 * terms of the GNU General Public License version 2. This program is licensed
9 * "as is" without any warranty of any kind, whether express or implied.
10 */
11
12#ifdef __KERNEL__
13#ifndef __ASM_XILINX_ML300_H__
14#define __ASM_XILINX_ML300_H__
15
16/* ML300 has a Xilinx Virtex-II Pro processor */
17#include <platforms/4xx/virtex.h>
18
19#ifndef __ASSEMBLY__
20
21#include <linux/types.h>
22
23typedef struct board_info {
24 unsigned int bi_memsize; /* DRAM installed, in bytes */
25 unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
26 unsigned int bi_intfreq; /* Processor speed, in Hz */
27 unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
28 unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
29} bd_t;
30
31/* Some 4xx parts use a different timebase frequency from the internal clock.
32*/
33#define bi_tbfreq bi_intfreq
34
35#endif /* !__ASSEMBLY__ */
36
37/* We don't need anything mapped. Size of zero will accomplish that. */
38#define PPC4xx_ONB_IO_PADDR 0u
39#define PPC4xx_ONB_IO_VADDR 0u
40#define PPC4xx_ONB_IO_SIZE 0u
41
42#define PPC4xx_MACHINE_NAME "Xilinx ML300 Reference System"
43
44#endif /* __ASM_XILINX_ML300_H__ */
45#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.c b/arch/ppc/platforms/4xx/xilinx_ml403.c
index cb3bf7a2bcbe..bc3ace3762e7 100644
--- a/arch/ppc/platforms/4xx/xilinx_ml403.c
+++ b/arch/ppc/platforms/4xx/xilinx_ml403.c
@@ -1,11 +1,9 @@
1/* 1/*
2 * arch/ppc/platforms/4xx/xilinx_ml403.c
3 *
4 * Xilinx ML403 evaluation board initialization 2 * Xilinx ML403 evaluation board initialization
5 * 3 *
6 * Author: Grant Likely <grant.likely@secretlab.ca> 4 * Author: Grant Likely <grant.likely@secretlab.ca>
7 * 5 *
8 * 2005 (c) Secret Lab Technologies Ltd. 6 * 2005-2007 (c) Secret Lab Technologies Ltd.
9 * 2002-2004 (c) MontaVista Software, Inc. 7 * 2002-2004 (c) MontaVista Software, Inc.
10 * 8 *
11 * This file is licensed under the terms of the GNU General Public License 9 * This file is licensed under the terms of the GNU General Public License
@@ -22,9 +20,9 @@
22#include <linux/serialP.h> 20#include <linux/serialP.h>
23#include <asm/io.h> 21#include <asm/io.h>
24#include <asm/machdep.h> 22#include <asm/machdep.h>
25#include <asm/ppc_sys.h>
26 23
27#include <syslib/gen550.h> 24#include <syslib/gen550.h>
25#include <syslib/virtex_devices.h>
28#include <platforms/4xx/xparameters/xparameters.h> 26#include <platforms/4xx/xparameters/xparameters.h>
29 27
30/* 28/*
@@ -57,24 +55,9 @@
57 * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c 55 * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c
58 */ 56 */
59 57
60/* Board specifications structures */ 58const char* virtex_machine_name = "ML403 Reference Design";
61struct ppc_sys_spec *cur_ppc_sys_spec;
62struct ppc_sys_spec ppc_sys_specs[] = {
63 {
64 /* Only one entry, always assume the same design */
65 .ppc_sys_name = "Xilinx ML403 Reference Design",
66 .mask = 0x00000000,
67 .value = 0x00000000,
68 .num_devices = 1,
69 .device_list = (enum ppc_sys_devices[])
70 {
71 VIRTEX_UART,
72 },
73 },
74};
75 59
76#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) 60#if defined(XPAR_POWER_0_POWERDOWN_BASEADDR)
77
78static volatile unsigned *powerdown_base = 61static volatile unsigned *powerdown_base =
79 (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; 62 (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR;
80 63
@@ -99,47 +82,10 @@ ml403_map_io(void)
99#endif 82#endif
100} 83}
101 84
102/* Early serial support functions */
103static void __init
104ml403_early_serial_init(int num, struct plat_serial8250_port *pdata)
105{
106#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
107 struct uart_port serial_req;
108
109 memset(&serial_req, 0, sizeof(serial_req));
110 serial_req.mapbase = pdata->mapbase;
111 serial_req.membase = pdata->membase;
112 serial_req.irq = pdata->irq;
113 serial_req.uartclk = pdata->uartclk;
114 serial_req.regshift = pdata->regshift;
115 serial_req.iotype = pdata->iotype;
116 serial_req.flags = pdata->flags;
117 gen550_init(num, &serial_req);
118#endif
119}
120
121void __init
122ml403_early_serial_map(void)
123{
124#ifdef CONFIG_SERIAL_8250
125 struct plat_serial8250_port *pdata;
126 int i = 0;
127
128 pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART);
129 while(pdata && pdata->flags)
130 {
131 pdata->membase = ioremap(pdata->mapbase, 0x100);
132 ml403_early_serial_init(i, pdata);
133 pdata++;
134 i++;
135 }
136#endif /* CONFIG_SERIAL_8250 */
137}
138
139void __init 85void __init
140ml403_setup_arch(void) 86ml403_setup_arch(void)
141{ 87{
142 ml403_early_serial_map(); 88 virtex_early_serial_map();
143 ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ 89 ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */
144 90
145 /* Identify the system */ 91 /* Identify the system */
@@ -159,8 +105,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
159{ 105{
160 ppc4xx_init(r3, r4, r5, r6, r7); 106 ppc4xx_init(r3, r4, r5, r6, r7);
161 107
162 identify_ppc_sys_by_id(mfspr(SPRN_PVR));
163
164 ppc_md.setup_arch = ml403_setup_arch; 108 ppc_md.setup_arch = ml403_setup_arch;
165 ppc_md.setup_io_mappings = ml403_map_io; 109 ppc_md.setup_io_mappings = ml403_map_io;
166 ppc_md.init_IRQ = ml403_init_irq; 110 ppc_md.init_IRQ = ml403_init_irq;
@@ -170,7 +114,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
170#endif 114#endif
171 115
172#ifdef CONFIG_KGDB 116#ifdef CONFIG_KGDB
173 ppc_md.early_serial_map = ml403_early_serial_map; 117 ppc_md.early_serial_map = virtex_early_serial_map;
174#endif 118#endif
175} 119}
176 120
diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.h b/arch/ppc/platforms/4xx/xilinx_ml403.h
deleted file mode 100644
index 473596959902..000000000000
--- a/arch/ppc/platforms/4xx/xilinx_ml403.h
+++ /dev/null
@@ -1,49 +0,0 @@
1/*
2 * arch/ppc/platforms/4xx/xilinx_ml403.h
3 *
4 * Include file that defines the Xilinx ML403 reference design
5 *
6 * Author: Grant Likely <grant.likely@secretlab.ca>
7 *
8 * 2005 (c) Secret Lab Technologies Ltd.
9 * 2002-2004 (c) MontaVista Software, Inc.
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#ifdef __KERNEL__
17#ifndef __ASM_XILINX_ML403_H__
18#define __ASM_XILINX_ML403_H__
19
20/* ML403 has a Xilinx Virtex-4 FPGA with a PPC405 hard core */
21#include <platforms/4xx/virtex.h>
22
23#ifndef __ASSEMBLY__
24
25#include <linux/types.h>
26
27typedef struct board_info {
28 unsigned int bi_memsize; /* DRAM installed, in bytes */
29 unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
30 unsigned int bi_intfreq; /* Processor speed, in Hz */
31 unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
32 unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
33} bd_t;
34
35/* Some 4xx parts use a different timebase frequency from the internal clock.
36*/
37#define bi_tbfreq bi_intfreq
38
39#endif /* !__ASSEMBLY__ */
40
41/* We don't need anything mapped. Size of zero will accomplish that. */
42#define PPC4xx_ONB_IO_PADDR 0u
43#define PPC4xx_ONB_IO_VADDR 0u
44#define PPC4xx_ONB_IO_SIZE 0u
45
46#define PPC4xx_MACHINE_NAME "Xilinx ML403 Reference Design"
47
48#endif /* __ASM_XILINX_ML403_H__ */
49#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters.h b/arch/ppc/platforms/4xx/xparameters/xparameters.h
index 66ec5f35f306..01aa043ff381 100644
--- a/arch/ppc/platforms/4xx/xparameters/xparameters.h
+++ b/arch/ppc/platforms/4xx/xparameters/xparameters.h
@@ -34,3 +34,63 @@
34 .io_type = SERIAL_IO_MEM, \ 34 .io_type = SERIAL_IO_MEM, \
35 }, 35 },
36#endif 36#endif
37
38/*
39 * A few reasonable defaults for the #defines which could be missing depending
40 * on the IP version or variant (e.g. OPB vs PLB)
41 */
42
43#ifndef XPAR_EMAC_0_CAM_EXIST
44#define XPAR_EMAC_0_CAM_EXIST 0
45#endif
46#ifndef XPAR_EMAC_0_JUMBO_EXIST
47#define XPAR_EMAC_0_JUMBO_EXIST 0
48#endif
49#ifndef XPAR_EMAC_0_TX_DRE_TYPE
50#define XPAR_EMAC_0_TX_DRE_TYPE 0
51#endif
52#ifndef XPAR_EMAC_0_RX_DRE_TYPE
53#define XPAR_EMAC_0_RX_DRE_TYPE 0
54#endif
55#ifndef XPAR_EMAC_0_TX_INCLUDE_CSUM
56#define XPAR_EMAC_0_TX_INCLUDE_CSUM 0
57#endif
58#ifndef XPAR_EMAC_0_RX_INCLUDE_CSUM
59#define XPAR_EMAC_0_RX_INCLUDE_CSUM 0
60#endif
61
62#ifndef XPAR_EMAC_1_CAM_EXIST
63#define XPAR_EMAC_1_CAM_EXIST 0
64#endif
65#ifndef XPAR_EMAC_1_JUMBO_EXIST
66#define XPAR_EMAC_1_JUMBO_EXIST 0
67#endif
68#ifndef XPAR_EMAC_1_TX_DRE_TYPE
69#define XPAR_EMAC_1_TX_DRE_TYPE 0
70#endif
71#ifndef XPAR_EMAC_1_RX_DRE_TYPE
72#define XPAR_EMAC_1_RX_DRE_TYPE 0
73#endif
74#ifndef XPAR_EMAC_1_TX_INCLUDE_CSUM
75#define XPAR_EMAC_1_TX_INCLUDE_CSUM 0
76#endif
77#ifndef XPAR_EMAC_1_RX_INCLUDE_CSUM
78#define XPAR_EMAC_1_RX_INCLUDE_CSUM 0
79#endif
80
81#ifndef XPAR_GPIO_0_IS_DUAL
82#define XPAR_GPIO_0_IS_DUAL 0
83#endif
84#ifndef XPAR_GPIO_1_IS_DUAL
85#define XPAR_GPIO_1_IS_DUAL 0
86#endif
87#ifndef XPAR_GPIO_2_IS_DUAL
88#define XPAR_GPIO_2_IS_DUAL 0
89#endif
90#ifndef XPAR_GPIO_3_IS_DUAL
91#define XPAR_GPIO_3_IS_DUAL 0
92#endif
93#ifndef XPAR_GPIO_4_IS_DUAL
94#define XPAR_GPIO_4_IS_DUAL 0
95#endif
96
diff --git a/arch/ppc/platforms/rpxclassic.h b/arch/ppc/platforms/rpxclassic.h
index 57a2a55dab8c..a3c1118e5b09 100644
--- a/arch/ppc/platforms/rpxclassic.h
+++ b/arch/ppc/platforms/rpxclassic.h
@@ -69,10 +69,6 @@ extern bd_t m8xx_board_info;
69#define BCSR2_QSPACESEL ((uint)0x00004000) 69#define BCSR2_QSPACESEL ((uint)0x00004000)
70#define BCSR2_FETHLEDMODE ((uint)0x00000800) /* CLLF */ 70#define BCSR2_FETHLEDMODE ((uint)0x00000800) /* CLLF */
71 71
72#if defined(CONFIG_HTDMSOUND)
73#include <platforms/rpxhiox.h>
74#endif
75
76/* define IO_BASE for pcmcia, CLLF only */ 72/* define IO_BASE for pcmcia, CLLF only */
77#if !defined(CONFIG_PCI) 73#if !defined(CONFIG_PCI)
78#define _IO_BASE 0x80000000 74#define _IO_BASE 0x80000000
diff --git a/arch/ppc/platforms/rpxhiox.h b/arch/ppc/platforms/rpxhiox.h
deleted file mode 100644
index c3fa5a653762..000000000000
--- a/arch/ppc/platforms/rpxhiox.h
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * The Embedded Planet HIOX expansion card definitions.
3 * There were a few different versions of these cards, but only
4 * the one that escaped real production is defined here.
5 *
6 * Copyright (c) 2000 Dan Malek (dmalek@jlc.net)
7 */
8#ifndef __MACH_RPX_HIOX_DEFS
9#define __MACH_RPX_HIOX_DEFS
10
11#define HIOX_CSR_ADDR ((uint)0xfac00000)
12#define HIOX_CSR_SIZE ((uint)(4 * 1024))
13#define HIOX_CSR0_ADDR HIOX_CSR_ADDR
14#define HIOX_CSR4_ADDR ((uint)0xfac00004)
15
16#define HIOX_CSR0_DEFAULT ((uint)0x380f3c00)
17#define HIOX_CSR0_ENSCC2 ((uint)0x80000000)
18#define HIOX_CSR0_ENSMC2 ((uint)0x04000000)
19#define HIOX_CSR0_ENVDOCLK ((uint)0x02000000)
20#define HIOX_CSR0_VDORST_HL ((uint)0x01000000)
21#define HIOX_CSR0_RS232SEL ((uint)0x0000c000)
22#define HIOX_CSR0_SCC3SEL ((uint)0x0000c000)
23#define HIOX_CSR0_SMC1SEL ((uint)0x00008000)
24#define HIOX_CSR0_SCC1SEL ((uint)0x00004000)
25#define HIOX_CSR0_ENTOUCH ((uint)0x00000080)
26#define HIOX_CSR0_PDOWN100 ((uint)0x00000060)
27#define HIOX_CSR0_PDOWN10 ((uint)0x00000040)
28#define HIOX_CSR0_PDOWN1 ((uint)0x00000020)
29#define HIOX_CSR0_TSELSPI ((uint)0x00000010)
30#define HIOX_CSR0_TIRQSTAT ((uint)0x00000008)
31#define HIOX_CSR4_DEFAULT ((uint)0x00000000)
32#define HIOX_CSR4_ENTIRQ2 ((uint)0x20000000)
33#define HIOX_CSR4_ENTIRQ3 ((uint)0x10000000)
34#define HIOX_CSR4_ENAUDIO ((uint)0x00000080)
35#define HIOX_CSR4_RSTAUDIO ((uint)0x00000040) /* 0 == reset */
36#define HIOX_CSR4_AUDCLKHI ((uint)0x00000020)
37#define HIOX_CSR4_AUDSPISEL ((uint)0x00000010)
38#define HIOX_CSR4_AUDIRQSTAT ((uint)0x00000008)
39#define HIOX_CSR4_AUDCLKSEL ((uint)0x00000007)
40
41#endif
diff --git a/arch/ppc/platforms/rpxlite.h b/arch/ppc/platforms/rpxlite.h
index 719780646270..b615501d55fc 100644
--- a/arch/ppc/platforms/rpxlite.h
+++ b/arch/ppc/platforms/rpxlite.h
@@ -57,10 +57,6 @@ extern bd_t m8xx_board_info;
57#define BCSR1_PCVCTL6 ((uint)0x00020000) 57#define BCSR1_PCVCTL6 ((uint)0x00020000)
58#define BCSR1_PCVCTL7 ((uint)0x00010000) 58#define BCSR1_PCVCTL7 ((uint)0x00010000)
59 59
60#if defined(CONFIG_HTDMSOUND)
61#include <platforms/rpxhiox.h>
62#endif
63
64/* define IO_BASE for pcmcia */ 60/* define IO_BASE for pcmcia */
65#define _IO_BASE 0x80000000 61#define _IO_BASE 0x80000000
66#define _IO_BASE_SIZE 0x1000 62#define _IO_BASE_SIZE 0x1000
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 09911118c675..95694159b226 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -18,7 +18,8 @@ obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o
18obj-$(CONFIG_440SPE) += ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o 18obj-$(CONFIG_440SPE) += ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o
19ifeq ($(CONFIG_4xx),y) 19ifeq ($(CONFIG_4xx),y)
20ifeq ($(CONFIG_XILINX_VIRTEX),y) 20ifeq ($(CONFIG_XILINX_VIRTEX),y)
21obj-$(CONFIG_40x) += xilinx_pic.o ppc_sys.o 21obj-$(CONFIG_40x) += xilinx_pic.o
22obj-y += virtex_devices.o
22else 23else
23ifeq ($(CONFIG_403),y) 24ifeq ($(CONFIG_403),y)
24obj-$(CONFIG_40x) += ppc403_pic.o 25obj-$(CONFIG_40x) += ppc403_pic.o
diff --git a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h
deleted file mode 100644
index 5299bf8b5d01..000000000000
--- a/arch/ppc/syslib/cpc710.h
+++ /dev/null
@@ -1,81 +0,0 @@
1/*
2 * Definitions for the IBM CPC710 PCI Host Bridge
3 *
4 * Author: Matt Porter <mporter@mvista.com>
5 *
6 * 2001 (c) MontaVista, Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#ifndef __PPC_PLATFORMS_CPC710_H
13#define __PPC_PLATFORMS_CPC710_H
14
15/* General bridge and memory controller registers */
16#define PIDR 0xff000008
17#define CNFR 0xff00000c
18#define RSTR 0xff000010
19#define UCTL 0xff001000
20#define MPSR 0xff001010
21#define SIOC 0xff001020
22#define ABCNTL 0xff001030
23#define SRST 0xff001040
24#define ERRC 0xff001050
25#define SESR 0xff001060
26#define SEAR 0xff001070
27#define SIOC1 0xff001090
28#define PGCHP 0xff001100
29#define GPDIR 0xff001130
30#define GPOUT 0xff001150
31#define ATAS 0xff001160
32#define AVDG 0xff001170
33#define MCCR 0xff001200
34#define MESR 0xff001220
35#define MEAR 0xff001230
36#define MCER0 0xff001300
37#define MCER1 0xff001310
38#define MCER2 0xff001320
39#define MCER3 0xff001330
40#define MCER4 0xff001340
41#define MCER5 0xff001350
42#define MCER6 0xff001360
43#define MCER7 0xff001370
44
45/*
46 * PCI32/64 configuration registers
47 * Given as offsets from their
48 * respective physical segment BAR
49 */
50#define PIBAR 0x000f7800
51#define PMBAR 0x000f7810
52#define MSIZE 0x000f7f40
53#define IOSIZE 0x000f7f60
54#define SMBAR 0x000f7f80
55#define SIBAR 0x000f7fc0
56#define PSSIZE 0x000f8100
57#define PPSIZE 0x000f8110
58#define BARPS 0x000f8120
59#define BARPP 0x000f8130
60#define PSBAR 0x000f8140
61#define PPBAR 0x000f8150
62#define BPMDLK 0x000f8200 /* Bottom of Peripheral Memory Space */
63#define TPMDLK 0x000f8210 /* Top of Peripheral Memory Space */
64#define BIODLK 0x000f8220 /* Bottom of Peripheral I/O Space */
65#define TIODLK 0x000f8230 /* Top of Perioheral I/O Space */
66#define DLKCTRL 0x000f8240 /* Deadlock control */
67#define DLKDEV 0x000f8250 /* Deadlock device */
68
69/* System standard configuration registers space */
70#define DCR 0xff200000
71#define DID 0xff200004
72#define BAR 0xff200018
73
74/* Device specific configuration space */
75#define PCIENB 0xff201000
76
77/* Configuration space registers */
78#define CPC710_BUS_NUMBER 0x40
79#define CPC710_SUB_BUS_NUMBER 0x41
80
81#endif /* __PPC_PLATFORMS_CPC710_H */
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index 01e48d88f22d..9caf850c9b38 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -413,7 +413,7 @@ m8xx_map_io(void)
413 io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO); 413 io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO);
414#endif 414#endif
415#endif 415#endif
416#if defined(CONFIG_HTDMSOUND) || defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX) 416#if defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX)
417 io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO); 417 io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO);
418#endif 418#endif
419#ifdef CONFIG_FADS 419#ifdef CONFIG_FADS
diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c
index 2f83e162971f..939abe3c1f45 100644
--- a/arch/ppc/syslib/ppc4xx_sgdma.c
+++ b/arch/ppc/syslib/ppc4xx_sgdma.c
@@ -27,6 +27,7 @@
27 27
28#include <asm/system.h> 28#include <asm/system.h>
29#include <asm/io.h> 29#include <asm/io.h>
30#include <asm/dma-mapping.h>
30#include <asm/ppc4xx_dma.h> 31#include <asm/ppc4xx_dma.h>
31 32
32void 33void
diff --git a/arch/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c
new file mode 100644
index 000000000000..16546788e23b
--- /dev/null
+++ b/arch/ppc/syslib/virtex_devices.c
@@ -0,0 +1,233 @@
1/*
2 * Virtex hard ppc405 core common device listing
3 *
4 * Copyright 2005-2007 Secret Lab Technologies Ltd.
5 * Copyright 2005 Freescale Semiconductor Inc.
6 * Copyright 2002-2004 MontaVista Software, 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 as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/serial_8250.h>
18#include <syslib/virtex_devices.h>
19#include <platforms/4xx/xparameters/xparameters.h>
20#include <asm/io.h>
21
22/*
23 * UARTLITE: shortcut macro for single instance
24 */
25#define XPAR_UARTLITE(num) { \
26 .name = "uartlite", \
27 .id = num, \
28 .num_resources = 2, \
29 .resource = (struct resource[]) { \
30 { \
31 .start = XPAR_UARTLITE_##num##_BASEADDR + 3, \
32 .end = XPAR_UARTLITE_##num##_HIGHADDR, \
33 .flags = IORESOURCE_MEM, \
34 }, \
35 { \
36 .start = XPAR_INTC_0_UARTLITE_##num##_VEC_ID, \
37 .flags = IORESOURCE_IRQ, \
38 }, \
39 }, \
40}
41
42/*
43 * Full UART: shortcut macro for single instance + platform data structure
44 */
45#define XPAR_UART(num) { \
46 .mapbase = XPAR_UARTNS550_##num##_BASEADDR + 3, \
47 .irq = XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \
48 .iotype = UPIO_MEM, \
49 .uartclk = XPAR_UARTNS550_##num##_CLOCK_FREQ_HZ, \
50 .flags = UPF_BOOT_AUTOCONF, \
51 .regshift = 2, \
52}
53
54/*
55 * SystemACE: shortcut macro for single instance
56 */
57#define XPAR_SYSACE(num) { \
58 .name = "xsysace", \
59 .id = XPAR_SYSACE_##num##_DEVICE_ID, \
60 .num_resources = 2, \
61 .resource = (struct resource[]) { \
62 { \
63 .start = XPAR_SYSACE_##num##_BASEADDR, \
64 .end = XPAR_SYSACE_##num##_HIGHADDR, \
65 .flags = IORESOURCE_MEM, \
66 }, \
67 { \
68 .start = XPAR_INTC_0_SYSACE_##num##_VEC_ID, \
69 .flags = IORESOURCE_IRQ, \
70 }, \
71 }, \
72}
73
74
75/* UART 8250 driver platform data table */
76struct plat_serial8250_port virtex_serial_platform_data[] = {
77#if defined(XPAR_UARTNS550_0_BASEADDR)
78 XPAR_UART(0),
79#endif
80#if defined(XPAR_UARTNS550_1_BASEADDR)
81 XPAR_UART(1),
82#endif
83#if defined(XPAR_UARTNS550_2_BASEADDR)
84 XPAR_UART(2),
85#endif
86#if defined(XPAR_UARTNS550_3_BASEADDR)
87 XPAR_UART(3),
88#endif
89#if defined(XPAR_UARTNS550_4_BASEADDR)
90 XPAR_UART(4),
91#endif
92#if defined(XPAR_UARTNS550_5_BASEADDR)
93 XPAR_UART(5),
94#endif
95#if defined(XPAR_UARTNS550_6_BASEADDR)
96 XPAR_UART(6),
97#endif
98#if defined(XPAR_UARTNS550_7_BASEADDR)
99 XPAR_UART(7),
100#endif
101 { }, /* terminated by empty record */
102};
103
104
105struct platform_device virtex_platform_devices[] = {
106 /* UARTLITE instances */
107#if defined(XPAR_UARTLITE_0_BASEADDR)
108 XPAR_UARTLITE(0),
109#endif
110#if defined(XPAR_UARTLITE_1_BASEADDR)
111 XPAR_UARTLITE(1),
112#endif
113#if defined(XPAR_UARTLITE_2_BASEADDR)
114 XPAR_UARTLITE(2),
115#endif
116#if defined(XPAR_UARTLITE_3_BASEADDR)
117 XPAR_UARTLITE(3),
118#endif
119#if defined(XPAR_UARTLITE_4_BASEADDR)
120 XPAR_UARTLITE(4),
121#endif
122#if defined(XPAR_UARTLITE_5_BASEADDR)
123 XPAR_UARTLITE(5),
124#endif
125#if defined(XPAR_UARTLITE_6_BASEADDR)
126 XPAR_UARTLITE(6),
127#endif
128#if defined(XPAR_UARTLITE_7_BASEADDR)
129 XPAR_UARTLITE(7),
130#endif
131
132 /* Full UART instances */
133#if defined(XPAR_UARTNS550_0_BASEADDR)
134 {
135 .name = "serial8250",
136 .id = 0,
137 .dev.platform_data = virtex_serial_platform_data,
138 },
139#endif
140
141 /* SystemACE instances */
142#if defined(XPAR_SYSACE_0_BASEADDR)
143 XPAR_SYSACE(0),
144#endif
145#if defined(XPAR_SYSACE_1_BASEADDR)
146 XPAR_SYSACE(1),
147#endif
148
149 /* ML300/403 reference design framebuffer */
150#if defined(XPAR_TFT_0_BASEADDR)
151 {
152 .name = "xilinxfb",
153 .id = 0,
154 .num_resources = 1,
155 .resource = (struct resource[]) {
156 {
157 .start = XPAR_TFT_0_BASEADDR,
158 .end = XPAR_TFT_0_BASEADDR+7,
159 .flags = IORESOURCE_IO,
160 },
161 },
162 },
163#endif
164};
165
166/* Early serial support functions */
167static void __init
168virtex_early_serial_init(int num, struct plat_serial8250_port *pdata)
169{
170#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
171 struct uart_port serial_req;
172
173 memset(&serial_req, 0, sizeof(serial_req));
174 serial_req.mapbase = pdata->mapbase;
175 serial_req.membase = pdata->membase;
176 serial_req.irq = pdata->irq;
177 serial_req.uartclk = pdata->uartclk;
178 serial_req.regshift = pdata->regshift;
179 serial_req.iotype = pdata->iotype;
180 serial_req.flags = pdata->flags;
181 gen550_init(num, &serial_req);
182#endif
183}
184
185void __init
186virtex_early_serial_map(void)
187{
188#ifdef CONFIG_SERIAL_8250
189 struct plat_serial8250_port *pdata;
190 int i = 0;
191
192 pdata = virtex_serial_platform_data;
193 while(pdata && pdata->flags) {
194 pdata->membase = ioremap(pdata->mapbase, 0x100);
195 virtex_early_serial_init(i, pdata);
196 pdata++;
197 i++;
198 }
199#endif /* CONFIG_SERIAL_8250 */
200}
201
202/*
203 * default fixup routine; do nothing and return success.
204 *
205 * Reimplement this routine in your custom board support file to
206 * override the default behaviour
207 */
208int __attribute__ ((weak))
209virtex_device_fixup(struct platform_device *dev)
210{
211 return 0;
212}
213
214static int __init virtex_init(void)
215{
216 struct platform_device *index = virtex_platform_devices;
217 unsigned int ret = 0;
218 int i;
219
220 for (i = 0; i < ARRAY_SIZE(virtex_platform_devices); i++, index++) {
221 if (virtex_device_fixup(index) != 0)
222 continue;
223
224 if (platform_device_register(index)) {
225 ret = 1;
226 printk(KERN_ERR "cannot register dev %s:%d\n",
227 index->name, index->id);
228 }
229 }
230 return ret;
231}
232
233subsys_initcall(virtex_init);
diff --git a/arch/ppc/syslib/virtex_devices.h b/arch/ppc/syslib/virtex_devices.h
new file mode 100644
index 000000000000..4a17dd3927c1
--- /dev/null
+++ b/arch/ppc/syslib/virtex_devices.h
@@ -0,0 +1,27 @@
1/*
2 * Common support header for virtex ppc405 platforms
3 *
4 * Copyright 2007 Secret Lab Technologies Ltd.
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 */
10
11#ifndef __ASM_VIRTEX_DEVICES_H__
12#define __ASM_VIRTEX_DEVICES_H__
13
14#include <linux/platform_device.h>
15
16void __init virtex_early_serial_map(void);
17
18/* Prototype for device fixup routine. Implement this routine in the
19 * board specific fixup code and the generic setup code will call it for
20 * each device is the platform device list.
21 *
22 * If the hook returns a non-zero value, then the device will not get
23 * registered with the platform bus
24 */
25int virtex_device_fixup(struct platform_device *dev);
26
27#endif /* __ASM_VIRTEX_DEVICES_H__ */