Lines Matching +full:adc +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Aspeed AST2400/2500/2600 ADC
8 * ADC clock formula:
15 #include <linux/clk.h>
16 #include <linux/clk-provider.h>
45 * hardware logic in each version of ADC.
79 * When the sampling rate is too high, the ADC may not have enough charging
184 dev_warn(data->dev, "Couldn't find syscon node\n"); in aspeed_adc_set_trim_data()
185 return -EOPNOTSUPP; in aspeed_adc_set_trim_data()
190 dev_warn(data->dev, "Failed to get syscon regmap\n"); in aspeed_adc_set_trim_data()
191 return -EOPNOTSUPP; in aspeed_adc_set_trim_data()
193 if (data->model_data->trim_locate) { in aspeed_adc_set_trim_data()
194 if (regmap_read(scu, data->model_data->trim_locate->offset, in aspeed_adc_set_trim_data()
196 dev_warn(data->dev, in aspeed_adc_set_trim_data()
197 "Failed to get adc trimming data\n"); in aspeed_adc_set_trim_data()
202 (data->model_data->trim_locate->field)) >> in aspeed_adc_set_trim_data()
203 __ffs(data->model_data->trim_locate->field); in aspeed_adc_set_trim_data()
207 dev_dbg(data->dev, in aspeed_adc_set_trim_data()
209 trimming_val, data->model_data->trim_locate->offset, in aspeed_adc_set_trim_data()
210 data->model_data->trim_locate->field); in aspeed_adc_set_trim_data()
211 writel(trimming_val, data->base + ASPEED_REG_COMPENSATION_TRIM); in aspeed_adc_set_trim_data()
223 readl(data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_compensation()
230 * After that, the input voltage of ADC will force to half of the reference in aspeed_adc_compensation()
232 * value. We can get compensating value = 0x200 - ADC read raw value. in aspeed_adc_compensation()
237 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_compensation()
239 * After enable compensating sensing mode need to wait some time for ADC stable in aspeed_adc_compensation()
249 ndelay(data->sample_period_ns); in aspeed_adc_compensation()
250 adc_raw += readw(data->base + aspeed_adc_iio_channels[0].address); in aspeed_adc_compensation()
253 data->cv = BIT(ASPEED_RESOLUTION_BITS - 1) - adc_raw; in aspeed_adc_compensation()
255 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_compensation()
256 dev_dbg(data->dev, "Compensating value = %d\n", data->cv); in aspeed_adc_compensation()
265 if (rate < data->model_data->min_sampling_rate || in aspeed_adc_set_sampling_rate()
266 rate > data->model_data->max_sampling_rate) in aspeed_adc_set_sampling_rate()
267 return -EINVAL; in aspeed_adc_set_sampling_rate()
269 clk_set_rate(data->clk_scaler->clk, rate * ASPEED_CLOCKS_PER_SAMPLE); in aspeed_adc_set_sampling_rate()
270 rate = clk_get_rate(data->clk_scaler->clk); in aspeed_adc_set_sampling_rate()
271 data->sample_period_ns = DIV_ROUND_UP_ULL( in aspeed_adc_set_sampling_rate()
273 dev_dbg(data->dev, "Adc clock = %d sample period = %d ns", rate, in aspeed_adc_set_sampling_rate()
274 data->sample_period_ns); in aspeed_adc_set_sampling_rate()
288 if (data->battery_sensing && chan->channel == 7) { in aspeed_adc_read_raw()
290 readl(data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_read_raw()
295 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_read_raw()
297 * After enable battery sensing mode need to wait some time for adc stable in aspeed_adc_read_raw()
301 *val = readw(data->base + chan->address); in aspeed_adc_read_raw()
302 *val = (*val * data->battery_mode_gain.mult) / in aspeed_adc_read_raw()
303 data->battery_mode_gain.div; in aspeed_adc_read_raw()
306 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_read_raw()
308 *val = readw(data->base + chan->address); in aspeed_adc_read_raw()
312 if (data->battery_sensing && chan->channel == 7) in aspeed_adc_read_raw()
313 *val = (data->cv * data->battery_mode_gain.mult) / in aspeed_adc_read_raw()
314 data->battery_mode_gain.div; in aspeed_adc_read_raw()
316 *val = data->cv; in aspeed_adc_read_raw()
320 *val = data->vref_mv; in aspeed_adc_read_raw()
325 *val = clk_get_rate(data->clk_scaler->clk) / in aspeed_adc_read_raw()
330 return -EINVAL; in aspeed_adc_read_raw()
350 return -EPERM; in aspeed_adc_write_raw()
353 return -EINVAL; in aspeed_adc_write_raw()
364 return -EINVAL; in aspeed_adc_reg_access()
366 *readval = readl(data->base + reg); in aspeed_adc_reg_access()
379 struct clk_hw *clk = data; in aspeed_adc_unregister_fixed_divider() local
381 clk_hw_unregister_fixed_factor(clk); in aspeed_adc_unregister_fixed_divider()
393 struct clk *clk = data; in aspeed_adc_clk_disable_unprepare() local
395 clk_disable_unprepare(clk); in aspeed_adc_clk_disable_unprepare()
403 priv_data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_power_down()
412 if (data->model_data->vref_fixed_mv) { in aspeed_adc_vref_config()
413 data->vref_mv = data->model_data->vref_fixed_mv; in aspeed_adc_vref_config()
417 readl(data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_vref_config()
419 ret = devm_regulator_get_enable_read_voltage(data->dev, "vref"); in aspeed_adc_vref_config()
420 if (ret < 0 && ret != -ENODEV) in aspeed_adc_vref_config()
423 if (ret != -ENODEV) { in aspeed_adc_vref_config()
424 data->vref_mv = ret / 1000; in aspeed_adc_vref_config()
426 if ((data->vref_mv >= 1550) && (data->vref_mv <= 2700)) in aspeed_adc_vref_config()
431 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_vref_config()
432 else if ((data->vref_mv >= 900) && (data->vref_mv <= 1650)) in aspeed_adc_vref_config()
437 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_vref_config()
439 dev_err(data->dev, "Regulator voltage %d not support", in aspeed_adc_vref_config()
440 data->vref_mv); in aspeed_adc_vref_config()
441 return -EOPNOTSUPP; in aspeed_adc_vref_config()
444 data->vref_mv = 2500000; in aspeed_adc_vref_config()
445 of_property_read_u32(data->dev->of_node, in aspeed_adc_vref_config()
446 "aspeed,int-vref-microvolt", in aspeed_adc_vref_config()
447 &data->vref_mv); in aspeed_adc_vref_config()
449 data->vref_mv /= 1000; in aspeed_adc_vref_config()
450 if (data->vref_mv == 2500) in aspeed_adc_vref_config()
454 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_vref_config()
455 else if (data->vref_mv == 1200) in aspeed_adc_vref_config()
459 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_vref_config()
461 dev_err(data->dev, "Voltage %d not support", data->vref_mv); in aspeed_adc_vref_config()
462 return -EOPNOTSUPP; in aspeed_adc_vref_config()
478 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data)); in aspeed_adc_probe()
480 return -ENOMEM; in aspeed_adc_probe()
483 data->dev = &pdev->dev; in aspeed_adc_probe()
484 data->model_data = of_device_get_match_data(&pdev->dev); in aspeed_adc_probe()
487 data->base = devm_platform_ioremap_resource(pdev, 0); in aspeed_adc_probe()
488 if (IS_ERR(data->base)) in aspeed_adc_probe()
489 return PTR_ERR(data->base); in aspeed_adc_probe()
491 /* Register ADC clock prescaler with source specified by device tree. */ in aspeed_adc_probe()
492 spin_lock_init(&data->clk_lock); in aspeed_adc_probe()
494 of_clk_get_parent_name(pdev->dev.of_node, 0)); in aspeed_adc_probe()
495 snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-fixed-div", in aspeed_adc_probe()
496 data->model_data->model_name); in aspeed_adc_probe()
497 data->fixed_div_clk = clk_hw_register_fixed_factor( in aspeed_adc_probe()
498 &pdev->dev, clk_name, clk_parent_name, 0, 1, 2); in aspeed_adc_probe()
499 if (IS_ERR(data->fixed_div_clk)) in aspeed_adc_probe()
500 return PTR_ERR(data->fixed_div_clk); in aspeed_adc_probe()
502 ret = devm_add_action_or_reset(data->dev, in aspeed_adc_probe()
504 data->fixed_div_clk); in aspeed_adc_probe()
509 if (data->model_data->need_prescaler) { in aspeed_adc_probe()
510 snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-prescaler", in aspeed_adc_probe()
511 data->model_data->model_name); in aspeed_adc_probe()
512 data->clk_prescaler = devm_clk_hw_register_divider( in aspeed_adc_probe()
513 &pdev->dev, clk_name, clk_parent_name, 0, in aspeed_adc_probe()
514 data->base + ASPEED_REG_CLOCK_CONTROL, 17, 15, 0, in aspeed_adc_probe()
515 &data->clk_lock); in aspeed_adc_probe()
516 if (IS_ERR(data->clk_prescaler)) in aspeed_adc_probe()
517 return PTR_ERR(data->clk_prescaler); in aspeed_adc_probe()
523 * Register ADC clock scaler downstream from the prescaler. Allow rate in aspeed_adc_probe()
526 snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-scaler", in aspeed_adc_probe()
527 data->model_data->model_name); in aspeed_adc_probe()
528 data->clk_scaler = devm_clk_hw_register_divider( in aspeed_adc_probe()
529 &pdev->dev, clk_name, clk_parent_name, scaler_flags, in aspeed_adc_probe()
530 data->base + ASPEED_REG_CLOCK_CONTROL, 0, in aspeed_adc_probe()
531 data->model_data->scaler_bit_width, in aspeed_adc_probe()
532 data->model_data->need_prescaler ? CLK_DIVIDER_ONE_BASED : 0, in aspeed_adc_probe()
533 &data->clk_lock); in aspeed_adc_probe()
534 if (IS_ERR(data->clk_scaler)) in aspeed_adc_probe()
535 return PTR_ERR(data->clk_scaler); in aspeed_adc_probe()
537 data->rst = devm_reset_control_get_shared(&pdev->dev, NULL); in aspeed_adc_probe()
538 if (IS_ERR(data->rst)) { in aspeed_adc_probe()
539 dev_err(&pdev->dev, in aspeed_adc_probe()
541 return PTR_ERR(data->rst); in aspeed_adc_probe()
543 reset_control_deassert(data->rst); in aspeed_adc_probe()
545 ret = devm_add_action_or_reset(data->dev, aspeed_adc_reset_assert, in aspeed_adc_probe()
546 data->rst); in aspeed_adc_probe()
558 if (of_property_present(data->dev->of_node, "aspeed,battery-sensing")) { in aspeed_adc_probe()
559 if (data->model_data->bat_sense_sup) { in aspeed_adc_probe()
560 data->battery_sensing = 1; in aspeed_adc_probe()
561 if (readl(data->base + ASPEED_REG_ENGINE_CONTROL) & in aspeed_adc_probe()
563 data->battery_mode_gain.mult = 3; in aspeed_adc_probe()
564 data->battery_mode_gain.div = 1; in aspeed_adc_probe()
566 data->battery_mode_gain.mult = 3; in aspeed_adc_probe()
567 data->battery_mode_gain.div = 2; in aspeed_adc_probe()
570 dev_warn(&pdev->dev, in aspeed_adc_probe()
571 "Failed to enable battery-sensing mode\n"); in aspeed_adc_probe()
574 ret = clk_prepare_enable(data->clk_scaler->clk); in aspeed_adc_probe()
577 ret = devm_add_action_or_reset(data->dev, in aspeed_adc_probe()
579 data->clk_scaler->clk); in aspeed_adc_probe()
588 readl(data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_probe()
594 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_probe()
596 ret = devm_add_action_or_reset(data->dev, aspeed_adc_power_down, in aspeed_adc_probe()
601 if (data->model_data->wait_init_sequence) { in aspeed_adc_probe()
603 ret = readl_poll_timeout(data->base + ASPEED_REG_ENGINE_CONTROL, in aspeed_adc_probe()
616 readl(data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_probe()
619 data->base + ASPEED_REG_ENGINE_CONTROL); in aspeed_adc_probe()
621 indio_dev->name = data->model_data->model_name; in aspeed_adc_probe()
622 indio_dev->info = &aspeed_adc_iio_info; in aspeed_adc_probe()
623 indio_dev->modes = INDIO_DIRECT_MODE; in aspeed_adc_probe()
624 indio_dev->channels = data->battery_sensing ? in aspeed_adc_probe()
627 indio_dev->num_channels = data->model_data->num_channels; in aspeed_adc_probe()
629 ret = devm_iio_device_register(data->dev, indio_dev); in aspeed_adc_probe()
649 .model_name = "ast2400-adc",
659 .model_name = "ast2500-adc",
671 .model_name = "ast2600-adc0",
682 .model_name = "ast2600-adc1",
693 { .compatible = "aspeed,ast2400-adc", .data = &ast2400_model_data },
694 { .compatible = "aspeed,ast2500-adc", .data = &ast2500_model_data },
695 { .compatible = "aspeed,ast2600-adc0", .data = &ast2600_adc0_model_data },
696 { .compatible = "aspeed,ast2600-adc1", .data = &ast2600_adc1_model_data },
712 MODULE_DESCRIPTION("Aspeed AST2400/2500/2600 ADC Driver");