/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include struct rk3399_tsadc_regs { u32 user_con; u32 auto_con; u32 int_en; u32 int_pd; u32 reserved0[(0x20 - 0x10) / 4]; u32 data0; u32 data1; u32 data2; u32 data3; u32 comp0_int; u32 comp1_int; u32 comp2_int; u32 comp3_int; u32 comp0_shut; u32 comp1_shut; u32 comp2_shut; u32 comp3_shut; u32 reserved1[(0x60 - 0x50) / 4]; u32 hight_int_debounce; u32 hight_tshut_debounce; u32 auto_period; u32 auto_period_ht; }; check_member(rk3399_tsadc_regs, auto_period_ht, 0x6c); /* user_con */ #define ADC_POWER_CTRL (1 << 3) #define START_MODE (1 << 4) #define START_SHIFT 5 #define START_MASK 1 #define INTER_PD_SHIFT 6 #define INTER_PD_MASK 0x3f /* auto_con */ #define LAST_TSHUT (1 << 24) #define SRC3_EN (1 << 7) #define SRC2_EN (1 << 6) #define SRC1_EN (1 << 5) #define SRC0_EN (1 << 4) #define Q_SEL (1 << 1) #define AUTO_EN (1 << 0) /* int_en */ #define TSHUT_CRU_EN_SRC3 (1 << 11) #define TSHUT_CRU_EN_SRC2 (1 << 10) #define TSHUT_CRU_EN_SRC1 (1 << 9) #define TSHUT_CRU_EN_SRC0 (1 << 8) #define TSHUT_GPIO_EN_SRC3 (1 << 7) #define TSHUT_GPIO_EN_SRC2 (1 << 6) #define TSHUT_GPIO_EN_SRC1 (1 << 5) #define TSHUT_GPIO_EN_SRC0 (1 << 4) #define AUTO_PERIOD 187500 /* 250ms */ #define AUTO_DEBOUNCE 4 #define AUTO_PERIOD_HT 37500 /* 50ms */ #define AUTO_DEBOUNCE_HT 4 #define TSADC_CLOCK_HZ (750 * KHz) /* AD value, correspond to 120 degrees Celsius, * Please refer shut value table in: * https://patchwork.kernel.org/patch/8908411/ * A quick ref: * {573, 60000}, {599, 75000}, {616, 85000}, {633, 95000}, * {642, 100000}, {659, 110000}, {677, 120000}, {685, 125000} */ #define TSADC_SHUT_VALUE 677 #define GRF_TSADC_TSEN_PD0_ON RK_SETBITS(0) #define GRF_TSADC_TSEN_PD0_OFF RK_CLRBITS(0) #define GRF_SARADC_TSEN_ON RK_SETBITS(0) struct rk3399_tsadc_regs *rk3399_tsadc = (void *)TSADC_BASE; void tsadc_init(uint32_t polarity) { rkclk_configure_tsadc(TSADC_CLOCK_HZ); /* tsadc power sequence */ clrbits32(&rk3399_tsadc->user_con, ADC_POWER_CTRL); write32(&rk3399_grf->tsadc_testbit_l, GRF_TSADC_TSEN_PD0_ON); udelay(50); write32(&rk3399_grf->tsadc_testbit_l, GRF_TSADC_TSEN_PD0_OFF); udelay(20); write32(&rk3399_grf->saradc_testbit, GRF_SARADC_TSEN_ON); udelay(100); /* set the tshut polarity */ write32(&rk3399_tsadc->auto_con, polarity); /* setup the automatic mode: * AUTO_PERIOD: interleave between every two accessing of TSADC * AUTO_DEBOUNCE: only generate interrupt or TSHUT when temperature * is higher than COMP_INT for "debounce" times * AUTO_PERIOD_HT: the interleave between every two accessing after the * temperature is higher than COMP_SHUT or COMP_INT * AUTO_DEBOUNCE_HT: only generate interrupt or TSHUT when temperature * is higher than COMP_SHUT for "debounce" times. */ write32(&rk3399_tsadc->auto_period, AUTO_PERIOD); write32(&rk3399_tsadc->hight_int_debounce, AUTO_DEBOUNCE); write32(&rk3399_tsadc->auto_period_ht, AUTO_PERIOD_HT); write32(&rk3399_tsadc->hight_tshut_debounce, AUTO_DEBOUNCE_HT); /* Enable the src0, negative temperature coefficient */ setbits32(&rk3399_tsadc->auto_con, Q_SEL | SRC0_EN); udelay(100); setbits32(&rk3399_tsadc->auto_con, AUTO_EN); write32(&rk3399_tsadc->comp0_shut, TSADC_SHUT_VALUE); write32(&rk3399_tsadc->int_en, TSHUT_CRU_EN_SRC0 | TSHUT_GPIO_EN_SRC0); /* Set the tsadc_int pinmux */ write32(&rk3399_pmugrf->tsadc_int, IOMUX_TSADC_INT); }