1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * CS42L43 SoundWire driver 4 * 5 * Copyright (C) 2022-2023 Cirrus Logic, Inc. and 6 * Cirrus Logic International Semiconductor Ltd. 7 */ 8 9 #include <linux/err.h> 10 #include <linux/errno.h> 11 #include <linux/mfd/cs42l43-regs.h> 12 #include <linux/module.h> 13 #include <linux/device.h> 14 #include <linux/soundwire/sdw.h> 15 #include <linux/soundwire/sdw_registers.h> 16 #include <linux/soundwire/sdw_type.h> 17 18 #include "cs42l43.h" 19 20 #define CS42L43_SDW_PORT(port, chans) { \ 21 .num = port, \ 22 .max_ch = chans, \ 23 .type = SDW_DPN_FULL, \ 24 .max_word = 24, \ 25 } 26 27 static const struct regmap_config cs42l43_sdw_regmap = { 28 .reg_bits = 32, 29 .reg_stride = 4, 30 .val_bits = 32, 31 .reg_format_endian = REGMAP_ENDIAN_LITTLE, 32 .val_format_endian = REGMAP_ENDIAN_LITTLE, 33 34 .max_register = CS42L43_MCU_RAM_MAX, 35 .readable_reg = cs42l43_readable_register, 36 .volatile_reg = cs42l43_volatile_register, 37 .precious_reg = cs42l43_precious_register, 38 39 .cache_type = REGCACHE_MAPLE, 40 .reg_defaults = cs42l43_reg_default, 41 .num_reg_defaults = ARRAY_SIZE(cs42l43_reg_default), 42 }; 43 44 static const struct sdw_dpn_prop cs42l43_src_port_props[] = { 45 CS42L43_SDW_PORT(1, 4), 46 CS42L43_SDW_PORT(2, 2), 47 CS42L43_SDW_PORT(3, 2), 48 CS42L43_SDW_PORT(4, 2), 49 }; 50 51 static const struct sdw_dpn_prop cs42l43_sink_port_props[] = { 52 CS42L43_SDW_PORT(5, 2), 53 CS42L43_SDW_PORT(6, 2), 54 CS42L43_SDW_PORT(7, 2), 55 }; 56 57 static int cs42l43_read_prop(struct sdw_slave *sdw) 58 { 59 struct sdw_slave_prop *prop = &sdw->prop; 60 struct device *dev = &sdw->dev; 61 int i; 62 63 prop->use_domain_irq = true; 64 prop->paging_support = true; 65 prop->wake_capable = true; 66 prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; 67 prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY | 68 SDW_SCP_INT1_IMPL_DEF; 69 70 for (i = 0; i < ARRAY_SIZE(cs42l43_src_port_props); i++) 71 prop->source_ports |= BIT(cs42l43_src_port_props[i].num); 72 73 prop->src_dpn_prop = devm_kmemdup(dev, cs42l43_src_port_props, 74 sizeof(cs42l43_src_port_props), GFP_KERNEL); 75 if (!prop->src_dpn_prop) 76 return -ENOMEM; 77 78 for (i = 0; i < ARRAY_SIZE(cs42l43_sink_port_props); i++) 79 prop->sink_ports |= BIT(cs42l43_sink_port_props[i].num); 80 81 prop->sink_dpn_prop = devm_kmemdup(dev, cs42l43_sink_port_props, 82 sizeof(cs42l43_sink_port_props), GFP_KERNEL); 83 if (!prop->sink_dpn_prop) 84 return -ENOMEM; 85 86 return 0; 87 } 88 89 static int cs42l43_sdw_update_status(struct sdw_slave *sdw, enum sdw_slave_status status) 90 { 91 struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev); 92 93 switch (status) { 94 case SDW_SLAVE_ATTACHED: 95 dev_dbg(cs42l43->dev, "Device attach\n"); 96 97 sdw_write_no_pm(sdw, CS42L43_GEN_INT_MASK_1, 98 CS42L43_INT_STAT_GEN1_MASK); 99 100 cs42l43->attached = true; 101 102 complete(&cs42l43->device_attach); 103 break; 104 case SDW_SLAVE_UNATTACHED: 105 dev_dbg(cs42l43->dev, "Device detach\n"); 106 107 cs42l43->attached = false; 108 109 reinit_completion(&cs42l43->device_attach); 110 complete(&cs42l43->device_detach); 111 break; 112 default: 113 break; 114 } 115 116 return 0; 117 } 118 119 static int cs42l43_sdw_interrupt(struct sdw_slave *sdw, 120 struct sdw_slave_intr_status *status) 121 { 122 /* 123 * The IRQ itself was handled through the regmap_irq handler, this is 124 * just clearing up the additional Cirrus SoundWire registers that are 125 * not covered by the SoundWire framework or the IRQ handler itself. 126 * There is only a single bit in GEN_INT_STAT_1 and it doesn't clear if 127 * IRQs are still pending so doing a read/write here after handling the 128 * IRQ is fine. 129 */ 130 sdw_read_no_pm(sdw, CS42L43_GEN_INT_STAT_1); 131 sdw_write_no_pm(sdw, CS42L43_GEN_INT_STAT_1, CS42L43_INT_STAT_GEN1_MASK); 132 133 return 0; 134 } 135 136 static int cs42l43_sdw_bus_config(struct sdw_slave *sdw, 137 struct sdw_bus_params *params) 138 { 139 struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev); 140 int ret = 0; 141 142 mutex_lock(&cs42l43->pll_lock); 143 144 if (cs42l43->sdw_freq != params->curr_dr_freq / 2) { 145 if (cs42l43->sdw_pll_active) { 146 dev_err(cs42l43->dev, 147 "PLL active can't change SoundWire bus clock\n"); 148 ret = -EBUSY; 149 } else { 150 cs42l43->sdw_freq = params->curr_dr_freq / 2; 151 } 152 } 153 154 mutex_unlock(&cs42l43->pll_lock); 155 156 return ret; 157 } 158 159 static const struct sdw_slave_ops cs42l43_sdw_ops = { 160 .read_prop = cs42l43_read_prop, 161 .update_status = cs42l43_sdw_update_status, 162 .interrupt_callback = cs42l43_sdw_interrupt, 163 .bus_config = cs42l43_sdw_bus_config, 164 }; 165 166 static int cs42l43_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id) 167 { 168 struct cs42l43 *cs42l43; 169 struct device *dev = &sdw->dev; 170 int ret; 171 172 cs42l43 = devm_kzalloc(dev, sizeof(*cs42l43), GFP_KERNEL); 173 if (!cs42l43) 174 return -ENOMEM; 175 176 cs42l43->dev = dev; 177 cs42l43->sdw = sdw; 178 179 cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap); 180 if (IS_ERR(cs42l43->regmap)) { 181 ret = PTR_ERR(cs42l43->regmap); 182 dev_err(cs42l43->dev, "Failed to allocate regmap: %d\n", ret); 183 return ret; 184 } 185 186 return cs42l43_dev_probe(cs42l43); 187 } 188 189 static int cs42l43_sdw_remove(struct sdw_slave *sdw) 190 { 191 struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev); 192 193 cs42l43_dev_remove(cs42l43); 194 195 return 0; 196 } 197 198 static const struct sdw_device_id cs42l43_sdw_id[] = { 199 SDW_SLAVE_ENTRY(0x01FA, 0x4243, 0), 200 {} 201 }; 202 MODULE_DEVICE_TABLE(sdw, cs42l43_sdw_id); 203 204 static struct sdw_driver cs42l43_sdw_driver = { 205 .driver = { 206 .name = "cs42l43", 207 .pm = pm_ptr(&cs42l43_pm_ops), 208 }, 209 210 .probe = cs42l43_sdw_probe, 211 .remove = cs42l43_sdw_remove, 212 .id_table = cs42l43_sdw_id, 213 .ops = &cs42l43_sdw_ops, 214 }; 215 module_sdw_driver(cs42l43_sdw_driver); 216 217 MODULE_IMPORT_NS(MFD_CS42L43); 218 219 MODULE_DESCRIPTION("CS42L43 SoundWire Driver"); 220 MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>"); 221 MODULE_LICENSE("GPL"); 222