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