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

iio: adc: sc27xx: structure adjustment and optimization

Introduce one variant device data structure to be compatible
with SC2731 PMIC since it has different scale and ratio calculation
and so on. also rename the SC27xx to SC2731 for some definition
and function.

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-5-gengcixi@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Cixi Geng and committed by
Jonathan Cameron
e4171388 5a7a184b

+76 -15
+76 -15
drivers/iio/adc/sc27xx_adc.c
··· 12 12 #include <linux/slab.h> 13 13 14 14 /* PMIC global registers definition */ 15 - #define SC27XX_MODULE_EN 0xc08 15 + #define SC2731_MODULE_EN 0xc08 16 16 #define SC27XX_MODULE_ADC_EN BIT(5) 17 - #define SC27XX_ARM_CLK_EN 0xc10 17 + #define SC2731_ARM_CLK_EN 0xc10 18 18 #define SC27XX_CLK_ADC_EN BIT(5) 19 19 #define SC27XX_CLK_ADC_CLK_EN BIT(6) 20 20 ··· 78 78 int channel_scale[SC27XX_ADC_CHANNEL_MAX]; 79 79 u32 base; 80 80 int irq; 81 + const struct sc27xx_adc_variant_data *var_data; 82 + }; 83 + 84 + /* 85 + * Since different PMICs of SC27xx series can have different 86 + * address and ratio, we should save ratio config and base 87 + * in the device data structure. 88 + */ 89 + struct sc27xx_adc_variant_data { 90 + u32 module_en; 91 + u32 clk_en; 92 + u32 scale_shift; 93 + u32 scale_mask; 94 + const struct sc27xx_adc_linear_graph *bscale_cal; 95 + const struct sc27xx_adc_linear_graph *sscale_cal; 96 + void (*init_scale)(struct sc27xx_adc_data *data); 97 + int (*get_ratio)(int channel, int scale); 81 98 }; 82 99 83 100 struct sc27xx_adc_linear_graph { ··· 147 130 size_t len; 148 131 149 132 if (big_scale) { 150 - calib_graph = &sc2731_big_scale_graph_calib; 133 + calib_graph = data->var_data->bscale_cal; 151 134 graph = &big_scale_graph; 152 135 cell_name = "big_scale_calib"; 153 136 } else { 154 - calib_graph = &sc2731_small_scale_graph_calib; 137 + calib_graph = data->var_data->sscale_cal; 155 138 graph = &small_scale_graph; 156 139 cell_name = "small_scale_calib"; 157 140 } ··· 177 160 return 0; 178 161 } 179 162 180 - static int sc27xx_adc_get_ratio(int channel, int scale) 163 + static int sc2731_adc_get_ratio(int channel, int scale) 181 164 { 182 165 switch (channel) { 183 166 case 1: ··· 200 183 return SC27XX_VOLT_RATIO(1, 1); 201 184 } 202 185 return SC27XX_VOLT_RATIO(1, 1); 186 + } 187 + 188 + /* 189 + * According to the datasheet set specific value on some channel. 190 + */ 191 + static void sc2731_adc_scale_init(struct sc27xx_adc_data *data) 192 + { 193 + int i; 194 + /* 195 + * In the current software design, SC2731 support 2 scales, 196 + * channels 5 uses big scale, others use smale. 197 + */ 198 + for (i = 0; i < SC27XX_ADC_CHANNEL_MAX; i++) { 199 + switch (i) { 200 + case 5: 201 + data->channel_scale[i] = 1; 202 + break; 203 + default: 204 + data->channel_scale[i] = 0; 205 + break; 206 + } 207 + } 203 208 } 204 209 205 210 static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, ··· 247 208 goto disable_adc; 248 209 249 210 /* Configure the channel id and scale */ 250 - tmp = (scale << SC27XX_ADC_SCALE_SHIFT) & SC27XX_ADC_SCALE_MASK; 211 + tmp = (scale << data->var_data->scale_shift) & data->var_data->scale_mask; 251 212 tmp |= channel & SC27XX_ADC_CHN_ID_MASK; 252 213 ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CH_CFG, 253 - SC27XX_ADC_CHN_ID_MASK | SC27XX_ADC_SCALE_MASK, 214 + SC27XX_ADC_CHN_ID_MASK | 215 + data->var_data->scale_mask, 254 216 tmp); 255 217 if (ret) 256 218 goto disable_adc; ··· 302 262 int channel, int scale, 303 263 u32 *div_numerator, u32 *div_denominator) 304 264 { 305 - u32 ratio = sc27xx_adc_get_ratio(channel, scale); 265 + u32 ratio; 306 266 267 + ratio = data->var_data->get_ratio(channel, scale); 307 268 *div_numerator = ratio >> SC27XX_RATIO_NUMERATOR_OFFSET; 308 269 *div_denominator = ratio & SC27XX_RATIO_DENOMINATOR_MASK; 309 270 } ··· 473 432 { 474 433 int ret; 475 434 476 - ret = regmap_update_bits(data->regmap, SC27XX_MODULE_EN, 435 + ret = regmap_update_bits(data->regmap, data->var_data->module_en, 477 436 SC27XX_MODULE_ADC_EN, SC27XX_MODULE_ADC_EN); 478 437 if (ret) 479 438 return ret; 480 439 481 440 /* Enable ADC work clock and controller clock */ 482 - ret = regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN, 441 + ret = regmap_update_bits(data->regmap, data->var_data->clk_en, 483 442 SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 484 443 SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN); 485 444 if (ret) ··· 497 456 return 0; 498 457 499 458 disable_clk: 500 - regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN, 459 + regmap_update_bits(data->regmap, data->var_data->clk_en, 501 460 SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0); 502 461 disable_adc: 503 - regmap_update_bits(data->regmap, SC27XX_MODULE_EN, 462 + regmap_update_bits(data->regmap, data->var_data->module_en, 504 463 SC27XX_MODULE_ADC_EN, 0); 505 464 506 465 return ret; ··· 511 470 struct sc27xx_adc_data *data = _data; 512 471 513 472 /* Disable ADC work clock and controller clock */ 514 - regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN, 473 + regmap_update_bits(data->regmap, data->var_data->clk_en, 515 474 SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0); 516 475 517 - regmap_update_bits(data->regmap, SC27XX_MODULE_EN, 476 + regmap_update_bits(data->regmap, data->var_data->module_en, 518 477 SC27XX_MODULE_ADC_EN, 0); 519 478 } 479 + 480 + static const struct sc27xx_adc_variant_data sc2731_data = { 481 + .module_en = SC2731_MODULE_EN, 482 + .clk_en = SC2731_ARM_CLK_EN, 483 + .scale_shift = SC27XX_ADC_SCALE_SHIFT, 484 + .scale_mask = SC27XX_ADC_SCALE_MASK, 485 + .bscale_cal = &sc2731_big_scale_graph_calib, 486 + .sscale_cal = &sc2731_small_scale_graph_calib, 487 + .init_scale = sc2731_adc_scale_init, 488 + .get_ratio = sc2731_adc_get_ratio, 489 + }; 520 490 521 491 static int sc27xx_adc_probe(struct platform_device *pdev) 522 492 { 523 493 struct device *dev = &pdev->dev; 524 494 struct device_node *np = dev->of_node; 525 495 struct sc27xx_adc_data *sc27xx_data; 496 + const struct sc27xx_adc_variant_data *pdata; 526 497 struct iio_dev *indio_dev; 527 498 int ret; 499 + 500 + pdata = of_device_get_match_data(dev); 501 + if (!pdata) { 502 + dev_err(dev, "No matching driver data found\n"); 503 + return -EINVAL; 504 + } 528 505 529 506 indio_dev = devm_iio_device_alloc(dev, sizeof(*sc27xx_data)); 530 507 if (!indio_dev) ··· 579 520 } 580 521 581 522 sc27xx_data->dev = dev; 523 + sc27xx_data->var_data = pdata; 524 + sc27xx_data->var_data->init_scale(sc27xx_data); 582 525 583 526 ret = sc27xx_adc_enable(sc27xx_data); 584 527 if (ret) { ··· 607 546 } 608 547 609 548 static const struct of_device_id sc27xx_adc_of_match[] = { 610 - { .compatible = "sprd,sc2731-adc", }, 549 + { .compatible = "sprd,sc2731-adc", .data = &sc2731_data}, 611 550 { } 612 551 }; 613 552 MODULE_DEVICE_TABLE(of, sc27xx_adc_of_match);