1*d6869352SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2888dcb7cSJohannes Berg /*
3888dcb7cSJohannes Berg * i2sbus driver -- bus control routines
4888dcb7cSJohannes Berg *
5888dcb7cSJohannes Berg * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
6888dcb7cSJohannes Berg */
7888dcb7cSJohannes Berg
8888dcb7cSJohannes Berg #include <linux/kernel.h>
9888dcb7cSJohannes Berg #include <linux/delay.h>
105a0e3ad6STejun Heo #include <linux/slab.h>
116cbbfe1cSTakashi Iwai #include <linux/io.h>
12888dcb7cSJohannes Berg
13888dcb7cSJohannes Berg #include <asm/prom.h>
14888dcb7cSJohannes Berg #include <asm/macio.h>
15888dcb7cSJohannes Berg #include <asm/pmac_feature.h>
16888dcb7cSJohannes Berg #include <asm/pmac_pfunc.h>
17888dcb7cSJohannes Berg #include <asm/keylargo.h>
18888dcb7cSJohannes Berg
19888dcb7cSJohannes Berg #include "i2sbus.h"
20888dcb7cSJohannes Berg
i2sbus_control_init(struct macio_dev * dev,struct i2sbus_control ** c)21888dcb7cSJohannes Berg int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
22888dcb7cSJohannes Berg {
23888dcb7cSJohannes Berg *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);
24888dcb7cSJohannes Berg if (!*c)
25888dcb7cSJohannes Berg return -ENOMEM;
26888dcb7cSJohannes Berg
27888dcb7cSJohannes Berg INIT_LIST_HEAD(&(*c)->list);
28888dcb7cSJohannes Berg
29888dcb7cSJohannes Berg (*c)->macio = dev->bus->chip;
30888dcb7cSJohannes Berg return 0;
31888dcb7cSJohannes Berg }
32888dcb7cSJohannes Berg
i2sbus_control_destroy(struct i2sbus_control * c)33888dcb7cSJohannes Berg void i2sbus_control_destroy(struct i2sbus_control *c)
34888dcb7cSJohannes Berg {
35888dcb7cSJohannes Berg kfree(c);
36888dcb7cSJohannes Berg }
37888dcb7cSJohannes Berg
38888dcb7cSJohannes Berg /* this is serialised externally */
i2sbus_control_add_dev(struct i2sbus_control * c,struct i2sbus_dev * i2sdev)39888dcb7cSJohannes Berg int i2sbus_control_add_dev(struct i2sbus_control *c,
40888dcb7cSJohannes Berg struct i2sbus_dev *i2sdev)
41888dcb7cSJohannes Berg {
42888dcb7cSJohannes Berg struct device_node *np;
43888dcb7cSJohannes Berg
4461c7a080SGrant Likely np = i2sdev->sound.ofdev.dev.of_node;
45888dcb7cSJohannes Berg i2sdev->enable = pmf_find_function(np, "enable");
46888dcb7cSJohannes Berg i2sdev->cell_enable = pmf_find_function(np, "cell-enable");
47888dcb7cSJohannes Berg i2sdev->clock_enable = pmf_find_function(np, "clock-enable");
48888dcb7cSJohannes Berg i2sdev->cell_disable = pmf_find_function(np, "cell-disable");
49888dcb7cSJohannes Berg i2sdev->clock_disable = pmf_find_function(np, "clock-disable");
50888dcb7cSJohannes Berg
51888dcb7cSJohannes Berg /* if the bus number is not 0 or 1 we absolutely need to use
52888dcb7cSJohannes Berg * the platform functions -- there's nothing in Darwin that
53888dcb7cSJohannes Berg * would allow seeing a system behind what the FCRs are then,
54888dcb7cSJohannes Berg * and I don't want to go parsing a bunch of platform functions
55888dcb7cSJohannes Berg * by hand to try finding a system... */
56888dcb7cSJohannes Berg if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 &&
57888dcb7cSJohannes Berg (!i2sdev->enable ||
58888dcb7cSJohannes Berg !i2sdev->cell_enable || !i2sdev->clock_enable ||
59888dcb7cSJohannes Berg !i2sdev->cell_disable || !i2sdev->clock_disable)) {
60888dcb7cSJohannes Berg pmf_put_function(i2sdev->enable);
61888dcb7cSJohannes Berg pmf_put_function(i2sdev->cell_enable);
62888dcb7cSJohannes Berg pmf_put_function(i2sdev->clock_enable);
63888dcb7cSJohannes Berg pmf_put_function(i2sdev->cell_disable);
64888dcb7cSJohannes Berg pmf_put_function(i2sdev->clock_disable);
65888dcb7cSJohannes Berg return -ENODEV;
66888dcb7cSJohannes Berg }
67888dcb7cSJohannes Berg
68888dcb7cSJohannes Berg list_add(&i2sdev->item, &c->list);
69888dcb7cSJohannes Berg
70888dcb7cSJohannes Berg return 0;
71888dcb7cSJohannes Berg }
72888dcb7cSJohannes Berg
i2sbus_control_remove_dev(struct i2sbus_control * c,struct i2sbus_dev * i2sdev)73888dcb7cSJohannes Berg void i2sbus_control_remove_dev(struct i2sbus_control *c,
74888dcb7cSJohannes Berg struct i2sbus_dev *i2sdev)
75888dcb7cSJohannes Berg {
76888dcb7cSJohannes Berg /* this is serialised externally */
77888dcb7cSJohannes Berg list_del(&i2sdev->item);
78888dcb7cSJohannes Berg if (list_empty(&c->list))
79888dcb7cSJohannes Berg i2sbus_control_destroy(c);
80888dcb7cSJohannes Berg }
81888dcb7cSJohannes Berg
i2sbus_control_enable(struct i2sbus_control * c,struct i2sbus_dev * i2sdev)82888dcb7cSJohannes Berg int i2sbus_control_enable(struct i2sbus_control *c,
83888dcb7cSJohannes Berg struct i2sbus_dev *i2sdev)
84888dcb7cSJohannes Berg {
85888dcb7cSJohannes Berg struct pmf_args args = { .count = 0 };
86888dcb7cSJohannes Berg struct macio_chip *macio = c->macio;
87888dcb7cSJohannes Berg
88888dcb7cSJohannes Berg if (i2sdev->enable)
89888dcb7cSJohannes Berg return pmf_call_one(i2sdev->enable, &args);
90888dcb7cSJohannes Berg
91888dcb7cSJohannes Berg if (macio == NULL || macio->base == NULL)
92888dcb7cSJohannes Berg return -ENODEV;
93888dcb7cSJohannes Berg
94888dcb7cSJohannes Berg switch (i2sdev->bus_number) {
95888dcb7cSJohannes Berg case 0:
96888dcb7cSJohannes Berg /* these need to be locked or done through
97888dcb7cSJohannes Berg * newly created feature calls! */
98888dcb7cSJohannes Berg MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);
99888dcb7cSJohannes Berg break;
100888dcb7cSJohannes Berg case 1:
101888dcb7cSJohannes Berg MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE);
102888dcb7cSJohannes Berg break;
103888dcb7cSJohannes Berg default:
104888dcb7cSJohannes Berg return -ENODEV;
105888dcb7cSJohannes Berg }
106888dcb7cSJohannes Berg return 0;
107888dcb7cSJohannes Berg }
108888dcb7cSJohannes Berg
i2sbus_control_cell(struct i2sbus_control * c,struct i2sbus_dev * i2sdev,int enable)109888dcb7cSJohannes Berg int i2sbus_control_cell(struct i2sbus_control *c,
110888dcb7cSJohannes Berg struct i2sbus_dev *i2sdev,
111888dcb7cSJohannes Berg int enable)
112888dcb7cSJohannes Berg {
113888dcb7cSJohannes Berg struct pmf_args args = { .count = 0 };
114888dcb7cSJohannes Berg struct macio_chip *macio = c->macio;
115888dcb7cSJohannes Berg
116888dcb7cSJohannes Berg switch (enable) {
117888dcb7cSJohannes Berg case 0:
118888dcb7cSJohannes Berg if (i2sdev->cell_disable)
119888dcb7cSJohannes Berg return pmf_call_one(i2sdev->cell_disable, &args);
120888dcb7cSJohannes Berg break;
121888dcb7cSJohannes Berg case 1:
122888dcb7cSJohannes Berg if (i2sdev->cell_enable)
123888dcb7cSJohannes Berg return pmf_call_one(i2sdev->cell_enable, &args);
124888dcb7cSJohannes Berg break;
125888dcb7cSJohannes Berg default:
126888dcb7cSJohannes Berg printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");
127888dcb7cSJohannes Berg return -ENODEV;
128888dcb7cSJohannes Berg }
129888dcb7cSJohannes Berg
130888dcb7cSJohannes Berg if (macio == NULL || macio->base == NULL)
131888dcb7cSJohannes Berg return -ENODEV;
132888dcb7cSJohannes Berg
133888dcb7cSJohannes Berg switch (i2sdev->bus_number) {
134888dcb7cSJohannes Berg case 0:
135888dcb7cSJohannes Berg if (enable)
136888dcb7cSJohannes Berg MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
137888dcb7cSJohannes Berg else
138888dcb7cSJohannes Berg MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
139888dcb7cSJohannes Berg break;
140888dcb7cSJohannes Berg case 1:
141888dcb7cSJohannes Berg if (enable)
142888dcb7cSJohannes Berg MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
143888dcb7cSJohannes Berg else
144888dcb7cSJohannes Berg MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
145888dcb7cSJohannes Berg break;
146888dcb7cSJohannes Berg default:
147888dcb7cSJohannes Berg return -ENODEV;
148888dcb7cSJohannes Berg }
149888dcb7cSJohannes Berg return 0;
150888dcb7cSJohannes Berg }
151888dcb7cSJohannes Berg
i2sbus_control_clock(struct i2sbus_control * c,struct i2sbus_dev * i2sdev,int enable)152888dcb7cSJohannes Berg int i2sbus_control_clock(struct i2sbus_control *c,
153888dcb7cSJohannes Berg struct i2sbus_dev *i2sdev,
154888dcb7cSJohannes Berg int enable)
155888dcb7cSJohannes Berg {
156888dcb7cSJohannes Berg struct pmf_args args = { .count = 0 };
157888dcb7cSJohannes Berg struct macio_chip *macio = c->macio;
158888dcb7cSJohannes Berg
159888dcb7cSJohannes Berg switch (enable) {
160888dcb7cSJohannes Berg case 0:
161888dcb7cSJohannes Berg if (i2sdev->clock_disable)
162888dcb7cSJohannes Berg return pmf_call_one(i2sdev->clock_disable, &args);
163888dcb7cSJohannes Berg break;
164888dcb7cSJohannes Berg case 1:
165888dcb7cSJohannes Berg if (i2sdev->clock_enable)
166888dcb7cSJohannes Berg return pmf_call_one(i2sdev->clock_enable, &args);
167888dcb7cSJohannes Berg break;
168888dcb7cSJohannes Berg default:
169888dcb7cSJohannes Berg printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");
170888dcb7cSJohannes Berg return -ENODEV;
171888dcb7cSJohannes Berg }
172888dcb7cSJohannes Berg
173888dcb7cSJohannes Berg if (macio == NULL || macio->base == NULL)
174888dcb7cSJohannes Berg return -ENODEV;
175888dcb7cSJohannes Berg
176888dcb7cSJohannes Berg switch (i2sdev->bus_number) {
177888dcb7cSJohannes Berg case 0:
178888dcb7cSJohannes Berg if (enable)
179888dcb7cSJohannes Berg MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
180888dcb7cSJohannes Berg else
181888dcb7cSJohannes Berg MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
182888dcb7cSJohannes Berg break;
183888dcb7cSJohannes Berg case 1:
184888dcb7cSJohannes Berg if (enable)
185888dcb7cSJohannes Berg MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
186888dcb7cSJohannes Berg else
187888dcb7cSJohannes Berg MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
188888dcb7cSJohannes Berg break;
189888dcb7cSJohannes Berg default:
190888dcb7cSJohannes Berg return -ENODEV;
191888dcb7cSJohannes Berg }
192888dcb7cSJohannes Berg return 0;
193888dcb7cSJohannes Berg }
194