2 * i2sbus driver -- bus control routines
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
6 * GPL v2, can be found in COPYING.
10 #include <linux/delay.h>
12 #include <asm/macio.h>
13 #include <asm/pmac_feature.h>
14 #include <asm/pmac_pfunc.h>
17 int i2sbus_control_init(struct macio_dev
* dev
, struct i2sbus_control
**c
)
19 *c
= kzalloc(sizeof(struct i2sbus_control
), GFP_KERNEL
);
23 INIT_LIST_HEAD(&(*c
)->list
);
25 if (of_address_to_resource(dev
->ofdev
.node
, 0, &(*c
)->rsrc
))
27 /* we really should be using feature calls instead of mapping
28 * these registers. It's safe for now since no one else is
30 (*c
)->controlregs
= ioremap((*c
)->rsrc
.start
,
31 sizeof(struct i2s_control_regs
));
32 if (!(*c
)->controlregs
)
42 void i2sbus_control_destroy(struct i2sbus_control
*c
)
44 iounmap(c
->controlregs
);
48 /* this is serialised externally */
49 int i2sbus_control_add_dev(struct i2sbus_control
*c
,
50 struct i2sbus_dev
*i2sdev
)
52 struct device_node
*np
;
54 np
= i2sdev
->sound
.ofdev
.node
;
55 i2sdev
->enable
= pmf_find_function(np
, "enable");
56 i2sdev
->cell_enable
= pmf_find_function(np
, "cell-enable");
57 i2sdev
->clock_enable
= pmf_find_function(np
, "clock-enable");
58 i2sdev
->cell_disable
= pmf_find_function(np
, "cell-disable");
59 i2sdev
->clock_disable
= pmf_find_function(np
, "clock-disable");
61 /* if the bus number is not 0 or 1 we absolutely need to use
62 * the platform functions -- there's nothing in Darwin that
63 * would allow seeing a system behind what the FCRs are then,
64 * and I don't want to go parsing a bunch of platform functions
65 * by hand to try finding a system... */
66 if (i2sdev
->bus_number
!= 0 && i2sdev
->bus_number
!= 1 &&
68 !i2sdev
->cell_enable
|| !i2sdev
->clock_enable
||
69 !i2sdev
->cell_disable
|| !i2sdev
->clock_disable
)) {
70 pmf_put_function(i2sdev
->enable
);
71 pmf_put_function(i2sdev
->cell_enable
);
72 pmf_put_function(i2sdev
->clock_enable
);
73 pmf_put_function(i2sdev
->cell_disable
);
74 pmf_put_function(i2sdev
->clock_disable
);
78 list_add(&i2sdev
->item
, &c
->list
);
83 void i2sbus_control_remove_dev(struct i2sbus_control
*c
,
84 struct i2sbus_dev
*i2sdev
)
86 /* this is serialised externally */
87 list_del(&i2sdev
->item
);
88 if (list_empty(&c
->list
))
89 i2sbus_control_destroy(c
);
92 int i2sbus_control_enable(struct i2sbus_control
*c
,
93 struct i2sbus_dev
*i2sdev
)
95 struct pmf_args args
= { .count
= 0 };
99 return pmf_call_one(i2sdev
->enable
, &args
);
101 switch (i2sdev
->bus_number
) {
103 cc
= in_le32(&c
->controlregs
->cell_control
);
104 out_le32(&c
->controlregs
->cell_control
, cc
| CTRL_CLOCK_INTF_0_ENABLE
);
107 cc
= in_le32(&c
->controlregs
->cell_control
);
108 out_le32(&c
->controlregs
->cell_control
, cc
| CTRL_CLOCK_INTF_1_ENABLE
);
116 int i2sbus_control_cell(struct i2sbus_control
*c
,
117 struct i2sbus_dev
*i2sdev
,
120 struct pmf_args args
= { .count
= 0 };
125 if (i2sdev
->cell_disable
)
126 return pmf_call_one(i2sdev
->cell_disable
, &args
);
129 if (i2sdev
->cell_enable
)
130 return pmf_call_one(i2sdev
->cell_enable
, &args
);
133 printk(KERN_ERR
"i2sbus: INVALID CELL ENABLE VALUE\n");
136 switch (i2sdev
->bus_number
) {
138 cc
= in_le32(&c
->controlregs
->cell_control
);
139 cc
&= ~CTRL_CLOCK_CELL_0_ENABLE
;
140 cc
|= enable
* CTRL_CLOCK_CELL_0_ENABLE
;
141 out_le32(&c
->controlregs
->cell_control
, cc
);
144 cc
= in_le32(&c
->controlregs
->cell_control
);
145 cc
&= ~CTRL_CLOCK_CELL_1_ENABLE
;
146 cc
|= enable
* CTRL_CLOCK_CELL_1_ENABLE
;
147 out_le32(&c
->controlregs
->cell_control
, cc
);
155 int i2sbus_control_clock(struct i2sbus_control
*c
,
156 struct i2sbus_dev
*i2sdev
,
159 struct pmf_args args
= { .count
= 0 };
164 if (i2sdev
->clock_disable
)
165 return pmf_call_one(i2sdev
->clock_disable
, &args
);
168 if (i2sdev
->clock_enable
)
169 return pmf_call_one(i2sdev
->clock_enable
, &args
);
172 printk(KERN_ERR
"i2sbus: INVALID CLOCK ENABLE VALUE\n");
175 switch (i2sdev
->bus_number
) {
177 cc
= in_le32(&c
->controlregs
->cell_control
);
178 cc
&= ~CTRL_CLOCK_CLOCK_0_ENABLE
;
179 cc
|= enable
* CTRL_CLOCK_CLOCK_0_ENABLE
;
180 out_le32(&c
->controlregs
->cell_control
, cc
);
183 cc
= in_le32(&c
->controlregs
->cell_control
);
184 cc
&= ~CTRL_CLOCK_CLOCK_1_ENABLE
;
185 cc
|= enable
* CTRL_CLOCK_CLOCK_1_ENABLE
;
186 out_le32(&c
->controlregs
->cell_control
, cc
);