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

iio: adc: sc27xx: add support for PMIC sc2720 and sc2721

sc2720 and sc2721 is the product of sc27xx series.

Co-developed-by: Yuming Zhu <yuming.zhu1@unisoc.com>
Signed-off-by: Yuming Zhu <yuming.zhu1@unisoc.com>
Signed-off-by: Cixi Geng <cixi.geng1@unisoc.com>
Link: https://lore.kernel.org/r/20220419142458.884933-7-gengcixi@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Cixi Geng and committed by
Jonathan Cameron
fff4a7a8 aac053d0

+201 -2
+201 -2
drivers/iio/adc/sc27xx_adc.c
··· 9 9 #include <linux/of_device.h> 10 10 #include <linux/platform_device.h> 11 11 #include <linux/regmap.h> 12 + #include <linux/regulator/consumer.h> 12 13 #include <linux/slab.h> 13 14 14 15 /* PMIC global registers definition */ 15 16 #define SC2731_MODULE_EN 0xc08 16 17 #define SC27XX_MODULE_ADC_EN BIT(5) 18 + #define SC2721_ARM_CLK_EN 0xc0c 17 19 #define SC2731_ARM_CLK_EN 0xc10 18 20 #define SC27XX_CLK_ADC_EN BIT(5) 19 21 #define SC27XX_CLK_ADC_CLK_EN BIT(6) ··· 39 37 /* Bits and mask definition for SC27XX_ADC_CH_CFG register */ 40 38 #define SC27XX_ADC_CHN_ID_MASK GENMASK(4, 0) 41 39 #define SC27XX_ADC_SCALE_MASK GENMASK(10, 9) 40 + #define SC2721_ADC_SCALE_MASK BIT(5) 42 41 #define SC27XX_ADC_SCALE_SHIFT 9 42 + #define SC2721_ADC_SCALE_SHIFT 5 43 43 44 44 /* Bits definitions for SC27XX_ADC_INT_EN registers */ 45 45 #define SC27XX_ADC_IRQ_EN BIT(0) ··· 71 67 #define SC27XX_RATIO_NUMERATOR_OFFSET 16 72 68 #define SC27XX_RATIO_DENOMINATOR_MASK GENMASK(15, 0) 73 69 70 + /* ADC specific channel reference voltage 3.5V */ 71 + #define SC27XX_ADC_REFVOL_VDD35 3500000 72 + 73 + /* ADC default channel reference voltage is 2.8V */ 74 + #define SC27XX_ADC_REFVOL_VDD28 2800000 75 + 74 76 struct sc27xx_adc_data { 75 77 struct device *dev; 78 + struct regulator *volref; 76 79 struct regmap *regmap; 77 80 /* 78 81 * One hardware spinlock to synchronize between the multiple ··· 106 95 const struct sc27xx_adc_linear_graph *sscale_cal; 107 96 void (*init_scale)(struct sc27xx_adc_data *data); 108 97 int (*get_ratio)(int channel, int scale); 98 + bool set_volref; 109 99 }; 110 100 111 101 struct sc27xx_adc_linear_graph { ··· 140 128 static const struct sc27xx_adc_linear_graph sc2731_small_scale_graph_calib = { 141 129 1000, 838, 142 130 100, 84, 131 + }; 132 + 133 + static const struct sc27xx_adc_linear_graph big_scale_graph_calib = { 134 + 4200, 856, 135 + 3600, 733, 136 + }; 137 + 138 + static const struct sc27xx_adc_linear_graph small_scale_graph_calib = { 139 + 1000, 833, 140 + 100, 80, 143 141 }; 144 142 145 143 static int sc27xx_adc_get_calib_data(u32 calib_data, int calib_adc) ··· 213 191 return 0; 214 192 } 215 193 194 + static int sc2720_adc_get_ratio(int channel, int scale) 195 + { 196 + switch (channel) { 197 + case 14: 198 + switch (scale) { 199 + case 0: 200 + return SC27XX_VOLT_RATIO(68, 900); 201 + case 1: 202 + return SC27XX_VOLT_RATIO(68, 1760); 203 + case 2: 204 + return SC27XX_VOLT_RATIO(68, 2327); 205 + case 3: 206 + return SC27XX_VOLT_RATIO(68, 3654); 207 + default: 208 + return SC27XX_VOLT_RATIO(1, 1); 209 + } 210 + case 16: 211 + switch (scale) { 212 + case 0: 213 + return SC27XX_VOLT_RATIO(48, 100); 214 + case 1: 215 + return SC27XX_VOLT_RATIO(480, 1955); 216 + case 2: 217 + return SC27XX_VOLT_RATIO(480, 2586); 218 + case 3: 219 + return SC27XX_VOLT_RATIO(48, 406); 220 + default: 221 + return SC27XX_VOLT_RATIO(1, 1); 222 + } 223 + case 21: 224 + case 22: 225 + case 23: 226 + switch (scale) { 227 + case 0: 228 + return SC27XX_VOLT_RATIO(3, 8); 229 + case 1: 230 + return SC27XX_VOLT_RATIO(375, 1955); 231 + case 2: 232 + return SC27XX_VOLT_RATIO(375, 2586); 233 + case 3: 234 + return SC27XX_VOLT_RATIO(300, 3248); 235 + default: 236 + return SC27XX_VOLT_RATIO(1, 1); 237 + } 238 + default: 239 + switch (scale) { 240 + case 0: 241 + return SC27XX_VOLT_RATIO(1, 1); 242 + case 1: 243 + return SC27XX_VOLT_RATIO(1000, 1955); 244 + case 2: 245 + return SC27XX_VOLT_RATIO(1000, 2586); 246 + case 3: 247 + return SC27XX_VOLT_RATIO(100, 406); 248 + default: 249 + return SC27XX_VOLT_RATIO(1, 1); 250 + } 251 + } 252 + return SC27XX_VOLT_RATIO(1, 1); 253 + } 254 + 255 + static int sc2721_adc_get_ratio(int channel, int scale) 256 + { 257 + switch (channel) { 258 + case 1: 259 + case 2: 260 + case 3: 261 + case 4: 262 + return scale ? SC27XX_VOLT_RATIO(400, 1025) : 263 + SC27XX_VOLT_RATIO(1, 1); 264 + case 5: 265 + return SC27XX_VOLT_RATIO(7, 29); 266 + case 7: 267 + case 9: 268 + return scale ? SC27XX_VOLT_RATIO(100, 125) : 269 + SC27XX_VOLT_RATIO(1, 1); 270 + case 14: 271 + return SC27XX_VOLT_RATIO(68, 900); 272 + case 16: 273 + return SC27XX_VOLT_RATIO(48, 100); 274 + case 19: 275 + return SC27XX_VOLT_RATIO(1, 3); 276 + default: 277 + return SC27XX_VOLT_RATIO(1, 1); 278 + } 279 + return SC27XX_VOLT_RATIO(1, 1); 280 + } 281 + 216 282 static int sc2731_adc_get_ratio(int channel, int scale) 217 283 { 218 284 switch (channel) { ··· 329 219 /* 330 220 * According to the datasheet set specific value on some channel. 331 221 */ 222 + static void sc2720_adc_scale_init(struct sc27xx_adc_data *data) 223 + { 224 + int i; 225 + 226 + for (i = 0; i < SC27XX_ADC_CHANNEL_MAX; i++) { 227 + switch (i) { 228 + case 5: 229 + data->channel_scale[i] = 3; 230 + break; 231 + case 7: 232 + case 9: 233 + data->channel_scale[i] = 2; 234 + break; 235 + case 13: 236 + data->channel_scale[i] = 1; 237 + break; 238 + case 19: 239 + case 30: 240 + case 31: 241 + data->channel_scale[i] = 3; 242 + break; 243 + default: 244 + data->channel_scale[i] = 0; 245 + break; 246 + } 247 + } 248 + } 249 + 332 250 static void sc2731_adc_scale_init(struct sc27xx_adc_data *data) 333 251 { 334 252 int i; ··· 379 241 static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, 380 242 int scale, int *val) 381 243 { 382 - int ret; 244 + int ret, ret_volref; 383 245 u32 tmp, value, status; 384 246 385 247 ret = hwspin_lock_timeout_raw(data->hwlock, SC27XX_ADC_HWLOCK_TIMEOUT); ··· 388 250 return ret; 389 251 } 390 252 253 + /* 254 + * According to the sc2721 chip data sheet, the reference voltage of 255 + * specific channel 30 and channel 31 in ADC module needs to be set from 256 + * the default 2.8v to 3.5v. 257 + */ 258 + if ((data->var_data->set_volref) && (channel == 30 || channel == 31)) { 259 + ret = regulator_set_voltage(data->volref, 260 + SC27XX_ADC_REFVOL_VDD35, 261 + SC27XX_ADC_REFVOL_VDD35); 262 + if (ret) { 263 + dev_err(data->dev, "failed to set the volref 3.5v\n"); 264 + goto unlock_adc; 265 + } 266 + } 267 + 391 268 ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, 392 269 SC27XX_ADC_EN, SC27XX_ADC_EN); 393 270 if (ret) 394 - goto unlock_adc; 271 + goto regulator_restore; 395 272 396 273 ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, 397 274 SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); ··· 456 303 disable_adc: 457 304 regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, 458 305 SC27XX_ADC_EN, 0); 306 + regulator_restore: 307 + if ((data->var_data->set_volref) && (channel == 30 || channel == 31)) { 308 + ret_volref = regulator_set_voltage(data->volref, 309 + SC27XX_ADC_REFVOL_VDD28, 310 + SC27XX_ADC_REFVOL_VDD28); 311 + if (ret_volref) { 312 + dev_err(data->dev, "failed to set the volref 2.8v,ret_volref = 0x%x\n", 313 + ret_volref); 314 + ret = ret || ret_volref; 315 + } 316 + } 459 317 unlock_adc: 460 318 hwspin_unlock_raw(data->hwlock); 461 319 ··· 715 551 .sscale_cal = &sc2731_small_scale_graph_calib, 716 552 .init_scale = sc2731_adc_scale_init, 717 553 .get_ratio = sc2731_adc_get_ratio, 554 + .set_volref = false, 555 + }; 556 + 557 + static const struct sc27xx_adc_variant_data sc2721_data = { 558 + .module_en = SC2731_MODULE_EN, 559 + .clk_en = SC2721_ARM_CLK_EN, 560 + .scale_shift = SC2721_ADC_SCALE_SHIFT, 561 + .scale_mask = SC2721_ADC_SCALE_MASK, 562 + .bscale_cal = &sc2731_big_scale_graph_calib, 563 + .sscale_cal = &sc2731_small_scale_graph_calib, 564 + .init_scale = sc2731_adc_scale_init, 565 + .get_ratio = sc2721_adc_get_ratio, 566 + .set_volref = true, 567 + }; 568 + 569 + static const struct sc27xx_adc_variant_data sc2720_data = { 570 + .module_en = SC2731_MODULE_EN, 571 + .clk_en = SC2721_ARM_CLK_EN, 572 + .scale_shift = SC27XX_ADC_SCALE_SHIFT, 573 + .scale_mask = SC27XX_ADC_SCALE_MASK, 574 + .bscale_cal = &big_scale_graph_calib, 575 + .sscale_cal = &small_scale_graph_calib, 576 + .init_scale = sc2720_adc_scale_init, 577 + .get_ratio = sc2720_adc_get_ratio, 578 + .set_volref = false, 718 579 }; 719 580 720 581 static int sc27xx_adc_probe(struct platform_device *pdev) ··· 792 603 } 793 604 794 605 sc27xx_data->dev = dev; 606 + if (pdata->set_volref) { 607 + sc27xx_data->volref = devm_regulator_get(dev, "vref"); 608 + if (IS_ERR(sc27xx_data->volref)) { 609 + ret = PTR_ERR(sc27xx_data->volref); 610 + return dev_err_probe(dev, ret, "failed to get ADC volref\n"); 611 + } 612 + } 613 + 795 614 sc27xx_data->var_data = pdata; 796 615 sc27xx_data->var_data->init_scale(sc27xx_data); 797 616 ··· 829 632 830 633 static const struct of_device_id sc27xx_adc_of_match[] = { 831 634 { .compatible = "sprd,sc2731-adc", .data = &sc2731_data}, 635 + { .compatible = "sprd,sc2721-adc", .data = &sc2721_data}, 636 + { .compatible = "sprd,sc2720-adc", .data = &sc2720_data}, 832 637 { } 833 638 }; 834 639 MODULE_DEVICE_TABLE(of, sc27xx_adc_of_match);