|
|
1.1 root 1: /* $Id: ad184x.c,v 1.1 2009/06/17 22:41:30 fredette Exp $ */
2:
3: /* ic/ad184x.c - Analog Devices 184x (and Crystal Semiconductors 4248
4: and 423x) implementation: */
5:
6: /*
7: * Copyright (c) 2009 Matt Fredette
8: * All rights reserved.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by Matt Fredette.
21: * 4. The name of the author may not be used to endorse or promote products
22: * derived from this software without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34: * POSSIBILITY OF SUCH DAMAGE.
35: */
36:
37: #include <tme/common.h>
38: _TME_RCSID("$Id: ad184x.c,v 1.1 2009/06/17 22:41:30 fredette Exp $");
39:
40: /* includes: */
41: #include <tme/completion.h>
42: #include <tme/generic/bus-device.h>
43:
44: /* macros: */
45:
46: /* the different parts: */
47: #define TME_AD184X_PART_AD1848 (0)
48: #define TME_AD184X_PART_CS4231 (10)
49: #define TME_AD184X_PART_CS4231A (11)
50:
51: /* direct registers: */
52: #define TME_AD184X_REG_IADDR (0)
53: #define TME_AD184X_REG_IDATA (1)
54: #define TME_AD184X_REG_STATUS (2)
55: #define TME_AD184X_REG_PIO (3)
56: #define TME_AD184X_SIZ (4)
57:
58: /* the IADDR register: */
59: #define TME_AD184X_IADDR_INIT (1 << 7)
60: #define TME_AD184X_IADDR_MCE (1 << 6)
61: #define TME_AD184X_IADDR_TRD (1 << 5)
62: #define TME_AD184X_IADDR_IXA (0x0f)
63: #define TME_CS423X_IADDR_IXA (0x1f)
64:
65: /* inputs: */
66: #define TME_AD184X_INPUT_MAIN (0)
67: #define TME_AD184X_INPUT_AUX1 (1)
68: #define TME_AD184X_INPUT_AUX2 (2)
69:
70: /* channels: */
71: #define TME_AD184X_CHANNEL_L (0)
72: #define TME_AD184X_CHANNEL_R (1)
73: #define TME_AD184X_CHANNEL_COUNT (2)
74:
75: /* the indirect registers: */
76: #define TME_AD184X_IREG_INPUT(input, channel) (((input) * 2) + (channel))
77: #define TME_AD184X_IREG_OUTPUT(channel) (6 + (channel))
78: #define TME_AD184X_IREG_CLOCK_DATA (8)
79: #define TME_AD184X_IREG_INTERFACE (9)
80: #define TME_AD184X_IREG_PINCONTROL (10)
81: #define TME_AD184X_IREG_TEST_INIT (11)
82: #define TME_AD184X_IREG_MISC (12)
83: #define TME_AD184X_IREG_DIGITALMIX (13)
84: #define TME_AD184X_IREG_BASECOUNT_UPPER (14)
85: #define TME_AD184X_IREG_BASECOUNT_LOWER (15)
86: #define TME_CS423X_IREG_VERSION_ID (25)
87: #define TME_CS423X_SIZ_IREG (32)
88:
89: /* the MISC register: */
90: #define TME_AD184X_MISC_CS423X_MODE2 (1 << 6)
91:
92: #define TME_AD184X_LOG_HANDLE(ad184x) (&(ad184x)->tme_ad184x_element->tme_element_log_handle)
93:
94: #define TME_AD184X_BUS_TRANSITION (1)
95:
96: /* structures: */
97:
98: /* the device: */
99: struct tme_ad184x {
100:
101: /* our simple bus device header: */
102: struct tme_bus_device tme_ad184x_device;
103: #define tme_ad184x_element tme_ad184x_device.tme_bus_device_element
104:
105: /* the mutex: */
106: tme_mutex_t tme_ad184x_mutex;
107:
108: /* the part: */
109: unsigned int tme_ad184x_part;
110: #define TME_AD184X_IS_AD184X(ad184x) ((ad184x)->tme_ad184x_part < TME_AD184X_PART_CS4231)
111: #define TME_AD184X_IS_CS423X(ad184x) ((ad184x)->tme_ad184x_part >= TME_AD184X_PART_CS4231)
112: #define TME_AD184X_IS_CS4231A(ad184x) ((ad184x)->tme_ad184x_part == TME_AD184X_PART_CS4231A)
113:
114: /* the IADDR register: */
115: tme_uint8_t tme_ad184x_iaddr;
116:
117: /* the STATUS register: */
118: tme_uint8_t tme_ad184x_status;
119:
120: /* the indirect registers: */
121: tme_uint8_t tme_ad184x_ireg[TME_CS423X_SIZ_IREG];
122: };
123:
124: /* this resets: */
125: static void
126: _tme_ad184x_reset(struct tme_ad184x *ad184x)
127: {
128: }
129:
130: /* this enters: */
131: static struct tme_ad184x *
132: _tme_ad184x_enter(struct tme_ad184x *ad184x)
133: {
134:
135: /* lock the mutex: */
136: tme_mutex_lock(&ad184x->tme_ad184x_mutex);
137:
138: return (ad184x);
139: }
140: #define _tme_ad184x_enter_bus(conn_bus) \
141: ((struct tme_ad184x *) _tme_ad184x_enter((struct tme_ad184x *) (conn_bus)->tme_bus_connection.tme_connection_element->tme_element_private))
142:
143: /* this leaves: */
144: #define _tme_ad184x_leave(ad184x) tme_mutex_unlock(&(ad184x)->tme_ad184x_mutex)
145:
146: /* this busies a generic bus connection: */
147: #define _tme_ad184x_busy_bus(ad184x, conn_index) \
148: ((ad184x)->tme_ad184x_conns[conn_index])
149:
150: /* this unbusies a generic bus connection: */
151: #define _tme_ad184x_unbusy_bus(ad184x, conn_bus) \
152: do { } while (/* CONSTCOND */ 0 && (ad184x)->tme_ad184x_element && (conn_bus)->tme_bus_connection.tme_connection_element)
153:
154: /* this returns the current indirect register: */
155: static unsigned int
156: _tme_ad184x_ireg(const struct tme_ad184x *ad184x)
157: {
158: return (ad184x->tme_ad184x_iaddr
159: & ((TME_AD184X_IS_CS423X(ad184x)
160: && (ad184x->tme_ad184x_ireg[TME_AD184X_IREG_MISC]
161: & TME_AD184X_MISC_CS423X_MODE2))
162: ? TME_CS423X_IADDR_IXA
163: : TME_AD184X_IADDR_IXA));
164: }
165:
166: /* the bus cycle handler: */
167: static void
168: _tme_ad184x_cycle(struct tme_bus_connection *master_conn_bus,
169: struct tme_bus_cycle *master_cycle,
170: tme_uint32_t *_master_fast_cycle_types,
171: struct tme_completion *master_completion)
172: {
173: struct tme_ad184x *ad184x;
174: tme_uint32_t address;
175: tme_uint8_t value;
176: const char *reg;
177: tme_uint32_t ireg;
178:
179: /* enter: */
180: ad184x = _tme_ad184x_enter_bus(master_conn_bus);
181:
182: /* this must be an eight-bit cycle: */
183: if (master_cycle->tme_bus_cycle_size != sizeof(tme_uint8_t)) {
184: abort();
185: }
186:
187: /* get the address: */
188: address = master_cycle->tme_bus_cycle_address;
189:
190: /* if this is a write: */
191: if (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
192:
193: /* run the bus cycle: */
194: tme_bus_cycle_xfer_reg(master_cycle,
195: &value,
196: TME_BUS8_LOG2);
197:
198: /* dispatch on the register: */
199: switch (address) {
200: default: assert(FALSE);
201:
202: case TME_AD184X_REG_IADDR:
203: ad184x->tme_ad184x_iaddr
204: = ((ad184x->tme_ad184x_iaddr
205: & TME_AD184X_IADDR_INIT)
206: | (value
207: & ~TME_AD184X_IADDR_INIT));
208: reg = "IADDR";
209: break;
210:
211: case TME_AD184X_REG_IDATA:
212: ireg = _tme_ad184x_ireg(ad184x);
213: reg = "(IDATA)";
214:
215: /* if this is an input or output control: */
216: if (ireg <= TME_AD184X_IREG_OUTPUT(TME_AD184X_CHANNEL_COUNT - 1)) {
217:
218: /* write the new control: */
219: ad184x->tme_ad184x_ireg[ireg] = value;
220: }
221:
222: /* otherwise, this is another register: */
223: else {
224: switch (ireg) {
225:
226: default:
227: /* temporarily, just write any unknown registers: */
228: ad184x->tme_ad184x_ireg[ireg] = value;
229: break;
230: }
231: }
232: break;
233:
234: case TME_AD184X_REG_STATUS:
235: reg = "STATUS";
236: break;
237:
238: case TME_AD184X_REG_PIO:
239: reg = "PIO";
240: break;
241: }
242:
243: tme_log(TME_AD184X_LOG_HANDLE(ad184x), 1000, TME_OK,
244: (TME_AD184X_LOG_HANDLE(ad184x),
245: _("%s <- 0x%02x"),
246: reg,
247: value));
248: }
249:
250: /* otherwise, this must be a read: */
251: else {
252: assert (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
253:
254: /* dispatch on the register: */
255: switch (address) {
256: default: assert(FALSE);
257:
258: case TME_AD184X_REG_IADDR:
259: value = ad184x->tme_ad184x_iaddr;
260: reg = "IADDR";
261: break;
262:
263: case TME_AD184X_REG_IDATA:
264: ireg = _tme_ad184x_ireg(ad184x);
265: reg = "(IDATA)";
266:
267: /* assume that this is a simple read: */
268: value = ad184x->tme_ad184x_ireg[ireg];
269:
270: switch (ireg) {
271: default:
272: break;
273: case TME_CS423X_IREG_VERSION_ID:
274: value = 0xa0;
275: reg = "VERSION_ID";
276: break;
277: }
278: break;
279:
280: case TME_AD184X_REG_STATUS:
281: value = ad184x->tme_ad184x_status;
282: reg = "STATUS";
283: break;
284:
285: case TME_AD184X_REG_PIO:
286: abort();
287: reg = "PIO";
288: break;
289: }
290:
291: /* run the bus cycle: */
292: tme_bus_cycle_xfer_reg(master_cycle,
293: &value,
294: TME_BUS8_LOG2);
295:
296: tme_log(TME_AD184X_LOG_HANDLE(ad184x), 1000, TME_OK,
297: (TME_AD184X_LOG_HANDLE(ad184x),
298: _("%s -> 0x%02x"),
299: reg,
300: value));
301: }
302:
303: /* complete the cycle: */
304: master_completion->tme_completion_error = TME_OK;
305: tme_memory_barrier(master_completion, sizeof(*master_completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE);
306: tme_completion_validate(master_completion);
307: *_master_fast_cycle_types = 0;
308:
309: /* leave: */
310: _tme_ad184x_leave(ad184x);
311: }
312:
313: /* this fills a TLB entry: */
314: static void
315: _tme_ad184x_tlb_fill(struct tme_bus_connection *agent_conn_bus,
316: struct tme_bus_tlb *tlb,
317: tme_bus_addr_t address_wider,
318: unsigned int cycle_type)
319: {
320:
321: /* initialize the TLB entry: */
322: tme_bus_tlb_initialize(tlb);
323:
324: /* this TLB entry covers only this address: */
325: tlb->tme_bus_tlb_addr_first = address_wider;
326: tlb->tme_bus_tlb_addr_last = address_wider;
327: }
328:
329: #if TME_AD184X_BUS_TRANSITION
330:
331: /* this is the bus cycle transition glue: */
332: static int
333: _tme_ad184x_cycle_transition(void *_master_conn_bus,
334: struct tme_bus_cycle *master_cycle)
335: {
336: struct tme_completion completion_buffer;
337: struct tme_ad184x *ad184x;
338: struct tme_bus_connection *master_conn_bus;
339: tme_uint32_t master_fast_cycle_types;
340:
341: tme_completion_init(&completion_buffer);
342:
343: master_conn_bus = (struct tme_bus_connection *) _master_conn_bus;
344: ad184x = (struct tme_ad184x *) master_conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
345: _tme_ad184x_cycle(master_conn_bus,
346: master_cycle,
347: &master_fast_cycle_types,
348: &completion_buffer);
349: return (completion_buffer.tme_completion_error);
350: }
351:
352: /* this is the TLB fill transition glue: */
353: static int
354: _tme_ad184x_tlb_fill_transition(void *_ad184x,
355: struct tme_bus_tlb *tlb,
356: tme_bus_addr_t address_wider,
357: unsigned int cycle_type)
358: {
359: struct tme_ad184x *ad184x;
360: struct tme_bus_connection *agent_conn_bus;
361:
362: ad184x = (struct tme_ad184x *) _ad184x;
363: agent_conn_bus = (struct tme_bus_connection *) ad184x->tme_ad184x_device.tme_bus_device_connection->tme_bus_connection.tme_connection_other;
364:
365: _tme_ad184x_tlb_fill(agent_conn_bus,
366: tlb,
367: address_wider,
368: cycle_type);
369:
370: /* we always handle any slow cycles: */
371: tlb->tme_bus_tlb_cycles_ok |= cycle_type;
372: tlb->tme_bus_tlb_addr_offset = 0;
373: tlb->tme_bus_tlb_addr_shift = 0;
374: tlb->tme_bus_tlb_cycle = _tme_ad184x_cycle_transition;
375: tlb->tme_bus_tlb_cycle_private = agent_conn_bus;
376: assert (tlb->tme_bus_tlb_fault_handler_count == 0);
377:
378: return (TME_OK);
379: }
380: #define _tme_ad184x_tlb_fill _tme_ad184x_tlb_fill_transition
381:
382: #endif /* TME_AD184X_BUS_TRANSITION */
383:
384: /* the new ad184x function: */
385: static int
386: _tme_ad184x_new(struct tme_element *element,
387: const char * const *args,
388: const void *extra,
389: char **_output,
390: unsigned int part)
391: {
392: struct tme_ad184x *ad184x;
393: int arg_i;
394: int usage;
395: const char *type;
396:
397: /* check our arguments: */
398: usage = 0;
399: arg_i = 1;
400: type = NULL;
401: for (;;) {
402:
403: if (0) {
404: }
405:
406: /* if we ran out of arguments: */
407: else if (args[arg_i] == NULL) {
408:
409: break;
410: }
411:
412: /* otherwise this is a bad argument: */
413: else {
414: tme_output_append_error(_output,
415: "%s %s, ",
416: args[arg_i],
417: _("unexpected"));
418: usage = TRUE;
419: break;
420: }
421: }
422:
423: if (usage) {
424: tme_output_append_error(_output,
425: "%s %s",
426: _("usage:"),
427: args[0]);
428: return (EINVAL);
429: }
430:
431: /* start the ad184x structure: */
432: ad184x = tme_new0(struct tme_ad184x, 1);
433: tme_mutex_init(&ad184x->tme_ad184x_mutex);
434: ad184x->tme_ad184x_part = part;
435: ad184x->tme_ad184x_element = element;
436: _tme_ad184x_reset(ad184x);
437:
438: /* initialize our simple bus device descriptor: */
439: ad184x->tme_ad184x_device.tme_bus_device_tlb_fill = _tme_ad184x_tlb_fill;
440: ad184x->tme_ad184x_device.tme_bus_device_address_last = TME_AD184X_SIZ - 1;
441:
442: /* fill the element: */
443: element->tme_element_private = ad184x;
444: element->tme_element_connections_new = tme_bus_device_connections_new;
445:
446: return (TME_OK);
447: }
448:
449: TME_ELEMENT_X_NEW_DECL(tme_ic_,ad184x,cs4231A) {
450: return (_tme_ad184x_new(element, args, extra, _output, TME_AD184X_PART_CS4231A));
451: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.