Import first batch of sunxi64 patches

This commit is contained in:
zador-blood-stained 2017-05-06 11:47:22 +03:00
parent d8332dbe22
commit dd47a94472
6 changed files with 970 additions and 61 deletions

View File

@ -2442,6 +2442,7 @@ CONFIG_THERMAL_EMULATION=y
#
# ACPI INT340X thermal drivers
#
CONFIG_SUN8I_THS=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@ -2623,6 +2624,7 @@ CONFIG_REGULATOR_QCOM_SPMI=y
# CONFIG_REGULATOR_S2MPA01 is not set
CONFIG_REGULATOR_S2MPS11=y
# CONFIG_REGULATOR_S5M8767 is not set
CONFIG_REGULATOR_SY8106A=y
# CONFIG_REGULATOR_TPS51632 is not set
# CONFIG_REGULATOR_TPS62360 is not set
# CONFIG_REGULATOR_TPS65023 is not set
@ -3608,13 +3610,7 @@ CONFIG_SUNXI_CCU_NKMP=y
CONFIG_SUNXI_CCU_NM=y
CONFIG_SUNXI_CCU_MP=y
CONFIG_SUN50I_A64_CCU=y
# CONFIG_SUN5I_CCU is not set
# CONFIG_SUN6I_A31_CCU is not set
# CONFIG_SUN8I_A23_CCU is not set
# CONFIG_SUN8I_A33_CCU is not set
CONFIG_SUN8I_H3_CCU=y
# CONFIG_SUN8I_V3S_CCU is not set
# CONFIG_SUN9I_A80_CCU is not set
CONFIG_SUN8I_R_CCU=y
#

View File

