Hello,

i've written a short kernel module to readout the onchip thermal register 
of the A23 CPU.
Should also work on other Allwinner CPUs with thermal base register at 
0x01C25000.

Pls note that there are errors in the A23 User Manual, Page 248.
Allwinner is informed but no feedback so far.
The calculus of the T value is wrong by an offset of 0x10.
Also the bit numbering of the CTRL1 is wrong by one bit.

Tested with A20 CPU on cubietruck and kernel 3.4.103-sunxi7.
Compiles also under Kernel 4.1rc7 (but no Tests been done so far.)

It is my first kernel module and may be some find it also useful and could 
test in their setup if the module compiles and loads.

The results are output via /proc/a23_thermal. Value needs to be divided by 
100.

If a driver already exists pls let me know.

Regards
Heiko

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
>From 1dd6cceffdf4b12701c10aad8daf6c304b5bbfd3 Mon Sep 17 00:00:00 2001
From: Heiko Schroeter <[email protected]>
Date: Wed, 10 Jun 2015 12:29:00 +0200
Subject: [PATCH 1/1] arm: Allwinner CPU onchip temperature sensor readout to
 /proc/filesystem

Tested with A20 on cubieboard

Signed-off-by: Heiko Schroeter <[email protected]>
---
 drivers/thermal/Kconfig                   |   5 +
 drivers/thermal/Makefile                  |   1 +
 drivers/thermal/a23_thermal/Kconfig       |  15 +++
 drivers/thermal/a23_thermal/Makefile      |   5 +
 drivers/thermal/a23_thermal/a23_thermal.c | 119 ++++++++++++++++++
 drivers/thermal/a23_thermal/a23_thermal.h | 196 ++++++++++++++++++++++++++++++
 6 files changed, 341 insertions(+)
 create mode 100644 drivers/thermal/a23_thermal/Kconfig
 create mode 100644 drivers/thermal/a23_thermal/Makefile
 create mode 100644 drivers/thermal/a23_thermal/a23_thermal.c
 create mode 100644 drivers/thermal/a23_thermal/a23_thermal.h

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index af40db0..a6bf022 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -299,4 +299,9 @@ depends on ARCH_STI && OF
 source "drivers/thermal/st/Kconfig"
 endmenu
 
+menu "Alwinner CPU chip thermal driver"
+source "drivers/thermal/a23_thermal/Kconfig"
+endmenu
+
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index fa0dc48..1038de1 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/
 obj-$(CONFIG_INT340X_THERMAL)  += int340x_thermal/
 obj-$(CONFIG_ST_THERMAL)	+= st/
 obj-$(CONFIG_TEGRA_SOCTHERM)	+= tegra_soctherm.o
