1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * i2sbus driver -- bus control routines 4 * 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 20 int 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 32 void i2sbus_control_destroy(struct i2sbus_control *c) 33 { 34 kfree(c); 35 } 36 37 /* this is serialised externally */ 38 int 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 use 51 * the platform functions -- there's nothing in Darwin that 52 * would allow seeing a system behind what the FCRs are then, 53 * and I don't want to go parsing a bunch of platform functions 54 * 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 72 void 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 81 int 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 through 96 * 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 108 int 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 else 137 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 else 143 MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE); 144 break; 145 default: 146 return -ENODEV; 147 } 148 return 0; 149 } 150 151 int 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 else 180 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 else 186 MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT); 187 break; 188 default: 189 return -ENODEV; 190 } 191 return 0; 192 } 193