mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-27 09:11:49 +00:00
818 lines
23 KiB
Text
818 lines
23 KiB
Text
From 1c44b2c7ee26d4a3b6d6710181203bf3c8491a79 Mon Sep 17 00:00:00 2001
|
|
From: Chen-Yu Tsai <wens@csie.org>
|
|
Date: Wed, 20 Jun 2018 15:13:41 +0800
|
|
Subject: [PATCH 08/45] arm64: dts: allwinner: h6: Add LED device nodes for
|
|
Pine H64
|
|
|
|
The Pine H64 has 3 GPIO-controlled LEDs, which are labeled "heartbeat",
|
|
"link", and "status".
|
|
|
|
Add device nodes for them.
|
|
|
|
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
|
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
|
|
---
|
|
.../boot/dts/allwinner/sun50i-h6-pine-h64.dts | 19 +++++++++++++++++++
|
|
1 file changed, 19 insertions(+)
|
|
|
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
|
|
index b6f2d6b2ecae..2e97173c9204 100644
|
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
|
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
|
|
@@ -20,6 +20,25 @@
|
|
chosen {
|
|
stdout-path = "serial0:115200n8";
|
|
};
|
|
+
|
|
+ leds {
|
|
+ compatible = "gpio-leds";
|
|
+
|
|
+ heartbeat {
|
|
+ label = "pine-h64:green:heartbeat";
|
|
+ gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
|
|
+ };
|
|
+
|
|
+ link {
|
|
+ label = "pine-h64:white:link";
|
|
+ gpios = <&r_pio 0 3 GPIO_ACTIVE_HIGH>; /* PL3 */
|
|
+ };
|
|
+
|
|
+ status {
|
|
+ label = "pine-h64:blue:status";
|
|
+ gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
|
|
+ };
|
|
+ };
|
|
};
|
|
|
|
&r_i2c {
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 6bfc6aab9a9cd82578a7e782c83d04f4cf7fe6c4 Mon Sep 17 00:00:00 2001
|
|
From: Icenowy Zheng <icenowy@aosc.io>
|
|
Date: Fri, 27 Jul 2018 16:22:01 +0800
|
|
Subject: [PATCH 37/45] nvmem: sunxi-sid: add support for H6 SID
|
|
|
|
The SID controller in Allwinner H6 SoC is similar to the one in
|
|
Allwinner A64, except the size of the eFUSE is enlarged to 512 bytes
|
|
(4Kbit).
|
|
|
|
Add support for it.
|
|
|
|
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
|
---
|
|
.../devicetree/bindings/nvmem/allwinner,sunxi-sid.txt | 1 +
|
|
drivers/nvmem/sunxi_sid.c | 6 ++++++
|
|
2 files changed, 7 insertions(+)
|
|
|
|
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
|
|
index e319fe5e205a..332de580e321 100644
|
|
--- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
|
|
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
|
|
@@ -7,6 +7,7 @@ Required properties:
|
|
"allwinner,sun8i-a83t-sid"
|
|
"allwinner,sun8i-h3-sid"
|
|
"allwinner,sun50i-a64-sid"
|
|
+ "allwinner,sun50i-h6-sid"
|
|
|
|
- reg: Should contain registers location and length
|
|
|
|
diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c
|
|
index d020f89248fd..fa58c3574afa 100644
|
|
--- a/drivers/nvmem/sunxi_sid.c
|
|
+++ b/drivers/nvmem/sunxi_sid.c
|
|
@@ -232,11 +232,17 @@ static const struct sunxi_sid_cfg sun50i_a64_cfg = {
|
|
.size = 0x100,
|
|
};
|
|
|
|
+static const struct sunxi_sid_cfg sun50i_h6_cfg = {
|
|
+ .value_offset = 0x200,
|
|
+ .size = 0x200,
|
|
+};
|
|
+
|
|
static const struct of_device_id sunxi_sid_of_match[] = {
|
|
{ .compatible = "allwinner,sun4i-a10-sid", .data = &sun4i_a10_cfg },
|
|
{ .compatible = "allwinner,sun7i-a20-sid", .data = &sun7i_a20_cfg },
|
|
{ .compatible = "allwinner,sun8i-h3-sid", .data = &sun8i_h3_cfg },
|
|
{ .compatible = "allwinner,sun50i-a64-sid", .data = &sun50i_a64_cfg },
|
|
+ { .compatible = "allwinner,sun50i-h6-sid", .data = &sun50i_h6_cfg },
|
|
{/* sentinel */},
|
|
};
|
|
MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From de62065cf1b55e48049c44076500a32eac08fe2f Mon Sep 17 00:00:00 2001
|
|
From: Icenowy Zheng <icenowy@aosc.io>
|
|
Date: Fri, 27 Jul 2018 16:24:18 +0800
|
|
Subject: [PATCH 38/45] arm64: allwinner: dts: h6: add H6 SID device tree node
|
|
|
|
The Allwinner H6 SoC has a SID like previous Allwinner SoCs.
|
|
|
|
Add a device tree node for it.
|
|
|
|
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
|
---
|
|
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
index 1a8086476514..8e3c47c7c797 100644
|
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
@@ -174,6 +174,11 @@
|
|
#interrupt-cells = <3>;
|
|
};
|
|
|
|
+ sid: efuse@3006000 {
|
|
+ compatible = "allwinner,sun50i-h6-sid";
|
|
+ reg = <0x03006000 0x1000>;
|
|
+ };
|
|
+
|
|
pio: pinctrl@300b000 {
|
|
compatible = "allwinner,sun50i-h6-pinctrl";
|
|
reg = <0x0300b000 0x400>;
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 8cdaf449f2936b608862b0a0175dd05fb52233b1 Mon Sep 17 00:00:00 2001
|
|
From: Icenowy Zheng <icenowy@aosc.io>
|
|
Date: Fri, 27 Jul 2018 17:34:35 +0800
|
|
Subject: [PATCH 39/45] nvmem: sunxi-sid: fix endian
|
|
|
|
The data in the SID is stored as little endian. However, when accessing
|
|
the SID via sunxi-sid driver, it converts little endian to big endian at
|
|
4 byte border. This makes addressing sub-4-byte items in the SID wrong.
|
|
|
|
Fix the endian by read out the SID 4-byte words as little endian, not
|
|
big endian.
|
|
|
|
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
|
---
|
|
drivers/nvmem/sunxi_sid.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c
|
|
index fa58c3574afa..af30d62b1426 100644
|
|
--- a/drivers/nvmem/sunxi_sid.c
|
|
+++ b/drivers/nvmem/sunxi_sid.c
|
|
@@ -63,7 +63,7 @@ static u8 sunxi_sid_read_byte(const struct sunxi_sid *sid,
|
|
{
|
|
u32 sid_key;
|
|
|
|
- sid_key = ioread32be(sid->base + round_down(offset, 4));
|
|
+ sid_key = readl(sid->base + round_down(offset, 4));
|
|
sid_key >>= (offset % 4) * 8;
|
|
|
|
return sid_key; /* Only return the last byte */
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From e7690d51c51dd6c97475bef2b207244d3a5f91b3 Mon Sep 17 00:00:00 2001
|
|
From: Icenowy Zheng <icenowy@aosc.io>
|
|
Date: Fri, 27 Jul 2018 16:18:35 +0800
|
|
Subject: [PATCH 40/45] sun50i-h6-ths
|
|
|
|
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
|
---
|
|
drivers/thermal/Kconfig | 11 +
|
|
drivers/thermal/Makefile | 1 +
|
|
drivers/thermal/sun50i_h6_ths.c | 365 ++++++++++++++++++++++++++++++++
|
|
3 files changed, 377 insertions(+)
|
|
create mode 100644 drivers/thermal/sun50i_h6_ths.c
|
|
|
|
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
|
|
index 82979880f985..1b302248633a 100644
|
|
--- a/drivers/thermal/Kconfig
|
|
+++ b/drivers/thermal/Kconfig
|
|
@@ -415,6 +415,17 @@ config MTK_THERMAL
|
|
Enable this option if you want to have support for thermal management
|
|
controller present in Mediatek SoCs
|
|
|
|
+config SUN50I_H6_THS
|
|
+ tristate "Thermal sensor driver for Allwinner H6"
|
|
+ depends on ARCH_SUNXI || COMPILE_TEST
|
|
+ depends on HAS_IOMEM
|
|
+ depends on NVMEM
|
|
+ depends on OF
|
|
+ depends on RESET_CONTROLLER
|
|
+ help
|
|
+ Enable this option if you want to have support for thermal reporting
|
|
+ on Allwinner H6.
|
|
+
|
|
menu "Broadcom thermal drivers"
|
|
depends on ARCH_BCM || ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
|
|
source "drivers/thermal/broadcom/Kconfig"
|
|
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
|
|
index 610344eb3e03..bdc5ba49f170 100644
|
|
--- a/drivers/thermal/Makefile
|
|
+++ b/drivers/thermal/Makefile
|
|
@@ -58,6 +58,7 @@ obj-$(CONFIG_QCOM_TSENS) += qcom/
|
|
obj-y += tegra/
|
|
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
|
|
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
|
|
+obj-$(CONFIG_SUN50I_H6_THS) += sun50i_h6_ths.o
|
|
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
|
|
obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
|
|
obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o
|
|
diff --git a/drivers/thermal/sun50i_h6_ths.c b/drivers/thermal/sun50i_h6_ths.c
|
|
new file mode 100644
|
|
index 000000000000..ad3c5f3e47c7
|
|
--- /dev/null
|
|
+++ b/drivers/thermal/sun50i_h6_ths.c
|
|
@@ -0,0 +1,365 @@
|
|
+/*
|
|
+ * Thermal sensor driver for Allwinner H6
|
|
+ *
|
|
+ * Copyright (C) 2018 Icenowy Zheng
|
|
+ *
|
|
+ * Based on the work of Ondřej Jirman
|
|
+ * Based on the work of Josef Gajdusek <atx@atx.name>
|
|
+ *
|
|
+ * This software is licensed under the terms of the GNU General Public
|
|
+ * License version 2, as published by the Free Software Foundation, and
|
|
+ * may be copied, distributed, and modified under those terms.
|
|
+ *
|
|
+ * 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 <linux/clk.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/io.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/nvmem-consumer.h>
|
|
+#include <linux/of_device.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/reset.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/thermal.h>
|
|
+#include <linux/printk.h>
|
|
+
|
|
+#define THS_H6_MAX_SENSOR_NUM 4
|
|
+
|
|
+#define THS_H6_CTRL0 0x00
|
|
+#define THS_H6_CTRL2 0x04
|
|
+#define THS_H6_PER 0x08
|
|
+#define THS_H6_DATA_INT_CTRL 0x10
|
|
+#define THS_H6_DATA_INT_STAT 0x20
|
|
+#define THS_H6_FILTER 0x30
|
|
+#define THS_H6_CDATA(n) (0xa0 + 4 * (n))
|
|
+#define THS_H6_DATA(n) (0xc0 + 4 * (n))
|
|
+
|
|
+#define THS_H6_CTRL0_SENSOR_ACQ0(x) ((x) << 16)
|
|
+#define THS_H6_CTRL2_SENSE_EN(n) BIT(0 + (n))
|
|
+#define THS_H6_PER_THERMAL_PER(x) ((x) << 12)
|
|
+#define THS_H6_INT_CTRL_DATA_IRQ_EN(n) BIT(0 + (n))
|
|
+#define THS_H6_STAT_DATA_IRQ_STS(n) BIT(0 + (n))
|
|
+#define THS_H6_FILTER_TYPE(x) ((x) << 0)
|
|
+#define THS_H6_FILTER_EN BIT(2)
|
|
+
|
|
+#define THS_H6_CLK_IN 240000000 /* Hz */
|
|
+#define THS_H6_DATA_PERIOD 10 /* ms */
|
|
+
|
|
+#define THS_H6_FILTER_TYPE_VALUE 2 /* average over 2^(n+1) samples */
|
|
+#define THS_H6_FILTER_DIV (1 << (THS_H6_FILTER_TYPE_VALUE + 1))
|
|
+#define THS_H6_INT_CTRL_THERMAL_PER_VALUE \
|
|
+ (THS_H6_DATA_PERIOD * (THS_H6_CLK_IN / 1000) / THS_H6_FILTER_DIV / 4096 - 1)
|
|
+#define THS_H6_CTRL0_SENSOR_ACQ0_VALUE 0x1df /* 20us */
|
|
+#define THS_H6_CTRL0_UNK 0x0000002f
|
|
+
|
|
+#define THS_H6_CAL_FT_TEMP_MASK 0x0fff
|
|
+#define THS_H6_CAL_FT_TEMP_DEVIATION_EN 0x3000
|
|
+#define THS_H6_CAL_DEFAULT 0x800
|
|
+#define THS_H6_CAL_VAL_MASK 0xfff
|
|
+
|
|
+struct sun50i_h6_ths_data;
|
|
+
|
|
+struct sun50i_h6_ths_sensor {
|
|
+ struct sun50i_h6_ths_data *data;
|
|
+ int id;
|
|
+ struct thermal_zone_device *tzd;
|
|
+ u32 val;
|
|
+};
|
|
+
|
|
+struct sun50i_h6_ths_cfg {
|
|
+ int sensor_num;
|
|
+ int (*calc_temp)(u32 val);
|
|
+};
|
|
+
|
|
+struct sun50i_h6_ths_data {
|
|
+ struct reset_control *reset;
|
|
+ struct clk *busclk;
|
|
+ void __iomem *regs;
|
|
+ const struct sun50i_h6_ths_cfg *cfg;
|
|
+ struct nvmem_cell *calcell;
|
|
+ struct sun50i_h6_ths_sensor sensors[THS_H6_MAX_SENSOR_NUM];
|
|
+};
|
|
+
|
|
+static int sun50i_h6_ths_calc_temp(u32 val)
|
|
+{
|
|
+ return (187744 - (int)((val * 1000000) / 14882));
|
|
+}
|
|
+
|
|
+static u16 sun50i_h6_ths_recalc_reg(u32 temp)
|
|
+{
|
|
+ return (u16)(2794 - temp * 14882 / 1000000);
|
|
+}
|
|
+
|
|
+static int sun50i_h6_ths_get_temp(void *_data, int *out)
|
|
+{
|
|
+ struct sun50i_h6_ths_sensor *sensor = _data;
|
|
+
|
|
+ if (sensor->val == 0)
|
|
+ return -EBUSY;
|
|
+
|
|
+ /* Formula and parameters from the Allwinner 3.4 kernel */
|
|
+ *out = sensor->data->cfg->calc_temp(sensor->val);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static irqreturn_t sun50i_h6_ths_irq_thread(int irq, void *_data)
|
|
+{
|
|
+ struct sun50i_h6_ths_data *data = _data;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < data->cfg->sensor_num; i++) {
|
|
+ if (!(readl(data->regs + THS_H6_DATA_INT_STAT) &
|
|
+ THS_H6_STAT_DATA_IRQ_STS(i)))
|
|
+ continue;
|
|
+
|
|
+ writel(THS_H6_STAT_DATA_IRQ_STS(i),
|
|
+ data->regs + THS_H6_DATA_INT_STAT);
|
|
+
|
|
+ data->sensors[i].val = readl(data->regs + THS_H6_DATA(i));
|
|
+ if (data->sensors[i].val)
|
|
+ thermal_zone_device_update(data->sensors[i].tzd,
|
|
+ THERMAL_EVENT_TEMP_SAMPLE);
|
|
+ }
|
|
+
|
|
+ return IRQ_HANDLED;
|
|
+}
|
|
+
|
|
+static void sun50i_h6_ths_init(struct sun50i_h6_ths_data *data)
|
|
+{
|
|
+ u32 val;
|
|
+ int i;
|
|
+
|
|
+ writel(THS_H6_CTRL0_SENSOR_ACQ0(THS_H6_CTRL0_SENSOR_ACQ0_VALUE) |
|
|
+ THS_H6_CTRL0_UNK, data->regs + THS_H6_CTRL0);
|
|
+ writel(THS_H6_FILTER_EN | THS_H6_FILTER_TYPE(THS_H6_FILTER_TYPE_VALUE),
|
|
+ data->regs + THS_H6_FILTER);
|
|
+
|
|
+ val = 0;
|
|
+ for (i = 0; i < data->cfg->sensor_num; i++)
|
|
+ val |= THS_H6_CTRL2_SENSE_EN(i);
|
|
+ writel(val, data->regs + THS_H6_CTRL2);
|
|
+
|
|
+ val = THS_H6_PER_THERMAL_PER(THS_H6_INT_CTRL_THERMAL_PER_VALUE);
|
|
+ writel(val, data->regs + THS_H6_PER);
|
|
+
|
|
+ val = 0;
|
|
+ for (i = 0; i < data->cfg->sensor_num; i++)
|
|
+ val |= THS_H6_INT_CTRL_DATA_IRQ_EN(i);
|
|
+ writel(val, data->regs + THS_H6_DATA_INT_CTRL);
|
|
+}
|
|
+
|
|
+static const struct thermal_zone_of_device_ops sun50i_h6_ths_thermal_ops = {
|
|
+ .get_temp = sun50i_h6_ths_get_temp,
|
|
+};
|
|
+
|
|
+static int sun50i_h6_ths_calibrate(struct sun50i_h6_ths_data *data)
|
|
+{
|
|
+ u16 *caldata;
|
|
+ size_t callen;
|
|
+ int i;
|
|
+ int ft_temp;
|
|
+ s16 ft_temp_orig_reg, diff, cal_val;
|
|
+ u32 reg_val;
|
|
+
|
|
+ caldata = nvmem_cell_read(data->calcell, &callen);
|
|
+ if (IS_ERR(caldata))
|
|
+ return PTR_ERR(caldata);
|
|
+
|
|
+ if (callen < 2 + 2 * data->cfg->sensor_num)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!caldata[0])
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * The calbration data on H6 is stored as temperature-value
|
|
+ * pair when being filled at factory test stage.
|
|
+ * The unit of stored FT temperature is 0.1 degreee celusis.
|
|
+ */
|
|
+ ft_temp = (caldata[0] & THS_H6_CAL_FT_TEMP_MASK) * 100;
|
|
+ ft_temp_orig_reg = sun50i_h6_ths_recalc_reg(ft_temp);
|
|
+
|
|
+ for (i = 0; i < data->cfg->sensor_num; i++)
|
|
+ {
|
|
+ diff = (ft_temp_orig_reg - (s16)caldata[1 + i]);
|
|
+ cal_val = THS_H6_CAL_DEFAULT - diff;
|
|
+
|
|
+ if (cal_val & ~THS_H6_CAL_VAL_MASK) {
|
|
+ pr_warn("Faulty thermal sensor %d calibration value, beyond the valid range.\n", i);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (i % 2) {
|
|
+ reg_val = readl(data->regs + THS_H6_CDATA(i / 2));
|
|
+ reg_val &= 0xffff;
|
|
+ reg_val |= cal_val << 16;
|
|
+ writel(reg_val, data->regs + THS_H6_CDATA(i / 2));
|
|
+ } else {
|
|
+ writel(cal_val, data->regs + THS_H6_CDATA(i / 2));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ kfree(caldata);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int sun50i_h6_ths_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct sun50i_h6_ths_data *data;
|
|
+ struct resource *res;
|
|
+ int ret, irq, i;
|
|
+
|
|
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
|
+ if (!data)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ data->cfg = of_device_get_match_data(&pdev->dev);
|
|
+ if (!data->cfg)
|
|
+ return -EINVAL;
|
|
+
|
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ if (!res) {
|
|
+ dev_err(&pdev->dev, "no memory resources defined\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ data->regs = devm_ioremap_resource(&pdev->dev, res);
|
|
+ if (IS_ERR(data->regs)) {
|
|
+ ret = PTR_ERR(data->regs);
|
|
+ dev_err(&pdev->dev, "failed to ioremap THS registers: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ irq = platform_get_irq(pdev, 0);
|
|
+ if (irq < 0) {
|
|
+ dev_err(&pdev->dev, "failed to get IRQ: %d\n", irq);
|
|
+ return irq;
|
|
+ }
|
|
+
|
|
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
|
+ sun50i_h6_ths_irq_thread, IRQF_ONESHOT,
|
|
+ dev_name(&pdev->dev), data);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ data->busclk = devm_clk_get(&pdev->dev, "bus");
|
|
+ if (IS_ERR(data->busclk)) {
|
|
+ ret = PTR_ERR(data->busclk);
|
|
+ dev_err(&pdev->dev, "failed to get ahb clk: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ data->reset = devm_reset_control_get(&pdev->dev, NULL);
|
|
+ if (IS_ERR(data->reset)) {
|
|
+ ret = PTR_ERR(data->reset);
|
|
+ dev_err(&pdev->dev, "failed to get reset: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = reset_control_deassert(data->reset);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "reset deassert failed: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = clk_prepare_enable(data->busclk);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "failed to enable bus clk: %d\n", ret);
|
|
+ goto err_assert_reset;
|
|
+ }
|
|
+
|
|
+ data->calcell = devm_nvmem_cell_get(&pdev->dev, "calibration");
|
|
+ if (IS_ERR(data->calcell)) {
|
|
+ if (PTR_ERR(data->calcell) == -EPROBE_DEFER) {
|
|
+ ret = PTR_ERR(data->calcell);
|
|
+ goto err_disable_bus;
|
|
+ }
|
|
+ /*
|
|
+ * Even if the external calibration data stored in eFUSE is
|
|
+ * not accessible, the THS hardware can still work, although
|
|
+ * the data won't be so accurate.
|
|
+ * The default value of calibration register is 0x800 for
|
|
+ * every sensor, and the calibration value is usually 0x7xx
|
|
+ * or 0x8xx, so they won't be away from the default value
|
|
+ * for a lot.
|
|
+ * So here we do not return if the calibartion data is not
|
|
+ * available, except the probe needs deferring.
|
|
+ */
|
|
+ } else {
|
|
+ ret = sun50i_h6_ths_calibrate(data);
|
|
+ if (ret) {
|
|
+ /* Revert calibrating */
|
|
+ for (i = 0; i < data->cfg->sensor_num; i += 2) {
|
|
+ writew(THS_H6_CAL_DEFAULT,
|
|
+ data->regs + THS_H6_CDATA(i / 2));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < data->cfg->sensor_num; i++) {
|
|
+ data->sensors[i].data = data;
|
|
+ data->sensors[i].id = i;
|
|
+ data->sensors[i].tzd =
|
|
+ devm_thermal_zone_of_sensor_register(&pdev->dev,
|
|
+ i, &data->sensors[i], &sun50i_h6_ths_thermal_ops);
|
|
+ if (IS_ERR(data->sensors[i].tzd)) {
|
|
+ ret = PTR_ERR(data->sensors[i].tzd);
|
|
+ dev_err(&pdev->dev,
|
|
+ "failed to register thermal zone %d: %d\n",
|
|
+ i, ret);
|
|
+ goto err_disable_bus;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ sun50i_h6_ths_init(data);
|
|
+
|
|
+ platform_set_drvdata(pdev, data);
|
|
+ return 0;
|
|
+
|
|
+err_disable_bus:
|
|
+ clk_disable_unprepare(data->busclk);
|
|
+err_assert_reset:
|
|
+ reset_control_assert(data->reset);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int sun50i_h6_ths_remove(struct platform_device *pdev)
|
|
+{
|
|
+ struct sun50i_h6_ths_data *data = platform_get_drvdata(pdev);
|
|
+
|
|
+ reset_control_assert(data->reset);
|
|
+ clk_disable_unprepare(data->busclk);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct sun50i_h6_ths_cfg sun50i_h6_ths_cfg = {
|
|
+ .sensor_num = 2,
|
|
+ .calc_temp = sun50i_h6_ths_calc_temp,
|
|
+};
|
|
+
|
|
+static const struct of_device_id sun50i_h6_ths_id_table[] = {
|
|
+ { .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths_cfg },
|
|
+ { /* sentinel */ },
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, sun50i_h6_ths_id_table);
|
|
+
|
|
+static struct platform_driver sun50i_h6_ths_driver = {
|
|
+ .probe = sun50i_h6_ths_probe,
|
|
+ .remove = sun50i_h6_ths_remove,
|
|
+ .driver = {
|
|
+ .name = "sun50i_h6_ths",
|
|
+ .of_match_table = sun50i_h6_ths_id_table,
|
|
+ },
|
|
+};
|
|
+
|
|
+module_platform_driver(sun50i_h6_ths_driver);
|
|
+
|
|
+MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
|
|
+MODULE_DESCRIPTION("Thermal sensor driver for Allwinner H6");
|
|
+MODULE_LICENSE("GPL v2");
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From b2efe78569663e3188d712699209126a535df23d Mon Sep 17 00:00:00 2001
|
|
From: Icenowy Zheng <icenowy@aosc.io>
|
|
Date: Fri, 27 Jul 2018 16:18:42 +0800
|
|
Subject: [PATCH 41/45] basic ths dt
|
|
|
|
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
|
---
|
|
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 35 ++++++++++++++++++++
|
|
1 file changed, 35 insertions(+)
|
|
|
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
index 8e3c47c7c797..cf125ebd1c7b 100644
|
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
@@ -10,6 +10,7 @@
|
|
#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
|
|
#include <dt-bindings/reset/sun50i-h6-ccu.h>
|
|
#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
|
|
+#include <dt-bindings/thermal/thermal.h>
|
|
|
|
/ {
|
|
interrupt-parent = <&gic>;
|
|
@@ -177,6 +178,12 @@
|
|
sid: efuse@3006000 {
|
|
compatible = "allwinner,sun50i-h6-sid";
|
|
reg = <0x03006000 0x1000>;
|
|
+ #address-cells = <1>;
|
|
+ #size-cells = <1>;
|
|
+
|
|
+ ths_calib: thermal-sensor-calibration@14 {
|
|
+ reg = <0x14 0x6>;
|
|
+ };
|
|
};
|
|
|
|
pio: pinctrl@300b000 {
|
|
@@ -445,6 +452,18 @@
|
|
};
|
|
};
|
|
|
|
+ ths: ths@5070400 {
|
|
+ compatible = "allwinner,sun50i-h6-ths";
|
|
+ reg = <0x05070400 0x100>;
|
|
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
|
+ clocks = <&ccu CLK_BUS_THS>;
|
|
+ clock-names = "bus";
|
|
+ resets = <&ccu RST_BUS_THS>;
|
|
+ nvmem-cells = <&ths_calib>;
|
|
+ nvmem-cell-names = "calibration";
|
|
+ #thermal-sensor-cells = <1>;
|
|
+ };
|
|
+
|
|
r_ccu: clock@7010000 {
|
|
compatible = "allwinner,sun50i-h6-r-ccu";
|
|
reg = <0x07010000 0x400>;
|
|
@@ -495,4 +514,20 @@
|
|
#size-cells = <0>;
|
|
};
|
|
};
|
|
+
|
|
+ thermal-zones {
|
|
+ cpu_thermal {
|
|
+ /* milliseconds */
|
|
+ polling-delay-passive = <250>;
|
|
+ polling-delay = <1000>;
|
|
+ thermal-sensors = <&ths 0>;
|
|
+ };
|
|
+
|
|
+ gpu_thermal {
|
|
+ /* milliseconds */
|
|
+ polling-delay-passive = <250>;
|
|
+ polling-delay = <1000>;
|
|
+ thermal-sensors = <&ths 1>;
|
|
+ };
|
|
+ };
|
|
};
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 5568aa53d90402816fe45ce30f7aaa6e577810aa Mon Sep 17 00:00:00 2001
|
|
From: Icenowy Zheng <icenowy@aosc.io>
|
|
Date: Fri, 27 Jul 2018 19:19:28 +0800
|
|
Subject: [PATCH 43/45] arm64: allwinner: dts: h6: add CPU supply for Pine H64
|
|
|
|
The Pine H64, follows the reference design on the AXP805 DCDC
|
|
assignment, connects DCDCA (polyphased with DCDCB) to the ARM
|
|
cores' power supply.
|
|
|
|
Add this to the device tree, to enable voltage scaling.
|
|
|
|
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
|
---
|
|
arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 4 ++++
|
|
1 file changed, 4 insertions(+)
|
|
|
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
|
|
index 3c74cbed319b..fb45e68bc441 100644
|
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
|
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
|
|
@@ -92,6 +92,10 @@
|
|
};
|
|
};
|
|
|
|
+&cpu0 {
|
|
+ cpu-supply = <®_dcdca>;
|
|
+};
|
|
+
|
|
&mmc0 {
|
|
pinctrl-names = "default";
|
|
pinctrl-0 = <&mmc0_pins>;
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 6a83e3542e2ad0388f5ee5b9beb7774467ab08bd Mon Sep 17 00:00:00 2001
|
|
From: Icenowy Zheng <icenowy@aosc.io>
|
|
Date: Fri, 27 Jul 2018 19:28:31 +0800
|
|
Subject: [PATCH 44/45] bind trips
|
|
|
|
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
|
---
|
|
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 35 ++++++++++++++++++++
|
|
1 file changed, 35 insertions(+)
|
|
|
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
index 5cc72c943374..000a681fb515 100644
|
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
@@ -540,6 +540,41 @@
|
|
polling-delay-passive = <250>;
|
|
polling-delay = <1000>;
|
|
thermal-sensors = <&ths 0>;
|
|
+
|
|
+ cooling-maps {
|
|
+ map0 {
|
|
+ trip = <&cpu_alert0>;
|
|
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
|
+ };
|
|
+
|
|
+ map1 {
|
|
+ trip = <&cpu_alert1>;
|
|
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
|
+ };
|
|
+ };
|
|
+
|
|
+ trips {
|
|
+ cpu_alert0: cpu_alert0 {
|
|
+ /* milliCelsius */
|
|
+ temperature = <75000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+
|
|
+ cpu_alert1: cpu_alert1 {
|
|
+ /* milliCelsius */
|
|
+ temperature = <90000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "hot";
|
|
+ };
|
|
+
|
|
+ cpu_crit: cpu_crit {
|
|
+ /* milliCelsius */
|
|
+ temperature = <1000000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "critical";
|
|
+ };
|
|
+ };
|
|
};
|
|
|
|
gpu_thermal {
|
|
--
|
|
2.17.1
|
|
|
|
|
|
From 32a3eba2d813fb311430f2275ba1dbe73c37da73 Mon Sep 17 00:00:00 2001
|
|
From: Icenowy Zheng <icenowy@aosc.io>
|
|
Date: Fri, 27 Jul 2018 19:30:10 +0800
|
|
Subject: [PATCH 45/45] add extra opps
|
|
|
|
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
|
---
|
|
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 18 ++++++++++++++++++
|
|
1 file changed, 18 insertions(+)
|
|
|
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
index 000a681fb515..bec8c4a46ec7 100644
|
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
|
@@ -41,6 +41,30 @@
|
|
opp-microvolt = <880000>;
|
|
clock-latency-ns = <244144>; /* 8 32k periods */
|
|
};
|
|
+
|
|
+ opp-1008000000 {
|
|
+ opp-hz = /bits/ 64 <1008000000>;
|
|
+ opp-microvolt = <940000>;
|
|
+ clock-latency-ns = <244144>; /* 8 32k periods */
|
|
+ };
|
|
+
|
|
+ opp-1320000000 {
|
|
+ opp-hz = /bits/ 64 <1320000000>;
|
|
+ opp-microvolt = <1000000>;
|
|
+ clock-latency-ns = <244144>; /* 8 32k periods */
|
|
+ };
|
|
+
|
|
+ opp-1488000000 {
|
|
+ opp-hz = /bits/ 64 <1488000000>;
|
|
+ opp-microvolt = <1060000>;
|
|
+ clock-latency-ns = <244144>; /* 8 32k periods */
|
|
+ };
|
|
+
|
|
+ opp-1800000000 {
|
|
+ opp-hz = /bits/ 64 <1800000000>;
|
|
+ opp-microvolt = <1160000>;
|
|
+ clock-latency-ns = <244144>; /* 8 32k periods */
|
|
+ };
|
|
};
|
|
|
|
cpus {
|
|
--
|
|
2.17.1
|
|
|