Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * i2sbus driver -- bus control routines
0004  *
0005  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/delay.h>
0010 #include <linux/slab.h>
0011 #include <linux/io.h>
0012 
0013 #include <asm/prom.h>
0014 #include <asm/macio.h>
0015 #include <asm/pmac_feature.h>
0016 #include <asm/pmac_pfunc.h>
0017 #include <asm/keylargo.h>
0018 
0019 #include "i2sbus.h"
0020 
0021 int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
0022 {
0023     *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);
0024     if (!*c)
0025         return -ENOMEM;
0026 
0027     INIT_LIST_HEAD(&(*c)->list);
0028 
0029     (*c)->macio = dev->bus->chip;
0030     return 0;
0031 }
0032 
0033 void i2sbus_control_destroy(struct i2sbus_control *c)
0034 {
0035     kfree(c);
0036 }
0037 
0038 /* this is serialised externally */
0039 int i2sbus_control_add_dev(struct i2sbus_control *c,
0040                struct i2sbus_dev *i2sdev)
0041 {
0042     struct device_node *np;
0043 
0044     np = i2sdev->sound.ofdev.dev.of_node;
0045     i2sdev->enable = pmf_find_function(np, "enable");
0046     i2sdev->cell_enable = pmf_find_function(np, "cell-enable");
0047     i2sdev->clock_enable = pmf_find_function(np, "clock-enable");
0048     i2sdev->cell_disable = pmf_find_function(np, "cell-disable");
0049     i2sdev->clock_disable = pmf_find_function(np, "clock-disable");
0050 
0051     /* if the bus number is not 0 or 1 we absolutely need to use
0052      * the platform functions -- there's nothing in Darwin that
0053      * would allow seeing a system behind what the FCRs are then,
0054      * and I don't want to go parsing a bunch of platform functions
0055      * by hand to try finding a system... */
0056     if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 &&
0057         (!i2sdev->enable ||
0058          !i2sdev->cell_enable || !i2sdev->clock_enable ||
0059          !i2sdev->cell_disable || !i2sdev->clock_disable)) {
0060         pmf_put_function(i2sdev->enable);
0061         pmf_put_function(i2sdev->cell_enable);
0062         pmf_put_function(i2sdev->clock_enable);
0063         pmf_put_function(i2sdev->cell_disable);
0064         pmf_put_function(i2sdev->clock_disable);
0065         return -ENODEV;
0066     }
0067 
0068     list_add(&i2sdev->item, &c->list);
0069 
0070     return 0;
0071 }
0072 
0073 void i2sbus_control_remove_dev(struct i2sbus_control *c,
0074                    struct i2sbus_dev *i2sdev)
0075 {
0076     /* this is serialised externally */
0077     list_del(&i2sdev->item);
0078     if (list_empty(&c->list))
0079         i2sbus_control_destroy(c);
0080 }
0081 
0082 int i2sbus_control_enable(struct i2sbus_control *c,
0083               struct i2sbus_dev *i2sdev)
0084 {
0085     struct pmf_args args = { .count = 0 };
0086     struct macio_chip *macio = c->macio;
0087 
0088     if (i2sdev->enable)
0089         return pmf_call_one(i2sdev->enable, &args);
0090 
0091     if (macio == NULL || macio->base == NULL)
0092         return -ENODEV;
0093 
0094     switch (i2sdev->bus_number) {
0095     case 0:
0096         /* these need to be locked or done through
0097          * newly created feature calls! */
0098         MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);
0099         break;
0100     case 1:
0101         MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE);
0102         break;
0103     default:
0104         return -ENODEV;
0105     }
0106     return 0;
0107 }
0108 
0109 int i2sbus_control_cell(struct i2sbus_control *c,
0110             struct i2sbus_dev *i2sdev,
0111             int enable)
0112 {
0113     struct pmf_args args = { .count = 0 };
0114     struct macio_chip *macio = c->macio;
0115 
0116     switch (enable) {
0117     case 0:
0118         if (i2sdev->cell_disable)
0119             return pmf_call_one(i2sdev->cell_disable, &args);
0120         break;
0121     case 1:
0122         if (i2sdev->cell_enable)
0123             return pmf_call_one(i2sdev->cell_enable, &args);
0124         break;
0125     default:
0126         printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");
0127         return -ENODEV;
0128     }
0129 
0130     if (macio == NULL || macio->base == NULL)
0131         return -ENODEV;
0132 
0133     switch (i2sdev->bus_number) {
0134     case 0:
0135         if (enable)
0136             MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
0137         else
0138             MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
0139         break;
0140     case 1:
0141         if (enable)
0142             MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
0143         else
0144             MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
0145         break;
0146     default:
0147         return -ENODEV;
0148     }
0149     return 0;
0150 }
0151 
0152 int i2sbus_control_clock(struct i2sbus_control *c,
0153              struct i2sbus_dev *i2sdev,
0154              int enable)
0155 {
0156     struct pmf_args args = { .count = 0 };
0157     struct macio_chip *macio = c->macio;
0158 
0159     switch (enable) {
0160     case 0:
0161         if (i2sdev->clock_disable)
0162             return pmf_call_one(i2sdev->clock_disable, &args);
0163         break;
0164     case 1:
0165         if (i2sdev->clock_enable)
0166             return pmf_call_one(i2sdev->clock_enable, &args);
0167         break;
0168     default:
0169         printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");
0170         return -ENODEV;
0171     }
0172 
0173     if (macio == NULL || macio->base == NULL)
0174         return -ENODEV;
0175 
0176     switch (i2sdev->bus_number) {
0177     case 0:
0178         if (enable)
0179             MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
0180         else
0181             MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
0182         break;
0183     case 1:
0184         if (enable)
0185             MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
0186         else
0187             MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
0188         break;
0189     default:
0190         return -ENODEV;
0191     }
0192     return 0;
0193 }