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