brintos

brintos / linux-shallow public Read only

0
0
Text · 4.5 KiB · a003ef0 Raw
193 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * i2sbus driver -- bus control routines4 *5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>6 */7 8#include <linux/kernel.h>9#include <linux/delay.h>10#include <linux/slab.h>11#include <linux/io.h>12 13#include <asm/macio.h>14#include <asm/pmac_feature.h>15#include <asm/pmac_pfunc.h>16#include <asm/keylargo.h>17 18#include "i2sbus.h"19 20int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)21{22	*c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);23	if (!*c)24		return -ENOMEM;25 26	INIT_LIST_HEAD(&(*c)->list);27 28	(*c)->macio = dev->bus->chip;29	return 0;30}31 32void i2sbus_control_destroy(struct i2sbus_control *c)33{34	kfree(c);35}36 37/* this is serialised externally */38int i2sbus_control_add_dev(struct i2sbus_control *c,39			   struct i2sbus_dev *i2sdev)40{41	struct device_node *np;42 43	np = i2sdev->sound.ofdev.dev.of_node;44	i2sdev->enable = pmf_find_function(np, "enable");45	i2sdev->cell_enable = pmf_find_function(np, "cell-enable");46	i2sdev->clock_enable = pmf_find_function(np, "clock-enable");47	i2sdev->cell_disable = pmf_find_function(np, "cell-disable");48	i2sdev->clock_disable = pmf_find_function(np, "clock-disable");49 50	/* if the bus number is not 0 or 1 we absolutely need to use51	 * the platform functions -- there's nothing in Darwin that52	 * would allow seeing a system behind what the FCRs are then,53	 * and I don't want to go parsing a bunch of platform functions54	 * by hand to try finding a system... */55	if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 &&56	    (!i2sdev->enable ||57	     !i2sdev->cell_enable || !i2sdev->clock_enable ||58	     !i2sdev->cell_disable || !i2sdev->clock_disable)) {59		pmf_put_function(i2sdev->enable);60		pmf_put_function(i2sdev->cell_enable);61		pmf_put_function(i2sdev->clock_enable);62		pmf_put_function(i2sdev->cell_disable);63		pmf_put_function(i2sdev->clock_disable);64		return -ENODEV;65	}66 67	list_add(&i2sdev->item, &c->list);68 69	return 0;70}71 72void i2sbus_control_remove_dev(struct i2sbus_control *c,73			       struct i2sbus_dev *i2sdev)74{75	/* this is serialised externally */76	list_del(&i2sdev->item);77	if (list_empty(&c->list))78		i2sbus_control_destroy(c);79}80 81int i2sbus_control_enable(struct i2sbus_control *c,82			  struct i2sbus_dev *i2sdev)83{84	struct pmf_args args = { .count = 0 };85	struct macio_chip *macio = c->macio;86 87	if (i2sdev->enable)88		return pmf_call_one(i2sdev->enable, &args);89 90	if (macio == NULL || macio->base == NULL)91		return -ENODEV;92 93	switch (i2sdev->bus_number) {94	case 0:95		/* these need to be locked or done through96		 * newly created feature calls! */97		MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);98		break;99	case 1:100		MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE);101		break;102	default:103		return -ENODEV;104	}105	return 0;106}107 108int i2sbus_control_cell(struct i2sbus_control *c,109			struct i2sbus_dev *i2sdev,110			int enable)111{112	struct pmf_args args = { .count = 0 };113	struct macio_chip *macio = c->macio;114 115	switch (enable) {116	case 0:117		if (i2sdev->cell_disable)118			return pmf_call_one(i2sdev->cell_disable, &args);119		break;120	case 1:121		if (i2sdev->cell_enable)122			return pmf_call_one(i2sdev->cell_enable, &args);123		break;124	default:125		printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");126		return -ENODEV;127	}128 129	if (macio == NULL || macio->base == NULL)130		return -ENODEV;131 132	switch (i2sdev->bus_number) {133	case 0:134		if (enable)135			MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);136		else137			MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);138		break;139	case 1:140		if (enable)141			MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);142		else143			MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);144		break;145	default:146		return -ENODEV;147	}148	return 0;149}150 151int i2sbus_control_clock(struct i2sbus_control *c,152			 struct i2sbus_dev *i2sdev,153			 int enable)154{155	struct pmf_args args = { .count = 0 };156	struct macio_chip *macio = c->macio;157 158	switch (enable) {159	case 0:160		if (i2sdev->clock_disable)161			return pmf_call_one(i2sdev->clock_disable, &args);162		break;163	case 1:164		if (i2sdev->clock_enable)165			return pmf_call_one(i2sdev->clock_enable, &args);166		break;167	default:168		printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");169		return -ENODEV;170	}171 172	if (macio == NULL || macio->base == NULL)173		return -ENODEV;174 175	switch (i2sdev->bus_number) {176	case 0:177		if (enable)178			MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);179		else180			MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);181		break;182	case 1:183		if (enable)184			MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);185		else186			MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);187		break;188	default:189		return -ENODEV;190	}191	return 0;192}193