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

Configure Feed

Select the types of activity you want to include in your feed.

mfd: adp5585: Add support for adp5589

The ADP5589 is a 19 I/O port expander with built-in keypad matrix decoder,
programmable logic, reset generator, and PWM generator.

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20250701-dev-adp5589-fw-v7-7-b1fcfe9e9826@analog.com
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Nuno Sá and committed by
Lee Jones
0190a72f 1a4eabf6

+124 -9
+114 -9
drivers/mfd/adp5585.c
··· 29 29 MFD_CELL_NAME("adp5585-pwm"), 30 30 }; 31 31 32 + static const struct mfd_cell adp5589_devs[] = { 33 + MFD_CELL_NAME("adp5589-gpio"), 34 + MFD_CELL_NAME("adp5589-pwm"), 35 + }; 36 + 32 37 static const struct regmap_range adp5585_volatile_ranges[] = { 33 38 regmap_reg_range(ADP5585_ID, ADP5585_GPI_STATUS_B), 34 39 }; ··· 41 36 static const struct regmap_access_table adp5585_volatile_regs = { 42 37 .yes_ranges = adp5585_volatile_ranges, 43 38 .n_yes_ranges = ARRAY_SIZE(adp5585_volatile_ranges), 39 + }; 40 + 41 + static const struct regmap_range adp5589_volatile_ranges[] = { 42 + regmap_reg_range(ADP5585_ID, ADP5589_GPI_STATUS_C), 43 + }; 44 + 45 + static const struct regmap_access_table adp5589_volatile_regs = { 46 + .yes_ranges = adp5589_volatile_ranges, 47 + .n_yes_ranges = ARRAY_SIZE(adp5589_volatile_ranges), 44 48 }; 45 49 46 50 /* ··· 95 81 /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00, 96 82 }; 97 83 84 + static const u8 adp5589_regmap_defaults_00[ADP5589_MAX_REG + 1] = { 85 + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 87 + /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 88 + /* 0x18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 89 + /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 90 + /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 91 + /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 92 + /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 93 + /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 + /* 0x48 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 95 + }; 96 + 97 + static const u8 adp5589_regmap_defaults_01[ADP5589_MAX_REG + 1] = { 98 + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 99 + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 100 + /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 101 + /* 0x18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 102 + /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 103 + /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 104 + /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 105 + /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 106 + /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 107 + /* 0x48 */ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 108 + }; 109 + 110 + static const u8 adp5589_regmap_defaults_02[ADP5589_MAX_REG + 1] = { 111 + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 112 + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 113 + /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 114 + /* 0x18 */ 0x00, 0x41, 0x01, 0x00, 0x11, 0x04, 0x00, 0x00, 115 + /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 116 + /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 117 + /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 118 + /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 119 + /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 120 + /* 0x48 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 121 + }; 122 + 98 123 static const u8 *adp5585_regmap_defaults[ADP5585_MAX] = { 99 124 [ADP5585_00] = adp5585_regmap_defaults_00, 100 125 [ADP5585_01] = adp5585_regmap_defaults_00, 101 126 [ADP5585_02] = adp5585_regmap_defaults_02, 102 127 [ADP5585_03] = adp5585_regmap_defaults_00, 103 128 [ADP5585_04] = adp5585_regmap_defaults_04, 129 + [ADP5589_00] = adp5589_regmap_defaults_00, 130 + [ADP5589_01] = adp5589_regmap_defaults_01, 131 + [ADP5589_02] = adp5589_regmap_defaults_02, 104 132 }; 105 133 106 134 static const struct regmap_config adp5585_regmap_config_template = { ··· 154 98 .num_reg_defaults_raw = ADP5585_MAX_REG + 1, 155 99 }; 156 100 157 - static struct regmap_config *adp5585_fill_regmap_config(const struct adp5585_dev *adp5585) 101 + static const struct regmap_config adp5589_regmap_config_template = { 102 + .reg_bits = 8, 103 + .val_bits = 8, 104 + .max_register = ADP5589_MAX_REG, 105 + .volatile_table = &adp5589_volatile_regs, 106 + .cache_type = REGCACHE_MAPLE, 107 + .num_reg_defaults_raw = ADP5589_MAX_REG + 1, 108 + }; 109 + 110 + static struct regmap_config *adp5585_fill_variant_config(struct adp5585_dev *adp5585) 158 111 { 159 112 struct regmap_config *regmap_config; 160 113 161 - regmap_config = devm_kmemdup(adp5585->dev, &adp5585_regmap_config_template, 162 - sizeof(*regmap_config), GFP_KERNEL); 114 + switch (adp5585->variant) { 115 + case ADP5585_00: 116 + case ADP5585_01: 117 + case ADP5585_02: 118 + case ADP5585_03: 119 + case ADP5585_04: 120 + adp5585->id = ADP5585_MAN_ID_VALUE; 121 + regmap_config = devm_kmemdup(adp5585->dev, &adp5585_regmap_config_template, 122 + sizeof(*regmap_config), GFP_KERNEL); 123 + break; 124 + case ADP5589_00: 125 + case ADP5589_01: 126 + case ADP5589_02: 127 + adp5585->id = ADP5589_MAN_ID_VALUE; 128 + regmap_config = devm_kmemdup(adp5585->dev, &adp5589_regmap_config_template, 129 + sizeof(*regmap_config), GFP_KERNEL); 130 + break; 131 + default: 132 + return ERR_PTR(-ENODEV); 133 + } 134 + 163 135 if (!regmap_config) 164 136 return ERR_PTR(-ENOMEM); 165 137 166 138 regmap_config->reg_defaults_raw = adp5585_regmap_defaults[adp5585->variant]; 139 + 167 140 return regmap_config; 168 141 } 169 142 170 - static int adp5585_add_devices(struct device *dev) 143 + static int adp5585_add_devices(const struct adp5585_dev *adp5585) 171 144 { 145 + struct device *dev = adp5585->dev; 146 + const struct mfd_cell *cells; 172 147 int ret; 148 + 149 + if (adp5585->id == ADP5585_MAN_ID_VALUE) 150 + cells = adp5585_devs; 151 + else 152 + cells = adp5589_devs; 173 153 174 154 if (device_property_present(dev, "#pwm-cells")) { 175 155 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, 176 - &adp5585_devs[ADP5585_DEV_PWM], 1, NULL, 0, NULL); 156 + &cells[ADP5585_DEV_PWM], 1, NULL, 0, NULL); 177 157 if (ret) 178 158 return dev_err_probe(dev, ret, "Failed to add PWM device\n"); 179 159 } 180 160 181 161 if (device_property_present(dev, "#gpio-cells")) { 182 162 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, 183 - &adp5585_devs[ADP5585_DEV_GPIO], 1, NULL, 0, NULL); 163 + &cells[ADP5585_DEV_GPIO], 1, NULL, 0, NULL); 184 164 if (ret) 185 165 return dev_err_probe(dev, ret, "Failed to add GPIO device\n"); 186 166 } ··· 249 157 if (!adp5585->variant) 250 158 return -ENODEV; 251 159 252 - regmap_config = adp5585_fill_regmap_config(adp5585); 160 + regmap_config = adp5585_fill_variant_config(adp5585); 253 161 if (IS_ERR(regmap_config)) 254 162 return PTR_ERR(regmap_config); 255 163 ··· 263 171 return dev_err_probe(&i2c->dev, ret, 264 172 "Failed to read device ID\n"); 265 173 266 - if ((id & ADP5585_MAN_ID_MASK) != ADP5585_MAN_ID_VALUE) 174 + id &= ADP5585_MAN_ID_MASK; 175 + if (id != adp5585->id) 267 176 return dev_err_probe(&i2c->dev, -ENODEV, 268 177 "Invalid device ID 0x%02x\n", id); 269 178 ··· 280 187 if (ret) 281 188 return ret; 282 189 283 - return adp5585_add_devices(&i2c->dev); 190 + return adp5585_add_devices(adp5585); 284 191 } 285 192 286 193 static int adp5585_suspend(struct device *dev) ··· 320 227 }, { 321 228 .compatible = "adi,adp5585-04", 322 229 .data = (void *)ADP5585_04, 230 + }, { 231 + .compatible = "adi,adp5589-00", 232 + .data = (void *)ADP5589_00, 233 + }, { 234 + .compatible = "adi,adp5589-01", 235 + .data = (void *)ADP5589_01, 236 + }, { 237 + .compatible = "adi,adp5589-02", 238 + .data = (void *)ADP5589_02, 239 + }, { 240 + .compatible = "adi,adp5589", 241 + .data = (void *)ADP5589_00, 323 242 }, 324 243 { /* sentinel */ } 325 244 };
+10
include/linux/mfd/adp5585.h
··· 117 117 #define ADP5585_BANK(n) ((n) >= 6 ? 1 : 0) 118 118 #define ADP5585_BIT(n) ((n) >= 6 ? BIT((n) - 6) : BIT(n)) 119 119 120 + /* ADP5589 */ 121 + #define ADP5589_MAN_ID_VALUE 0x10 122 + #define ADP5589_GPI_STATUS_C 0x18 123 + #define ADP5589_INT_EN 0x4e 124 + #define ADP5589_MAX_REG ADP5589_INT_EN 125 + 120 126 struct regmap; 121 127 122 128 enum adp5585_variant { ··· 131 125 ADP5585_02, 132 126 ADP5585_03, 133 127 ADP5585_04, 128 + ADP5589_00, 129 + ADP5589_01, 130 + ADP5589_02, 134 131 ADP5585_MAX 135 132 }; 136 133 ··· 141 132 struct device *dev; 142 133 struct regmap *regmap; 143 134 enum adp5585_variant variant; 135 + unsigned int id; 144 136 }; 145 137 146 138 #endif