@ -0,0 +1,340 @@
From d622c59b1a71f9e5e20663fae693b268fcb2d39b Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 25 Jun 2016 21:51:05 +0200
Subject: [PATCH] thermal: sun8i_ths: Add support for the thermal sensor on
Allwinner H3
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds support for the sun8i thermal sensor on
Allwinner H3 SoC.
Signed-off-by: Ondřej Jirman <megous@megous.com>
---
drivers/thermal/Kconfig | 7 ++
drivers/thermal/Makefile | 1 +
drivers/thermal/sun8i_ths.c | 239 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 247 insertions(+)
create mode 100644 drivers/thermal/sun8i_ths.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 776b3439..d46d97b 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -392,6 +392,13 @@ config MTK_THERMAL
Enable this option if you want to have support for thermal management
controller present in Mediatek SoCs
+config SUN8I_THS
+ tristate "Thermal sensor driver for Allwinner H3"
+ depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI)
+ depends on OF
+ help
+ Enable this to support thermal reporting on some newer Allwinner SoCs.
+
menu "Texas Instruments thermal drivers"
depends on ARCH_HAS_BANDGAP || COMPILE_TEST
depends on HAS_IOMEM
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 7adae20..2480dc5 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
+obj-$(CONFIG_SUN8I_THS) += sun8i_ths.o
diff --git a/drivers/thermal/sun8i_ths.c b/drivers/thermal/sun8i_ths.c
new file mode 100644
index 0000000..cfe7d10
--- /dev/null
+++ b/drivers/thermal/sun8i_ths.c
@@ -0,0 +1,239 @@
+/*
+ * Thermal sensor driver for Allwinner H3 SoC
+ *
+ * Copyright (C) 2016 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/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_H3_CTRL0 0x00
+#define THS_H3_CTRL2 0x40
+#define THS_H3_INT_CTRL 0x44
+#define THS_H3_STAT 0x48
+#define THS_H3_FILTER 0x70
+#define THS_H3_CDATA 0x74
+#define THS_H3_DATA 0x80
+
+#define THS_H3_CTRL0_SENSOR_ACQ0(x) (x)
+#define THS_H3_CTRL2_SENSE_EN BIT(0)
+#define THS_H3_CTRL2_SENSOR_ACQ1(x) ((x) << 16)
+#define THS_H3_INT_CTRL_DATA_IRQ_EN BIT(8)
+#define THS_H3_INT_CTRL_THERMAL_PER(x) ((x) << 12)
+#define THS_H3_STAT_DATA_IRQ_STS BIT(8)
+#define THS_H3_FILTER_TYPE(x) ((x) << 0)
+#define THS_H3_FILTER_EN BIT(2)
+
+#define THS_H3_CLK_IN 40000000 /* Hz */
+#define THS_H3_DATA_PERIOD 330 /* ms */
+
+#define THS_H3_FILTER_TYPE_VALUE 2 /* average over 2^(n+1) samples */
+#define THS_H3_FILTER_DIV (1 << (THS_H3_FILTER_TYPE_VALUE + 1))
+#define THS_H3_INT_CTRL_THERMAL_PER_VALUE \
+ (THS_H3_DATA_PERIOD * (THS_H3_CLK_IN / 1000) / THS_H3_FILTER_DIV / 4096 - 1)
+#define THS_H3_CTRL0_SENSOR_ACQ0_VALUE 0x3f /* 16us */
+#define THS_H3_CTRL2_SENSOR_ACQ1_VALUE 0x3f
+
+struct sun8i_ths_data {
+ struct reset_control *reset;
+ struct clk *clk;
+ struct clk *busclk;
+ void __iomem *regs;
+ struct thermal_zone_device *tzd;
+ u32 temp;
+};
+
+static int sun8i_ths_get_temp(void *_data, int *out)
+{
+ struct sun8i_ths_data *data = _data;
+
+ if (data->temp == 0)
+ return -EBUSY;
+
+ /* Formula and parameters from the Allwinner 3.4 kernel */
+ *out = 217000 - (int)((data->temp * 1000000) / 8253);
+ return 0;
+}
+
+static irqreturn_t sun8i_ths_irq_thread(int irq, void *_data)
+{
+ struct sun8i_ths_data *data = _data;
+
+ writel(THS_H3_STAT_DATA_IRQ_STS, data->regs + THS_H3_STAT);
+
+ data->temp = readl(data->regs + THS_H3_DATA);
+ if (data->temp)
+ thermal_zone_device_update(data->tzd, THERMAL_EVENT_TEMP_SAMPLE);
+
+ return IRQ_HANDLED;
+}
+
+static void sun8i_ths_h3_init(struct sun8i_ths_data *data)
+{
+ writel(THS_H3_CTRL0_SENSOR_ACQ0(THS_H3_CTRL0_SENSOR_ACQ0_VALUE),
+ data->regs + THS_H3_CTRL0);
+ writel(THS_H3_FILTER_EN | THS_H3_FILTER_TYPE(THS_H3_FILTER_TYPE_VALUE),
+ data->regs + THS_H3_FILTER);
+ writel(THS_H3_CTRL2_SENSOR_ACQ1(THS_H3_CTRL2_SENSOR_ACQ1_VALUE) |
+ THS_H3_CTRL2_SENSE_EN,
+ data->regs + THS_H3_CTRL2);
+ writel(THS_H3_INT_CTRL_THERMAL_PER(THS_H3_INT_CTRL_THERMAL_PER_VALUE) |
+ THS_H3_INT_CTRL_DATA_IRQ_EN,
+ data->regs + THS_H3_INT_CTRL);
+}
+
+static const struct thermal_zone_of_device_ops sun8i_ths_thermal_ops = {
+ .get_temp = sun8i_ths_get_temp,
+};
+
+static int sun8i_ths_probe(struct platform_device *pdev)
+{
+ struct sun8i_ths_data *data;
+ struct resource *res;
+ int ret;
+ int irq;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ 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,
+ sun8i_ths_irq_thread, IRQF_ONESHOT,
+ dev_name(&pdev->dev), data);
+ if (ret)
+ return ret;
+
+ data->busclk = devm_clk_get(&pdev->dev, "ahb");
+ 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->clk = devm_clk_get(&pdev->dev, "ths");
+ if (IS_ERR(data->clk)) {
+ ret = PTR_ERR(data->clk);
+ dev_err(&pdev->dev, "failed to get ths clk: %d\n", ret);
+ return ret;
+ }
+
+ data->reset = devm_reset_control_get(&pdev->dev, "ahb");
+ 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;
+ }
+
+ ret = clk_prepare_enable(data->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable ths clk: %d\n", ret);
+ goto err_disable_bus;
+ }
+
+ ret = clk_set_rate(data->clk, THS_H3_CLK_IN);
+ if (ret)
+ goto err_disable_ths;
+
+ data->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, data,
+ &sun8i_ths_thermal_ops);
+ if (IS_ERR(data->tzd)) {
+ ret = PTR_ERR(data->tzd);
+ dev_err(&pdev->dev, "failed to register thermal zone: %d\n",
+ ret);
+ goto err_disable_ths;
+ }
+
+ sun8i_ths_h3_init(data);
+
+ platform_set_drvdata(pdev, data);
+ return 0;
+
+err_disable_ths:
+ clk_disable_unprepare(data->clk);
+err_disable_bus:
+ clk_disable_unprepare(data->busclk);
+err_assert_reset:
+ reset_control_assert(data->reset);
+ return ret;
+}
+
+static int sun8i_ths_remove(struct platform_device *pdev)
+{
+ struct sun8i_ths_data *data = platform_get_drvdata(pdev);
+
+ reset_control_assert(data->reset);
+ clk_disable_unprepare(data->clk);
+ clk_disable_unprepare(data->busclk);
+ return 0;
+}
+
+static const struct of_device_id sun8i_ths_id_table[] = {
+ { .compatible = "allwinner,sun8i-h3-ths", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, sun8i_ths_id_table);
+
+static struct platform_driver sun8i_ths_driver = {
+ .probe = sun8i_ths_probe,
+ .remove = sun8i_ths_remove,
+ .driver = {
+ .name = "sun8i_ths",
+ .of_match_table = sun8i_ths_id_table,
+ },
+};
+
+module_platform_driver(sun8i_ths_driver);
+
+MODULE_AUTHOR("Ondřej Jirman <megous@megous.com>");
+MODULE_DESCRIPTION("Thermal sensor driver for Allwinner H3 SoC");
+MODULE_LICENSE("GPL v2");
From 71010833320fd2ffded4e7d6ee5e49902f6827c7 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 25 Jun 2016 00:02:04 +0200
Subject: [PATCH] dt-bindings: document sun8i_ths - H3 thermal sensor driver
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds the binding documentation for the
sun8i_ths driver. This is a driver for thermal sensor
found in Allwinner H3 SoC.
Signed-off-by: Ondřej Jirman <megous@megous.com>
---
.../devicetree/bindings/thermal/sun8i-ths.txt | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-ths.txt
diff --git a/Documentation/devicetree/bindings/thermal/sun8i-ths.txt b/Documentation/devicetree/bindings/thermal/sun8i-ths.txt
new file mode 100644
index 0000000..ba12881
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/sun8i-ths.txt
@@ -0,0 +1,24 @@
+* Thermal sensor driver for Allwinner H3 SoC
+
+Required properties:
+- compatible : "allwinner,sun8i-h3-ths"
+- reg : Address range of the thermal sensor registers
+- resets : Must contain phandles to reset controls matching the entries
+ of the names
+- reset-names : Must include the name "ahb"
+- clocks : Must contain phandles to clock controls matching the entries
+ of the names
+- clock-names : Must contain "ahb" for the bus gate and "ths" for the THS
+ clock
+
+Example:
+ths: ths@01c25000 {
+ #thermal-sensor-cells = <0>;
+ compatible = "allwinner,sun8i-h3-ths";
+ reg = <0x01c25000 0x400>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&bus_rst 136>;
+ reset-names = "ahb";
+ clocks = <&bus_gates 72>, <&ths_clk>;
+ clock-names = "ahb", "ths";
+};

View File

@ -97,7 +97,17 @@ diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f901..5ccd3490 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -312,6 +312,23 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
@@ -278,6 +278,9 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
# ---------------------------------------------------------------------------
DTC ?= $(objtree)/scripts/dtc/dtc
+# Overlay support
+DTC_FLAGS += -@ -Wno-unit_address_format
+
# Disable noisy checks by default
ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),)
DTC_FLAGS += -Wno-unit_address_vs_reg
@@ -312,6 +315,23 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
$(obj)/%.dtb: $(src)/%.dts FORCE
$(call if_changed_dep,dtc)

