xref: /openbmc/linux/sound/aoa/soundbus/i2sbus/control.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
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