/* SPDX-License-Identifier: GPL-2.0-only */ #include <device/mmio.h> #include <assert.h> #include <delay.h> #include <soc/clock.h> #include <soc/saradc.h> #include <stdint.h> #include <timer.h> struct rk3399_saradc_regs { u32 data; u32 stas; u32 ctrl; u32 dly_pu_soc; }; check_member(rk3399_saradc_regs, dly_pu_soc, 0xc); struct rk3399_saradc_regs *rk3399_saradc = (void *)SARADC_BASE; /* SARADC_STAS: conversion done */ #define ADC_STOP 0 /* SARADC_CTRL */ #define INT_EN (1 << 5) #define ADC_PWR_CTRL (1 << 3) #define ADC_CHN_SEL_MASK 7 #define ADC_CHN_SEL_SHIFT 0 /* SARADC_DATA, 10[0:9] bits */ #define DATA_MASK 0x3FF #define SARADC_HZ (4*MHz) #define SARADC_MAX_CHANNEL 6 #define SARADC_DELAY_PU (1 * 1000 * 1000 * 1000 / SARADC_HZ * 4) u32 get_saradc_value(u32 chn) { u32 adc_value; struct stopwatch sw; assert(chn < SARADC_MAX_CHANNEL); rkclk_configure_saradc(SARADC_HZ); /* power down adc converter */ clrbits32(&rk3399_saradc->ctrl, ADC_PWR_CTRL); /* select channel */ clrsetbits32(&rk3399_saradc->ctrl, ADC_CHN_SEL_MASK << ADC_CHN_SEL_SHIFT, chn << ADC_CHN_SEL_SHIFT); /* power up */ setbits32(&rk3399_saradc->ctrl, ADC_PWR_CTRL); udelay(SARADC_DELAY_PU); stopwatch_init_msecs_expire(&sw, 10); do { if (read32(&rk3399_saradc->stas) == ADC_STOP) { adc_value = read32(&rk3399_saradc->data) & DATA_MASK; return adc_value; } } while (!stopwatch_expired(&sw)); return -1; }