View File

@ -0,0 +1,271 @@
From 5bcc6066f1dfbbef937ca8584a0fba44bb1468f0 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 25 Jun 2016 02:13:50 +0200
Subject: [PATCH] regulator: SY8106A regulator driver
SY8106A is I2C attached single output voltage regulator
made by Silergy.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/regulator/Kconfig | 8 +-
drivers/regulator/Makefile | 2 +-
drivers/regulator/sy8106a-regulator.c | 167 ++++++++++++++++++++++++++++++++++
3 files changed, 175 insertions(+), 2 deletions(-)
create mode 100644 drivers/regulator/sy8106a-regulator.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index be06eb2..9c4b51e 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -727,6 +727,13 @@ config REGULATOR_STW481X_VMMC
This driver supports the internal VMMC regulator in the STw481x
PMIC chips.
+config REGULATOR_SY8106A
+ tristate "Silergy SY8106A"
+ depends on I2C && (OF || COMPILE_TEST)
+ select REGMAP_I2C
+ help
+ This driver provides support for SY8106A voltage regulator.
+
config REGULATOR_TPS51632
tristate "TI TPS51632 Power Regulator"
depends on I2C
@@ -886,4 +893,3 @@ config REGULATOR_WM8994
WM8994 CODEC.
endif
-
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index ef7725e..a829718 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
+obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
@@ -114,5 +115,4 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
-
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c
new file mode 100644
index 0000000..7274965
--- /dev/null
+++ b/drivers/regulator/sy8106a-regulator.c
@@ -0,0 +1,167 @@
+/*
+ * sy8106a-regulator.c - Regulator device driver for SY8106A
+ *
+ * Copyright (C) 2016 Ondřej Jirman <megous@megous.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define SY8106A_REG_VOUT1_SEL 0x01
+#define SY8106A_REG_VOUT_COM 0x02
+#define SY8106A_REG_VOUT1_SEL_MASK 0x7f
+#define SY8106A_DISABLE_REG BIT(0)
+#define SY8106A_GO_BIT BIT(7)
+
+struct sy8106a {
+ struct regulator_dev *rdev;
+ struct regmap *regmap;
+};
+
+static const struct regmap_config sy8106a_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int sy8106a_set_voltage_sel(struct regulator_dev *rdev, unsigned sel)
+{
+ /* We use our set_voltage_sel in order to avoid unnecessary I2C chatter,
+ * because the regulator_get_voltage_sel_regmap using apply_bit
+ * would perform 4 unnecessary transfers instead of one, increasing the
+ * chance of error.
+ */
+ return regmap_write(rdev->regmap, rdev->desc->vsel_reg,
+ sel | SY8106A_GO_BIT);
+}
+
+static const struct regulator_ops sy8106a_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_voltage_sel = sy8106a_set_voltage_sel,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+};
+
+/* Default limits measured in millivolts and milliamps */
+#define SY8106A_MIN_MV 680
+#define SY8106A_MAX_MV 1950
+#define SY8106A_STEP_MV 10
+
+static const struct regulator_desc sy8106a_reg = {
+ .name = "SY8106A",
+ .id = 0,
+ .ops = &sy8106a_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = ((SY8106A_MAX_MV - SY8106A_MIN_MV) / SY8106A_STEP_MV) + 1,
+ .min_uV = (SY8106A_MIN_MV * 1000),
+ .uV_step = (SY8106A_STEP_MV * 1000),
+ .vsel_reg = SY8106A_REG_VOUT1_SEL,
+ .vsel_mask = SY8106A_REG_VOUT1_SEL_MASK,
+ .enable_reg = SY8106A_REG_VOUT_COM,
+ .enable_mask = SY8106A_DISABLE_REG,
+ .disable_val = SY8106A_DISABLE_REG,
+ .enable_is_inverted = 1,
+ .owner = THIS_MODULE,
+};
+
+/*
+ * I2C driver interface functions
+ */
+static int sy8106a_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct sy8106a *chip;
+ struct device *dev = &i2c->dev;
+ struct regulator_dev *rdev = NULL;
+ struct regulator_config config = { };
+ unsigned int selector;
+ int error;
+
+ chip = devm_kzalloc(&i2c->dev, sizeof(struct sy8106a), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->regmap = devm_regmap_init_i2c(i2c, &sy8106a_regmap_config);
+ if (IS_ERR(chip->regmap)) {
+ error = PTR_ERR(chip->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ error);
+ return error;
+ }
+
+ config.dev = &i2c->dev;
+ config.regmap = chip->regmap;
+ config.driver_data = chip;
+
+ config.of_node = dev->of_node;
+ config.init_data = of_get_regulator_init_data(dev, dev->of_node, &sy8106a_reg);
+ if (!config.init_data) {
+ return -ENOMEM;
+ }
+
+ /* Probe regulator */
+ error = regmap_read(chip->regmap, SY8106A_REG_VOUT1_SEL, &selector);
+ if (error) {
+ dev_err(&i2c->dev, "Failed to read voltage at probe time: %d\n", error);
+ return error;
+ }
+
+ rdev = devm_regulator_register(&i2c->dev, &sy8106a_reg, &config);
+ if (IS_ERR(rdev)) {
+ error = PTR_ERR(rdev);
+ dev_err(&i2c->dev, "Failed to register SY8106A regulator: %d\n", error);
+ return error;
+ }
+
+ chip->rdev = rdev;
+
+ i2c_set_clientdata(i2c, chip);
+
+ return 0;
+}
+
+static const struct of_device_id sy8106a_i2c_of_match[] = {
+ { .compatible = "silergy,sy8106a" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sy8106a_i2c_of_match);
+
+static const struct i2c_device_id sy8106a_i2c_id[] = {
+ { "sy8106a", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id);
+
+static struct i2c_driver sy8106a_regulator_driver = {
+ .driver = {
+ .name = "sy8106a",
+ .of_match_table = of_match_ptr(sy8106a_i2c_of_match),
+ },
+ .probe = sy8106a_i2c_probe,
+ .id_table = sy8106a_i2c_id,
+};
+
+module_i2c_driver(sy8106a_regulator_driver);
+
+MODULE_AUTHOR("Ondřej Jirman <megous@megous.com>");
+MODULE_DESCRIPTION("Regulator device driver for Silergy SY8106A");
+MODULE_LICENSE("GPL v2");
From cbbe21d790a5a47e69238ed64d53acd36752d7ae Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 25 Jun 2016 02:20:08 +0200
Subject: [PATCH] dt-bindings: document SY8106A regulator driver
This patch adds the binding documentation for the
sy8106a regulator driver.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
.../bindings/regulator/sy8106a-regulator.txt | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt
diff --git a/Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt b/Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt
new file mode 100644
index 0000000..1e623a34
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt
@@ -0,0 +1,21 @@
+SY8106A Voltage regulator
+
+Required properties:
+- compatible: Must be "silergy,sy8106a"
+- reg: I2C slave address - must be <0x65>
+
+Any property defined as part of the core regulator binding, defined in
+regulator.txt, can also be used.
+
+Example:
+
+ sy8106a {
+ compatible = "silergy,sy8106a";
+ reg = <0x65>;
+ regulator-name = "sy8106a-vdd";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-ramp-delay = <200>;
+ regulator-boot-on;
+ regulator-always-on;
+ };

View File

@ -0,0 +1,346 @@
From 8ef4d5e976df3c15453b827e5fdcb4c3fb3598dd Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 24 Mar 2017 16:33:05 +0800
Subject: [PATCH] clk: sunxi-ng: use 1 as fallback for minimum multiplier
A zero multiplier does not make sense for clocks.
Use 1 as the minimum when a multiplier minimum isn't specified.
Fixes: 2beaa601c849 ("clk: sunxi-ng: Implement minimum for multipliers")
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/clk/sunxi-ng/ccu_nk.c | 8 ++++----
drivers/clk/sunxi-ng/ccu_nkm.c | 8 ++++----
drivers/clk/sunxi-ng/ccu_nkmp.c | 4 ++--
drivers/clk/sunxi-ng/ccu_nm.c | 2 +-
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c
index b9e9b8a..2485bda 100644
--- a/drivers/clk/sunxi-ng/ccu_nk.c
+++ b/drivers/clk/sunxi-ng/ccu_nk.c
@@ -102,9 +102,9 @@ static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate,
if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= nk->fixed_post_div;
- _nk.min_n = nk->n.min;
+ _nk.min_n = nk->n.min ?: 1;
_nk.max_n = nk->n.max ?: 1 << nk->n.width;
- _nk.min_k = nk->k.min;
+ _nk.min_k = nk->k.min ?: 1;
_nk.max_k = nk->k.max ?: 1 << nk->k.width;
ccu_nk_find_best(*parent_rate, rate, &_nk);
@@ -127,9 +127,9 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate = rate * nk->fixed_post_div;
- _nk.min_n = nk->n.min;
+ _nk.min_n = nk->n.min ?: 1;
_nk.max_n = nk->n.max ?: 1 << nk->n.width;
- _nk.min_k = nk->k.min;
+ _nk.min_k = nk->k.min ?: 1;
_nk.max_k = nk->k.max ?: 1 << nk->k.width;
ccu_nk_find_best(parent_rate, rate, &_nk);
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 71f81e9..cba84af 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -109,9 +109,9 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
struct ccu_nkm *nkm = data;
struct _ccu_nkm _nkm;
- _nkm.min_n = nkm->n.min;
+ _nkm.min_n = nkm->n.min ?: 1;
_nkm.max_n = nkm->n.max ?: 1 << nkm->n.width;
- _nkm.min_k = nkm->k.min;
+ _nkm.min_k = nkm->k.min ?: 1;
_nkm.max_k = nkm->k.max ?: 1 << nkm->k.width;
_nkm.min_m = 1;
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
@@ -138,9 +138,9 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags;
u32 reg;
- _nkm.min_n = nkm->n.min;
+ _nkm.min_n = nkm->n.min ?: 1;
_nkm.max_n = nkm->n.max ?: 1 << nkm->n.width;
- _nkm.min_k = nkm->k.min;
+ _nkm.min_k = nkm->k.min ?: 1;
_nkm.max_k = nkm->k.max ?: 1 << nkm->k.width;
_nkm.min_m = 1;
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
index 488055e..162ff26 100644
--- a/drivers/clk/sunxi-ng/ccu_nkmp.c
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
@@ -116,9 +116,9 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
struct _ccu_nkmp _nkmp;
- _nkmp.min_n = nkmp->n.min;
+ _nkmp.min_n = nkmp->n.min ?: 1;
_nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
- _nkmp.min_k = nkmp->k.min;
+ _nkmp.min_k = nkmp->k.min ?: 1;
_nkmp.max_k = nkmp->k.max ?: 1 << nkmp->k.width;
_nkmp.min_m = 1;
_nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index af71b19..f312c92 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -99,7 +99,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
struct ccu_nm *nm = hw_to_ccu_nm(hw);
struct _ccu_nm _nm;
- _nm.min_n = nm->n.min;
+ _nm.min_n = nm->n.min ?: 1;
_nm.max_n = nm->n.max ?: 1 << nm->n.width;
_nm.min_m = 1;
_nm.max_m = nm->m.max ?: 1 << nm->m.width;
From bafee6723b1c425dee1c415463b7386ea923d2cd Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 24 Mar 2017 16:33:06 +0800
Subject: [PATCH] clk: sunxi-ng: Fix round_rate/set_rate multiplier minimum
mismatch
In commit 2beaa601c849 ("clk: sunxi-ng: Implement minimum for
multipliers"), the multiplier minimums in the set_rate callback
for NM and NKMP style clocks were not updated.
This patch fixes them to match their round_rate callbacks.
Fixes: 2beaa601c849 ("clk: sunxi-ng: Implement minimum for multipliers")
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/clk/sunxi-ng/ccu_nkmp.c | 4 ++--
drivers/clk/sunxi-ng/ccu_nm.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
index 162ff26..e58c9578 100644
--- a/drivers/clk/sunxi-ng/ccu_nkmp.c
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
@@ -138,9 +138,9 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags;
u32 reg;
- _nkmp.min_n = 1;
+ _nkmp.min_n = nkmp->n.min ?: 1;
_nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
- _nkmp.min_k = 1;
+ _nkmp.min_k = nkmp->k.min ?: 1;
_nkmp.max_k = nkmp->k.max ?: 1 << nkmp->k.width;
_nkmp.min_m = 1;
_nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index f312c92..5e5e90a 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -122,7 +122,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
else
ccu_frac_helper_disable(&nm->common, &nm->frac);
- _nm.min_n = 1;
+ _nm.min_n = nm->n.min ?: 1;
_nm.max_n = nm->n.max ?: 1 << nm->n.width;
_nm.min_m = 1;
_nm.max_m = nm->m.max ?: 1 << nm->m.width;
From 43b883c1d002fa910e88e5776a0c42c733bb151f Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 24 Mar 2017 16:33:07 +0800
Subject: [PATCH] clk: sunxi-ng: a80: Fix audio PLL comment not matching actual
code
We ignore the d1 and d2 dividers in the audio PLL, and force them to
1 (register value 0) at probe time. However the comment preceding the
audio PLL definition says we enforce the default value, which is not
the same.
Fix the preceding comment to match what we do in code.
Fixes: b8eb71dcdd08 ("clk: sunxi-ng: Add A80 CCU")
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/clk/sunxi-ng/ccu-sun9i-a80.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
index e13e313..a031bee 100644
--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
@@ -70,8 +70,7 @@ static struct ccu_nm pll_c1cpux_clk = {
/*
* The Audio PLL has d1, d2 dividers in addition to the usual N, M
* factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
- * and 24.576 MHz, ignore them for now. Enforce the default for them,
- * which is d1 = 0, d2 = 1.
+ * and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0.
*/
#define SUN9I_A80_PLL_AUDIO_REG 0x008
From 9594d638564896ac0f40cfd316e87a55c8d30570 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Tue, 14 Feb 2017 11:35:23 +0800
Subject: [PATCH] clk: sunxi-ng: gate: Support common pre-dividers
Some clock gates have a pre-divider between the source input and the
gate itself. A notable example is the HSIC 12 MHz clock found on the
A83T, which has the 24 MHz main oscillator as its input, and a /2
pre-divider.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/clk/sunxi-ng/ccu_gate.c | 47 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
index 8a81f9d..cd069d5 100644
--- a/drivers/clk/sunxi-ng/ccu_gate.c
+++ b/drivers/clk/sunxi-ng/ccu_gate.c
@@ -75,8 +75,55 @@ static int ccu_gate_is_enabled(struct clk_hw *hw)
return ccu_gate_helper_is_enabled(&cg->common, cg->enable);
}
+static unsigned long ccu_gate_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct ccu_gate *cg = hw_to_ccu_gate(hw);
+ unsigned long rate = parent_rate;
+
+ if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
+ rate /= cg->common.prediv;
+
+ return rate;
+}
+
+static long ccu_gate_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct ccu_gate *cg = hw_to_ccu_gate(hw);
+ int div = 1;
+
+ if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
+ div = cg->common.prediv;
+
+ if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
+ unsigned long best_parent = rate;
+
+ if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
+ best_parent *= div;
+ *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
+ }
+
+ return *prate / div;
+}
+
+static int ccu_gate_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ /*
+ * We must report success but we can do so unconditionally because
+ * clk_factor_round_rate returns values that ensure this call is a
+ * nop.
+ */
+
+ return 0;
+}
+
const struct clk_ops ccu_gate_ops = {
.disable = ccu_gate_disable,
.enable = ccu_gate_enable,
.is_enabled = ccu_gate_is_enabled,
+ .round_rate = ccu_gate_round_rate,
+ .set_rate = ccu_gate_set_rate,
+ .recalc_rate = ccu_gate_recalc_rate,
};
From 272bce4ab673fca0e42add73189e559acbf8e0ca Mon Sep 17 00:00:00 2001
From: Peter Robinson <pbrobinson@gmail.com>
Date: Thu, 2 Mar 2017 17:43:57 +0000
Subject: [PATCH] clk: sunxi-ng: tighten SoC deps on explicit AllWinner SoCs
Tighten the depends on the various AllWinn SoCs so we don't
inadvertantly get clock drivers when we're not wanting them
like 32 bit SoC clocks for 64 bit configs. Ensure there's
still test coverage though.
Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/clk/sunxi-ng/Kconfig | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 6b347d4..cf8dc27 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -64,6 +64,7 @@ config SUN50I_A64_CCU
select SUNXI_CCU_MP
select SUNXI_CCU_PHASE
default ARM64 && ARCH_SUNXI
+ depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN5I_CCU
bool "Support for the Allwinner sun5i family CCM"
@@ -75,6 +76,7 @@ config SUN5I_CCU
select SUNXI_CCU_MP
select SUNXI_CCU_PHASE
default MACH_SUN5I
+ depends on MACH_SUN5I || COMPILE_TEST
config SUN6I_A31_CCU
bool "Support for the Allwinner A31/A31s CCU"
@@ -86,6 +88,7 @@ config SUN6I_A31_CCU
select SUNXI_CCU_MP
select SUNXI_CCU_PHASE
default MACH_SUN6I
+ depends on MACH_SUN6I || COMPILE_TEST
config SUN8I_A23_CCU
bool "Support for the Allwinner A23 CCU"
@@ -98,6 +101,7 @@ config SUN8I_A23_CCU
select SUNXI_CCU_MP
select SUNXI_CCU_PHASE
default MACH_SUN8I
+ depends on MACH_SUN8I || COMPILE_TEST
config SUN8I_A33_CCU
bool "Support for the Allwinner A33 CCU"
@@ -110,6 +114,7 @@ config SUN8I_A33_CCU
select SUNXI_CCU_MP
select SUNXI_CCU_PHASE
default MACH_SUN8I
+ depends on MACH_SUN8I || COMPILE_TEST
config SUN8I_H3_CCU
bool "Support for the Allwinner H3 CCU"
@@ -121,6 +126,7 @@ config SUN8I_H3_CCU
select SUNXI_CCU_MP
select SUNXI_CCU_PHASE
default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
+ depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN8I_V3S_CCU
bool "Support for the Allwinner V3s CCU"
@@ -132,6 +138,7 @@ config SUN8I_V3S_CCU
select SUNXI_CCU_MP
select SUNXI_CCU_PHASE
default MACH_SUN8I
+ depends on MACH_SUN8I || COMPILE_TEST
config SUN9I_A80_CCU
bool "Support for the Allwinner A80 CCU"
@@ -143,5 +150,6 @@ config SUN9I_A80_CCU
select SUNXI_CCU_MP
select SUNXI_CCU_PHASE
default MACH_SUN9I
+ depends on MACH_SUN9I || COMPILE_TEST
endif

