From f4181ce3b312b2113010403feb40fd3d179acad1 Mon Sep 17 00:00:00 2001 From: Shunqian Zheng Date: Fri, 6 May 2016 16:50:48 +0800 Subject: rockchip: rk3399: add tsadc driver This patch configures clock for tsadc and then makes it in automatic mode to generate TSHUT when CPU temperature is higer than 120 degree Celsius. BRANCH=none BUG=chrome-os-partner:52382,chrome-os-partner:51537 TEST=Set a lower tshut threshold(45C), run coreboot and check that coreboot reboot again and again. Change-Id: I0b070a059d2941f12d31fc3002e78ea083e70b13 Signed-off-by: Martin Roth Original-Commit-Id: 05107bd6a3430e31db216c247ff0213e12373390 Original-Change-Id: Iffe54d3b09080d0f1ff31e8b3020d69510f07c95 Original-Signed-off-by: Lin Huang Original-Signed-off-by: Shunqian Zheng Original-Reviewed-on: https://chromium-review.googlesource.com/342797 Original-Tested-by: Vadim Bendebury Original-Reviewed-by: Shelley Chen Reviewed-on: https://review.coreboot.org/14848 Tested-by: build bot (Jenkins) Reviewed-by: Vadim Bendebury --- src/soc/rockchip/rk3399/Makefile.inc | 1 + src/soc/rockchip/rk3399/clock.c | 22 +++++ src/soc/rockchip/rk3399/include/soc/clock.h | 1 + src/soc/rockchip/rk3399/include/soc/tsadc.h | 26 ++++++ src/soc/rockchip/rk3399/romstage.c | 2 + src/soc/rockchip/rk3399/tsadc.c | 139 ++++++++++++++++++++++++++++ 6 files changed, 191 insertions(+) create mode 100644 src/soc/rockchip/rk3399/include/soc/tsadc.h create mode 100644 src/soc/rockchip/rk3399/tsadc.c (limited to 'src') diff --git a/src/soc/rockchip/rk3399/Makefile.inc b/src/soc/rockchip/rk3399/Makefile.inc index 4d5091df76..9af451c08c 100644 --- a/src/soc/rockchip/rk3399/Makefile.inc +++ b/src/soc/rockchip/rk3399/Makefile.inc @@ -46,6 +46,7 @@ romstage-y += mmu_operations.c romstage-y += ../common/pwm.c romstage-y += timer.c romstage-y += romstage.c +romstage-y += tsadc.c ################################################################################ diff --git a/src/soc/rockchip/rk3399/clock.c b/src/soc/rockchip/rk3399/clock.c index 46c7a39006..53c6e30e5b 100644 --- a/src/soc/rockchip/rk3399/clock.c +++ b/src/soc/rockchip/rk3399/clock.c @@ -159,6 +159,13 @@ enum { CLK_SARADC_DIV_CON_MASK = 0xff, CLK_SARADC_DIV_CON_SHIFT = 8, + /* CLKSEL_CON27 */ + CLK_TSADC_SEL_X24M = 0x0, + CLK_TSADC_SEL_MASK = 1, + CLK_TSADC_SEL_SHIFT = 15, + CLK_TSADC_DIV_CON_MASK = 0x3ff, + CLK_TSADC_DIV_CON_SHIFT = 0, + /* CLKSEL_CON47 & CLKSEL_CON48 */ ACLK_VOP_PLL_SEL_MASK = 0x3, ACLK_VOP_PLL_SEL_SHIFT = 6, @@ -714,3 +721,18 @@ int rkclk_configure_vop_dclk(u32 vop_id, u32 dclk_hz) return 0; } + +void rkclk_configure_tsadc(unsigned int hz) +{ + int src_clk_div; + + /* use 24M as src clock */ + src_clk_div = OSC_HZ / hz; + assert((src_clk_div - 1 < 1024) && (src_clk_div * hz == OSC_HZ)); + + write32(&cru_ptr->clksel_con[27], RK_CLRSETBITS( + CLK_TSADC_DIV_CON_MASK << CLK_TSADC_DIV_CON_SHIFT | + CLK_TSADC_SEL_MASK << CLK_TSADC_SEL_SHIFT, + src_clk_div << CLK_TSADC_DIV_CON_SHIFT | + CLK_TSADC_SEL_X24M << CLK_TSADC_SEL_SHIFT)); +} diff --git a/src/soc/rockchip/rk3399/include/soc/clock.h b/src/soc/rockchip/rk3399/include/soc/clock.h index 65e2e74a57..3b60d547cf 100644 --- a/src/soc/rockchip/rk3399/include/soc/clock.h +++ b/src/soc/rockchip/rk3399/include/soc/clock.h @@ -108,6 +108,7 @@ void rkclk_configure_cpu(enum apll_l_frequencies apll_l_freq); void rkclk_configure_ddr(unsigned int hz); void rkclk_configure_saradc(unsigned int hz); void rkclk_configure_spi(unsigned int bus, unsigned int hz); +void rkclk_configure_tsadc(unsigned int hz); void rkclk_configure_vop_aclk(u32 vop_id, u32 aclk_hz); void rkclk_ddr_reset(u32 ch, u32 ctl, u32 phy); uint32_t rkclk_i2c_clock_for_bus(unsigned bus); diff --git a/src/soc/rockchip/rk3399/include/soc/tsadc.h b/src/soc/rockchip/rk3399/include/soc/tsadc.h new file mode 100644 index 0000000000..b1f617df75 --- /dev/null +++ b/src/soc/rockchip/rk3399/include/soc/tsadc.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __SOC_ROCKCHIP_RK3399_TSADC_H__ +#define __SOC_ROCKCHIP_RK3399_TSADC_H__ + +enum { + TSHUT_POL_HIGH = 1 << 8, + TSHUT_POL_LOW = 0 << 8 +}; + +void tsadc_init(uint32_t polarity); + +#endif diff --git a/src/soc/rockchip/rk3399/romstage.c b/src/soc/rockchip/rk3399/romstage.c index f22b8c9116..ae0264e828 100644 --- a/src/soc/rockchip/rk3399/romstage.c +++ b/src/soc/rockchip/rk3399/romstage.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,7 @@ static void init_dvs_outputs(void) void main(void) { console_init(); + tsadc_init(TSHUT_POL_HIGH); exception_init(); /* Init DVS to conservative values. */ diff --git a/src/soc/rockchip/rk3399/tsadc.c b/src/soc/rockchip/rk3399/tsadc.c new file mode 100644 index 0000000000..234cd23377 --- /dev/null +++ b/src/soc/rockchip/rk3399/tsadc.c @@ -0,0 +1,139 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#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 */ + clrbits_le32(&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 temprature + * 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 temprature coefficient */ + setbits_le32(&rk3399_tsadc->auto_con, Q_SEL | SRC0_EN); + udelay(100); + setbits_le32(&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); +} -- cgit v1.2.3