Fri, Aug 04, 2023 at 11:45:59AM +0100, Charles Keepax kirjoitti: > The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface > (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed > for portable applications. It provides a high dynamic range, stereo > DAC for headphone output, two integrated Class D amplifiers for > loudspeakers, and two ADCs for wired headset microphone input or > stereo line input. PDM inputs are provided for digital microphones. > > The MFD component registers and initialises the device and provides > PM/system power management. ... > +#include <linux/err.h> > +#include <linux/errno.h> It seems errno is not used (as Linux kernel error codes, otherwise err.h already includes necessary header). Also seems array_size.h, mod_devicetable.h are missing (at least). ... > +#if IS_ENABLED(CONFIG_OF) We are trying hard to get rid of this ugly ifdefferies (ACPI as well) along with respective macros that are often the PITA for CIs. > +static const struct of_device_id cs42l43_of_match[] = { > + { .compatible = "cirrus,cs42l43", }, > + {} > +}; > +MODULE_DEVICE_TABLE(of, cs42l43_of_match); > +#endif > + > +#if IS_ENABLED(CONFIG_ACPI) > +static const struct acpi_device_id cs42l43_acpi_match[] = { > + { "CSC4243", 0 }, > + {} > +}; > +MODULE_DEVICE_TABLE(acpi, cs42l43_acpi_match); > +#endif > + > +static struct i2c_driver cs42l43_i2c_driver = { > + .driver = { > + .name = "cs42l43", > + .pm = pm_ptr(&cs42l43_pm_ops), > + .of_match_table = of_match_ptr(cs42l43_of_match), > + .acpi_match_table = ACPI_PTR(cs42l43_acpi_match), > + }, > + > + .probe = cs42l43_i2c_probe, > + .remove = cs42l43_i2c_remove, > +}; ... > +#include <linux/err.h> > +#include <linux/errno.h> As per above. > +#include <linux/mfd/cs42l43-regs.h> > +#include <linux/module.h> > +#include <linux/device.h> > +#include <linux/soundwire/sdw.h> > +#include <linux/soundwire/sdw_registers.h> > +#include <linux/soundwire/sdw_type.h> ... > + mutex_lock(&cs42l43->pll_lock); This can be converted using cleanup.h. > + mutex_unlock(&cs42l43->pll_lock); ... > + cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap); > + if (IS_ERR(cs42l43->regmap)) { > + ret = PTR_ERR(cs42l43->regmap); > + dev_err(cs42l43->dev, "Failed to allocate regmap: %d\n", ret); > + return ret; > + } Can be simplified as cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap); if (IS_ERR(cs42l43->regmap)) dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->regmap), "Failed to allocate regmap: %d\n", ret); ... > +#include <linux/err.h> > +#include <linux/errno.h> As per above. ... > +#define CS42L43_RESET_DELAY 20 > + > +#define CS42L43_SDW_ATTACH_TIMEOUT 500 > +#define CS42L43_SDW_DETACH_TIMEOUT 100 > + > +#define CS42L43_MCU_POLL 5000 > +#define CS42L43_MCU_CMD_TIMEOUT 20000 > +#define CS42L43_MCU_UPDATE_TIMEOUT 500000 > +#define CS42L43_VDDP_DELAY 50 > +#define CS42L43_VDDD_DELAY 1000 > + > +#define CS42L43_AUTOSUSPEND_TIME 250 Usually we use units for the macro names as suffixes... E.g., _US (for microseconds). ... > +struct cs42l43_patch_header { > + __le16 version; > + __le16 size; > + u8 reserved; > + u8 secure; Seems to me that __u8 is appropriate as patch is external to the kernel and it's kinda firmware interface. > + __le16 bss_size; > + __le32 apply_addr; > + __le32 checksum; > + __le32 sha; > + __le16 swrev; > + __le16 patchid; > + __le16 ipxid; > + __le16 romver; > + __le32 load_addr; > +} __packed; ... > +static const struct mfd_cell cs42l43_devs[] = { > + { .name = "cs42l43-pinctrl", }, > + { .name = "cs42l43-spi", }, Inner commas are not needed > + { > + .name = "cs42l43-codec", > + .parent_supplies = cs42l43_parent_supplies, > + .num_parent_supplies = ARRAY_SIZE(cs42l43_parent_supplies), > + }, > +}; > + case CS42L43_MCU_BOOT_STAGE2: > + if (!patched) { > + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, > + "cs42l43.bin", cs42l43->dev, > + GFP_KERNEL, cs42l43, > + cs42l43_mcu_load_firmware); > + if (ret) { > + dev_err(cs42l43->dev, "Failed to request firmware: %d\n", ret); > + return ret; > + } > + > + wait_for_completion(&cs42l43->firmware_download); > + > + if (cs42l43->firmware_error) > + return cs42l43->firmware_error; > + > + return -EAGAIN; > + } else { Redundant 'else' and > + return cs42l43_mcu_stage_2_3(cs42l43, shadow); > + } why not positive conditional as below? if (patched) return ... ... > + case CS42L43_MCU_BOOT_STAGE3: > + if (patched) > + return cs42l43_mcu_disable(cs42l43); > + else > + return cs42l43_mcu_stage_3_2(cs42l43); ... > + irq_flags = irqd_get_trigger_type(irq_data); > + switch (irq_flags) { > + case IRQF_TRIGGER_LOW: > + case IRQF_TRIGGER_HIGH: > + case IRQF_TRIGGER_RISING: > + case IRQF_TRIGGER_FALLING: > + break; > + case IRQ_TYPE_NONE: Are you sure it's a right place to interpret no type flags as a default? > + default: > + irq_flags = IRQF_TRIGGER_LOW; > + break; > + } ... > +static int cs42l43_suspend(struct device *dev) > +{ > + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); > + int ret; > + > + /* > + * Don't care about being resumed here, but the driver does want > + * force_resume to always trigger an actual resume, so that register > + * state for the MCU/GPIOs is returned as soon as possible after system > + * resume. force_resume will resume if the reference count is resumed on > + * suspend hence the get_noresume. > + */ > + pm_runtime_get_noresume(dev); > + > + ret = pm_runtime_force_suspend(dev); > + if (ret) { > + dev_err(cs42l43->dev, "Failed to force suspend: %d\n", ret); > + pm_runtime_put_noidle(dev); > + return ret; > + } > + > + pm_runtime_put_noidle(dev); > + > + ret = cs42l43_power_down(cs42l43); > + if (ret) > + return ret; > + > + return 0; return cs42l43_power_down(cs42l43); > +} ... > +EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = { > + SET_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) > + SET_RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL) > +}; Why do you need SET_*() versions of those macros? They are not supposed to be used with the new macros such as EXPORT_NS_GPL_DEV_PM_OPS(). ... > +++ b/drivers/mfd/cs42l43.h > +#include <linux/mfd/cs42l43.h> How is this header being used? Wouldn't the forward declaration fulfill the need? > +#include <linux/pm.h> > +#include <linux/regmap.h> > +#ifndef CS42L43_CORE_INT_H > +#define CS42L43_CORE_INT_H Why you don't guard other headers with this? It will slow down the build. > +#define CS42L43_N_DEFAULTS 176 > + > +extern const struct dev_pm_ops cs42l43_pm_ops; > +extern const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS]; Missing forward declaration for struct device; > +bool cs42l43_readable_register(struct device *dev, unsigned int reg); > +bool cs42l43_precious_register(struct device *dev, unsigned int reg); > +bool cs42l43_volatile_register(struct device *dev, unsigned int reg); > +int cs42l43_dev_probe(struct cs42l43 *cs42l43); > +void cs42l43_dev_remove(struct cs42l43 *cs42l43); > + > +#endif /* CS42L43_CORE_INT_H */ ... > +#define CS42L43_MIXER_VOL_MASK 0x00FE0000 > +#define CS42L43_MIXER_VOL_SHIFT 17 > +#define CS42L43_MIXER_SRC_MASK 0x000001FF > +#define CS42L43_MIXER_SRC_SHIFT 0 This header would benefit from bits.h... (the above is just a little example). ... > +++ b/include/linux/mfd/cs42l43.h > +#include <linux/device.h> > +#include <linux/gpio/consumer.h> > +#include <linux/soundwire/sdw.h> Missing forward declarations (instead of inclusions). struct device; struct gpio_desc; struct sdw_slave; Missing types.h. ... > +#ifndef CS42L43_CORE_EXT_H > +#define CS42L43_CORE_EXT_H Same questions as per another header. -- With Best Regards, Andy Shevchenko