+obj-$(CONFIG_A23_THERMAL)       += a23_thermal/
diff --git a/drivers/thermal/a23_thermal/Kconfig b/drivers/thermal/a23_thermal/Kconfig
new file mode 100644
index 0000000..383f427
--- /dev/null
+++ b/drivers/thermal/a23_thermal/Kconfig
@@ -0,0 +1,15 @@
+#
+# Allwinner A23 Thermal device configuration
+#
+
+config A23_THERMAL
+	tristate "Allwinner A23 CPU devices"
+	depends on THERMAL && ARCH_SUN7I
+	---help---
+
+          A23 Arm Processor Thermal register access.
+          Might also work for other ARM CPUs.
+          Creates entry in procfs/allwinner_thermal.
+          Prints (CPU temperature in [C])*100 or EAGAIN to /procfs/a23_thermal.
+          Divide by 100 to convert to plain [C].
+
diff --git a/drivers/thermal/a23_thermal/Makefile b/drivers/thermal/a23_thermal/Makefile
new file mode 100644
index 0000000..384b1b2
--- /dev/null
+++ b/drivers/thermal/a23_thermal/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Allwinner device drivers.
+#
+
+obj-$(CONFIG_A23_THERMAL) += a23_thermal.o
diff --git a/drivers/thermal/a23_thermal/a23_thermal.c b/drivers/thermal/a23_thermal/a23_thermal.c
new file mode 100644
index 0000000..1ed2b2b
--- /dev/null
+++ b/drivers/thermal/a23_thermal/a23_thermal.c
@@ -0,0 +1,119 @@
+/*
+ * a23_thermal.c
+ * Thermal onchip readout for Allwinner ARM CPUs
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Heiko Schroeter <[email protected]>
+ *
+ */
+
+#include <linux/io.h>
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <linux/proc_fs.h>  /* for the proc filesystem */
+#include <linux/seq_file.h> /* for sequence files */
+
+#include "a23_thermal.h"
+
+
+/*
+ * Setup the A23 thermal registers with fixed values.
+ * TODO: Make this configurable for users via procfile
+ */
+static int
+a23_ths_setup(void) {
+
+	/* Setup THS registers */
+	a23_ths_regs->ctrl0 = (uint32_t) ((0x02 << A23_DATA_CLK_DIVIDER) |
+					  (0x05 << A23_FS_DIV) |
+					  (0xF8 << A23_TACQ));
+
+	a23_ths_regs->ctrl1 = (uint32_t) ((0x01 << A23_CHOP_TEMP_EN) |
+					  (0x01 << A23_DATA_EN));
+
+	a23_ths_regs->tpr   = (uint32_t) ((0x001 << A23_THS_EN) |
+					  (0xFF8 << A23_THS_PER));
+
+	return 0;
+}
+
+/* Get A23 temperature value and print to procfile */
+static int
+a23_ths_show(struct seq_file *m, void *v)
+{
+/* Init again in case something has changed */
+	a23_ths_setup();
+
+	/* Resource temporarily unavailable */
+	if (a23_ths_regs->fifos == 0x0)
+		return -EAGAIN;
+
+	/* Clear Int Flag */
+	a23_ths_regs->fifos = (uint32_t) (0x1 << A23_DATA_PENDING);
+
+/*
+ * Read THS_DATA
+ * Calculate Temperature in Celcius as:
+ * Error in datasheet A23 User Manual, Revision 1.0, Page 248.
+ * T  = ((THS_DATA - 1669 + 100)*16) [C].
+ * Divide Result by 100 for Celsius.
+ *
+ * Print Celsius * 100 to procfile.
+ */
+	seq_printf(m, "%u\n",
+		   (uint32_t) ((a23_ths_regs->data & A23_THS_DATA_MASK)
+			       - 1669 + 100) << 4);
+
+	return 0;
+}
+
+/* Open Procfile */
+static int
+a23_ths_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, a23_ths_show, NULL);
+}
+
+/* Procfile definition */
+static const struct
+file_operations a23_ths_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = a23_ths_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release
+};
+
+/* Init */
+static int __init
+a23_ths_init(void)
+{
+
+	if (!proc_create(A23_PROC_FILE_NAME, 0, NULL, &a23_ths_fops))
+		return -ENOMEM;
+
+	a23_ths_setup();
+
+	return 0;
+}
+
+/* Exit */
+static void __exit
+a23_ths_exit(void)
+{
+	remove_proc_entry(A23_PROC_FILE_NAME, NULL);
+}
+
+module_init(a23_ths_init);
+module_exit(a23_ths_exit);
+
+MODULE_LICENSE(A23_LICENSE);
+MODULE_VERSION(A23_HEADER_VERSION);
+MODULE_AUTHOR(A23_AUTHOR);
diff --git a/drivers/thermal/a23_thermal/a23_thermal.h b/drivers/thermal/a23_thermal/a23_thermal.h
new file mode 100644
index 0000000..3d18f9c
--- /dev/null
+++ b/drivers/thermal/a23_thermal/a23_thermal.h
@@ -0,0 +1,196 @@
+/*
+ * a23_thermal.h
+ * Thermal onchip readout for Allwinner A23 ARM CPUs and derivatives
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Heiko Schroeter <[email protected]>
+ *
+ * From A23 User Manual (Revision 1.0):
+ *
+ * 3.19 Thermal Sensor Controller
+ * 3.19.1 Overview
+ *
+ * The A23 supports thermal sensor controller to monitor the chip temperature.
+ *
+ * 3.19.2 Clock Tree and ADC Conversion Time
+ *
+ * A/D CONVERSION TIME
+ * When the clock source is 24MHz and the prescaler value M*N is 6,
+ * total 12-bit conversion time is as follows.
+ *
+ * CLK_IN = 24MHz/6 = 4MHz
+ *
+ * Conversion Time = 1/(4MHz/14Cycles) =3.50us
+ *
+ * If  ADC acquire  time  divider  is, then  TACQ  =1/(4MHz/6)  =  1.50us
+ * FS_TIME (configured by the FS_DIV register) bases on the summation
+ * of Conversion Time and TACQ. The FS_TIME  must be greater or equal
+ * than (TACQ  +  Conversion Time)
+ *
+ * FS_TIME >= TACQ + Conversion ITime=5.0us
+ *
+ * This  A/D converter was designed to operate at maximum 24MHz clock,
+ * and the conversion rate can go up to 1 MSPS.
+ *
+ *
+ * 3.19.3 Thermal Measurement
+ *   T  = (V[AL] - 1669)/6.25 Celsius degree
+ *   The V[AL] should read from thermal value register.
+ *   FORMULA WRONG; offset of 0x10 = 100/6.25 is missing
+ *   correct: T = (V[al] - 1669 + 100)*16 / 100
+ *
+ * 3.19.4 Thermal Sensor Controller Register List
+ * Module Name      Base Address
+ * THS              0x01C25000
+ *
+ * Register Name    Offset        Description
+ * THS_CTRL0        0x00          THS Control Register0
+ * THS_CTRL1        0x04          THS Control Register1
+ * THS_DATA_PENDING 0x14          THS Data Status
+ * THS_PER          0x18          THS Period Register
+ * THS_DATA         0x20          THS Data Register
+ *
+ * 3.19.5 Thermal Sensor Controller Register Description
+ * THS CONTROL REGISTER 0
+ *
+ * Offset:  0x00  Register Name: THS_CTRL0
+ * Bit      Read/     Default/    Description
+ *          Write     Hex
+ * 31:24    R/W       0xF         DATA_FIRST_DLY.
+ *                                DATA  First Convert Delay Time(T_FCDT)setting.
+ *                                Based on Data First Convert Delay Mode
+ *                                select (Bit 23).
+ *                                T_FCDT = DATA_FIRST_DLY * DATA_FIRST_DLY_MODE
+ * 23       R/W       0x1         DATA_FIRST_DLY_MODE.
+ *                                TDATA First Convert Delay Mode Select.
+ *                                0: CLK_IN/16
+ *                                1: CLK_IN/16*256
+ * 22      /          /           /
+ * 21:20   R/W        0x0         DATA_CLK_DIVIDER.
+ *                                DATA Clock Divider(CLK_IN).
+ *                                00: CLK/2
+ *                                01: CLK/3
+ *                                10: CLK/6
+ *                                11: CLK/1
+ * 19:16   R/W        0x0         FS_DIV.
+ *                                DATA Sample Frequency Divider.
+ *                                0000: CLK_IN/(2 power (20-n))
+ *                                0001: CLK_IN/(2 power (20-n))
+ *                                ....
+ *                                1111: CLK_IN/32
+ * 15:0    R/W        0x0         TACQ.
+ *                                DATA acquire time.
+ *                                CLK_IN/(16*(N+1))
+ *
+ * THS CONTROL REGISTER 1
+ * !! ATTENTION: ERROR in DATASHEET !!
+ * First HEX Value should be BITPOS 0-3 and not 0-4 !
+ * Offset: 0x04 Register Name: THS_CTRL1
+ * Bit      Read/     Default/    Description
+ *          Write     Hex
+ * 31:8     /         /           /
+ * 7        R/W       0x1         CHOP_TEMP_EN.
+ *                                Chop temperature calibration enable.
+ *                                0: Disable
+ *                                1: Enable
+ * 6:5      /         /           /
+ * 4        R/W       0x0         DATA_EN.
+ *                                DATA Function Enable.
+ *                                0: Disable
+ *                                1: Enable
+ * 3:0      R/W       0x1         /
+ *
+ * THS DATA STATUS REGISTER
+ * Offset: 0x14 Register Name: DATA_FIFOS
+ * Bit      Read/     Default/    Description
+ *          Write     Hex
+ * 31:19    /         /           /
+ * 18       R/W       0x0         THS_DATA_PENDING.
+ *                                Thermal sensor data pending.
+ *                                0: No Pending
+ *                                1: Thermal sensor data Pending
+ *                                Write ‘1’ to clear this interrupt or
+ *                                automatic clear if data pending
+ *                                condition fails.
+ *
+ * THS PERIOD REGISTER
+ * Offset: 0x18 Register Name: THS_TPR
+ * Bit      Read/     Default/    Description
+ *          Write     Hex
+ * 31:16    /         /           /
+ * 16       R/W       0x0         THS_EN.
+ *                                Thermal sensor enable.
+ * 15:0     R/W       0x0         THS_PER.
+ *                                Thermal sensor Period.
+ *                                4096*(1/clk_in)
+ *
+ * THS DATA REGISTER
+ * Offset: 0x20 Register Name: THS_DATA
+ * Bit      Read/     Default/    Description
+ *          Write     Hex         Default: 0x0000_0000
+ * 31:12    /         /           /
+ * 11:0     R         0x0         THS_DATA.
+ *                                Thermal sensor data.
+ */
+
+#ifndef __A23_THERMAL_H
+#define __A23_THERMAL_H
+
+/* ARM 23 Thermal Registers */
+#define A23_THS_BASE         0xF1C25000   /* Base */
+#define A23_THS_CTRL0        ((void *) (A23_THS_BASE + 0x00))
+#define A23_THS_CTRL1        ((void *) (A23_THS_BASE + 0x04))
+#define A23_THS_FIFOS        ((void *) (A23_THS_BASE + 0x14))
+#define A23_THS_TPR          ((void *) (A23_THS_BASE + 0x18))
+#define A23_THS_DATA         ((void *) (A23_THS_BASE + 0x20))
+
+/* Bitpositions in THS Registers */
+/* A23_THS_CTRL0 */
+#define A23_DATA_FIRST_DLY      24
+#define A23_DATA_FIRST_DLY_MODE 23
+#define A23_DATA_CLK_DIVIDER    20
+#define A23_FS_DIV              16
+#define A23_TACQ                 0
+
+/* A23_THS_CTRL1 */
+#define A23_CHOP_TEMP_EN     7
+#define A23_DATA_EN          4
+
+/* A23_THS_FIFOS */
+#define A23_DATA_PENDING    18
+
+/* A23_THS_TPR */
+#define A23_THS_EN          16
+#define A23_THS_PER          0
+
+/* A23_THS_DATA */
+#define A23_THS_DATA_MASK    0xFFF
+
+/* Thermal Register Structure for A23 et al */
+struct thermal_regs {
+	uint32_t ctrl0;      /* offset 0x0 */
+	uint32_t ctrl1;      /* offset 0x4 */
+	uint32_t pad1[3];    /* offset 0x8->0x13 */
+	uint32_t fifos;      /* offset 0x14 */
+	uint32_t tpr;        /* offset 0x18 */
+	uint32_t pad2;       /* offset 0x1C */
+	uint32_t data;       /* offset 0x20 */
+};
+
+struct thermal_regs
+*a23_ths_regs = (struct thermal_regs *) A23_THS_BASE;
+
+
+#define A23_PROC_FILE_NAME  "a23_thermal"
+
+#define A23_LICENSE "GPL"
+#define A23_HEADER_VERSION  "1.0"
+#define A23_AUTHOR "Heiko Schroeter, maintainer"
+
+
+#endif /* __A23_THERMAL_H */
+
-- 
2.1.0

Reply via email to