View File

@ -1,54 +0,0 @@
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
index 495edf5f..c0edd5c2 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
@@ -45,6 +45,22 @@
/ {
interrupt-parent = <&gic>;
+ chosen {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ simplefb_hdmi: framebuffer@0 {
+ compatible = "allwinner,simple-framebuffer",
+ "simple-framebuffer";
+ allwinner,pipeline = "de0-lcd0-hdmi";
+ clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_BUS_DE>,
+ <&ccu CLK_BUS_HDMI>, <&ccu CLK_DE>,
+ <&ccu CLK_TCON0>, <&ccu CLK_HDMI>;
+ status = "disabled";
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 100e9b49..e208e005 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -52,6 +52,22 @@
#address-cells = <1>;
#size-cells = <1>;
+ chosen {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ simplefb_hdmi: framebuffer@0 {
+ compatible = "allwinner,simple-framebuffer",
+ "simple-framebuffer";
+ allwinner,pipeline = "de0-lcd0-hdmi";
+ clocks = <&ccu CLK_BUS_TCON1>, <&ccu CLK_BUS_DE>,
+ <&ccu CLK_BUS_HDMI>, <&ccu CLK_DE>,
+ <&ccu CLK_TCON1>, <&ccu CLK_HDMI>;
+ status = "disabled";
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;