Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: Add companion chip in 88pm80x

in hw design, 800 is mainly for pmic control, while 805 for audio.
but there are 3 registers which controls class D speaker property,
and they are defined in 800 i2c client domain. so 805 codec driver
needs to use 800 i2c client to access class D speaker reg for
audio path management. so add this workaround for the purpose to
let 805 access 800 i2c in some scenario.

Signed-off-by: Qiao Zhou <zhouqiao@marvell.com>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Qiao Zhou and committed by
Samuel Ortiz
5500e396 70c6cce0

+29
+28
drivers/mfd/88pm80x.c
··· 18 18 #include <linux/uaccess.h> 19 19 #include <linux/err.h> 20 20 21 + /* 22 + * workaround: some registers needed by pm805 are defined in pm800, so 23 + * need to use this global variable to maintain the relation between 24 + * pm800 and pm805. would remove it after HW chip fixes the issue. 25 + */ 26 + static struct pm80x_chip *g_pm80x_chip; 21 27 22 28 const struct regmap_config pm80x_regmap_config = { 23 29 .reg_bits = 8, ··· 67 61 68 62 device_init_wakeup(&client->dev, 1); 69 63 64 + /* 65 + * workaround: set g_pm80x_chip to the first probed chip. if the 66 + * second chip is probed, just point to the companion to each 67 + * other so that pm805 can access those specific register. would 68 + * remove it after HW chip fixes the issue. 69 + */ 70 + if (!g_pm80x_chip) 71 + g_pm80x_chip = chip; 72 + else { 73 + chip->companion = g_pm80x_chip->client; 74 + g_pm80x_chip->companion = chip->client; 75 + } 76 + 70 77 return 0; 71 78 72 79 err_chip_id: ··· 93 74 int __devexit pm80x_deinit(struct i2c_client *client) 94 75 { 95 76 struct pm80x_chip *chip = i2c_get_clientdata(client); 77 + 78 + /* 79 + * workaround: clear the dependency between pm800 and pm805. 80 + * would remove it after HW chip fixes the issue. 81 + */ 82 + if (g_pm80x_chip->companion) 83 + g_pm80x_chip->companion = NULL; 84 + else 85 + g_pm80x_chip = NULL; 96 86 97 87 regmap_exit(chip->regmap); 98 88 devm_kfree(&client->dev, chip);
+1
include/linux/mfd/88pm80x.h
··· 295 295 struct pm80x_subchip *subchip; 296 296 struct device *dev; 297 297 struct i2c_client *client; 298 + struct i2c_client *companion; 298 299 struct regmap *regmap; 299 300 struct regmap_irq_chip *regmap_irq_chip; 300 301 struct regmap_irq_chip_data *irq_data;