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 break; 103 case SDW_SLAVE_UNATTACHED: 104 dev_dbg(cs42l43->dev, "Device detach\n"); 105 106 complete(&cs42l43->device_detach); 107 break; 108 default: 109 break; 110 } 111 112 return 0; 113 } 114 115 static int cs42l43_sdw_interrupt(struct sdw_slave *sdw, 116 struct sdw_slave_intr_status *status) 117 { 118 /* 119 * The IRQ itself was handled through the regmap_irq handler, this is 120 * just clearing up the additional Cirrus SoundWire registers that are 121 * not covered by the SoundWire framework or the IRQ handler itself. 122 * There is only a single bit in GEN_INT_STAT_1 and it doesn't clear if 123 * IRQs are still pending so doing a read/write here after handling the 124 * IRQ is fine. 125 */ 126 sdw_read_no_pm(sdw, CS42L43_GEN_INT_STAT_1); 127 sdw_write_no_pm(sdw, CS42L43_GEN_INT_STAT_1, CS42L43_INT_STAT_GEN1_MASK); 128 129 return 0; 130 } 131 132 static int cs42l43_sdw_bus_config(struct sdw_slave *sdw, 133 struct sdw_bus_params *params) 134 { 135 struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev); 136 int ret = 0; 137 138 mutex_lock(&cs42l43->pll_lock); 139 140 if (cs42l43->sdw_freq != params->curr_dr_freq / 2) { 141 if (cs42l43->sdw_pll_active) { 142 dev_err(cs42l43->dev, 143 "PLL active can't change SoundWire bus clock\n"); 144 ret = -EBUSY; 145 } else { 146 cs42l43->sdw_freq = params->curr_dr_freq / 2; 147 } 148 } 149 150 mutex_unlock(&cs42l43->pll_lock); 151 152 return ret; 153 } 154 155 static const struct sdw_slave_ops cs42l43_sdw_ops = { 156 .read_prop = cs42l43_read_prop, 157 .update_status = cs42l43_sdw_update_status, 158 .interrupt_callback = cs42l43_sdw_interrupt, 159 .bus_config = cs42l43_sdw_bus_config, 160 }; 161 162 static int cs42l43_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id) 163 { 164 struct cs42l43 *cs42l43; 165 struct device *dev = &sdw->dev; 166 167 cs42l43 = devm_kzalloc(dev, sizeof(*cs42l43), GFP_KERNEL); 168 if (!cs42l43) 169 return -ENOMEM; 170 171 cs42l43->dev = dev; 172 cs42l43->sdw = sdw; 173 cs42l43->variant_id = (long)id->driver_data; 174 175 cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap); 176 if (IS_ERR(cs42l43->regmap)) 177 return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->regmap), 178 "Failed to allocate regmap\n"); 179 180 return cs42l43_dev_probe(cs42l43); 181 } 182 183 static const struct sdw_device_id cs42l43_sdw_id[] = { 184 SDW_SLAVE_ENTRY(0x01FA, 0x4243, (void *)CS42L43_DEVID_VAL), 185 SDW_SLAVE_ENTRY(0x01FA, 0x2A3B, (void *)CS42L43B_DEVID_VAL), 186 { } 187 }; 188 MODULE_DEVICE_TABLE(sdw, cs42l43_sdw_id); 189 190 static struct sdw_driver cs42l43_sdw_driver = { 191 .driver = { 192 .name = "cs42l43", 193 .pm = pm_ptr(&cs42l43_pm_ops), 194 }, 195 196 .probe = cs42l43_sdw_probe, 197 .id_table = cs42l43_sdw_id, 198 .ops = &cs42l43_sdw_ops, 199 }; 200 module_sdw_driver(cs42l43_sdw_driver); 201 202 MODULE_IMPORT_NS("MFD_CS42L43"); 203 204 MODULE_DESCRIPTION("CS42L43 SoundWire Driver"); 205 MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>"); 206 MODULE_LICENSE("GPL"); 207