Merge pull request #56 from resin-os/misc

Misc
This commit is contained in:
Florin Sarbu 2018-09-10 16:01:19 +03:00 committed by GitHub
commit c416abe9e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
186 changed files with 9 additions and 2516399 deletions

View file

@ -6,3 +6,5 @@ BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
BBFILE_COLLECTIONS += "resin-allwinner"
BBFILE_PATTERN_resin-allwinner := "^${LAYERDIR}/"
BBFILE_PRIORITY_resin-allwinner = "1337"
LAYERSERIES_COMPAT_resin-allwinner = "sumo"

View file

@ -1,97 +0,0 @@
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "resin-raspberrypi"
BBFILE_PATTERN_resin-raspberrypi := "^${LAYERDIR}/"
BBFILE_PRIORITY_resin-raspberrypi = "1337"
# Add all the overlays available in kernel source code
#
# The files below come from kernel-source/arch/arm/boot/dts/overlays/, but without
# the ones already defined in meta-raspberrypi/conf/machine/include/rpi-base.inc.
# They have been renamed to match rpi-base.inc.
KERNEL_DEVICETREE_append = " \
overlays/adau1977-adc.dtbo \
overlays/ads1015.dtbo \
overlays/ads7846.dtbo \
overlays/akkordion-iqdacplus.dtbo \
overlays/allo-piano-dac-pcm512x-audio.dtbo \
overlays/at86rf233.dtbo \
overlays/audioinjector-wm8731-audio.dtbo \
overlays/audremap.dtbo \
overlays/bmp085_i2c-sensor.dtbo \
overlays/dht11.dtbo \
overlays/dionaudio-loco.dtbo \
overlays/dpi18.dtbo \
overlays/dpi24.dtbo \
overlays/dwc2.dtbo \
overlays/dwc-otg.dtbo \
overlays/enc28j60.dtbo \
overlays/enc28j60-spi2.dtbo \
overlays/gpio-ir.dtbo \
overlays/gpio-poweroff.dtbo \
overlays/hifiberry-digi-pro.dtbo \
overlays/hy28a.dtbo \
overlays/hy28b.dtbo \
overlays/i2c0-bcm2708.dtbo \
overlays/i2c1-bcm2708.dtbo \
overlays/i2c-gpio.dtbo \
overlays/i2c-mux.dtbo \
overlays/i2c-pwm-pca9685a.dtbo \
overlays/i2c-sensor.dtbo \
overlays/i2s-gpio28-31.dtbo \
overlays/i2s-mmap.dtbo \
overlays/iqaudio-digi-wm8804-audio.dtbo \
overlays/justboom-dac.dtbo \
overlays/justboom-digi.dtbo \
overlays/mcp23017.dtbo \
overlays/mcp23s17.dtbo \
overlays/mcp2515-can0.dtbo \
overlays/mcp2515-can1.dtbo \
overlays/mcp3008.dtbo \
overlays/mmc.dtbo \
overlays/mz61581.dtbo \
overlays/pi3-act-led.dtbo \
overlays/pi3-disable-wifi.dtbo \
overlays/piscreen2r.dtbo \
overlays/piscreen.dtbo \
overlays/pisound.dtbo \
overlays/pitft28-capacitive.dtbo \
overlays/pitft35-resistive.dtbo \
overlays/pwm-2chan.dtbo \
overlays/pwm.dtbo \
overlays/qca7000.dtbo \
overlays/raspidac3.dtbo \
overlays/rpi-backlight.dtbo \
overlays/rpi-dac.dtbo \
overlays/rpi-display.dtbo \
overlays/rpi-proto.dtbo \
overlays/rpi-sense.dtbo \
overlays/rra-digidac1-wm8741-audio.dtbo \
overlays/sc16is750-i2c.dtbo \
overlays/sc16is752-spi1.dtbo \
overlays/sdhost.dtbo \
overlays/sdio-1bit.dtbo \
overlays/sdio.dtbo \
overlays/sdtweak.dtbo \
overlays/smi-dev.dtbo \
overlays/smi.dtbo \
overlays/smi-nand.dtbo \
overlays/spi0-cs.dtbo \
overlays/spi0-hw-cs.dtbo \
overlays/spi1-1cs.dtbo \
overlays/spi1-2cs.dtbo \
overlays/spi1-3cs.dtbo \
overlays/spi2-1cs.dtbo \
overlays/spi2-2cs.dtbo \
overlays/spi2-3cs.dtbo \
overlays/spi-gpio35-39.dtbo \
overlays/spi-rtc.dtbo \
overlays/tinylcd35.dtbo \
overlays/uart1.dtbo \
overlays/vc4-fkms-v3d.dtbo \
overlays/vga666.dtbo \
overlays/wittypi.dtbo \
"

View file

@ -8,4 +8,4 @@ include conf/machine/bananapi.conf
KERNEL_DEVICETREE = "sun7i-a20-bananapi-m1-plus.dtb"
UBOOT_MACHINE = "bananapi_m1_plus_config"
PREFERRED_VERSION_linux-mainline = "4.14.15"
PREFERRED_VERSION_linux-mainline = "4.17.3"

View file

@ -1,36 +0,0 @@
#@TYPE: Machine
#@NAME: nanopi-neo-air
#@DESCRIPTION: Machine configuration for the nanopi-neo-air, base on allwinner H3 CPU
require conf/machine/include/sun8i.inc
PREFERRED_VERSION_linux = "4.14%"
PREFERRED_VERSION_u-boot = "v2017.11%"
KERNEL_DEVICETREE = "sun8i-h3-nanopi-neo-air.dtb \
overlay/sun8i-h3-analog-codec.dtbo \
overlay/sun8i-h3-cir.dtbo \
overlay/sun8i-h3-fixup.scr \
overlay/sun8i-h3-i2c0.dtbo \
overlay/sun8i-h3-i2c1.dtbo \
overlay/sun8i-h3-i2c2.dtbo \
overlay/sun8i-h3-pps-gpio.dtbo \
overlay/sun8i-h3-pwm.dtbo \
overlay/sun8i-h3-spdif-out.dtbo \
overlay/sun8i-h3-spi-add-cs1.dtbo \
overlay/sun8i-h3-spi-jedec-nor.dtbo \
overlay/sun8i-h3-spi-spidev.dtbo \
overlay/sun8i-h3-uart1.dtbo \
overlay/sun8i-h3-uart2.dtbo \
overlay/sun8i-h3-uart3.dtbo \
overlay/sun8i-h3-usbhost0.dtbo \
overlay/sun8i-h3-usbhost2.dtbo \
overlay/sun8i-h3-usbhost3.dtbo \
overlay/sun8i-h3-w1-gpio.dtbo \
"
MACHINE_EXTRA_RRECOMMENDS += "linux-firmware-ap6212"
UBOOT_MACHINE = "nanopi_neo_air_defconfig"
DEFAULTTUNE = "cortexa7hf-neon-vfpv4"

View file

@ -1,16 +0,0 @@
_____ _ _
| __ \ (_) (_)
| |__) |___ ___ _ _ __ _ ___
| _ // _ \/ __| | '_ \ | |/ _ \
| | \ \ __/\__ \ | | | |_| | (_) |
|_| \_\___||___/_|_| |_(_)_|\___/
----------------------------------
Resin specific targets are:
resin-image
Nanopi Neo Air (EXPERIMENTAL) : $ MACHINE=nanopi-neo-air bitbake resin-image
Orange Pi Lite (EXPERIMENTAL) : $ MACHINE=orange-pi-lite bitbake resin-image

View file

@ -1,18 +0,0 @@
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index d0fc165..4510c2d 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -809,6 +809,13 @@ static const struct flash_info spi_nor_ids[] = {
{ "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
+ /* BergMicro Flashes */
+ { "bg25q80", INFO(0xe04014, 0, 64 * 1024, 16, SECT_4K) },
+ { "bg25q16", INFO(0xe04015, 0, 64 * 1024, 32, SECT_4K) },
+ { "bg25q32", INFO(0xe04016, 0, 64 * 1024, 64, SECT_4K) },
+ { "bg25q64", INFO(0xe04017, 0, 64 * 1024, 128, SECT_4K) },
+ { "bg25q128", INFO(0xe04018, 0, 64 * 1024, 256, SECT_4K) },
+
/* EON -- en25xxx */
{ "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },

View file

@ -1,174 +0,0 @@
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index 19216af1..e839d23a 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -13,11 +13,14 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/module.h>
#include <asm/div64.h>
+#include <linux/clk.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -316,14 +319,81 @@ static const struct iio_info ad9833_info = {
.driver_module = THIS_MODULE,
};
+#if defined(CONFIG_OF)
+static struct ad9834_platform_data *ad9834_parse_dt(struct spi_device *spi)
+{
+ struct ad9834_platform_data *pdata;
+ struct device_node *np = spi->dev.of_node;
+
+ pdata = devm_kzalloc(&spi->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ pdata->freq0 = 134000;
+ of_property_read_u32(np, "freq0", &pdata->freq0);
+
+ pdata->freq1 = 134000;
+ of_property_read_u32(np, "freq1", &pdata->freq1);
+
+ pdata->phase0 = 0;
+ of_property_read_u16(np, "phase0", &pdata->phase0);
+
+ pdata->phase1 = 0;
+ of_property_read_u16(np, "phase1", &pdata->phase1);
+
+ pdata->en_div2 = of_property_read_bool(np, "en_div2");
+ pdata->en_signbit_msb_out = of_property_read_bool(np,
+ "en_signbit_msb_out");
+
+ return pdata;
+}
+#else
+static struct ad9834_platform_data *ad9834_parse_dt(struct spi_device *spi)
+{
+ return NULL;
+}
+#endif
+
+static const struct of_device_id ad9834_of_match[] = {
+ {
+ .compatible = "adi,ad9833",
+ .data = (void *)ID_AD9833,
+ },
+ {
+ .compatible = "adi,ad9834",
+ .data = (void *)ID_AD9834,
+ },
+ {
+ .compatible = "adi,ad9837",
+ .data = (void *)ID_AD9837,
+ },
+ {
+ .compatible = "adi,ad9838",
+ .data = (void *)ID_AD9838,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad9834_of_match);
+
static int ad9834_probe(struct spi_device *spi)
{
- struct ad9834_platform_data *pdata = dev_get_platdata(&spi->dev);
+ const struct of_device_id *of_id = of_match_device(ad9834_of_match,
+ &spi->dev);
+ struct ad9834_platform_data *pdata;
struct ad9834_state *st;
struct iio_dev *indio_dev;
struct regulator *reg;
+ struct clk *clk = NULL;
int ret;
+ if (!pdata && spi->dev.of_node) {
+ pdata = ad9834_parse_dt(spi);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ } else {
+ pdata = spi->dev.platform_data;
+ }
+
if (!pdata) {
dev_dbg(&spi->dev, "no platform data?\n");
return -ENODEV;
@@ -346,9 +416,30 @@ static int ad9834_probe(struct spi_device *spi)
}
spi_set_drvdata(spi, indio_dev);
st = iio_priv(indio_dev);
- st->mclk = pdata->mclk;
+
+ if (!pdata->mclk) {
+ clk = devm_clk_get(&spi->dev, NULL);
+ if (IS_ERR(clk))
+ return -EPROBE_DEFER;
+
+ ret = clk_prepare_enable(clk);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (clk) {
+ st->clk = clk;
+ st->mclk = clk_get_rate(clk);
+ } else {
+ st->mclk = pdata->mclk;
+ }
+
+ if (of_id)
+ st->devid = (enum ad9834_supported_device_ids)of_id->data;
+ else
+ st->devid = spi_get_device_id(spi)->driver_data;
+
st->spi = spi;
- st->devid = spi_get_device_id(spi)->driver_data;
st->reg = reg;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -421,6 +512,9 @@ static int ad9834_probe(struct spi_device *spi)
error_disable_reg:
regulator_disable(reg);
+if (clk)
+ clk_disable_unprepare(clk);
+
return ret;
}
@@ -431,6 +525,8 @@ static int ad9834_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
regulator_disable(st->reg);
+if (st->clk)
+ clk_disable_unprepare(st->clk);
return 0;
}
@@ -447,6 +543,7 @@ MODULE_DEVICE_TABLE(spi, ad9834_id);
static struct spi_driver ad9834_driver = {
.driver = {
.name = "ad9834",
+ .of_match_table = of_match_ptr(ad9834_of_match),
},
.probe = ad9834_probe,
.remove = ad9834_remove,
diff --git a/drivers/staging/iio/frequency/ad9834.h b/drivers/staging/iio/frequency/ad9834.h
index 40fdd5da..fd9cccf3 100644
--- a/drivers/staging/iio/frequency/ad9834.h
+++ b/drivers/staging/iio/frequency/ad9834.h
@@ -53,6 +53,7 @@
struct ad9834_state {
struct spi_device *spi;
struct regulator *reg;
+ struct clk *clk;
unsigned int mclk;
unsigned short control;
unsigned short devid;

View file

@ -1,360 +0,0 @@
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index bc07ad3..e9da9cf 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -113,6 +113,13 @@ config OF_OVERLAY
While this option is selected automatically when needed, you can
enable it manually to improve device tree unit test coverage.
+config OF_CONFIGFS
+ bool "Device Tree Overlay ConfigFS interface"
+ select CONFIGFS_FS
+ depends on OF_OVERLAY
+ help
+ Enable a simple user-space driven DT overlay interface.
+
config OF_NUMA
bool
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index d7efd9d..a06cc35 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
obj-$(CONFIG_OF_RESOLVE) += resolver.o
obj-$(CONFIG_OF_OVERLAY) += overlay.o
+obj-$(CONFIG_OF_CONFIGFS) += configfs.o
obj-$(CONFIG_OF_NUMA) += of_numa.o
obj-$(CONFIG_OF_UNITTEST) += unittest-data/
diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c
new file mode 100644
index 0000000..68f889d
--- /dev/null
+++ b/drivers/of/configfs.c
@@ -0,0 +1,311 @@
+/*
+ * Configfs entries for device-tree
+ *
+ * Copyright (C) 2013 - Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * 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.
+ */
+#include <linux/ctype.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/configfs.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/limits.h>
+#include <linux/file.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/sizes.h>
+
+#include "of_private.h"
+
+struct cfs_overlay_item {
+ struct config_item item;
+
+ char path[PATH_MAX];
+
+ const struct firmware *fw;
+ struct device_node *overlay;
+ int ov_id;
+
+ void *dtbo;
+ int dtbo_size;
+};
+
+static int create_overlay(struct cfs_overlay_item *overlay, void *blob)
+{
+ int err;
+
+ /* unflatten the tree */
+ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay);
+ if (overlay->overlay == NULL) {
+ pr_err("%s: failed to unflatten tree\n", __func__);
+ err = -EINVAL;
+ goto out_err;
+ }
+ pr_debug("%s: unflattened OK\n", __func__);
+
+ /* mark it as detached */
+ of_node_set_flag(overlay->overlay, OF_DETACHED);
+
+ /* perform resolution */
+ err = of_resolve_phandles(overlay->overlay);
+ if (err != 0) {
+ pr_err("%s: Failed to resolve tree\n", __func__);
+ goto out_err;
+ }
+ pr_debug("%s: resolved OK\n", __func__);
+
+ err = of_overlay_create(overlay->overlay);
+ if (err < 0) {
+ pr_err("%s: Failed to create overlay (err=%d)\n",
+ __func__, err);
+ goto out_err;
+ }
+ overlay->ov_id = err;
+
+out_err:
+ return err;
+}
+
+static inline struct cfs_overlay_item *to_cfs_overlay_item(
+ struct config_item *item)
+{
+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL;
+}
+
+static ssize_t cfs_overlay_item_path_show(struct config_item *item,
+ char *page)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+ return sprintf(page, "%s\n", overlay->path);
+}
+
+static ssize_t cfs_overlay_item_path_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+ const char *p = page;
+ char *s;
+ int err;
+
+ /* if it's set do not allow changes */
+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
+ return -EPERM;
+
+ /* copy to path buffer (and make sure it's always zero terminated */
+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p);
+ overlay->path[sizeof(overlay->path) - 1] = '\0';
+
+ /* strip trailing newlines */
+ s = overlay->path + strlen(overlay->path);
+ while (s > overlay->path && *--s == '\n')
+ *s = '\0';
+
+ pr_debug("%s: path is '%s'\n", __func__, overlay->path);
+
+ err = request_firmware(&overlay->fw, overlay->path, NULL);
+ if (err != 0)
+ goto out_err;
+
+ err = create_overlay(overlay, (void *)overlay->fw->data);
+ if (err != 0)
+ goto out_err;
+
+ return count;
+
+out_err:
+
+ release_firmware(overlay->fw);
+ overlay->fw = NULL;
+
+ overlay->path[0] = '\0';
+ return err;
+}
+
+static ssize_t cfs_overlay_item_status_show(struct config_item *item,
+ char *page)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ return sprintf(page, "%s\n",
+ overlay->ov_id >= 0 ? "applied" : "unapplied");
+}
+
+CONFIGFS_ATTR(cfs_overlay_item_, path);
+CONFIGFS_ATTR_RO(cfs_overlay_item_, status);
+
+static struct configfs_attribute *cfs_overlay_attrs[] = {
+ &cfs_overlay_item_attr_path,
+ &cfs_overlay_item_attr_status,
+ NULL,
+};
+
+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item,
+ void *buf, size_t max_count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ pr_debug("%s: buf=%p max_count=%zu\n", __func__,
+ buf, max_count);
+
+ if (overlay->dtbo == NULL)
+ return 0;
+
+ /* copy if buffer provided */
+ if (buf != NULL) {
+ /* the buffer must be large enough */
+ if (overlay->dtbo_size > max_count)
+ return -ENOSPC;
+
+ memcpy(buf, overlay->dtbo, overlay->dtbo_size);
+ }
+
+ return overlay->dtbo_size;
+}
+
+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item,
+ const void *buf, size_t count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+ int err;
+
+ /* if it's set do not allow changes */
+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
+ return -EPERM;
+
+ /* copy the contents */
+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL);
+ if (overlay->dtbo == NULL)
+ return -ENOMEM;
+
+ overlay->dtbo_size = count;
+
+ err = create_overlay(overlay, overlay->dtbo);
+ if (err != 0)
+ goto out_err;
+
+ return count;
+
+out_err:
+ kfree(overlay->dtbo);
+ overlay->dtbo = NULL;
+ overlay->dtbo_size = 0;
+
+ return err;
+}
+
+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M);
+
+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = {
+ &cfs_overlay_item_attr_dtbo,
+ NULL,
+};
+
+static void cfs_overlay_release(struct config_item *item)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ if (overlay->ov_id >= 0)
+ of_overlay_destroy(overlay->ov_id);
+ if (overlay->fw)
+ release_firmware(overlay->fw);
+ /* kfree with NULL is safe */
+ kfree(overlay->dtbo);
+ kfree(overlay);
+}
+
+static struct configfs_item_operations cfs_overlay_item_ops = {
+ .release = cfs_overlay_release,
+};
+
+static struct config_item_type cfs_overlay_type = {
+ .ct_item_ops = &cfs_overlay_item_ops,
+ .ct_attrs = cfs_overlay_attrs,
+ .ct_bin_attrs = cfs_overlay_bin_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_item *cfs_overlay_group_make_item(
+ struct config_group *group, const char *name)
+{
+ struct cfs_overlay_item *overlay;
+
+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
+ if (!overlay)
+ return ERR_PTR(-ENOMEM);
+ overlay->ov_id = -1;
+
+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type);
+ return &overlay->item;
+}
+
+static void cfs_overlay_group_drop_item(struct config_group *group,
+ struct config_item *item)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ config_item_put(&overlay->item);
+}
+
+static struct configfs_group_operations overlays_ops = {
+ .make_item = cfs_overlay_group_make_item,
+ .drop_item = cfs_overlay_group_drop_item,
+};
+
+static struct config_item_type overlays_type = {
+ .ct_group_ops = &overlays_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_group_operations of_cfs_ops = {
+ /* empty - we don't allow anything to be created */
+};
+
+static struct config_item_type of_cfs_type = {
+ .ct_group_ops = &of_cfs_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+struct config_group of_cfs_overlay_group;
+
+static struct configfs_subsystem of_cfs_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "device-tree",
+ .ci_type = &of_cfs_type,
+ },
+ },
+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex),
+};
+
+static int __init of_cfs_init(void)
+{
+ int ret;
+
+ pr_info("%s\n", __func__);
+
+ config_group_init(&of_cfs_subsys.su_group);
+ config_group_init_type_name(&of_cfs_overlay_group, "overlays",
+ &overlays_type);
+ configfs_add_default_group(&of_cfs_overlay_group,
+ &of_cfs_subsys.su_group);
+
+ ret = configfs_register_subsystem(&of_cfs_subsys);
+ if (ret != 0) {
+ pr_err("%s: failed to register subsys\n", __func__);
+ goto out;
+ }
+ pr_info("%s: OK\n", __func__);
+out:
+ return ret;
+}
+late_initcall(of_cfs_init);
diff --git a/drivers/of/fdt_address.c b/drivers/of/fdt_address.c
index dca8f9b..ec7e167 100644
--- a/drivers/of/fdt_address.c
+++ b/drivers/of/fdt_address.c
@@ -161,7 +161,7 @@ static int __init fdt_translate_one(const void *blob, int parent,
* that can be mapped to a cpu physical address). This is not really specified
* that way, but this is traditionally the way IBM at least do things
*/
-static u64 __init fdt_translate_address(const void *blob, int node_offset)
+u64 __init fdt_translate_address(const void *blob, int node_offset)
{
int parent, len;
const struct of_bus *bus, *pbus;

View file

@ -1,103 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi b/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
index 2216e68d..143ebc06 100644
--- a/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
@@ -48,6 +48,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
aliases {
@@ -88,12 +89,90 @@
gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
};
};
+
+ vdd_cpux: gpio-regulator {
+ compatible = "regulator-gpio";
+ regulator-name = "vdd-cpux";
+ regulator-type = "voltage";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-ramp-delay = <50>; /* 4ms */
+ gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>;
+ gpios-states = <0x1>;
+ states = <1100000 0x0
+ 1300000 0x1>;
+ };
+};
+
+&cpu0 {
+ operating-points = <
+ 1008000 1300000
+ 816000 1100000
+ 624000 1100000
+ 480000 1100000
+ 312000 1100000
+ 240000 1100000
+ 120000 1100000
+ >;
+ #cooling-cells = <2>;
+ cooling-min-level = <0>;
+ cooling-max-level = <6>;
+ cpu0-supply = <&vdd_cpux>;
+};
+
+&cpu_thermal {
+ trips {
+ cpu_warm: cpu_warm {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_hot: cpu_hot {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_very_hot: cpu_very_hot {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit: cpu_crit {
+ temperature = <105000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ cpu_warm_limit_cpu {
+ trip = <&cpu_warm>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT 1>;
+ };
+ cpu_hot_limit_cpu {
+ trip = <&cpu_hot>;
+ cooling-device = <&cpu0 2 3>;
+ };
+ cpu_very_hot_limit_cpu {
+ trip = <&cpu_very_hot>;
+ cooling-device = <&cpu0 5 THERMAL_NO_LIMIT>;
+ };
+ };
};
&ehci3 {
status = "okay";
};
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
&mmc0 {
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;

View file

@ -1,36 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
index 5851a47a..c2f1baa2 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
@@ -50,4 +50,31 @@
/ {
model = "Xunlong Orange Pi Plus 2E";
compatible = "xunlong,orangepi-plus2e", "allwinner,sun8i-h3";
+
+ reg_gmac_3v3: gmac-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "gmac-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <100000>;
+ enable-active-high;
+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ reg = <0>;
+ };
+};
+
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+
+ allwinner,leds-active-low;
+ status = "okay";
};

View file

@ -1,20 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
index e94f196..69a4840 100644
--- a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
@@ -104,6 +104,15 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ phy-supply = <&reg_vcc3v3>;
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>;

View file

@ -1,999 +0,0 @@
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 01180849..81523d5a 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -1016,4 +1017,7 @@ dtstree := $(srctree)/$(src)
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
always := $(dtb-y)
+subdir-y := overlay
clean-files := *.dtb
+
+dts-dirs += overlay
diff --git a/arch/arm/boot/dts/overlay/Makefile b/arch/arm/boot/dts/overlay/Makefile
new file mode 100644
index 00000000..f9ca2574
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/Makefile
@@ -0,0 +1,28 @@
+dtbo-$(CONFIG_MACH_SUN8I) += \
+ sun8i-h3-analog-codec.dtbo \
+ sun8i-h3-cir.dtbo \
+ sun8i-h3-i2c0.dtbo \
+ sun8i-h3-i2c1.dtbo \
+ sun8i-h3-i2c2.dtbo \
+ sun8i-h3-pps-gpio.dtbo \
+ sun8i-h3-pwm.dtbo \
+ sun8i-h3-spdif-out.dtbo \
+ sun8i-h3-spi-add-cs1.dtbo \
+ sun8i-h3-spi-jedec-nor.dtbo \
+ sun8i-h3-spi-spidev.dtbo \
+ sun8i-h3-uart1.dtbo \
+ sun8i-h3-uart2.dtbo \
+ sun8i-h3-uart3.dtbo \
+ sun8i-h3-usbhost0.dtbo \
+ sun8i-h3-usbhost2.dtbo \
+ sun8i-h3-usbhost3.dtbo \
+ sun8i-h3-w1-gpio.dtbo
+
+scr-$(CONFIG_MACH_SUN8I) += sun8i-h3-fixup.scr
+
+dtbotxt-$(CONFIG_MACH_SUN8I) += README.sun8i-h3-overlays
+
+targets += $(dtbo-y) $(scr-y) $(dtbotxt-y)
+
+always := $(dtbo-y) $(scr-y) $(dtbotxt-y)
+clean-files := *.dtbo *.scr
diff --git a/arch/arm/boot/dts/overlay/README.sun8i-h3-overlays b/arch/arm/boot/dts/overlay/README.sun8i-h3-overlays
new file mode 100644
index 00000000..0ae207a1
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/README.sun8i-h3-overlays
@@ -0,0 +1,245 @@
+This document describes overlays provided in the kernel packages
+For generic Armbian overlays documentation please see
+https://docs.armbian.com/User-Guide_Allwinner_overlays/
+
+### Platform:
+
+sun8i-h3 (Allwinner H3)
+
+### Platform details:
+
+Supported pin banks: PA, PC, PD, PG
+
+Both SPI controllers have only one hardware CS pin exposed,
+adding fixed software (GPIO) chip selects is possible with a separate overlay
+
+### Provided overlays:
+
+- analog-codec
+- cir
+- i2c0
+- i2c1
+- i2c2
+- pps-gpio
+- pwm
+- spdif-out
+- spi-add-cs1
+- spi-jedec-nor
+- spi-spidev
+- uart1
+- uart2
+- uart3
+- usbhost0
+- usbhost2
+- usbhost3
+- w1-gpio
+
+### Overlay details:
+
+### analog-codec
+
+Activates SoC analog codec driver that provides Line Out and Mic In
+functionality
+
+### cir
+
+Activates CIR (Infrared remote) receiver
+
+CIR pin: PL11
+
+### i2c0
+
+Activates TWI/I2C bus 0
+
+I2C0 pins (SCL, SDA): PA11, PA12
+
+### i2c1
+
+Activates TWI/I2C bus 1
+
+I2C1 pins (SCL, SDA): PA18, PA19
+
+### i2c2
+
+Activates TWI/I2C bus 2
+
+I2C2 pins (SCL, SDA): PE12, PE13
+
+On most board this bus is wired to Camera (CSI) socket
+
+### pps-gpio
+
+Activates pulse-per-second GPIO client
+
+Parameters:
+
+param_pps_pin (pin)
+ Pin PPS source is connected to
+ Optional
+ Default: PD14
+
+param_pps_falling_edge (bool)
+ Assert by falling edge
+ Optional
+ Default: 0
+ When set (to 1), assert is indicated by a falling edge
+ (instead of by a rising edge)
+
+### pwm
+
+Activates hardware PWM controller
+
+PWM pin: PA5
+
+Pin PA5 is used as UART0 RX by default, so if this overlay is activated,
+UART0 and kernel console on ttyS0 will be disabled
+
+### spdif-out
+
+Activates SPDIF/Toslink audio output
+
+SPDIF pin: PA17
+
+### spi-add-cs1
+
+Adds support for using SPI chip select 1 with GPIO for both SPI controllers
+Respective GPIO will be claimed only if controller is enabled by another
+overlay
+This overlay is required for using chip select 1 with other SPI overlays
+Due to the u-boot limitations CS1 pin can't be customized by a parameter, but
+it can be changed by using an edited copy of this overlay
+A total of 4 chip selects can be used with custom overlays (1 HW + 3 GPIO)
+
+SPI 0 pins (CS1): PA21
+SPI 1 pins (CS1): PA10
+
+### spi-jedec-nor
+
+Activates MTD support for JEDEC compatible SPI NOR flash chips on SPI bus
+supported by the kernel SPI NOR driver
+
+SPI 0 pins (MOSI, MISO, SCK, CS): PC0, PC1, PC2, PC3
+SPI 1 pins (MOSI, MISO, SCK, CS): PA15, PA16, PA14, PA13
+
+Parameters:
+
+param_spinor_spi_bus (int)
+ SPI bus to activate SPI NOR flash support on
+ Required
+ Supported values: 0, 1
+
+param_spinor_spi_cs (int)
+ SPI chip select number
+ Optional
+ Default: 0
+ Supported values: 0, 1
+ Using chip select 1 requires using "spi-add-cs1" overlay
+
+param_spinor_max_freq (int)
+ Maximum SPI frequency
+ Optional
+ Default: 1000000
+ Range: 3000 - 100000000
+
+### spi-spidev
+
+Activates SPIdev device node (/dev/spidevX.Y) for userspace SPI access,
+where X is the bus number and Y is the CS number
+
+SPI 0 pins (MOSI, MISO, SCK, CS): PC0, PC1, PC2, PC3
+SPI 1 pins (MOSI, MISO, SCK, CS): PA15, PA16, PA14, PA13
+
+Parameters:
+
+param_spidev_spi_bus (int)
+ SPI bus to activate SPIdev support on
+ Required
+ Supported values: 0, 1
+
+param_spidev_spi_cs (int)
+ SPI chip select number
+ Optional
+ Default: 0
+ Supported values: 0, 1
+ Using chip select 1 requires using "spi-add-cs1" overlay
+
+param_spidev_max_freq (int)
+ Maximum SPIdev frequency
+ Optional
+ Default: 1000000
+ Range: 3000 - 100000000
+
+### uart1
+
+Activates serial port 1 (/dev/ttyS1)
+
+UART 1 pins (TX, RX, RTS, CTS): PG6, PG7, PG8, PG9
+
+Parameters:
+
+param_uart1_rtscts (bool)
+ Enable RTS and CTS pins
+ Optional
+ Default: 0
+ Set to 1 to enable
+
+### uart2
+
+Activates serial port 2 (/dev/ttyS2)
+
+UART 2 pins (TX, RX, RTS, CTS): PA0, PA1, PA2, PA3
+
+Parameters:
+
+param_uart2_rtscts (bool)
+ Enable RTS and CTS pins
+ Optional
+ Default: 0
+ Set to 1 to enable CTS and RTS pins
+
+### uart3
+
+Activates serial port 3 (/dev/ttyS3)
+
+UART 3 pins (TX, RX, RTS, CTS): PA13, PA14, PA15, PA16
+
+Parameters:
+
+param_uart3_rtscts (bool)
+ Enable RTS and CTS pins
+ Optional
+ Default: 0
+ Set to 1 to enable CTS and RTS pins
+
+### usbhost0
+
+Activates USB host controller 0
+
+### usbhost2
+
+Activates USB host controller 2
+
+### usbhost3
+
+Activates USB host controller 3
+
+### w1-gpio
+
+Activates 1-Wire GPIO master
+Requires an external pull-up resistor on the data pin
+or enabling the internal pull-up
+
+Parameters:
+
+param_w1_pin (pin)
+ Data pin for 1-Wire master
+ Optional
+ Default: PD14
+
+param_w1_pin_int_pullup (bool)
+ Enable internal pull-up for the data pin
+ Optional
+ Default: 0
+ Set to 1 to enable the pull-up
+ This option should not be used with multiple devices, parasite power setup
+ or long wires - please use external pull-up resistor instead
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-analog-codec.dts b/arch/arm/boot/dts/overlay/sun8i-h3-analog-codec.dts
new file mode 100644
index 00000000..36dbc31a
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-analog-codec.dts
@@ -0,0 +1,17 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&codec>;
+ __overlay__ {
+ allwinner,audio-routing =
+ "Line Out", "LINEOUT",
+ "MIC1", "Mic",
+ "Mic", "MBIAS";
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-cir.dts b/arch/arm/boot/dts/overlay/sun8i-h3-cir.dts
new file mode 100644
index 00000000..9b62fd2b
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-cir.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&ir>;
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_pins_a>;
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-fixup.scr-cmd b/arch/arm/boot/dts/overlay/sun8i-h3-fixup.scr-cmd
new file mode 100644
index 00000000..744889c6
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-fixup.scr-cmd
@@ -0,0 +1,110 @@
+# overlays fixup script
+# implements (or rather substitutes) overlay arguments functionality
+# using u-boot scripting, environment variables and "fdt" command
+
+# setexpr test_var ${tmp_bank} - A
+# works only for hex numbers (A-F)
+
+setenv decompose_pin 'setexpr tmp_bank sub "P(A|C|D|G)\\d+" "\\1";
+setexpr tmp_pin sub "P\\S(\\d+)" "\\1";
+test "${tmp_bank}" = "A" && setenv tmp_bank 0;
+test "${tmp_bank}" = "C" && setenv tmp_bank 2;
+test "${tmp_bank}" = "D" && setenv tmp_bank 3;
+test "${tmp_bank}" = "G" && setenv tmp_bank 6'
+
+if test -n "${param_spinor_spi_bus}"; then
+ test "${param_spinor_spi_bus}" = "0" && setenv tmp_spi_path "spi@01c68000"
+ test "${param_spinor_spi_bus}" = "1" && setenv tmp_spi_path "spi@01c69000"
+ fdt set /soc/${tmp_spi_path} status "okay"
+ fdt set /soc/${tmp_spi_path}/spiflash status "okay"
+ if test -n "${param_spinor_max_freq}"; then
+ fdt set /soc/${tmp_spi_path}/spiflash spi-max-frequency "<${param_spinor_max_freq}>"
+ fi
+ if test "${param_spinor_spi_cs}" = "1"; then
+ fdt set /soc/${tmp_spi_path}/spiflash reg "<1>"
+ fi
+ env delete tmp_spi_path
+fi
+
+if test -n "${param_spidev_spi_bus}"; then
+ test "${param_spidev_spi_bus}" = "0" && setenv tmp_spi_path "spi@01c68000"
+ test "${param_spidev_spi_bus}" = "1" && setenv tmp_spi_path "spi@01c69000"
+ fdt set /soc/${tmp_spi_path} status "okay"
+ fdt set /soc/${tmp_spi_path}/spidev status "okay"
+ if test -n "${param_spidev_max_freq}"; then
+ fdt set /soc/${tmp_spi_path}/spidev spi-max-frequency "<${param_spidev_max_freq}>"
+ fi
+ if test "${param_spidev_spi_cs}" = "1"; then
+ fdt set /soc/${tmp_spi_path}/spidev reg "<1>"
+ fi
+ env delete tmp_spi_path
+fi
+
+if test -n "${param_pps_pin}"; then
+ setenv tmp_bank "${param_pps_pin}"
+ setenv tmp_pin "${param_pps_pin}"
+ run decompose_pin
+ fdt set /soc/pinctrl@01c20800/pps_pins pins "${param_pps_pin}"
+ fdt get value tmp_phandle /soc/pinctrl@01c20800 phandle
+ fdt set /pps@0 gpios "<${tmp_phandle} ${tmp_bank} ${tmp_pin} 0>"
+ env delete tmp_pin tmp_bank tmp_phandle
+fi
+
+if test "${param_pps_falling_edge}" = "1"; then
+ fdt set /pps@0 assert-falling-edge
+fi
+
+for f in ${overlays}; do
+ if test "${f}" = "pwm"; then
+ setenv bootargs_new ""
+ for arg in ${bootargs}; do
+ if test "${arg}" = "console=ttyS0,115200"; then
+ echo "Warning: Disabling ttyS0 console due to enabled PWM overlay"
+ else
+ setenv bootargs_new "${bootargs_new} ${arg}"
+ fi
+ done
+ setenv bootargs "${bootargs_new}"
+ fi
+done
+
+if test -n "${param_w1_pin}"; then
+ setenv tmp_bank "${param_w1_pin}"
+ setenv tmp_pin "${param_w1_pin}"
+ run decompose_pin
+ fdt set /soc/pinctrl@01c20800/w1_pins pins "${param_w1_pin}"
+ fdt get value tmp_phandle /soc/pinctrl@01c20800 phandle
+ fdt set /onewire@0 gpios "<${tmp_phandle} ${tmp_bank} ${tmp_pin} 0>"
+ env delete tmp_pin tmp_bank tmp_phandle
+fi
+
+if test "${param_w1_pin_int_pullup}" = "1"; then
+ fdt set /soc/pinctrl@01c20800/w1_pins bias-pull-up
+fi
+
+if test "${param_uart1_rtscts}" = "1"; then
+ fdt get value tmp_phandle1 /soc/pinctrl@01c20800/uart1 phandle
+ fdt get value tmp_phandle2 /soc/pinctrl@01c20800/uart1_rts_cts phandle
+ fdt set /soc/serial@01c28400 pinctrl-names "default" "default"
+ fdt set /soc/serial@01c28400 pinctrl-0 "<${tmp_phandle1}>"
+ fdt set /soc/serial@01c28400 pinctrl-1 "<${tmp_phandle2}>"
+ env delete tmp_phandle1 tmp_phandle2
+fi
+
+if test "${param_uart2_rtscts}" = "1"; then
+ fdt get value tmp_phandle1 /soc/pinctrl@01c20800/uart2 phandle
+ fdt get value tmp_phandle2 /soc/pinctrl@01c20800/uart2_rts_cts phandle
+ fdt set /soc/serial@01c28800 pinctrl-names "default" "default"
+ fdt set /soc/serial@01c28800 pinctrl-0 "<${tmp_phandle1}>"
+ fdt set /soc/serial@01c28800 pinctrl-1 "<${tmp_phandle2}>"
+ env delete tmp_phandle1 tmp_phandle2
+fi
+
+if test "${param_uart3_rtscts}" = "1"; then
+ fdt get value tmp_phandle1 /soc/pinctrl@01c20800/uart3 phandle
+ fdt get value tmp_phandle2 /soc/pinctrl@01c20800/uart3_rts_cts phandle
+ fdt set /soc/serial@01c28c00 pinctrl-names "default" "default"
+ fdt set /soc/serial@01c28c00 pinctrl-0 "<${tmp_phandle1}>"
+ fdt set /soc/serial@01c28c00 pinctrl-1 "<${tmp_phandle2}>"
+ env delete tmp_phandle1 tmp_phandle2
+fi
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-i2c0.dts b/arch/arm/boot/dts/overlay/sun8i-h3-i2c0.dts
new file mode 100644
index 00000000..b457ac71
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-i2c0.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/aliases";
+ __overlay__ {
+ i2c0 = "/soc/i2c@01c2ac00";
+ };
+ };
+
+ fragment@1 {
+ target = <&i2c0>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-i2c1.dts b/arch/arm/boot/dts/overlay/sun8i-h3-i2c1.dts
new file mode 100644
index 00000000..fd0928a1
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-i2c1.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/aliases";
+ __overlay__ {
+ i2c1 = "/soc/i2c@01c2b000";
+ };
+ };
+
+ fragment@1 {
+ target = <&i2c1>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-i2c2.dts b/arch/arm/boot/dts/overlay/sun8i-h3-i2c2.dts
new file mode 100644
index 00000000..25b75b71
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-i2c2.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/aliases";
+ __overlay__ {
+ i2c2 = "/soc/i2c@01c2b400";
+ };
+ };
+
+ fragment@1 {
+ target = <&i2c2>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-pps-gpio.dts b/arch/arm/boot/dts/overlay/sun8i-h3-pps-gpio.dts
new file mode 100644
index 00000000..16a737b0
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-pps-gpio.dts
@@ -0,0 +1,29 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&pio>;
+ __overlay__ {
+ pps_pins: pps_pins {
+ pins = "PD14";
+ function = "gpio_in";
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/";
+ __overlay__ {
+ pps@0 {
+ compatible = "pps-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pps_pins>;
+ gpios = <&pio 3 14 0>; /* PD14 */
+ status = "okay";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-pwm.dts b/arch/arm/boot/dts/overlay/sun8i-h3-pwm.dts
new file mode 100644
index 00000000..ed3b8e60
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-pwm.dts
@@ -0,0 +1,39 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/chosen";
+ __overlay__ {
+ /delete-property/ stdout-path;
+ };
+ };
+
+ fragment@1 {
+ target = <&uart0>;
+ __overlay__ {
+ status = "disabled";
+ };
+ };
+
+ fragment@2 {
+ target = <&pio>;
+ __overlay__ {
+ pwm0_pin: pwm0 {
+ pins = "PA5";
+ function = "pwm0";
+ };
+ };
+ };
+
+ fragment@3 {
+ target = <&pwm>;
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_pin>;
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-spdif-out.dts b/arch/arm/boot/dts/overlay/sun8i-h3-spdif-out.dts
new file mode 100644
index 00000000..c7c01411
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-spdif-out.dts
@@ -0,0 +1,38 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&spdif>;
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spdif_tx_pins_a>;
+ status = "okay";
+ };
+ };
+
+ fragment@1 {
+ target-path = "/";
+ __overlay__ {
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "On-board SPDIF";
+
+ simple-audio-card,cpu {
+ sound-dai = <&spdif>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&spdif_out>;
+ };
+ };
+
+ spdif_out: spdif-out {
+ #sound-dai-cells = <0>;
+ compatible = "linux,spdif-dit";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-spi-add-cs1.dts b/arch/arm/boot/dts/overlay/sun8i-h3-spi-add-cs1.dts
new file mode 100644
index 00000000..bd8e2561
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-spi-add-cs1.dts
@@ -0,0 +1,41 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&pio>;
+ __overlay__ {
+ spi0_cs1: spi0_cs1 {
+ pins = "PA21";
+ function = "gpio_out";
+ output-high;
+ };
+
+ spi1_cs1: spi1_cs1 {
+ pins = "PA10";
+ function = "gpio_out";
+ output-high;
+ };
+ };
+ };
+
+ fragment@1 {
+ target = <&spi0>;
+ __overlay__ {
+ pinctrl-names = "default", "default";
+ pinctrl-1 = <&spi0_cs1>;
+ cs-gpios = <0>, <&pio 0 21 0>; /* PA21 */
+ };
+ };
+
+ fragment@2 {
+ target = <&spi1>;
+ __overlay__ {
+ pinctrl-names = "default", "default";
+ pinctrl-1 = <&spi1_cs1>;
+ cs-gpios = <0>, <&pio 0 10 0>; /* PA10 */
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-spi-jedec-nor.dts b/arch/arm/boot/dts/overlay/sun8i-h3-spi-jedec-nor.dts
new file mode 100644
index 00000000..ad22a71a
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-spi-jedec-nor.dts
@@ -0,0 +1,42 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/aliases";
+ __overlay__ {
+ spi0 = "/soc/spi@01c68000";
+ spi1 = "/soc/spi@01c69000";
+ };
+ };
+
+ fragment@1 {
+ target = <&spi0>;
+ __overlay__ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spiflash {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ status = "disabled";
+ };
+ };
+ };
+
+ fragment@2 {
+ target = <&spi1>;
+ __overlay__ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spiflash {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-spi-spidev.dts b/arch/arm/boot/dts/overlay/sun8i-h3-spi-spidev.dts
new file mode 100644
index 00000000..180979e0
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-spi-spidev.dts
@@ -0,0 +1,42 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/aliases";
+ __overlay__ {
+ spi0 = "/soc/spi@01c68000";
+ spi1 = "/soc/spi@01c69000";
+ };
+ };
+
+ fragment@1 {
+ target = <&spi0>;
+ __overlay__ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spidev {
+ compatible = "spidev";
+ status = "disabled";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+ };
+
+ fragment@2 {
+ target = <&spi1>;
+ __overlay__ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spidev {
+ compatible = "spidev";
+ status = "disabled";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-uart1.dts b/arch/arm/boot/dts/overlay/sun8i-h3-uart1.dts
new file mode 100644
index 00000000..8a4f7e49
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-uart1.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/aliases";
+ __overlay__ {
+ serial1 = "/soc/serial@01c28400";
+ };
+ };
+
+ fragment@1 {
+ target = <&uart1>;
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-uart2.dts b/arch/arm/boot/dts/overlay/sun8i-h3-uart2.dts
new file mode 100644
index 00000000..499a1b49
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-uart2.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/aliases";
+ __overlay__ {
+ serial2 = "/soc/serial@01c28800";
+ };
+ };
+
+ fragment@1 {
+ target = <&uart2>;
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins>;
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-uart3.dts b/arch/arm/boot/dts/overlay/sun8i-h3-uart3.dts
new file mode 100644
index 00000000..b5734c5b
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-uart3.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target-path = "/aliases";
+ __overlay__ {
+ serial3 = "/soc/serial@01c28c00";
+ };
+ };
+
+ fragment@1 {
+ target = <&uart3>;
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pins>;
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-usbhost0.dts b/arch/arm/boot/dts/overlay/sun8i-h3-usbhost0.dts
new file mode 100644
index 00000000..ff1d82fd
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-usbhost0.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&ehci0>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@1 {
+ target = <&ohci0>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-usbhost2.dts b/arch/arm/boot/dts/overlay/sun8i-h3-usbhost2.dts
new file mode 100644
index 00000000..bf0c4f59
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-usbhost2.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&ehci2>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@1 {
+ target = <&ohci2>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-usbhost3.dts b/arch/arm/boot/dts/overlay/sun8i-h3-usbhost3.dts
new file mode 100644
index 00000000..f737075b
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-usbhost3.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&ehci3>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@1 {
+ target = <&ohci3>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/overlay/sun8i-h3-w1-gpio.dts b/arch/arm/boot/dts/overlay/sun8i-h3-w1-gpio.dts
new file mode 100644
index 00000000..f4ccb7fb
--- /dev/null
+++ b/arch/arm/boot/dts/overlay/sun8i-h3-w1-gpio.dts
@@ -0,0 +1,29 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ compatible = "allwinner,sun8i-h3";
+
+ fragment@0 {
+ target = <&pio>;
+ __overlay__ {
+ w1_pins: w1_pins {
+ pins = "PD14";
+ function = "gpio_in";
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/";
+ __overlay__ {
+ onewire@0 {
+ compatible = "w1-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&w1_pins>;
+ gpios = <&pio 3 14 0>; /* PD14 */
+ status = "okay";
+ };
+ };
+ };
+};

View file

@ -1,37 +0,0 @@
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index c3e22263..b5845ad8 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -49,6 +49,32 @@
#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 = "mixer0-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";
+ };
+
+ simplefb_tv: framebuffer@1 {
+ compatible = "allwinner,simple-framebuffer",
+ "simple-framebuffer";
+ allwinner,pipeline = "de0-lcd1-tve0";
+ clocks = <&ccu CLK_BUS_TCON1>, <&ccu CLK_BUS_DE>,
+ <&ccu CLK_BUS_TVE>, <&ccu CLK_DE>,
+ <&ccu CLK_TCON0>, <&ccu CLK_TVE>;
+ status = "disabled";
+ };
+ };
+
clocks {
#address-cells = <1>;
#size-cells = <1>;

View file

@ -1,112 +0,0 @@
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
old mode 100644
new mode 100755
index 81523d5..6f8b2cb
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -868,6 +868,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-h3-beelink-x2.dtb \
sun8i-h3-nanopi-m1.dtb \
sun8i-h3-nanopi-neo.dtb \
+ sun8i-h3-nanopi-neo-air.dtb \
sun8i-h3-orangepi-2.dtb \
sun8i-h3-orangepi-lite.dtb \
sun8i-h3-orangepi-one.dtb \
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts
new file mode 100755
index 0000000..9160d42
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 James Pettigrew <james@innovum.com.au>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file 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.
+ *
+ * This file 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sun8i-h3-nanopi.dtsi"
+
+/ {
+ model = "FriendlyARM NanoPi NEO";
+ compatible = "friendlyarm,nanopi-neo", "allwinner,sun8i-h3";
+
+ aliases {
+ serial3 = &uart3;
+ };
+
+ wifi_pwrseq: wifi_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
+ };
+};
+
+&mmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins_a>;
+ vmmc-supply = <&reg_vcc3v3>;
+ vqmmc-supply = <&reg_vcc3v3>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ interrupt-parent = <&pio>;
+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 / EINT10 */
+ interrupt-names = "host-wake";
+ };
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_8bit_pins>;
+ vmmc-supply = <&reg_vcc3v3>;
+ vqmmc-supply = <&reg_vcc3v3>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&uart3 { /* Connected to AP6212 on Neo Air */
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pins>;
+ status = "okay";
+};

View file

@ -1,126 +0,0 @@
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 01180849..99c1809a 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -875,6 +875,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-h3-orangepi-pc-plus.dtb \
sun8i-h3-orangepi-plus.dtb \
sun8i-h3-orangepi-plus2e.dtb \
+ sun8i-h3-orangepi-zeroplus.dtb \
sun8i-r16-parrot.dtb \
sun8i-v3s-licheepi-zero.dtb
dtb-$(CONFIG_MACH_SUN9I) += \
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-zeroplus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-zeroplus.dts
new file mode 100644
index 00000000..f89d1207
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-zeroplus.dts
@@ -0,0 +1,108 @@
+
+#include "sun8i-h2-plus-orangepi-zero.dts"
+
+/ {
+ model = "Xunlong Orange Pi Zero Plus";
+ compatible = "xunlong,orangepi-zeroplus", "allwinner,sun8i-h3";
+
+ aliases {
+ ethernet1 = &brcmf;
+ };
+
+ /delete-node/ reg_vcc_wifi;
+
+ wifi_pwrseq: wifi_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_pwrseq_pin_orangepi>;
+ reset-gpios = <&pio 0 9 GPIO_ACTIVE_LOW>;
+ post-power-on-delay-ms = <50>;
+ };
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_vbus_pin_a>;
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ enable-active-high;
+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ };
+};
+
+&ehci2 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&mmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins_a>;
+ vmmc-supply = <&reg_vcc3v3>;
+ vqmmc-supply = <&reg_vcc3v3>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ /delete-node/ sdio_wifi@1;
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ interrupt-parent = <&r_pio>;
+ interrupts = <0 7 IRQ_TYPE_LEVEL_LOW>; /* PL7 / EINT7 */
+ interrupt-names = "host-wake";
+ };
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_8bit_pins>;
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-hw-reset;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pio {
+ wifi_pwrseq_pin_orangepi: wifi_pwrseq_pin@0 {
+ allwinner,pins = "PA9";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+};
+
+&r_pio {
+ wifi_wake: wifi_wake@0 {
+ allwinner,pins = "PL7";
+ allwinner,function = "irq";
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+};
+
+&spi0 {
+ /delete-node/ spi-flash@0;
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
+

View file

@ -1,133 +0,0 @@
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index ab30cc63..cc176797 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -339,6 +339,12 @@ $(INSTALL_TARGETS):
%.dtb: | scripts
$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
+%.dtbo: | scripts
+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
+
+%.scr: | scripts
+ $(Q)$(MAKE) $(build)=$(boot)/dts ARCH=$(ARCH) $(boot)/dts/$@
+
PHONY += dtbs dtbs_install
dtbs: prepare scripts
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
index 3c79f859..eaaeb17e 100644
--- a/arch/arm/boot/.gitignore
+++ b/arch/arm/boot/.gitignore
@@ -3,4 +3,5 @@ zImage
xipImage
bootpImage
uImage
-*.dtb
+*.dtb*
+*.scr
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index b9a4a934..54e3c38d 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -119,6 +119,12 @@ zinstall install:
%.dtb: scripts
$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
+%.dtbo: | scripts
+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
+
+%.scr: | scripts
+ $(Q)$(MAKE) $(build)=$(boot)/dts ARCH=$(ARCH) $(boot)/dts/$@
+
PHONY += dtbs dtbs_install
dtbs: prepare scripts
diff --git a/arch/arm64/boot/dts/.gitignore b/arch/arm64/boot/dts/.gitignore
index b60ed208..5d65b54b 100644
--- a/arch/arm64/boot/dts/.gitignore
+++ b/arch/arm64/boot/dts/.gitignore
@@ -1 +1,2 @@
-*.dtb
+*.dtb*
+*.scr
diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst
index a1be75d0..ad8dc1c9 100644
--- a/scripts/Makefile.dtbinst
+++ b/scripts/Makefile.dtbinst
@@ -27,6 +27,9 @@ ifeq ("$(dtbinst-root)", "$(obj)")
endif
dtbinst-files := $(dtb-y)
+dtboinst-files := $(dtbo-y)
+script-files := $(scr-y)
+readme-files := $(dtbotxt-y)
dtbinst-dirs := $(dts-dirs)
# Helper targets for Installing DTBs into the boot directory
@@ -35,15 +38,24 @@ quiet_cmd_dtb_install = INSTALL $<
install-dir = $(patsubst $(dtbinst-root)%,$(INSTALL_DTBS_PATH)%,$(obj))
-$(dtbinst-files) $(dtbinst-dirs): | __dtbs_install_prep
+$(dtbinst-files) $(dtboinst-files) $(readme-files) $(script-files) $(dtbinst-dirs): | __dtbs_install_prep
$(dtbinst-files): %.dtb: $(obj)/%.dtb
$(call cmd,dtb_install,$(install-dir))
+$(dtboinst-files): %.dtbo: $(obj)/%.dtbo
+ $(call cmd,dtb_install,$(install-dir))
+
+$(script-files): %.scr: $(obj)/%.scr
+ $(call cmd,dtb_install,$(install-dir))
+
+$(readme-files): %: $(src)/%
+ $(call cmd,dtb_install,$(install-dir))
+
$(dtbinst-dirs):
$(Q)$(MAKE) $(dtbinst)=$(obj)/$@
-PHONY += $(dtbinst-files) $(dtbinst-dirs)
-__dtbs_install: $(dtbinst-files) $(dtbinst-dirs)
+PHONY += $(dtbinst-files) $(dtboinst-files) $(script-files) $(readme-files) $(dtbinst-dirs)
+__dtbs_install: $(dtbinst-files) $(dtboinst-files) $(script-files) $(readme-files) $(dtbinst-dirs)
.PHONY: $(PHONY)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f901..5ccd3490 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -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 -Wno-simple_bus_reg
+
# 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)
+quiet_cmd_dtco = DTCO $@
+cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \
+ $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
+ $(DTC) -O dtb -o $@ -b 0 \
+ -i $(dir $<) $(DTC_FLAGS) \
+ -d $(depfile).dtc.tmp $(dtc-tmp) ; \
+ cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
+
+$(obj)/%.dtbo: $(src)/%.dts FORCE
+ $(call if_changed_dep,dtco)
+
+quiet_cmd_scr = MKIMAGE $@
+cmd_scr = mkimage -C none -A $(ARCH) -T script -d $< $@
+
+$(obj)/%.scr: $(src)/%.scr-cmd FORCE
+ $(call if_changed,scr)
+
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
# Bzip2

View file

@ -1,16 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index ea74f58..d1aced2 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -43,6 +43,11 @@
#include "sunxi-h3-h5.dtsi"
/ {
+ aliases {
+ spi0 = &spi0;
+ spi1 = &spi1;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;

View file

@ -1,40 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
index e94f196b..9967fa66 100644
--- a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
@@ -144,6 +144,35 @@
status = "okay";
};
+&spi0 {
+ status = "okay";
+ spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "jedec,spi-nor";
+ reg = <0>; /* Chip select 0 */
+ spi-max-frequency = <10000000>;
+ status = "okay";
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@0 {
+ label = "uboot";
+ reg = <0x0 0x100000>;
+ };
+ partition@100000 {
+ label = "env";
+ reg = <0x100000 0x100000>;
+ };
+ partition@200000 {
+ label = "data";
+ reg = <0x200000 0x200000>;
+ };
+ };
+ };
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;

View file

@ -1,130 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
index 22b99b40..cc4e5398 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
@@ -47,6 +47,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
model = "Xunlong Orange Pi Lite";
@@ -90,6 +91,82 @@
gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
};
};
+
+ wifi_pwrseq: wifi_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 WIFI_EN */
+ };
+
+ vdd_cpux: gpio-regulator {
+ compatible = "regulator-gpio";
+ regulator-name = "vdd-cpux";
+ regulator-type = "voltage";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-ramp-delay = <50>; /* 4ms */
+ gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>;
+ gpios-states = <0x1>;
+ states = <1100000 0x0
+ 1300000 0x1>;
+ };
+};
+
+&cpu0 {
+ operating-points = <
+ 1008000 1300000
+ 816000 1100000
+ 624000 1100000
+ 480000 1100000
+ 312000 1100000
+ 240000 1100000
+ 120000 1100000
+ >;
+ #cooling-cells = <2>;
+ cooling-min-level = <0>;
+ cooling-max-level = <6>;
+ cpu0-supply = <&vdd_cpux>;
+};
+
+&cpu_thermal {
+ trips {
+ cpu_warm: cpu_warm {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_hot: cpu_hot {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_very_hot: cpu_very_hot {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu_crit: cpu_crit {
+ temperature = <105000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ cpu_warm_limit_cpu {
+ trip = <&cpu_warm>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT 1>;
+ };
+ cpu_hot_limit_cpu {
+ trip = <&cpu_hot>;
+ cooling-device = <&cpu0 2 3>;
+ };
+ cpu_very_hot_limit_cpu {
+ trip = <&cpu_very_hot>;
+ cooling-device = <&cpu0 5 THERMAL_NO_LIMIT>;
+ };
+ };
};
&ehci1 {
@@ -120,6 +197,7 @@
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins_a>;
vmmc-supply = <&reg_vcc3v3>;
+ mmc-pwrseq = <&wifi_pwrseq>;
bus-width = <4>;
non-removable;
status = "okay";
@@ -160,13 +238,25 @@
};
};
+&reg_usb0_vbus {
+ gpio = <&r_pio 0 2 GPIO_ACTIVE_HIGH>; /* PL2 */
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
&usbphy {
- /* USB VBUS is always on */
+ /* USB VBUS is always on except for the OTG port */
status = "okay";
+ usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+ usb0_vbus-supply = <&reg_usb0_vbus>;
};

View file

@ -1,25 +0,0 @@
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index c3e22263..6e00fec3 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -465,10 +491,20 @@
function = "uart2";
};
+ uart2_rts_cts_pins: uart2_rts_cts {
+ pins = "PA2", "PA3";
+ function = "uart2";
+ };
+
uart3_pins: uart3 {
pins = "PA13", "PA14";
function = "uart3";
};
+
+ uart3_rts_cts_pins: uart3_rts_cts {
+ pins = "PA15", "PA16";
+ function = "uart3";
+ };
};
ths: ths@01c25000 {

View file

@ -1,23 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
index 8b93f5c7..db8c3fb4 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
@@ -51,12 +51,18 @@
/* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
ethernet1 = &rtl8189ftv;
};
+
+ wifi_pwrseq: wifi_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 WIFI_EN */
+ };
};
&mmc1 {
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins_a>;
vmmc-supply = <&reg_vcc3v3>;
+ mmc-pwrseq = <&wifi_pwrseq>;
bus-width = <4>;
non-removable;
status = "okay";

View file

@ -1,786 +0,0 @@
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_FHANDLE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_CGROUPS=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_BPF_SYSCALL=y
CONFIG_PERF_EVENTS=y
CONFIG_MODULES=y
CONFIG_BLK_DEV_BSGLIB=y
CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_MAC_PARTITION=y
CONFIG_LDM_PARTITION=y
CONFIG_ARCH_SUNXI=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_HIGHPTE=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=m
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_CPUFREQ_DT=y
CONFIG_CPU_IDLE=y
CONFIG_ARM_CPUIDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_KERNEL_MODE_NEON=y
CONFIG_HIBERNATION=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=m
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_FIB_TRIE_STATS=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_NET_IPIP=m
CONFIG_NET_IPGRE_DEMUX=m
CONFIG_NET_IPGRE=m
CONFIG_NET_FOU=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
CONFIG_INET_XFRM_MODE_TRANSPORT=m
CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_INET_XFRM_MODE_BEET=m
CONFIG_INET_LRO=m
CONFIG_INET_DIAG=m
CONFIG_INET_UDP_DIAG=m
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_HSTCP=m
CONFIG_TCP_CONG_HYBLA=m
CONFIG_TCP_CONG_SCALABLE=m
CONFIG_TCP_CONG_LP=m
CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_YEAH=m
CONFIG_TCP_CONG_ILLINOIS=m
CONFIG_TCP_CONG_DCTCP=m
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=m
CONFIG_IPV6_VTI=m
CONFIG_IPV6_GRE=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_IPV6_MROUTE=y
CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
CONFIG_IPV6_PIMSM_V2=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_TIMEOUT=y
CONFIG_NF_CONNTRACK_TIMESTAMP=y
CONFIG_NF_CT_PROTO_DCCP=m
CONFIG_NF_CT_PROTO_SCTP=m
CONFIG_NF_CT_PROTO_UDPLITE=m
CONFIG_NF_CONNTRACK_AMANDA=m
CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_H323=m
CONFIG_NF_CONNTRACK_IRC=m
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
CONFIG_NF_CONNTRACK_SNMP=m
CONFIG_NF_CONNTRACK_PPTP=m
CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CT_NETLINK_TIMEOUT=m
CONFIG_NF_CT_NETLINK_HELPER=m
CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
CONFIG_NFT_RBTREE=m
CONFIG_NFT_HASH=m
CONFIG_NFT_COUNTER=m
CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m
CONFIG_NFT_MASQ=m
CONFIG_NFT_REDIR=m
CONFIG_NFT_NAT=m
CONFIG_NFT_QUEUE=m
CONFIG_NFT_REJECT=m
CONFIG_NFT_COMPAT=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_HMARK=m
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
CONFIG_NETFILTER_XT_TARGET_LED=m
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_TEE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_BPF=m
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_CPU=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
CONFIG_NETFILTER_XT_MATCH_MARK=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_NFACCT=m
CONFIG_NETFILTER_XT_MATCH_OSF=m
CONFIG_NETFILTER_XT_MATCH_OWNER=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_RECENT=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_SOCKET=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_TIME=m
CONFIG_NETFILTER_XT_MATCH_U32=m
CONFIG_IP_VS=m
CONFIG_IP_VS_IPV6=y
CONFIG_IP_VS_DEBUG=y
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_PROTO_ESP=y
CONFIG_IP_VS_PROTO_AH=y
CONFIG_IP_VS_PROTO_SCTP=y
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_FO=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
CONFIG_IP_VS_FTP=m
CONFIG_IP_VS_PE_SIP=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NFT_CHAIN_ROUTE_IPV4=m
CONFIG_NF_TABLES_ARP=m
CONFIG_NF_LOG_ARP=m
CONFIG_NFT_CHAIN_NAT_IPV4=m
CONFIG_NFT_MASQ_IPV4=m
CONFIG_NFT_REDIR_IPV4=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_SYNPROXY=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_NETMAP=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_NFT_CHAIN_ROUTE_IPV6=m
CONFIG_NFT_CHAIN_NAT_IPV6=m
CONFIG_NFT_MASQ_IPV6=m
CONFIG_NFT_REDIR_IPV6=m
CONFIG_IP6_NF_MATCH_AH=m
CONFIG_IP6_NF_MATCH_EUI64=m
CONFIG_IP6_NF_MATCH_FRAG=m
CONFIG_IP6_NF_MATCH_OPTS=m
CONFIG_IP6_NF_MATCH_HL=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
CONFIG_IP6_NF_MATCH_MH=m
CONFIG_IP6_NF_MATCH_RPFILTER=m
CONFIG_IP6_NF_MATCH_RT=m
CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_TARGET_SYNPROXY=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_RAW=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_IP6_NF_TARGET_NPT=m
CONFIG_L2TP=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_6LOWPAN=m
CONFIG_IEEE802154=m
CONFIG_IEEE802154_6LOWPAN=m
CONFIG_MAC802154=m
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_HFSC=m
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_MULTIQ=m
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFB=m
CONFIG_NET_SCH_SFQ=y
CONFIG_NET_SCH_TEQL=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
CONFIG_NET_SCH_DRR=m
CONFIG_NET_SCH_MQPRIO=m
CONFIG_NET_SCH_CHOKE=m
CONFIG_NET_SCH_QFQ=m
CONFIG_NET_SCH_CODEL=m
CONFIG_NET_SCH_FQ_CODEL=y
CONFIG_NET_SCH_FQ=m
CONFIG_NET_SCH_HHF=m
CONFIG_NET_SCH_PIE=y
CONFIG_NET_SCH_PLUG=m
CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_FLOW=m
CONFIG_NET_CLS_CGROUP=m
CONFIG_NET_CLS_BPF=m
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_CMP=m
CONFIG_NET_EMATCH_NBYTE=m
CONFIG_NET_EMATCH_U32=m
CONFIG_NET_EMATCH_META=m
CONFIG_NET_EMATCH_TEXT=m
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=m
CONFIG_NET_ACT_GACT=m
CONFIG_NET_ACT_MIRRED=m
CONFIG_NET_ACT_IPT=m
CONFIG_NET_ACT_NAT=m
CONFIG_NET_ACT_SIMP=m
CONFIG_NET_ACT_SKBEDIT=m
CONFIG_NET_ACT_CSUM=m
CONFIG_NET_ACT_VLAN=m
CONFIG_NET_ACT_BPF=m
CONFIG_NET_ACT_CONNMARK=m
CONFIG_VSOCKETS=m
CONFIG_NETLINK_MMAP=y
CONFIG_NETLINK_DIAG=y
CONFIG_BPF_JIT=y
CONFIG_BT=m
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBTSDIO=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_ATH3K=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_3WIRE=y
CONFIG_BT_HCIUART_INTEL=y
CONFIG_BT_HCIUART_BCM=y
CONFIG_BT_HCIBCM203X=m
CONFIG_BT_HCIBPA10X=m
CONFIG_BT_HCIBFUSB=m
CONFIG_BT_MRVL=m
CONFIG_BT_MRVL_SDIO=m
CONFIG_BT_ATH3K=m
CONFIG_CFG80211=m
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=m
CONFIG_MAC80211_MESH=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_LOOP_MIN_COUNT=0
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_WCACHE=y
CONFIG_EEPROM_SUNXI_SID=y
CONFIG_SCSI_MQ_DEFAULT=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_ATA=y
CONFIG_AHCI_SUNXI=y
CONFIG_MD=y
CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
CONFIG_BCACHE=m
CONFIG_BLK_DEV_DM=m
CONFIG_DM_MQ_DEFAULT=y
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_LOG_USERSPACE=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_QL=m
CONFIG_DM_MULTIPATH_ST=m
CONFIG_DM_DELAY=m
CONFIG_DM_UEVENT=y
CONFIG_DM_FLAKEY=m
CONFIG_DM_VERITY=m
CONFIG_DM_SWITCH=m
CONFIG_DM_LOG_WRITES=m
CONFIG_NETDEVICES=y
CONFIG_BONDING=m
CONFIG_DUMMY=m
CONFIG_NET_TEAM=m
CONFIG_NET_TEAM_MODE_BROADCAST=m
CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
CONFIG_NET_TEAM_MODE_RANDOM=m
CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
CONFIG_NET_TEAM_MODE_LOADBALANCE=m
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
CONFIG_TUN=m
CONFIG_VETH=m
CONFIG_NLMON=m
CONFIG_SUN4I_EMAC=y
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
CONFIG_STMMAC_ETH=y
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
CONFIG_PPP=m
CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_DEFLATE=m
CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=m
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=m
CONFIG_PPTP=m
CONFIG_PPPOL2TP=m
CONFIG_PPP_ASYNC=m
CONFIG_PPP_SYNC_TTY=m
CONFIG_LIBERTAS_THINFIRM=m
CONFIG_LIBERTAS_THINFIRM_USB=m
CONFIG_AT76C50X_USB=m
CONFIG_USB_ZD1201=m
CONFIG_USB_NET_RNDIS_WLAN=m
CONFIG_RTL8187=m
CONFIG_ATH_CARDS=m
CONFIG_ATH9K=m
CONFIG_ATH9K_AHB=y
CONFIG_ATH9K_CHANNEL_CONTEXT=y
CONFIG_ATH9K_HTC=m
CONFIG_CARL9170=m
CONFIG_ATH6KL=m
CONFIG_ATH6KL_SDIO=m
CONFIG_ATH6KL_USB=m
CONFIG_AR5523=m
CONFIG_ATH10K=m
CONFIG_WCN36XX=m
CONFIG_B43=m
CONFIG_B43_SDIO=y
CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_USB=y
CONFIG_HOSTAP=m
CONFIG_HOSTAP_FIRMWARE=y
CONFIG_LIBERTAS=m
CONFIG_LIBERTAS_USB=m
CONFIG_LIBERTAS_SDIO=m
CONFIG_LIBERTAS_SPI=m
CONFIG_P54_COMMON=m
CONFIG_P54_USB=m
CONFIG_P54_SPI=m
CONFIG_RT2X00=m
CONFIG_RT2500USB=m
CONFIG_RT73USB=m
CONFIG_RT2800USB=m
CONFIG_RT2800USB_RT3573=y
CONFIG_RT2800USB_RT53XX=y
CONFIG_RT2800USB_RT55XX=y
CONFIG_RT2800USB_UNKNOWN=y
CONFIG_RTL8192CU=m
CONFIG_WL_TI=y
CONFIG_WL1251=m
CONFIG_WL1251_SPI=m
CONFIG_WL1251_SDIO=m
CONFIG_WL12XX=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SPI=m
CONFIG_WLCORE_SDIO=m
CONFIG_ZD1211RW=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_SDIO=m
CONFIG_MWIFIEX_USB=m
CONFIG_CW1200=m
CONFIG_CW1200_WLAN_SDIO=m
CONFIG_CW1200_WLAN_SPI=m
CONFIG_RSI_91X=m
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SUN4I=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_AXP20X_PEK=y
CONFIG_INPUT_EVDEV=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=8
CONFIG_SERIAL_8250_RUNTIME_UARTS=8
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_SUN6I_P2WI=y
CONFIG_SPI=y
CONFIG_SPI_SPIDEV=y
CONFIG_SPI_SUN4I=y
CONFIG_SPI_SUN6I=y
CONFIG_GPIO_SYSFS=y
CONFIG_POWER_SUPPLY=y
CONFIG_POWER_RESET=y
CONFIG_THERMAL=y
CONFIG_THERMAL_OF=y
CONFIG_CPU_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
CONFIG_MFD_AXP20X=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_GPIO=y
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_RADIO_SUPPORT=y
CONFIG_MEDIA_SDR_SUPPORT=y
CONFIG_MEDIA_RC_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_ADV_DEBUG=y
CONFIG_DVB_DYNAMIC_MINORS=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_M5602=m
CONFIG_USB_STV06XX=m
CONFIG_USB_GL860=m
CONFIG_USB_GSPCA_BENQ=m
CONFIG_USB_GSPCA_CONEX=m
CONFIG_USB_GSPCA_CPIA1=m
CONFIG_USB_GSPCA_DTCS033=m
CONFIG_USB_GSPCA_ETOMS=m
CONFIG_USB_GSPCA_FINEPIX=m
CONFIG_USB_GSPCA_JEILINJ=m
CONFIG_USB_GSPCA_JL2005BCD=m
CONFIG_USB_GSPCA_KINECT=m
CONFIG_USB_GSPCA_KONICA=m
CONFIG_USB_GSPCA_MARS=m
CONFIG_USB_GSPCA_MR97310A=m
CONFIG_USB_GSPCA_NW80X=m
CONFIG_USB_GSPCA_OV519=m
CONFIG_USB_GSPCA_OV534=m
CONFIG_USB_GSPCA_OV534_9=m
CONFIG_USB_GSPCA_PAC207=m
CONFIG_USB_GSPCA_PAC7302=m
CONFIG_USB_GSPCA_PAC7311=m
CONFIG_USB_GSPCA_SE401=m
CONFIG_USB_GSPCA_SN9C2028=m
CONFIG_USB_GSPCA_SN9C20X=m
CONFIG_USB_GSPCA_SONIXB=m
CONFIG_USB_GSPCA_SONIXJ=m
CONFIG_USB_GSPCA_SPCA500=m
CONFIG_USB_GSPCA_SPCA501=m
CONFIG_USB_GSPCA_SPCA505=m
CONFIG_USB_GSPCA_SPCA506=m
CONFIG_USB_GSPCA_SPCA508=m
CONFIG_USB_GSPCA_SPCA561=m
CONFIG_USB_GSPCA_SPCA1528=m
CONFIG_USB_GSPCA_SQ905=m
CONFIG_USB_GSPCA_SQ905C=m
CONFIG_USB_GSPCA_SQ930X=m
CONFIG_USB_GSPCA_STK014=m
CONFIG_USB_GSPCA_STK1135=m
CONFIG_USB_GSPCA_STV0680=m
CONFIG_USB_GSPCA_SUNPLUS=m
CONFIG_USB_GSPCA_T613=m
CONFIG_USB_GSPCA_TOPRO=m
CONFIG_USB_GSPCA_TOUPTEK=m
CONFIG_USB_GSPCA_TV8532=m
CONFIG_USB_GSPCA_VC032X=m
CONFIG_USB_GSPCA_VICAM=m
CONFIG_USB_GSPCA_XIRLINK_CIT=m
CONFIG_USB_GSPCA_ZC3XX=m
CONFIG_USB_PWC=m
CONFIG_VIDEO_CPIA2=m
CONFIG_USB_ZR364XX=m
CONFIG_USB_STKWEBCAM=m
CONFIG_USB_S2255=m
CONFIG_VIDEO_PVRUSB2=m
CONFIG_VIDEO_HDPVR=m
CONFIG_VIDEO_USBVISION=m
CONFIG_VIDEO_STK1160_COMMON=m
CONFIG_VIDEO_AU0828=m
CONFIG_VIDEO_AU0828_RC=y
CONFIG_VIDEO_CX231XX=m
CONFIG_VIDEO_CX231XX_DVB=m
CONFIG_VIDEO_TM6000=m
CONFIG_VIDEO_TM6000_DVB=m
CONFIG_DVB_USB=m
CONFIG_DVB_USB_A800=m
CONFIG_DVB_USB_DIBUSB_MB=m
CONFIG_DVB_USB_DIBUSB_MC=m
CONFIG_DVB_USB_DIB0700=m
CONFIG_DVB_USB_UMT_010=m
CONFIG_DVB_USB_CXUSB=m
CONFIG_DVB_USB_M920X=m
CONFIG_DVB_USB_DIGITV=m
CONFIG_DVB_USB_VP7045=m
CONFIG_DVB_USB_VP702X=m
CONFIG_DVB_USB_GP8PSK=m
CONFIG_DVB_USB_NOVA_T_USB2=m
CONFIG_DVB_USB_TTUSB2=m
CONFIG_DVB_USB_DTT200U=m
CONFIG_DVB_USB_OPERA1=m
CONFIG_DVB_USB_AF9005=m
CONFIG_DVB_USB_AF9005_REMOTE=m
CONFIG_DVB_USB_PCTV452E=m
CONFIG_DVB_USB_DW2102=m
CONFIG_DVB_USB_CINERGY_T2=m
CONFIG_DVB_USB_DTV5100=m
CONFIG_DVB_USB_FRIIO=m
CONFIG_DVB_USB_AZ6027=m
CONFIG_DVB_USB_TECHNISAT_USB2=m
CONFIG_DVB_USB_V2=m
CONFIG_DVB_USB_AF9015=m
CONFIG_DVB_USB_AF9035=m
CONFIG_DVB_USB_ANYSEE=m
CONFIG_DVB_USB_AU6610=m
CONFIG_DVB_USB_AZ6007=m
CONFIG_DVB_USB_CE6230=m
CONFIG_DVB_USB_EC168=m
CONFIG_DVB_USB_GL861=m
CONFIG_DVB_USB_LME2510=m
CONFIG_DVB_USB_MXL111SF=m
CONFIG_DVB_USB_RTL28XXU=m
CONFIG_DVB_USB_DVBSKY=m
CONFIG_SMS_USB_DRV=m
CONFIG_DVB_B2C2_FLEXCOP_USB=m
CONFIG_DVB_AS102=m
CONFIG_USB_AIRSPY=m
CONFIG_USB_HACKRF=m
CONFIG_USB_MSI2500=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_SOC_CAMERA=m
CONFIG_SOC_CAMERA_PLATFORM=m
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_V4L_TEST_DRIVERS=y
CONFIG_VIDEO_VIVID=m
CONFIG_VIDEO_VIM2M=m
CONFIG_SMS_SDIO_DRV=m
CONFIG_RADIO_SI470X=y
CONFIG_USB_SI470X=m
CONFIG_I2C_SI470X=m
CONFIG_RADIO_SI4713=m
CONFIG_USB_SI4713=m
CONFIG_PLATFORM_SI4713=m
CONFIG_USB_MR800=m
CONFIG_USB_DSBR=m
CONFIG_RADIO_SHARK=m
CONFIG_RADIO_SHARK2=m
CONFIG_USB_KEENE=m
CONFIG_USB_RAREMONO=m
CONFIG_USB_MA901=m
CONFIG_RADIO_TEA5764=m
CONFIG_RADIO_SAA7706H=m
CONFIG_RADIO_TEF6862=m
CONFIG_RADIO_WL1273=m
CONFIG_SOC_CAMERA_IMX074=m
CONFIG_SOC_CAMERA_MT9M001=m
CONFIG_SOC_CAMERA_MT9M111=m
CONFIG_SOC_CAMERA_MT9T031=m
CONFIG_SOC_CAMERA_MT9T112=m
CONFIG_SOC_CAMERA_MT9V022=m
CONFIG_SOC_CAMERA_OV2640=m
CONFIG_SOC_CAMERA_OV5642=m
CONFIG_SOC_CAMERA_OV6650=m
CONFIG_SOC_CAMERA_OV772X=m
CONFIG_SOC_CAMERA_OV9640=m
CONFIG_SOC_CAMERA_OV9740=m
CONFIG_SOC_CAMERA_RJ54N1=m
CONFIG_SOC_CAMERA_TW9910=m
CONFIG_FB=y
CONFIG_FB_SIMPLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_SIMPLE=m
CONFIG_USB_SERIAL_CP210X=m
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_KEYSPAN=m
CONFIG_USB_SERIAL_KEYSPAN_MPR=y
CONFIG_USB_SERIAL_KEYSPAN_USA28=y
CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
CONFIG_USB_SERIAL_KEYSPAN_USA19=y
CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_MOS7720=m
CONFIG_USB_SERIAL_MOS7840=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_MMC=y
CONFIG_MMC_SUNXI=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_CLASS_FLASH=y
CONFIG_LEDS_LM3530=m
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_LP3944=m
CONFIG_LEDS_LP5521=m
CONFIG_LEDS_LP5523=m
CONFIG_LEDS_LP5562=m
CONFIG_LEDS_LP8501=m
CONFIG_LEDS_PCA955X=m
CONFIG_LEDS_PCA963X=m
CONFIG_LEDS_DAC124S085=m
CONFIG_LEDS_REGULATOR=y
CONFIG_LEDS_BD2802=m
CONFIG_LEDS_LT3593=m
CONFIG_LEDS_TCA6507=m
CONFIG_LEDS_LM355x=m
CONFIG_LEDS_BLINKM=m
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_LEDS_TRIGGER_CAMERA=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_INTF_SYSFS is not set
# CONFIG_RTC_INTF_PROC is not set
CONFIG_RTC_DRV_SUN6I=y
CONFIG_RTC_DRV_SUNXI=y
CONFIG_DMADEVICES=y
CONFIG_DMA_SUN6I=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXTCON=y
CONFIG_PWM=y
CONFIG_PWM_SUN4I=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PHY_SUN9I_USB=y
CONFIG_EXT4_FS=y
CONFIG_XFS_FS=m
CONFIG_XFS_POSIX_ACL=y
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_FANOTIFY=y
CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
CONFIG_OVERLAY_FS=m
CONFIG_FSCACHE=m
CONFIG_FSCACHE_STATS=y
CONFIG_FSCACHE_HISTOGRAM=y
CONFIG_CACHEFILES=m
CONFIG_CACHEFILES_HISTOGRAM=y
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_CRYPTO_DEV_SUN4I_SS=y
CONFIG_ARM_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM_NEON=y
CONFIG_CRYPTO_SHA256_ARM=y
CONFIG_CRYPTO_SHA512_ARM_NEON=y
CONFIG_CRYPTO_AES_ARM_BS=y
CONFIG_USB_STORAGE=y

View file

@ -1,26 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
index 63c5498..c585618 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
@@ -122,7 +122,7 @@
&cpu0 {
operating-points = <
- 1008000 1300000
+ 1200000 1300000
816000 1100000
624000 1100000
480000 1100000
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
index 87e495f..fb85217 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
@@ -115,7 +115,7 @@
&cpu0 {
operating-points = <
- 1008000 1300000
+ 1200000 1300000
816000 1100000
624000 1100000
480000 1100000

View file

@ -1,19 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
index 50e7e770..16845848 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
@@ -107,6 +107,14 @@
};
};
+&codec {
+ allwinner,audio-routing =
+ "Line Out", "LINEOUT",
+ "MIC1", "Mic",
+ "Mic", "MBIAS";
+ status = "okay";
+};
+
&de {
status = "okay";
};

View file

@ -1,13 +0,0 @@
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 5b82d160..bccfb98f 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -560,7 +560,7 @@
i2c2: i2c@01c2b400 {
compatible = "allwinner,sun6i-a31-i2c";
- reg = <0x01c2b000 0x400>;
+ reg = <0x01c2b400 0x400>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_I2C2>;
resets = <&ccu RST_BUS_I2C2>;

View file

@ -1,198 +0,0 @@
From b56f5cbc7e08ec7d31c42fc41e5247677f20b143 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Date: Tue, 14 Feb 2017 21:51:01 +0000
Subject: crypto: arm/aes-neonbs - resolve fallback cipher at runtime
Currently, the bit sliced NEON AES code for ARM has a link time
dependency on the scalar ARM asm implementation, which it uses as a
fallback to perform CBC encryption and the encryption of the initial
XTS tweak.
The bit sliced NEON code is both fast and time invariant, which makes
it a reasonable default on hardware that supports it. However, the
ARM asm code it pulls in is not time invariant, and due to the way it
is linked in, cannot be overridden by the new generic time invariant
driver. In fact, it will not be used at all, given that the ARM asm
code registers itself as a cipher with a priority that exceeds the
priority of the fixed time cipher.
So remove the link time dependency, and allocate the fallback cipher
via the crypto API. Note that this requires this driver's module_init
call to be replaced with late_initcall, so that the (possibly generic)
fallback cipher is guaranteed to be available when the builtin test
is performed at registration time.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
arch/arm/crypto/Kconfig | 2 +-
arch/arm/crypto/aes-neonbs-glue.c | 60 +++++++++++++++++++++++++++++----------
2 files changed, 46 insertions(+), 16 deletions(-)
diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig
index a8fce93..b9adedc 100644
--- a/arch/arm/crypto/Kconfig
+++ b/arch/arm/crypto/Kconfig
@@ -73,7 +73,7 @@ config CRYPTO_AES_ARM_BS
depends on KERNEL_MODE_NEON
select CRYPTO_BLKCIPHER
select CRYPTO_SIMD
- select CRYPTO_AES_ARM
+ select CRYPTO_AES
help
Use a faster and more secure NEON based implementation of AES in CBC,
CTR and XTS modes
diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c
index 2920b96..c763779 100644
--- a/arch/arm/crypto/aes-neonbs-glue.c
+++ b/arch/arm/crypto/aes-neonbs-glue.c
@@ -42,9 +42,6 @@ asmlinkage void aesbs_xts_encrypt(u8 out[], u8 const in[], u8 const rk[],
asmlinkage void aesbs_xts_decrypt(u8 out[], u8 const in[], u8 const rk[],
int rounds, int blocks, u8 iv[]);
-asmlinkage void __aes_arm_encrypt(const u32 rk[], int rounds, const u8 in[],
- u8 out[]);
-
struct aesbs_ctx {
int rounds;
u8 rk[13 * (8 * AES_BLOCK_SIZE) + 32] __aligned(AES_BLOCK_SIZE);
@@ -52,12 +49,12 @@ struct aesbs_ctx {
struct aesbs_cbc_ctx {
struct aesbs_ctx key;
- u32 enc[AES_MAX_KEYLENGTH_U32];
+ struct crypto_cipher *enc_tfm;
};
struct aesbs_xts_ctx {
struct aesbs_ctx key;
- u32 twkey[AES_MAX_KEYLENGTH_U32];
+ struct crypto_cipher *tweak_tfm;
};
static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
@@ -132,20 +129,18 @@ static int aesbs_cbc_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
ctx->key.rounds = 6 + key_len / 4;
- memcpy(ctx->enc, rk.key_enc, sizeof(ctx->enc));
-
kernel_neon_begin();
aesbs_convert_key(ctx->key.rk, rk.key_enc, ctx->key.rounds);
kernel_neon_end();
- return 0;
+ return crypto_cipher_setkey(ctx->enc_tfm, in_key, key_len);
}
static void cbc_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst)
{
struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
- __aes_arm_encrypt(ctx->enc, ctx->key.rounds, src, dst);
+ crypto_cipher_encrypt_one(ctx->enc_tfm, dst, src);
}
static int cbc_encrypt(struct skcipher_request *req)
@@ -181,6 +176,23 @@ static int cbc_decrypt(struct skcipher_request *req)
return err;
}
+static int cbc_init(struct crypto_tfm *tfm)
+{
+ struct aesbs_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->enc_tfm = crypto_alloc_cipher("aes", 0, 0);
+ if (IS_ERR(ctx->enc_tfm))
+ return PTR_ERR(ctx->enc_tfm);
+ return 0;
+}
+
+static void cbc_exit(struct crypto_tfm *tfm)
+{
+ struct aesbs_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_cipher(ctx->enc_tfm);
+}
+
static int ctr_encrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
@@ -228,7 +240,6 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
unsigned int key_len)
{
struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
- struct crypto_aes_ctx rk;
int err;
err = xts_verify_key(tfm, in_key, key_len);
@@ -236,15 +247,30 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
return err;
key_len /= 2;
- err = crypto_aes_expand_key(&rk, in_key + key_len, key_len);
+ err = crypto_cipher_setkey(ctx->tweak_tfm, in_key + key_len, key_len);
if (err)
return err;
- memcpy(ctx->twkey, rk.key_enc, sizeof(ctx->twkey));
-
return aesbs_setkey(tfm, in_key, key_len);
}
+static int xts_init(struct crypto_tfm *tfm)
+{
+ struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->tweak_tfm = crypto_alloc_cipher("aes", 0, 0);
+ if (IS_ERR(ctx->tweak_tfm))
+ return PTR_ERR(ctx->tweak_tfm);
+ return 0;
+}
+
+static void xts_exit(struct crypto_tfm *tfm)
+{
+ struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_cipher(ctx->tweak_tfm);
+}
+
static int __xts_crypt(struct skcipher_request *req,
void (*fn)(u8 out[], u8 const in[], u8 const rk[],
int rounds, int blocks, u8 iv[]))
@@ -256,7 +282,7 @@ static int __xts_crypt(struct skcipher_request *req,
err = skcipher_walk_virt(&walk, req, true);
- __aes_arm_encrypt(ctx->twkey, ctx->key.rounds, walk.iv, walk.iv);
+ crypto_cipher_encrypt_one(ctx->tweak_tfm, walk.iv, walk.iv);
kernel_neon_begin();
while (walk.nbytes >= AES_BLOCK_SIZE) {
@@ -309,6 +335,8 @@ static struct skcipher_alg aes_algs[] = { {
.base.cra_ctxsize = sizeof(struct aesbs_cbc_ctx),
.base.cra_module = THIS_MODULE,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
+ .base.cra_init = cbc_init,
+ .base.cra_exit = cbc_exit,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
@@ -342,6 +370,8 @@ static struct skcipher_alg aes_algs[] = { {
.base.cra_ctxsize = sizeof(struct aesbs_xts_ctx),
.base.cra_module = THIS_MODULE,
.base.cra_flags = CRYPTO_ALG_INTERNAL,
+ .base.cra_init = xts_init,
+ .base.cra_exit = xts_exit,
.min_keysize = 2 * AES_MIN_KEY_SIZE,
.max_keysize = 2 * AES_MAX_KEY_SIZE,
@@ -402,5 +432,5 @@ unregister_simds:
return err;
}
-module_init(aes_init);
+late_initcall(aes_init);
module_exit(aes_exit);
--
cgit v1.1

View file

@ -1,190 +0,0 @@
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index e3114832..03a773a9 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -46,13 +46,19 @@
#define SUN6I_TFR_CTL_XCH BIT(31)
#define SUN6I_INT_CTL_REG 0x10
+#define SUN6I_INT_CTL_RF_RDY BIT(0)
+#define SUN6I_INT_CTL_TF_ERQ BIT(4)
#define SUN6I_INT_CTL_RF_OVF BIT(8)
#define SUN6I_INT_CTL_TC BIT(12)
#define SUN6I_INT_STA_REG 0x14
#define SUN6I_FIFO_CTL_REG 0x18
+#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_MASK 0xff
+#define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS 0
#define SUN6I_FIFO_CTL_RF_RST BIT(15)
+#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_MASK 0xff
+#define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS 16
#define SUN6I_FIFO_CTL_TF_RST BIT(31)
#define SUN6I_FIFO_STA_REG 0x1c
@@ -68,14 +74,16 @@
#define SUN6I_CLK_CTL_CDR1(div) (((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8)
#define SUN6I_CLK_CTL_DRS BIT(12)
+#define SUN6I_MAX_XFER_SIZE 0xffffff
+
#define SUN6I_BURST_CNT_REG 0x30
-#define SUN6I_BURST_CNT(cnt) ((cnt) & 0xffffff)
+#define SUN6I_BURST_CNT(cnt) ((cnt) & SUN6I_MAX_XFER_SIZE)
#define SUN6I_XMIT_CNT_REG 0x34
-#define SUN6I_XMIT_CNT(cnt) ((cnt) & 0xffffff)
+#define SUN6I_XMIT_CNT(cnt) ((cnt) & SUN6I_MAX_XFER_SIZE)
#define SUN6I_BURST_CTL_CNT_REG 0x38
-#define SUN6I_BURST_CTL_CNT_STC(cnt) ((cnt) & 0xffffff)
+#define SUN6I_BURST_CTL_CNT_STC(cnt) ((cnt) & SUN6I_MAX_XFER_SIZE)
#define SUN6I_TXDATA_REG 0x200
#define SUN6I_RXDATA_REG 0x300
@@ -105,6 +113,31 @@ static inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value)
writel(value, sspi->base_addr + reg);
}
+static inline u32 sun6i_spi_get_tx_fifo_count(struct sun6i_spi *sspi)
+{
+ u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
+
+ reg >>= SUN6I_FIFO_STA_TF_CNT_BITS;
+
+ return reg & SUN6I_FIFO_STA_TF_CNT_MASK;
+}
+
+static inline void sun6i_spi_enable_interrupt(struct sun6i_spi *sspi, u32 mask)
+{
+ u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG);
+
+ reg |= mask;
+ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
+}
+
+static inline void sun6i_spi_disable_interrupt(struct sun6i_spi *sspi, u32 mask)
+{
+ u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG);
+
+ reg &= ~mask;
+ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg);
+}
+
static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
{
u32 reg, cnt;
@@ -127,10 +160,13 @@ static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi, int len)
{
+ u32 cnt;
u8 byte;
- if (len > sspi->len)
- len = sspi->len;
+ /* See how much data we can fit */
+ cnt = sspi->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi);
+
+ len = min3(len, (int)cnt, sspi->len);
while (len--) {
byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
@@ -158,9 +194,7 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
{
- struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
-
- return sspi->fifo_depth - 1;
+ return SUN6I_MAX_XFER_SIZE - 1;
}
static int sun6i_spi_transfer_one(struct spi_master *master,
@@ -170,12 +204,12 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
struct sun6i_spi *sspi = spi_master_get_devdata(master);
unsigned int mclk_rate, div, timeout;
unsigned int start, end, tx_time;
+ unsigned int trig_level;
unsigned int tx_len = 0;
int ret = 0;
u32 reg;
- /* We don't support transfer larger than the FIFO */
- if (tfr->len > sspi->fifo_depth)
+ if (tfr->len > SUN6I_MAX_XFER_SIZE)
return -EINVAL;
reinit_completion(&sspi->done);
@@ -191,6 +225,17 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST);
/*
+ * Setup FIFO interrupt trigger level
+ * Here we choose 3/4 of the full fifo depth, as it's the hardcoded
+ * value used in old generation of Allwinner SPI controller.
+ * (See spi-sun4i.c)
+ */
+ trig_level = sspi->fifo_depth / 4 * 3;
+ sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
+ (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) |
+ (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS));
+
+ /*
* Setup the transfer control register: Chip Select,
* polarities, etc.
*/
@@ -274,6 +319,10 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
/* Enable the interrupts */
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
+ sun6i_spi_enable_interrupt(sspi, SUN6I_INT_CTL_TC |
+ SUN6I_INT_CTL_RF_RDY);
+ if (tx_len > sspi->fifo_depth)
+ sun6i_spi_enable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ);
/* Start the transfer */
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
@@ -293,8 +342,6 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
goto out;
}
- sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
-
out:
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
@@ -309,10 +356,33 @@ static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
/* Transfer complete */
if (status & SUN6I_INT_CTL_TC) {
sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
+ sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
complete(&sspi->done);
return IRQ_HANDLED;
}
+ /* Receive FIFO 3/4 full */
+ if (status & SUN6I_INT_CTL_RF_RDY) {
+ sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+ /* Only clear the interrupt _after_ draining the FIFO */
+ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_RF_RDY);
+ return IRQ_HANDLED;
+ }
+
+ /* Transmit FIFO 3/4 empty */
+ if (status & SUN6I_INT_CTL_TF_ERQ) {
+ sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+ if (!sspi->len)
+ /* nothing left to transmit */
+ sun6i_spi_disable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ);
+
+ /* Only clear the interrupt _after_ re-seeding the FIFO */
+ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TF_ERQ);
+
+ return IRQ_HANDLED;
+ }
+
return IRQ_NONE;
}

View file

@ -1,21 +0,0 @@
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 9e2e099b..a065943d 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -749,13 +749,11 @@ static int spidev_probe(struct spi_device *spi)
/*
* spidev should never be referenced in DT without a specific
- * compatible string, it is a Linux implementation thing
- * rather than a description of the hardware.
+ * compatible string, but people don't care and use DT overlays
+ * to activate SPIdev on demand
*/
if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) {
- dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n");
- WARN_ON(spi->dev.of_node &&
- !of_match_device(spidev_dt_ids, &spi->dev));
+ dev_info(&spi->dev, "probing from DT");
}
spidev_probe_acpi(spi);

View file

@ -1,35 +0,0 @@
From d51579e6effa19c1ca4d6a29c3841cb454d56af6 Mon Sep 17 00:00:00 2001
From: Fabio Estevam <fabio.estevam@nxp.com>
Date: Sun, 16 Jul 2017 18:11:06 -0300
Subject: ASoC: sun4i-codec: Remove unneeded gpiod NULL check
The gpiod API checks for NULL descriptors, so there is no need to
duplicate the check in the driver.
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-codec.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 1500699..4c37231 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -1171,9 +1171,8 @@ static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w,
{
struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card);
- if (scodec->gpio_pa)
- gpiod_set_value_cansleep(scodec->gpio_pa,
- !!SND_SOC_DAPM_EVENT_ON(event));
+ gpiod_set_value_cansleep(scodec->gpio_pa,
+ !!SND_SOC_DAPM_EVENT_ON(event));
return 0;
}
--
cgit v1.1

View file

@ -1,34 +0,0 @@
From fe49cd980fc15cbb7eeb8d1a4ef45a14b807b55d Mon Sep 17 00:00:00 2001
From: "Gustavo A. R. Silva" <garsilva@embeddedor.com>
Date: Thu, 13 Jul 2017 00:52:23 -0500
Subject: ASoC: sun8i-codec: constify snd_soc_dai_ops structure
This structure is only stored in the ops field of a snd_soc_dai_driver
structure. That field is declared const, so snd_soc_dai_ops structures
that have this property can be declared as const also.
Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun8i-codec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 5723c34..253ae0b 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -341,7 +341,7 @@ static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
"AIF1 Slot 0 Right"},
};
-static struct snd_soc_dai_ops sun8i_codec_dai_ops = {
+static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
.hw_params = sun8i_codec_hw_params,
.set_fmt = sun8i_set_fmt,
};
--
cgit v1.1

View file

@ -1,72 +0,0 @@
From 72bfa2117bdb4bb5b07dd5ed833ff3c318fc70b6 Mon Sep 17 00:00:00 2001
From: Philipp Zabel <p.zabel@pengutronix.de>
Date: Wed, 19 Jul 2017 17:26:43 +0200
Subject: ASoC: sun4i: explicitly request exclusive reset control
Commit a53e35db70d1 ("reset: Ensure drivers are explicit when requesting
reset lines") started to transition the reset control request API calls
to explicitly state whether the driver needs exclusive or shared reset
control behavior. Convert all drivers requesting exclusive resets to the
explicit API call so the temporary transition helpers can be removed.
No functional changes.
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: alsa-devel@alsa-project.org
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-codec.c | 3 ++-
sound/soc/sunxi/sun4i-i2s.c | 2 +-
sound/soc/sunxi/sun4i-spdif.c | 3 ++-
3 files changed, 5 insertions(+), 3 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 4c37231..73d054f 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -1573,7 +1573,8 @@ static int sun4i_codec_probe(struct platform_device *pdev)
}
if (quirks->has_reset) {
- scodec->rst = devm_reset_control_get(&pdev->dev, NULL);
+ scodec->rst = devm_reset_control_get_exclusive(&pdev->dev,
+ NULL);
if (IS_ERR(scodec->rst)) {
dev_err(&pdev->dev, "Failed to get reset control\n");
return PTR_ERR(scodec->rst);
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 3635bbc..62b307b 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -716,7 +716,7 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
}
if (quirks->has_reset) {
- i2s->rst = devm_reset_control_get(&pdev->dev, NULL);
+ i2s->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(i2s->rst)) {
dev_err(&pdev->dev, "Failed to get reset control\n");
return PTR_ERR(i2s->rst);
diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
index eaefd07..c49f375 100644
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -520,7 +520,8 @@ static int sun4i_spdif_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
if (quirks->has_reset) {
- host->rst = devm_reset_control_get_optional(&pdev->dev, NULL);
+ host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
+ NULL);
if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
dev_err(&pdev->dev, "Failed to get reset: %d\n", ret);
--
cgit v1.1

View file

@ -1,42 +0,0 @@
From 3643e9172649f97f2e6301582890202abcc0f97e Mon Sep 17 00:00:00 2001
From: Arvind Yadav <arvind.yadav.cs@gmail.com>
Date: Tue, 25 Jul 2017 15:45:18 +0530
Subject: ASoC: sun4i-spdif: Handle return value of clk_prepare_enable.
clk_prepare_enable() can fail here and we must check its return value.
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-spdif.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
index c49f375..b4af4aa 100644
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -458,11 +458,16 @@ static int sun4i_spdif_runtime_suspend(struct device *dev)
static int sun4i_spdif_runtime_resume(struct device *dev)
{
struct sun4i_spdif_dev *host = dev_get_drvdata(dev);
+ int ret;
- clk_prepare_enable(host->spdif_clk);
- clk_prepare_enable(host->apb_clk);
+ ret = clk_prepare_enable(host->spdif_clk);
+ if (ret)
+ return ret;
+ ret = clk_prepare_enable(host->apb_clk);
+ if (ret)
+ clk_disable_unprepare(host->spdif_clk);
- return 0;
+ return ret;
}
static int sun4i_spdif_probe(struct platform_device *pdev)
--
cgit v1.1

View file

@ -1,88 +0,0 @@
From 47bea0c836867b6b1cdb714d58f2bfc8e2f5c386 Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 29 Jul 2017 16:17:42 +0200
Subject: ASoC: sun4i-i2s: Extend quirks scope
In preparation for the changes required to support newer SoCs then
quirks has been moved and also added to the device structure.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 62b307b..d7ee7a4 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -90,6 +90,15 @@
#define SUN4I_I2S_RX_CHAN_SEL_REG 0x38
#define SUN4I_I2S_RX_CHAN_MAP_REG 0x3c
+/**
+ * struct sun4i_i2s_quirks - Differences between SoC variants.
+ *
+ * @has_reset: SoC needs reset deasserted.
+ */
+struct sun4i_i2s_quirks {
+ bool has_reset;
+};
+
struct sun4i_i2s {
struct clk *bus_clk;
struct clk *mod_clk;
@@ -100,6 +109,8 @@ struct sun4i_i2s {
struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data;
+
+ const struct sun4i_i2s_quirks *variant;
};
struct sun4i_i2s_clk_div {
@@ -654,10 +665,6 @@ static int sun4i_i2s_runtime_suspend(struct device *dev)
return 0;
}
-struct sun4i_i2s_quirks {
- bool has_reset;
-};
-
static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.has_reset = false,
};
@@ -669,7 +676,6 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
static int sun4i_i2s_probe(struct platform_device *pdev)
{
struct sun4i_i2s *i2s;
- const struct sun4i_i2s_quirks *quirks;
struct resource *res;
void __iomem *regs;
int irq, ret;
@@ -690,8 +696,8 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
return irq;
}
- quirks = of_device_get_match_data(&pdev->dev);
- if (!quirks) {
+ i2s->variant = of_device_get_match_data(&pdev->dev);
+ if (!i2s->variant) {
dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
return -ENODEV;
}
@@ -715,7 +721,7 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
return PTR_ERR(i2s->mod_clk);
}
- if (quirks->has_reset) {
+ if (i2s->variant->has_reset) {
i2s->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(i2s->rst)) {
dev_err(&pdev->dev, "Failed to get reset control\n");
--
cgit v1.1

View file

@ -1,67 +0,0 @@
From 92ff5d085ecc8255600551055262bf98a8f3f1d0 Mon Sep 17 00:00:00 2001
From: Bhumika Goyal <bhumirks@gmail.com>
Date: Thu, 3 Aug 2017 21:30:20 +0530
Subject: ASoC: sunxi: make snd_soc_codec_driver structures as const
Declare snd_soc_codec_driver structures as const as they are either
passed as an argument to the function snd_soc_register_codec or stored as
reference in field codec of type sun4i_codec_quirks. Both the fucntion
argument and the codec field are of type const, so declare the
structures with this property as const.
Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-codec.c | 6 +++---
sound/soc/sunxi/sun8i-codec.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 73d054f..c668b8b 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -762,7 +762,7 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = {
{ "Mic1", NULL, "VMIC" },
};
-static struct snd_soc_codec_driver sun4i_codec_codec = {
+static const struct snd_soc_codec_driver sun4i_codec_codec = {
.component_driver = {
.controls = sun4i_codec_controls,
.num_controls = ARRAY_SIZE(sun4i_codec_controls),
@@ -1068,7 +1068,7 @@ static const struct snd_soc_dapm_route sun6i_codec_codec_dapm_routes[] = {
{ "Right ADC", NULL, "Right ADC Mixer" },
};
-static struct snd_soc_codec_driver sun6i_codec_codec = {
+static const struct snd_soc_codec_driver sun6i_codec_codec = {
.component_driver = {
.controls = sun6i_codec_codec_widgets,
.num_controls = ARRAY_SIZE(sun6i_codec_codec_widgets),
@@ -1096,7 +1096,7 @@ static const struct snd_soc_dapm_widget sun8i_a23_codec_codec_widgets[] = {
};
-static struct snd_soc_codec_driver sun8i_a23_codec_codec = {
+static const struct snd_soc_codec_driver sun8i_a23_codec_codec = {
.component_driver = {
.controls = sun8i_a23_codec_codec_controls,
.num_controls = ARRAY_SIZE(sun8i_a23_codec_codec_controls),
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 253ae0b..abfb710 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -360,7 +360,7 @@ static struct snd_soc_dai_driver sun8i_codec_dai = {
.ops = &sun8i_codec_dai_ops,
};
-static struct snd_soc_codec_driver sun8i_soc_codec = {
+static const struct snd_soc_codec_driver sun8i_soc_codec = {
.component_driver = {
.dapm_widgets = sun8i_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets),
--
cgit v1.1

View file

@ -1,50 +0,0 @@
From 0aef27cab880d9612331350c008aec00cbb3d247 Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 12 Aug 2017 13:00:49 +0200
Subject: ASoC: sun4i-i2s: Add clkdiv offsets to quirks
The BCLKDIV and MCLKDIV found on newer SoCs start from an offset of 1.
Add the functionality to adjust the division values according to the
needs to the device being used.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 8 ++++++++
1 file changed, 8 insertions(+)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index d7ee7a4..9a35313 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -94,9 +94,13 @@
* struct sun4i_i2s_quirks - Differences between SoC variants.
*
* @has_reset: SoC needs reset deasserted.
+ * @mclk_offset: Value by which mclkdiv needs to be adjusted.
+ * @bclk_offset: Value by which bclkdiv needs to be adjusted.
*/
struct sun4i_i2s_quirks {
bool has_reset;
+ unsigned int mclk_offset;
+ unsigned int bclk_offset;
};
struct sun4i_i2s {
@@ -237,6 +241,10 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s,
if (mclk_div < 0)
return -EINVAL;
+ /* Adjust the clock division values if needed */
+ bclk_div += i2s->variant->bclk_offset;
+ mclk_div += i2s->variant->mclk_offset;
+
regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG,
SUN4I_I2S_CLK_DIV_BCLK(bclk_div) |
SUN4I_I2S_CLK_DIV_MCLK(mclk_div) |
--
cgit v1.1

View file

@ -1,64 +0,0 @@
From cd1c63df5fa8196d8ed5138f1ecc22bbabf5f6df Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 12 Aug 2017 13:00:50 +0200
Subject: ASoC: sun4i-i2s: Add regmap config to quirks
The newer SoCs have a larger range than the original SoC that this
driver was developed for. By adding the regmap config to the quirks
then the driver can initialise the managed register map correctly.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 9a35313..f6f3c40 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -94,11 +94,13 @@
* struct sun4i_i2s_quirks - Differences between SoC variants.
*
* @has_reset: SoC needs reset deasserted.
+ * @sun4i_i2s_regmap: regmap config to use.
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
* @bclk_offset: Value by which bclkdiv needs to be adjusted.
*/
struct sun4i_i2s_quirks {
bool has_reset;
+ const struct regmap_config *sun4i_i2s_regmap;
unsigned int mclk_offset;
unsigned int bclk_offset;
};
@@ -674,11 +676,13 @@ static int sun4i_i2s_runtime_suspend(struct device *dev)
}
static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
- .has_reset = false,
+ .has_reset = false,
+ .sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
};
static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
- .has_reset = true,
+ .has_reset = true,
+ .sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
};
static int sun4i_i2s_probe(struct platform_device *pdev)
@@ -717,7 +721,7 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
}
i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
- &sun4i_i2s_regmap_config);
+ i2s->variant->sun4i_i2s_regmap);
if (IS_ERR(i2s->regmap)) {
dev_err(&pdev->dev, "Regmap initialisation failed\n");
return PTR_ERR(i2s->regmap);
--
cgit v1.1

View file

@ -1,63 +0,0 @@
From 3509476e522baaa68813609801c48aa428bae81a Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 12 Aug 2017 13:00:51 +0200
Subject: ASoC: sun4i-i2s: Add TX FIFO offset to quirks
It has been seen that the newer SoCs have a different TX FIFO
address. Add this to the quirks structure.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index f6f3c40..dfb794f 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -94,12 +94,14 @@
* struct sun4i_i2s_quirks - Differences between SoC variants.
*
* @has_reset: SoC needs reset deasserted.
+ * @reg_offset_txdata: offset of the tx fifo.
* @sun4i_i2s_regmap: regmap config to use.
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
* @bclk_offset: Value by which bclkdiv needs to be adjusted.
*/
struct sun4i_i2s_quirks {
bool has_reset;
+ unsigned int reg_offset_txdata; /* TX FIFO */
const struct regmap_config *sun4i_i2s_regmap;
unsigned int mclk_offset;
unsigned int bclk_offset;
@@ -677,11 +679,13 @@ static int sun4i_i2s_runtime_suspend(struct device *dev)
static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.has_reset = false,
+ .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
};
static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.has_reset = true,
+ .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
};
@@ -750,7 +754,8 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
}
}
- i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG;
+ i2s->playback_dma_data.addr = res->start +
+ i2s->variant->reg_offset_txdata;
i2s->playback_dma_data.maxburst = 8;
i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG;
--
cgit v1.1

View file

@ -1,35 +0,0 @@
From 827807549e690c84bba5aac99b58dfbd52fcef8c Mon Sep 17 00:00:00 2001
From: Donglin Peng <dolinux.peng@gmail.com>
Date: Sun, 20 Aug 2017 13:55:13 +0800
Subject: ASoC: sun4i-codec: Remove unnecessary function call
First of all,the address of pdev->dev is assigned to card->dev in
create_card,then the function platform_set_drvdata copies the value
the variable card to pdev->dev.driver_data, but when calling
snd_soc_register_card,the function dev_set_drvdata(card->dev, card)
will also do the same copy operation,so i think that the former copy
operation can be removed.
Signed-off-by: Peng Donglin <dolinux.peng@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-codec.c | 1 -
1 file changed, 1 deletion(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index c668b8b..baa9007 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -1655,7 +1655,6 @@ static int sun4i_codec_probe(struct platform_device *pdev)
goto err_unregister_codec;
}
- platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, scodec);
ret = snd_soc_register_card(card);
--
cgit v1.1

View file

@ -1,170 +0,0 @@
From 6eb4f27419d9250ac632df15d9dcf916d84b9944 Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 19 Aug 2017 14:48:32 +0200
Subject: ASoC: sun4i-i2s: Add regmap fields for channels
On the original i2s block the channel mapping and selection were
configured for stereo audio by default: This is not the case with
the newer SoCs and they are also located at different offsets.
To support the newer SoC then regmap fields have been added to the
quirks and these are initialised to their correct settings during
probing.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 77 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 69 insertions(+), 8 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index dfb794f..87feb5a 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -82,7 +82,7 @@
#define SUN4I_I2S_TX_CNT_REG 0x2c
#define SUN4I_I2S_TX_CHAN_SEL_REG 0x30
-#define SUN4I_I2S_TX_CHAN_SEL(num_chan) (((num_chan) - 1) << 0)
+#define SUN4I_I2S_CHAN_SEL(num_chan) (((num_chan) - 1) << 0)
#define SUN4I_I2S_TX_CHAN_MAP_REG 0x34
#define SUN4I_I2S_TX_CHAN_MAP(chan, sample) ((sample) << (chan << 2))
@@ -98,6 +98,10 @@
* @sun4i_i2s_regmap: regmap config to use.
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
* @bclk_offset: Value by which bclkdiv needs to be adjusted.
+ * @field_txchanmap: location of the tx channel mapping register.
+ * @field_rxchanmap: location of the rx channel mapping register.
+ * @field_txchansel: location of the tx channel select bit fields.
+ * @field_rxchansel: location of the rx channel select bit fields.
*/
struct sun4i_i2s_quirks {
bool has_reset;
@@ -105,6 +109,12 @@ struct sun4i_i2s_quirks {
const struct regmap_config *sun4i_i2s_regmap;
unsigned int mclk_offset;
unsigned int bclk_offset;
+
+ /* Register fields for i2s */
+ struct reg_field field_txchanmap;
+ struct reg_field field_rxchanmap;
+ struct reg_field field_txchansel;
+ struct reg_field field_rxchansel;
};
struct sun4i_i2s {
@@ -118,6 +128,12 @@ struct sun4i_i2s {
struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data;
+ /* Register fields for i2s */
+ struct regmap_field *field_txchanmap;
+ struct regmap_field *field_rxchanmap;
+ struct regmap_field *field_txchansel;
+ struct regmap_field *field_rxchansel;
+
const struct sun4i_i2s_quirks *variant;
};
@@ -268,6 +284,17 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
if (params_channels(params) != 2)
return -EINVAL;
+ /* Map the channels for playback and capture */
+ regmap_field_write(i2s->field_txchanmap, 0x76543210);
+ regmap_field_write(i2s->field_rxchanmap, 0x00003210);
+
+ /* Configure the channels */
+ regmap_field_write(i2s->field_txchansel,
+ SUN4I_I2S_CHAN_SEL(params_channels(params)));
+
+ regmap_field_write(i2s->field_rxchansel,
+ SUN4I_I2S_CHAN_SEL(params_channels(params)));
+
switch (params_physical_width(params)) {
case 16:
width = DMA_SLAVE_BUSWIDTH_2_BYTES;
@@ -490,13 +517,6 @@ static int sun4i_i2s_startup(struct snd_pcm_substream *substream,
SUN4I_I2S_CTRL_SDO_EN_MASK,
SUN4I_I2S_CTRL_SDO_EN(0));
- /* Enable the first two channels */
- regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG,
- SUN4I_I2S_TX_CHAN_SEL(2));
-
- /* Map them to the two first samples coming in */
- regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG,
- SUN4I_I2S_TX_CHAN_MAP(0, 0) | SUN4I_I2S_TX_CHAN_MAP(1, 1));
return clk_prepare_enable(i2s->mod_clk);
}
@@ -681,14 +701,49 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.has_reset = false,
.reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
+ .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
+ .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
+ .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
+ .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
};
static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.has_reset = true,
.reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
+ .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
+ .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
+ .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
+ .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
};
+static int sun4i_i2s_init_regmap_fields(struct device *dev,
+ struct sun4i_i2s *i2s)
+{
+ i2s->field_txchanmap =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_txchanmap);
+ if (IS_ERR(i2s->field_txchanmap))
+ return PTR_ERR(i2s->field_txchanmap);
+
+ i2s->field_rxchanmap =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_rxchanmap);
+ if (IS_ERR(i2s->field_rxchanmap))
+ return PTR_ERR(i2s->field_rxchanmap);
+
+ i2s->field_txchansel =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_txchansel);
+ if (IS_ERR(i2s->field_txchansel))
+ return PTR_ERR(i2s->field_txchansel);
+
+ i2s->field_rxchansel =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_rxchansel);
+ return PTR_ERR_OR_ZERO(i2s->field_rxchansel);
+}
+
static int sun4i_i2s_probe(struct platform_device *pdev)
{
struct sun4i_i2s *i2s;
@@ -782,6 +837,12 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
goto err_suspend;
}
+ ret = sun4i_i2s_init_regmap_fields(&pdev->dev, i2s);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not initialise regmap fields\n");
+ goto err_suspend;
+ }
+
return 0;
err_suspend:
--
cgit v1.1

View file

@ -1,110 +0,0 @@
From 771647159125e93547f15daa14131a30a26f9b60 Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 19 Aug 2017 14:48:33 +0200
Subject: ASoC: sun4i-i2s: Add regfields for word size select and sample
resolution
On newer SoCs the location of the slot width select and sample
resolution are different and also there is a bigger range of
support.
For the current supported rates then an offset is required.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 87feb5a..563de78 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -98,6 +98,9 @@
* @sun4i_i2s_regmap: regmap config to use.
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
* @bclk_offset: Value by which bclkdiv needs to be adjusted.
+ * @fmt_offset: Value by which wss and sr needs to be adjusted.
+ * @field_fmt_wss: regmap field to set word select size.
+ * @field_fmt_sr: regmap field to set sample resolution.
* @field_txchanmap: location of the tx channel mapping register.
* @field_rxchanmap: location of the rx channel mapping register.
* @field_txchansel: location of the tx channel select bit fields.
@@ -109,8 +112,11 @@ struct sun4i_i2s_quirks {
const struct regmap_config *sun4i_i2s_regmap;
unsigned int mclk_offset;
unsigned int bclk_offset;
+ unsigned int fmt_offset;
/* Register fields for i2s */
+ struct reg_field field_fmt_wss;
+ struct reg_field field_fmt_sr;
struct reg_field field_txchanmap;
struct reg_field field_rxchanmap;
struct reg_field field_txchansel;
@@ -129,6 +135,8 @@ struct sun4i_i2s {
struct snd_dmaengine_dai_dma_data playback_dma_data;
/* Register fields for i2s */
+ struct regmap_field *field_fmt_wss;
+ struct regmap_field *field_fmt_sr;
struct regmap_field *field_txchanmap;
struct regmap_field *field_rxchanmap;
struct regmap_field *field_txchansel;
@@ -314,9 +322,10 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
- SUN4I_I2S_FMT0_WSS_MASK | SUN4I_I2S_FMT0_SR_MASK,
- SUN4I_I2S_FMT0_WSS(wss) | SUN4I_I2S_FMT0_SR(sr));
+ regmap_field_write(i2s->field_fmt_wss,
+ wss + i2s->variant->fmt_offset);
+ regmap_field_write(i2s->field_fmt_sr,
+ sr + i2s->variant->fmt_offset);
return sun4i_i2s_set_clk_rate(i2s, params_rate(params),
params_width(params));
@@ -701,6 +710,8 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.has_reset = false,
.reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
+ .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
+ .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -711,6 +722,8 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.has_reset = true,
.reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
+ .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
+ .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -720,6 +733,18 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
static int sun4i_i2s_init_regmap_fields(struct device *dev,
struct sun4i_i2s *i2s)
{
+ i2s->field_fmt_wss =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_fmt_wss);
+ if (IS_ERR(i2s->field_fmt_wss))
+ return PTR_ERR(i2s->field_fmt_wss);
+
+ i2s->field_fmt_sr =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_fmt_sr);
+ if (IS_ERR(i2s->field_fmt_sr))
+ return PTR_ERR(i2s->field_fmt_sr);
+
i2s->field_txchanmap =
devm_regmap_field_alloc(dev, i2s->regmap,
i2s->variant->field_txchanmap);
--
cgit v1.1

View file

@ -1,146 +0,0 @@
From 296935213feb7bcb72ab8750a8cacb66baeb0eb3 Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 19 Aug 2017 14:48:34 +0200
Subject: ASoC: sun4i-i2s: bclk and lrclk polarity tidyup
On newer SoCs the bit fields for the blck and lrclk polarity are in
a different locations. Use regmap fields to set the polarity bits
as intended.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 45 ++++++++++++++++++++++++++++++++-------------
1 file changed, 32 insertions(+), 13 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 563de78..8c7ad5b 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -50,6 +50,8 @@
#define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0)
#define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0)
#define SUN4I_I2S_FMT0_FMT_I2S (0 << 0)
+#define SUN4I_I2S_FMT0_POLARITY_INVERTED (1)
+#define SUN4I_I2S_FMT0_POLARITY_NORMAL (0)
#define SUN4I_I2S_FMT1_REG 0x08
#define SUN4I_I2S_FIFO_TX_REG 0x0c
@@ -101,6 +103,8 @@
* @fmt_offset: Value by which wss and sr needs to be adjusted.
* @field_fmt_wss: regmap field to set word select size.
* @field_fmt_sr: regmap field to set sample resolution.
+ * @field_fmt_bclk: regmap field to set clk polarity.
+ * @field_fmt_lrclk: regmap field to set frame polarity.
* @field_txchanmap: location of the tx channel mapping register.
* @field_rxchanmap: location of the rx channel mapping register.
* @field_txchansel: location of the tx channel select bit fields.
@@ -117,6 +121,8 @@ struct sun4i_i2s_quirks {
/* Register fields for i2s */
struct reg_field field_fmt_wss;
struct reg_field field_fmt_sr;
+ struct reg_field field_fmt_bclk;
+ struct reg_field field_fmt_lrclk;
struct reg_field field_txchanmap;
struct reg_field field_rxchanmap;
struct reg_field field_txchansel;
@@ -137,6 +143,8 @@ struct sun4i_i2s {
/* Register fields for i2s */
struct regmap_field *field_fmt_wss;
struct regmap_field *field_fmt_sr;
+ struct regmap_field *field_fmt_bclk;
+ struct regmap_field *field_fmt_lrclk;
struct regmap_field *field_txchanmap;
struct regmap_field *field_rxchanmap;
struct regmap_field *field_txchansel;
@@ -335,6 +343,8 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
u32 val;
+ u32 bclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL;
+ u32 lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL;
/* DAI Mode */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -359,32 +369,25 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_IB_IF:
/* Invert both clocks */
- val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED |
- SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
+ bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED;
+ lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED;
break;
case SND_SOC_DAIFMT_IB_NF:
/* Invert bit clock */
- val = SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED |
- SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL;
+ bclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED;
break;
case SND_SOC_DAIFMT_NB_IF:
/* Invert frame clock */
- val = SUN4I_I2S_FMT0_LRCLK_POLARITY_INVERTED |
- SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL;
+ lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_INVERTED;
break;
case SND_SOC_DAIFMT_NB_NF:
- /* Nothing to do for both normal cases */
- val = SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL |
- SUN4I_I2S_FMT0_LRCLK_POLARITY_NORMAL;
break;
default:
return -EINVAL;
}
- regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
- SUN4I_I2S_FMT0_BCLK_POLARITY_MASK |
- SUN4I_I2S_FMT0_LRCLK_POLARITY_MASK,
- val);
+ regmap_field_write(i2s->field_fmt_bclk, bclk_polarity);
+ regmap_field_write(i2s->field_fmt_lrclk, lrclk_polarity);
/* DAI clock master masks */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -712,6 +715,8 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
.field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
+ .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
+ .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -724,6 +729,8 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
.field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
+ .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
+ .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -745,6 +752,18 @@ static int sun4i_i2s_init_regmap_fields(struct device *dev,
if (IS_ERR(i2s->field_fmt_sr))
return PTR_ERR(i2s->field_fmt_sr);
+ i2s->field_fmt_bclk =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_fmt_bclk);
+ if (IS_ERR(i2s->field_fmt_bclk))
+ return PTR_ERR(i2s->field_fmt_bclk);
+
+ i2s->field_fmt_lrclk =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_fmt_lrclk);
+ if (IS_ERR(i2s->field_fmt_lrclk))
+ return PTR_ERR(i2s->field_fmt_lrclk);
+
i2s->field_txchanmap =
devm_regmap_field_alloc(dev, i2s->regmap,
i2s->variant->field_txchanmap);
--
cgit v1.1

View file

@ -1,89 +0,0 @@
From 5f93b0639634929b8349f9f9d83e1d881c1c7d4a Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 19 Aug 2017 14:48:35 +0200
Subject: ASoC: sun4i-i2s: Add mclk enable regmap field
The location of the mclk output enable bit is different on newer
SoCs. Use a regmap field to enable it.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 8c7ad5b..761b7c0 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -101,6 +101,7 @@
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
* @bclk_offset: Value by which bclkdiv needs to be adjusted.
* @fmt_offset: Value by which wss and sr needs to be adjusted.
+ * @field_clkdiv_mclk_en: regmap field to enable mclk output.
* @field_fmt_wss: regmap field to set word select size.
* @field_fmt_sr: regmap field to set sample resolution.
* @field_fmt_bclk: regmap field to set clk polarity.
@@ -119,6 +120,7 @@ struct sun4i_i2s_quirks {
unsigned int fmt_offset;
/* Register fields for i2s */
+ struct reg_field field_clkdiv_mclk_en;
struct reg_field field_fmt_wss;
struct reg_field field_fmt_sr;
struct reg_field field_fmt_bclk;
@@ -141,6 +143,7 @@ struct sun4i_i2s {
struct snd_dmaengine_dai_dma_data playback_dma_data;
/* Register fields for i2s */
+ struct regmap_field *field_clkdiv_mclk_en;
struct regmap_field *field_fmt_wss;
struct regmap_field *field_fmt_sr;
struct regmap_field *field_fmt_bclk;
@@ -283,8 +286,9 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s,
regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG,
SUN4I_I2S_CLK_DIV_BCLK(bclk_div) |
- SUN4I_I2S_CLK_DIV_MCLK(mclk_div) |
- SUN4I_I2S_CLK_DIV_MCLK_EN);
+ SUN4I_I2S_CLK_DIV_MCLK(mclk_div));
+
+ regmap_field_write(i2s->field_clkdiv_mclk_en, 1);
return 0;
}
@@ -713,6 +717,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.has_reset = false,
.reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
+ .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
.field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
@@ -727,6 +732,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.has_reset = true,
.reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
+ .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
.field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3),
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
@@ -740,6 +746,12 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
static int sun4i_i2s_init_regmap_fields(struct device *dev,
struct sun4i_i2s *i2s)
{
+ i2s->field_clkdiv_mclk_en =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_clkdiv_mclk_en);
+ if (IS_ERR(i2s->field_clkdiv_mclk_en))
+ return PTR_ERR(i2s->field_clkdiv_mclk_en);
+
i2s->field_fmt_wss =
devm_regmap_field_alloc(dev, i2s->regmap,
i2s->variant->field_fmt_wss);
--
cgit v1.1

View file

@ -1,89 +0,0 @@
From dfd2293c8626f1282e6a6e30f591c0a83146f3d4 Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 19 Aug 2017 14:48:36 +0200
Subject: ASoC: sun4i-i2s: Add regmap field to set DAI format
On the newer SoCs the bits to configure the operational mode are
located in a different register. Add a regmap field so that this
location can be configured.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 761b7c0..d9910f6 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -106,6 +106,7 @@
* @field_fmt_sr: regmap field to set sample resolution.
* @field_fmt_bclk: regmap field to set clk polarity.
* @field_fmt_lrclk: regmap field to set frame polarity.
+ * @field_fmt_mode: regmap field to set the operational mode.
* @field_txchanmap: location of the tx channel mapping register.
* @field_rxchanmap: location of the rx channel mapping register.
* @field_txchansel: location of the tx channel select bit fields.
@@ -125,6 +126,7 @@ struct sun4i_i2s_quirks {
struct reg_field field_fmt_sr;
struct reg_field field_fmt_bclk;
struct reg_field field_fmt_lrclk;
+ struct reg_field field_fmt_mode;
struct reg_field field_txchanmap;
struct reg_field field_rxchanmap;
struct reg_field field_txchansel;
@@ -148,6 +150,7 @@ struct sun4i_i2s {
struct regmap_field *field_fmt_sr;
struct regmap_field *field_fmt_bclk;
struct regmap_field *field_fmt_lrclk;
+ struct regmap_field *field_fmt_mode;
struct regmap_field *field_txchanmap;
struct regmap_field *field_rxchanmap;
struct regmap_field *field_txchansel;
@@ -365,9 +368,7 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return -EINVAL;
}
- regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
- SUN4I_I2S_FMT0_FMT_MASK,
- val);
+ regmap_field_write(i2s->field_fmt_mode, val);
/* DAI clock polarity */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -722,6 +723,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
+ .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -737,6 +739,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
+ .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -776,6 +779,12 @@ static int sun4i_i2s_init_regmap_fields(struct device *dev,
if (IS_ERR(i2s->field_fmt_lrclk))
return PTR_ERR(i2s->field_fmt_lrclk);
+ i2s->field_fmt_mode =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_fmt_mode);
+ if (IS_ERR(i2s->field_fmt_mode))
+ return PTR_ERR(i2s->field_fmt_mode);
+
i2s->field_txchanmap =
devm_regmap_field_alloc(dev, i2s->regmap,
i2s->variant->field_txchanmap);
--
cgit v1.1

View file

@ -1,99 +0,0 @@
From d03d2737e2d20c6ffb242154a69e1a9313adb632 Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 19 Aug 2017 14:48:37 +0200
Subject: ASoC: sun4i-i2s: Check for slave select bit
The newer SoCs do not have this setting. Instead they set the pin
direction. Add a check to see if the bit is valid and if so set
it accordingly.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 37 +++++++++++++++++++++----------------
1 file changed, 21 insertions(+), 16 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index d9910f6..573acca 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -96,6 +96,7 @@
* struct sun4i_i2s_quirks - Differences between SoC variants.
*
* @has_reset: SoC needs reset deasserted.
+ * @has_slave_select_bit: SoC has a bit to enable slave mode.
* @reg_offset_txdata: offset of the tx fifo.
* @sun4i_i2s_regmap: regmap config to use.
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
@@ -114,6 +115,7 @@
*/
struct sun4i_i2s_quirks {
bool has_reset;
+ bool has_slave_select_bit;
unsigned int reg_offset_txdata; /* TX FIFO */
const struct regmap_config *sun4i_i2s_regmap;
unsigned int mclk_offset;
@@ -394,24 +396,25 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
regmap_field_write(i2s->field_fmt_bclk, bclk_polarity);
regmap_field_write(i2s->field_fmt_lrclk, lrclk_polarity);
- /* DAI clock master masks */
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBS_CFS:
- /* BCLK and LRCLK master */
- val = SUN4I_I2S_CTRL_MODE_MASTER;
- break;
- case SND_SOC_DAIFMT_CBM_CFM:
- /* BCLK and LRCLK slave */
- val = SUN4I_I2S_CTRL_MODE_SLAVE;
- break;
- default:
- return -EINVAL;
+ if (i2s->variant->has_slave_select_bit) {
+ /* DAI clock master masks */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* BCLK and LRCLK master */
+ val = SUN4I_I2S_CTRL_MODE_MASTER;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* BCLK and LRCLK slave */
+ val = SUN4I_I2S_CTRL_MODE_SLAVE;
+ break;
+ default:
+ return -EINVAL;
+ }
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
+ SUN4I_I2S_CTRL_MODE_MASK,
+ val);
}
- regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
- SUN4I_I2S_CTRL_MODE_MASK,
- val);
-
/* Set significant bits in our FIFOs */
regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
SUN4I_I2S_FIFO_CTRL_TX_MODE_MASK |
@@ -723,6 +726,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
+ .has_slave_select_bit = true,
.field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
@@ -739,6 +743,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
+ .has_slave_select_bit = true,
.field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
--
cgit v1.1

View file

@ -1,47 +0,0 @@
From 043b8daa578f30c2ba685ad13b121fd138b95750 Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 19 Aug 2017 14:48:38 +0200
Subject: ASoC: sun4i-i2s: Update global enable with bitmask
The default value of the config register is different on newer
SoCs and therefore enabling/disabling with a register write
will clear bits used to set the direction of the clock and frame
pins.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/sunxi/sun4i-i2s.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
(limited to 'sound/soc/sunxi')
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 573acca..19d50ca 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -529,8 +529,8 @@ static int sun4i_i2s_startup(struct snd_pcm_substream *substream,
struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
/* Enable the whole hardware block */
- regmap_write(i2s->regmap, SUN4I_I2S_CTRL_REG,
- SUN4I_I2S_CTRL_GL_EN);
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
+ SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN);
/* Enable the first output line */
regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
@@ -553,7 +553,8 @@ static void sun4i_i2s_shutdown(struct snd_pcm_substream *substream,
SUN4I_I2S_CTRL_SDO_EN_MASK, 0);
/* Disable the whole hardware block */
- regmap_write(i2s->regmap, SUN4I_I2S_CTRL_REG, 0);
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
+ SUN4I_I2S_CTRL_GL_EN, 0);
}
static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
--
cgit v1.1

View file

@ -1,345 +0,0 @@
From 7d2993811a1e07cd128847f07f63aae66a78d14b Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Sat, 19 Aug 2017 14:48:39 +0200
Subject: ASoC: sun4i-i2s: Add support for H3
The sun8i-h3 introduces a lot of changes to the i2s block such
as different register locations, extended clock division and
more operational modes. As we have to consider the earlier
implementation then these changes need to be isolated.
None of the new functionality has been implemented yet, the
driver has just been expanded to allow it work on the H3 SoC.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
.../devicetree/bindings/sound/sun4i-i2s.txt | 2 +
sound/soc/sunxi/sun4i-i2s.c | 176 ++++++++++++++++++++-
2 files changed, 176 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
index ee21da8..fc5da608 100644
--- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
@@ -8,6 +8,7 @@ Required properties:
- compatible: should be one of the following:
- "allwinner,sun4i-a10-i2s"
- "allwinner,sun6i-a31-i2s"
+ - "allwinner,sun8i-h3-i2s"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: should contain the I2S interrupt.
@@ -22,6 +23,7 @@ Required properties:
Required properties for the following compatibles:
- "allwinner,sun6i-a31-i2s"
+ - "allwinner,sun8i-h3-i2s"
- resets: phandle to the reset line for this codec
Example:
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 19d50ca..04f9258 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -92,11 +92,41 @@
#define SUN4I_I2S_RX_CHAN_SEL_REG 0x38
#define SUN4I_I2S_RX_CHAN_MAP_REG 0x3c
+/* Defines required for sun8i-h3 support */
+#define SUN8I_I2S_CTRL_BCLK_OUT BIT(18)
+#define SUN8I_I2S_CTRL_LRCK_OUT BIT(17)
+
+#define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8)
+#define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8)
+
+#define SUN8I_I2S_INT_STA_REG 0x0c
+#define SUN8I_I2S_FIFO_TX_REG 0x20
+
+#define SUN8I_I2S_CHAN_CFG_REG 0x30
+#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4)
+#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) (chan - 1)
+#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0)
+#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1)
+
+#define SUN8I_I2S_TX_CHAN_MAP_REG 0x44
+#define SUN8I_I2S_TX_CHAN_SEL_REG 0x34
+#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 11)
+#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12)
+#define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4)
+#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4)
+
+#define SUN8I_I2S_RX_CHAN_SEL_REG 0x54
+#define SUN8I_I2S_RX_CHAN_MAP_REG 0x58
+
/**
* struct sun4i_i2s_quirks - Differences between SoC variants.
*
* @has_reset: SoC needs reset deasserted.
* @has_slave_select_bit: SoC has a bit to enable slave mode.
+ * @has_fmt_set_lrck_period: SoC requires lrclk period to be set.
+ * @has_chcfg: tx and rx slot number need to be set.
+ * @has_chsel_tx_chen: SoC requires that the tx channels are enabled.
+ * @has_chsel_offset: SoC uses offset for selecting dai operational mode.
* @reg_offset_txdata: offset of the tx fifo.
* @sun4i_i2s_regmap: regmap config to use.
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
@@ -116,6 +146,10 @@
struct sun4i_i2s_quirks {
bool has_reset;
bool has_slave_select_bit;
+ bool has_fmt_set_lrck_period;
+ bool has_chcfg;
+ bool has_chsel_tx_chen;
+ bool has_chsel_offset;
unsigned int reg_offset_txdata; /* TX FIFO */
const struct regmap_config *sun4i_i2s_regmap;
unsigned int mclk_offset;
@@ -173,6 +207,7 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_bclk_div[] = {
{ .div = 8, .val = 3 },
{ .div = 12, .val = 4 },
{ .div = 16, .val = 5 },
+ /* TODO - extend divide ratio supported by newer SoCs */
};
static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = {
@@ -184,6 +219,7 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = {
{ .div = 12, .val = 5 },
{ .div = 16, .val = 6 },
{ .div = 24, .val = 7 },
+ /* TODO - extend divide ratio supported by newer SoCs */
};
static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s,
@@ -295,6 +331,12 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s,
regmap_field_write(i2s->field_clkdiv_mclk_en, 1);
+ /* Set sync period */
+ if (i2s->variant->has_fmt_set_lrck_period)
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
+ SUN8I_I2S_FMT0_LRCK_PERIOD_MASK,
+ SUN8I_I2S_FMT0_LRCK_PERIOD(32));
+
return 0;
}
@@ -303,12 +345,22 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
- int sr, wss;
+ int sr, wss, channels;
u32 width;
- if (params_channels(params) != 2)
+ channels = params_channels(params);
+ if (channels != 2)
return -EINVAL;
+ if (i2s->variant->has_chcfg) {
+ regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
+ SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK,
+ SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels));
+ regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
+ SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK,
+ SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels));
+ }
+
/* Map the channels for playback and capture */
regmap_field_write(i2s->field_txchanmap, 0x76543210);
regmap_field_write(i2s->field_rxchanmap, 0x00003210);
@@ -320,6 +372,11 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
regmap_field_write(i2s->field_rxchansel,
SUN4I_I2S_CHAN_SEL(params_channels(params)));
+ if (i2s->variant->has_chsel_tx_chen)
+ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
+ SUN8I_I2S_TX_CHAN_EN_MASK,
+ SUN8I_I2S_TX_CHAN_EN(channels));
+
switch (params_physical_width(params)) {
case 16:
width = DMA_SLAVE_BUSWIDTH_2_BYTES;
@@ -352,6 +409,7 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
u32 val;
+ u32 offset = 0;
u32 bclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL;
u32 lrclk_polarity = SUN4I_I2S_FMT0_POLARITY_NORMAL;
@@ -359,6 +417,7 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
val = SUN4I_I2S_FMT0_FMT_I2S;
+ offset = 1;
break;
case SND_SOC_DAIFMT_LEFT_J:
val = SUN4I_I2S_FMT0_FMT_LEFT_J;
@@ -370,6 +429,21 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return -EINVAL;
}
+ if (i2s->variant->has_chsel_offset) {
+ /*
+ * offset being set indicates that we're connected to an i2s
+ * device, however offset is only used on the sun8i block and
+ * i2s shares the same setting with the LJ format. Increment
+ * val so that the bit to value to write is correct.
+ */
+ if (offset > 0)
+ val++;
+ /* blck offset determines whether i2s or LJ */
+ regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
+ SUN8I_I2S_TX_CHAN_OFFSET_MASK,
+ SUN8I_I2S_TX_CHAN_OFFSET(offset));
+ }
+
regmap_field_write(i2s->field_fmt_mode, val);
/* DAI clock polarity */
@@ -413,6 +487,29 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
SUN4I_I2S_CTRL_MODE_MASK,
val);
+ } else {
+ /*
+ * The newer i2s block does not have a slave select bit,
+ * instead the clk pins are configured as inputs.
+ */
+ /* DAI clock master masks */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* BCLK and LRCLK master */
+ val = SUN8I_I2S_CTRL_BCLK_OUT |
+ SUN8I_I2S_CTRL_LRCK_OUT;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* BCLK and LRCLK slave */
+ val = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
+ SUN8I_I2S_CTRL_BCLK_OUT |
+ SUN8I_I2S_CTRL_LRCK_OUT,
+ val);
}
/* Set significant bits in our FIFOs */
@@ -653,6 +750,27 @@ static bool sun4i_i2s_volatile_reg(struct device *dev, unsigned int reg)
}
}
+static bool sun8i_i2s_rd_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SUN8I_I2S_FIFO_TX_REG:
+ return false;
+
+ default:
+ return true;
+ }
+}
+
+static bool sun8i_i2s_volatile_reg(struct device *dev, unsigned int reg)
+{
+ if (reg == SUN8I_I2S_INT_STA_REG)
+ return true;
+ if (reg == SUN8I_I2S_FIFO_TX_REG)
+ return false;
+
+ return sun4i_i2s_volatile_reg(dev, reg);
+}
+
static const struct reg_default sun4i_i2s_reg_defaults[] = {
{ SUN4I_I2S_CTRL_REG, 0x00000000 },
{ SUN4I_I2S_FMT0_REG, 0x0000000c },
@@ -666,6 +784,20 @@ static const struct reg_default sun4i_i2s_reg_defaults[] = {
{ SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210 },
};
+static const struct reg_default sun8i_i2s_reg_defaults[] = {
+ { SUN4I_I2S_CTRL_REG, 0x00060000 },
+ { SUN4I_I2S_FMT0_REG, 0x00000033 },
+ { SUN4I_I2S_FMT1_REG, 0x00000030 },
+ { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 },
+ { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 },
+ { SUN4I_I2S_CLK_DIV_REG, 0x00000000 },
+ { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 },
+ { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 },
+ { SUN8I_I2S_TX_CHAN_MAP_REG, 0x00000000 },
+ { SUN8I_I2S_RX_CHAN_SEL_REG, 0x00000000 },
+ { SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 },
+};
+
static const struct regmap_config sun4i_i2s_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -680,6 +812,19 @@ static const struct regmap_config sun4i_i2s_regmap_config = {
.volatile_reg = sun4i_i2s_volatile_reg,
};
+static const struct regmap_config sun8i_i2s_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN8I_I2S_RX_CHAN_MAP_REG,
+ .cache_type = REGCACHE_FLAT,
+ .reg_defaults = sun8i_i2s_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(sun8i_i2s_reg_defaults),
+ .writeable_reg = sun4i_i2s_wr_reg,
+ .readable_reg = sun8i_i2s_rd_reg,
+ .volatile_reg = sun8i_i2s_volatile_reg,
+};
+
static int sun4i_i2s_runtime_resume(struct device *dev)
{
struct sun4i_i2s *i2s = dev_get_drvdata(dev);
@@ -752,6 +897,29 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
};
+static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
+ .has_reset = true,
+ .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
+ .sun4i_i2s_regmap = &sun8i_i2s_regmap_config,
+ .mclk_offset = 1,
+ .bclk_offset = 2,
+ .fmt_offset = 3,
+ .has_fmt_set_lrck_period = true,
+ .has_chcfg = true,
+ .has_chsel_tx_chen = true,
+ .has_chsel_offset = true,
+ .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
+ .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2),
+ .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6),
+ .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
+ .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19),
+ .field_fmt_mode = REG_FIELD(SUN4I_I2S_CTRL_REG, 4, 5),
+ .field_txchanmap = REG_FIELD(SUN8I_I2S_TX_CHAN_MAP_REG, 0, 31),
+ .field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31),
+ .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2),
+ .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2),
+};
+
static int sun4i_i2s_init_regmap_fields(struct device *dev,
struct sun4i_i2s *i2s)
{
@@ -952,6 +1120,10 @@ static const struct of_device_id sun4i_i2s_match[] = {
.compatible = "allwinner,sun6i-a31-i2s",
.data = &sun6i_a31_i2s_quirks,
},
+ {
+ .compatible = "allwinner,sun8i-h3-i2s",
+ .data = &sun8i_h3_i2s_quirks,
+ },
{}
};
MODULE_DEVICE_TABLE(of, sun4i_i2s_match);
--
cgit v1.1

View file

@ -1,50 +0,0 @@
Add the new DAI blocks to the device tree. I2S0 and I2S1 are for
connecting to an external codec.
Signed-off-by: Marcus Cooper <codek...@gmail.com>
---
v2 changes compared to v1 are:
- removed i2s2 which is used for HDMI audio
---
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 11240a8313c2..ef87d29036d9 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -450,6 +450,32 @@
status = "disabled";
};
+ i2s0: i2s@01c22000 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-h3-i2s";
+ reg = <0x01c22000 0x400>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S0>, <&ccu CLK_I2S0>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 3>, <&dma 3>;
+ resets = <&ccu RST_BUS_I2S0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ i2s1: i2s@01c22400 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-h3-i2s";
+ reg = <0x01c22400 0x400>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S1>, <&ccu CLK_I2S1>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 4>, <&dma 4>;
+ resets = <&ccu RST_BUS_I2S1>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
codec: codec@01c22c00 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun8i-h3-codec";
--
2.14.1

View file

@ -1,21 +0,0 @@
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 11240a83..6049895c 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -310,6 +310,16 @@
function = "i2c2";
};
+ i2s0_pins: i2s0 {
+ pins = "PA18", "PA19", "PA20", "PA21";
+ function = "i2s0";
+ };
+
+ i2s1_pins: i2s1 {
+ pins = "PG10", "PG11", "PG12", "PG13";
+ function = "i2s1";
+ };
+
mmc0_pins_a: mmc0@0 {
pins = "PF0", "PF1", "PF2", "PF3",
"PF4", "PF5";

View file

@ -1,307 +0,0 @@
From 89f47cc89889248c8747422d45ddfff9d6993aaf Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sun, 3 Sep 2017 17:30:46 +0800
Subject: [PATCH] Revert "arm64: dts: allwinner: Revert EMAC changes"
This reverts commit 87e1f5e8bb4bd584de0a8f3b1e42196dca221d02.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
.../boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 16 ++++++++++++++++
.../boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 15 +++++++++++++++
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 17 +++++++++++++++++
.../dts/allwinner/sun50i-a64-sopine-baseboard.dts | 16 ++++++++++++++++
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 20 ++++++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts | 17 +++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 17 +++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-orangepi-prime.dts | 17 +++++++++++++++++
8 files changed, 135 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
index 6872135d7f849..ba2fde2909f94 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
@@ -51,6 +51,7 @@
compatible = "sinovoip,bananapi-m64", "allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
};
@@ -67,6 +68,14 @@
};
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
@@ -77,6 +86,13 @@
bias-pull-up;
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
index f82ccf332c0fa..24f1aac366d64 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
@@ -48,3 +48,18 @@
/* TODO: Camera, touchscreen, etc. */
};
+
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index 7c533b6d4ba9a..827168bc22ed2 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -51,6 +51,7 @@
compatible = "pine64,pine64", "allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
@@ -78,6 +79,15 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rmii_pins>;
+ phy-mode = "rmii";
+ phy-handle = <&ext_rmii_phy1>;
+ status = "okay";
+
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
@@ -88,6 +98,13 @@
bias-pull-up;
};
+&mdio {
+ ext_rmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
index d891a1a27f6c5..216e3a5dafaef 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -53,6 +53,7 @@
"allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -76,6 +77,21 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 68aadc9b96dc1..bd0f33b77f572 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -449,6 +449,26 @@
#size-cells = <0>;
};
+ emac: ethernet@1c30000 {
+ compatible = "allwinner,sun50i-a64-emac";
+ syscon = <&syscon>;
+ reg = <0x01c30000 0x10000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
gic: interrupt-controller@1c81000 {
compatible = "arm,gic-400";
reg = <0x01c81000 0x1000>,
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
index 1c2387bd5df6f..9689087611945 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
@@ -50,6 +50,7 @@
compatible = "friendlyarm,nanopi-neo2", "allwinner,sun50i-h5";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -108,6 +109,22 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@7 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <7>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
index 4f77c8470f6c3..a8296feee8841 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
@@ -59,6 +59,7 @@
};
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -136,12 +137,28 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
index 6be06873e5afe..d906b302cbcdc 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
@@ -54,6 +54,7 @@
compatible = "xunlong,orangepi-prime", "allwinner,sun50i-h5";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -143,12 +144,28 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;

View file

@ -1,301 +0,0 @@
From 9b5c2c835ee29d5dce19b1cffe42cc2b47b6ac01 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sun, 3 Sep 2017 23:53:15 +0800
Subject: [PATCH] Revert "arm: dts: sunxi: Revert EMAC changes"
This reverts commit fe45174b72aead678da581bab9e9a37c9b26a070.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts | 9 ++++++++
arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts | 19 +++++++++++++++++
arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 7 ++++++
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 8 +++++++
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 8 +++++++
arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts | 5 +++++
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 8 +++++++
arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 22 +++++++++++++++++++
arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts | 16 ++++++++++++++
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 26 +++++++++++++++++++++++
10 files changed, 128 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
index b1502df7b5092..6713d0f2b3f4d 100644
--- a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
@@ -56,6 +56,8 @@
aliases {
serial0 = &uart0;
+ /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
+ ethernet0 = &emac;
ethernet1 = &xr819;
};
@@ -102,6 +104,13 @@
status = "okay";
};
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
index a337af1de3224..d756ff8251160 100644
--- a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
+++ b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
@@ -52,6 +52,7 @@
compatible = "sinovoip,bpi-m2-plus", "allwinner,sun8i-h3";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
};
@@ -114,12 +115,30 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
index 8d2cc6e9a03fa..78f6c24952dd1 100644
--- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
@@ -46,3 +46,10 @@
model = "FriendlyARM NanoPi NEO";
compatible = "friendlyarm,nanopi-neo", "allwinner,sun8i-h3";
};
+
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
index 8ff71b1bb45b1..17cdeae19c6f0 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
@@ -54,6 +54,7 @@
aliases {
serial0 = &uart0;
/* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
+ ethernet0 = &emac;
ethernet1 = &rtl8189;
};
@@ -117,6 +118,13 @@
status = "okay";
};
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
index 5fea430e0eb10..6880268e8b87b 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
@@ -52,6 +52,7 @@
compatible = "xunlong,orangepi-one", "allwinner,sun8i-h3";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -97,6 +98,13 @@
status = "okay";
};
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
index 8b93f5c781a70..a10281b455f50 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
@@ -53,6 +53,11 @@
};
};
+&emac {
+ /* LEDs changed to active high on the plus */
+ /delete-property/ allwinner,leds-active-low;
+};
+
&mmc1 {
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
index 1a044b17d6c61..998b60f8d295e 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
@@ -52,6 +52,7 @@
compatible = "xunlong,orangepi-pc", "allwinner,sun8i-h3";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -113,6 +114,13 @@
status = "okay";
};
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
index 828ae7a526d92..331ed683ac62c 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
@@ -47,6 +47,10 @@
model = "Xunlong Orange Pi Plus / Plus 2";
compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3";
+ aliases {
+ ethernet0 = &emac;
+ };
+
reg_gmac_3v3: gmac-3v3 {
compatible = "regulator-fixed";
regulator-name = "gmac-3v3";
@@ -74,6 +78,24 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ };
+};
+
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&mmc2_8bit_pins>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
index 97920b12a9445..80026f3caafc8 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
@@ -61,3 +61,19 @@
gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */
};
};
+
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 11240a8313c26..d38282b9e5d44 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -391,6 +391,32 @@
clocks = <&osc24M>;
};
+ emac: ethernet@1c30000 {
+ compatible = "allwinner,sun8i-h3-emac";
+ syscon = <&syscon>;
+ reg = <0x01c30000 0x10000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ mdio: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ int_mii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ clocks = <&ccu CLK_BUS_EPHY>;
+ resets = <&ccu RST_BUS_EPHY>;
+ };
+ };
+ };
+
spi0: spi@01c68000 {
compatible = "allwinner,sun8i-h3-spi";
reg = <0x01c68000 0x1000>;

View file

@ -1,31 +0,0 @@
From c2245f2ff7a5b41b9d5916097fbace8067e9ee65 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sun, 3 Sep 2017 17:29:56 +0800
Subject: [PATCH] Revert "net: stmmac: sun8i: Remove the compatibles"
This reverts commit ad4540cc5aa3dccb8e1e12458d57f8c40fae5a1c.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 39c2122a4f269..fffd6d5fc907b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -979,6 +979,14 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
}
static const struct of_device_id sun8i_dwmac_match[] = {
+ { .compatible = "allwinner,sun8i-h3-emac",
+ .data = &emac_variant_h3 },
+ { .compatible = "allwinner,sun8i-v3s-emac",
+ .data = &emac_variant_v3s },
+ { .compatible = "allwinner,sun8i-a83t-emac",
+ .data = &emac_variant_a83t },
+ { .compatible = "allwinner,sun50i-a64-emac",
+ .data = &emac_variant_a64 },
{ }
};
MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);

View file

@ -1,49 +0,0 @@
From b64dfec01050a010fa764dae3746353bdbdecfe1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jernej=20=C5=A0krabec?= <jernej.skrabec@siol.net>
Date: Sun, 30 Jul 2017 18:41:47 +0200
Subject: [PATCH] clk: sunxi-ng: Fix fractional mode for N-M clocks
N-M factor clock driver is missing a call to ccu_frac_helper_enable()
when fractional mode is used. Additionally, most SoCs require that M
factor must be set to 0 when fractional mode is used.
Without this patch, clock keeps the old value and clk_set_rate() returns
without error.
Fixes: 6174a1e24b0d ("clk: sunxi-ng: Add N-M-factor clock support")
CC: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/clk/sunxi-ng/ccu_nm.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index 5e5e90a4a50c8..c6ba866b99d3c 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -117,10 +117,22 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags;
u32 reg;
- if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate))
+ if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) {
+ spin_lock_irqsave(nm->common.lock, flags);
+
+ /* most SoCs require M to be 0 if fractional mode is used */
+ reg = readl(nm->common.base + nm->common.reg);
+ reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift);
+ writel(reg, nm->common.base + nm->common.reg);
+
+ spin_unlock_irqrestore(nm->common.lock, flags);
+
+ ccu_frac_helper_enable(&nm->common, &nm->frac);
+
return ccu_frac_helper_set_rate(&nm->common, &nm->frac, rate);
- else
+ } else {
ccu_frac_helper_disable(&nm->common, &nm->frac);
+ }
_nm.min_n = nm->n.min ?: 1;
_nm.max_n = nm->n.max ?: 1 << nm->n.width;

View file

@ -1,37 +0,0 @@
From 1e92ae651e766603d9c582ff356abf96ae90d933 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jernej=20=C5=A0krabec?= <jernej.skrabec@siol.net>
Date: Sun, 30 Jul 2017 18:41:48 +0200
Subject: [PATCH] clk: sunxi-ng: multiplier: Fix fractional mode
Driver for multiplier clock is missing a call to
ccu_frac_helper_enable() when fractional mode is selected.
Add a call to ccu_frac_helper_enable().
Fixes: d77e8135b340 ("clk: sunxi-ng: multiplier: Add fractional support")
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/clk/sunxi-ng/ccu_mult.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c
index 20d0300867f29..ee5e96222cb2f 100644
--- a/drivers/clk/sunxi-ng/ccu_mult.c
+++ b/drivers/clk/sunxi-ng/ccu_mult.c
@@ -111,10 +111,13 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags;
u32 reg;
- if (ccu_frac_helper_has_rate(&cm->common, &cm->frac, rate))
+ if (ccu_frac_helper_has_rate(&cm->common, &cm->frac, rate)) {
+ ccu_frac_helper_enable(&cm->common, &cm->frac);
+
return ccu_frac_helper_set_rate(&cm->common, &cm->frac, rate);
- else
+ } else {
ccu_frac_helper_disable(&cm->common, &cm->frac);
+ }
parent_rate = ccu_mux_helper_apply_prediv(&cm->common, &cm->mux, -1,
parent_rate);

View file

@ -1,45 +0,0 @@
From b655f36e2071a9a380477e2f07893c31cbf88f59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jernej=20=C5=A0krabec?= <jernej.skrabec@siol.net>
Date: Sun, 30 Jul 2017 18:41:49 +0200
Subject: [PATCH] clk: sunxi-ng: Make fractional helper less chatty
ccu_frac_helper_read_rate() prints some info which is not really
helpful except during debugging.
Replace printk() with pr_debug().
Fixes: 89a3dfb78707 ("clk: sunxi-ng: Add fractional lib")
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/clk/sunxi-ng/ccu_frac.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_frac.c b/drivers/clk/sunxi-ng/ccu_frac.c
index 8b5eb7756bf7d..ff9e72dc53372 100644
--- a/drivers/clk/sunxi-ng/ccu_frac.c
+++ b/drivers/clk/sunxi-ng/ccu_frac.c
@@ -67,18 +67,18 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
{
u32 reg;
- printk("%s: Read fractional\n", clk_hw_get_name(&common->hw));
+ pr_debug("%s: Read fractional\n", clk_hw_get_name(&common->hw));
if (!(common->features & CCU_FEATURE_FRACTIONAL))
return 0;
- printk("%s: clock is fractional (rates %lu and %lu)\n",
- clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]);
+ pr_debug("%s: clock is fractional (rates %lu and %lu)\n",
+ clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]);
reg = readl(common->base + common->reg);
- printk("%s: clock reg is 0x%x (select is 0x%x)\n",
- clk_hw_get_name(&common->hw), reg, cf->select);
+ pr_debug("%s: clock reg is 0x%x (select is 0x%x)\n",
+ clk_hw_get_name(&common->hw), reg, cf->select);
return (reg & cf->select) ? cf->rates[1] : cf->rates[0];
}

View file

@ -1,81 +0,0 @@
From 1d42460a49347af4d1db345197e5d1277336b312 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jernej=20=C5=A0krabec?= <jernej.skrabec@siol.net>
Date: Sun, 30 Jul 2017 18:41:50 +0200
Subject: [PATCH] clk: sunxi-ng: Wait for lock when using fractional mode
Currently ccu_frac_helper_set_rate() doesn't wait for a lock bit to be
set before returning. Because of that, unstable clock may be used.
Add a wait for lock in the helper function.
Fixes: 89a3dfb78707 ("clk: sunxi-ng: Add fractional lib")
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/clk/sunxi-ng/ccu_frac.c | 4 +++-
drivers/clk/sunxi-ng/ccu_frac.h | 2 +-
drivers/clk/sunxi-ng/ccu_mult.c | 3 ++-
drivers/clk/sunxi-ng/ccu_nm.c | 3 ++-
4 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_frac.c b/drivers/clk/sunxi-ng/ccu_frac.c
index ff9e72dc53372..d1d168d4c4f00 100644
--- a/drivers/clk/sunxi-ng/ccu_frac.c
+++ b/drivers/clk/sunxi-ng/ccu_frac.c
@@ -85,7 +85,7 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
int ccu_frac_helper_set_rate(struct ccu_common *common,
struct ccu_frac_internal *cf,
- unsigned long rate)
+ unsigned long rate, u32 lock)
{
unsigned long flags;
u32 reg, sel;
@@ -106,5 +106,7 @@ int ccu_frac_helper_set_rate(struct ccu_common *common,
writel(reg | sel, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags);
+ ccu_helper_wait_for_lock(common, lock);
+
return 0;
}
diff --git a/drivers/clk/sunxi-ng/ccu_frac.h b/drivers/clk/sunxi-ng/ccu_frac.h
index 7b1ee380156fa..efe2dd6bac01d 100644
--- a/drivers/clk/sunxi-ng/ccu_frac.h
+++ b/drivers/clk/sunxi-ng/ccu_frac.h
@@ -48,6 +48,6 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
int ccu_frac_helper_set_rate(struct ccu_common *common,
struct ccu_frac_internal *cf,
- unsigned long rate);
+ unsigned long rate, u32 lock);
#endif /* _CCU_FRAC_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c
index ee5e96222cb2f..12e0783caee64 100644
--- a/drivers/clk/sunxi-ng/ccu_mult.c
+++ b/drivers/clk/sunxi-ng/ccu_mult.c
@@ -114,7 +114,8 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
if (ccu_frac_helper_has_rate(&cm->common, &cm->frac, rate)) {
ccu_frac_helper_enable(&cm->common, &cm->frac);
- return ccu_frac_helper_set_rate(&cm->common, &cm->frac, rate);
+ return ccu_frac_helper_set_rate(&cm->common, &cm->frac,
+ rate, cm->lock);
} else {
ccu_frac_helper_disable(&cm->common, &cm->frac);
}
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index c6ba866b99d3c..a32158e8f2e35 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -129,7 +129,8 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
ccu_frac_helper_enable(&nm->common, &nm->frac);
- return ccu_frac_helper_set_rate(&nm->common, &nm->frac, rate);
+ return ccu_frac_helper_set_rate(&nm->common, &nm->frac,
+ rate, nm->lock);
} else {
ccu_frac_helper_disable(&nm->common, &nm->frac);
}

View file

@ -1,52 +0,0 @@
From cf9c6a1a49beecea35f395017a0e3aa9d97f2f17 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.xyz>
Date: Tue, 1 Aug 2017 21:12:53 +0800
Subject: [PATCH] drm: sun4i: add support for H3 mixers
Allwinner H3 SoC has two mixers, one has 1 VI channel and 3 UI channels,
and the other has 1 VI and 1 UI. There's also some graphics post-process
function that is missing on mixer1, however, as we currently support
none of these functions, the only difference that is shown to us is the
channel number difference.
Add support for these two variants.
Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
drivers/gpu/drm/sun4i/sun8i_mixer.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index cb193c5f16862..d658a3a8159a7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -390,11 +390,29 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
.ui_num = 1,
};
+static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
+ .vi_num = 1,
+ .ui_num = 3,
+};
+
+static const struct sun8i_mixer_cfg sun8i_h3_mixer1_cfg = {
+ .vi_num = 1,
+ .ui_num = 1,
+};
+
static const struct of_device_id sun8i_mixer_of_table[] = {
{
.compatible = "allwinner,sun8i-v3s-de2-mixer",
.data = &sun8i_v3s_mixer_cfg,
},
+ {
+ .compatible = "allwinner,sun8i-h3-de2-mixer0",
+ .data = &sun8i_h3_mixer0_cfg
+ },
+ {
+ .compatible = "allwinner,sun8i-h3-de2-mixer1",
+ .data = &sun8i_h3_mixer1_cfg
+ },
{ }
};
MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);

View file

@ -1,165 +0,0 @@
From 488fbb1ff0931604f2e97db76c840ef5f7305eae Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.xyz>
Date: Tue, 1 Aug 2017 21:12:54 +0800
Subject: [PATCH] drm: sun4i: add support for H3's TCON
Allwinner H3 has two special TCONs without channel 0.
Add support for this kind of TCON.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 43 +++++++++++++++++++++++++++-----------
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
3 files changed, 33 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index ace59651892fb..fd99fe8a4df72 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -188,6 +188,7 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
of_device_is_compatible(node, "allwinner,sun8i-a33-tcon") ||
+ of_device_is_compatible(node, "allwinner,sun8i-h3-tcon") ||
of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index d9791292553ef..270f09e381a5e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -59,6 +59,7 @@ void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
/* Disable the TCON's channel */
if (channel == 0) {
+ WARN_ON(!tcon->quirks->has_channel_0);
regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
SUN4I_TCON0_CTL_TCON_ENABLE, 0);
clk_disable_unprepare(tcon->dclk);
@@ -78,6 +79,7 @@ void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
/* Enable the TCON's channel */
if (channel == 0) {
+ WARN_ON(!tcon->quirks->has_channel_0);
regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
SUN4I_TCON0_CTL_TCON_ENABLE,
SUN4I_TCON0_CTL_TCON_ENABLE);
@@ -157,6 +159,8 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
u8 clk_delay;
u32 val = 0;
+ WARN_ON(!tcon->quirks->has_channel_0);
+
/* Configure the dot clock */
clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
@@ -366,10 +370,12 @@ static int sun4i_tcon_init_clocks(struct device *dev,
}
clk_prepare_enable(tcon->clk);
- tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
- if (IS_ERR(tcon->sclk0)) {
- dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
- return PTR_ERR(tcon->sclk0);
+ if (tcon->quirks->has_channel_0) {
+ tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
+ if (IS_ERR(tcon->sclk0)) {
+ dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
+ return PTR_ERR(tcon->sclk0);
+ }
}
if (tcon->quirks->has_channel_1) {
@@ -551,10 +557,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
goto err_free_clocks;
}
- ret = sun4i_dclk_create(dev, tcon);
- if (ret) {
- dev_err(dev, "Couldn't create our TCON dot clock\n");
- goto err_free_clocks;
+ if (tcon->quirks->has_channel_0) {
+ ret = sun4i_dclk_create(dev, tcon);
+ if (ret) {
+ dev_err(dev, "Couldn't create our TCON dot clock\n");
+ goto err_free_clocks;
+ }
}
ret = sun4i_tcon_init_irq(dev, tcon);
@@ -579,7 +587,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
return 0;
err_free_dotclock:
- sun4i_dclk_free(tcon);
+ if (tcon->quirks->has_channel_0)
+ sun4i_dclk_free(tcon);
err_free_clocks:
sun4i_tcon_free_clocks(tcon);
err_assert_reset:
@@ -593,7 +602,9 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
struct sun4i_tcon *tcon = dev_get_drvdata(dev);
list_del(&tcon->list);
- sun4i_dclk_free(tcon);
+
+ if (tcon->quirks->has_channel_0)
+ sun4i_dclk_free(tcon);
sun4i_tcon_free_clocks(tcon);
}
@@ -625,23 +636,30 @@ static int sun4i_tcon_remove(struct platform_device *pdev)
static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
.has_unknown_mux = true,
+ .has_channel_0 = true,
.has_channel_1 = true,
};
static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
+ .has_channel_0 = true,
.has_channel_1 = true,
};
static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
+ .has_channel_0 = true,
.has_channel_1 = true,
};
static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
- /* nothing is supported */
+ .has_channel_0 = true,
};
static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
- /* nothing is supported */
+ .has_channel_0 = true,
+};
+
+static const struct sun4i_tcon_quirks sun8i_h3_quirks = {
+ .has_channel_1 = true,
};
static const struct of_device_id sun4i_tcon_of_table[] = {
@@ -649,6 +667,7 @@ static const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
+ { .compatible = "allwinner,sun8i-h3-tcon", .data = &sun8i_h3_quirks },
{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
{ }
};
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 552c88ec16be3..de035e598129b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -145,6 +145,7 @@
struct sun4i_tcon_quirks {
bool has_unknown_mux; /* sun5i has undocumented mux */
+ bool has_channel_0; /* some A83T+ TCONs don't have channel 0*/
bool has_channel_1; /* a33 does not have channel 1 */
};

View file

@ -1,24 +0,0 @@
From bc3566abd1fa1a3333a15a0484d641d93343ce2c Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Tue, 1 Aug 2017 21:12:55 +0800
Subject: [PATCH] drm: sun4i: add compatible for H3 display engine
Add a compatible string for H3 display engine in sun4i_drv code.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index fd99fe8a4df72..02c80bb7b3856 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -314,6 +314,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
{ .compatible = "allwinner,sun6i-a31-display-engine" },
{ .compatible = "allwinner,sun6i-a31s-display-engine" },
{ .compatible = "allwinner,sun8i-a33-display-engine" },
+ { .compatible = "allwinner,sun8i-h3-display-engine" },
{ .compatible = "allwinner,sun8i-v3s-display-engine" },
{ }
};

View file

@ -1,32 +0,0 @@
From e591feb3b4929daf4eec146735d019291af5034e Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Tue, 1 Aug 2017 21:12:56 +0800
Subject: [PATCH] clk: sunxi-ng: allow CLK_DE to set CLK_PLL_DE for H3
Allwinner H3 features a PLL named CLK_PLL_DE, and a mod clock for the
"Display Engine 2.0" named CLK_DE. As the name indicated, the CLK_PLL_DE
is a PLL for CLK_DE.
Only CLK_DE and CLK_TVE have a parent of CLK_PLL_DE, and CLK_TVE is also
one part of the display clocks.
So allow CLK_DE to set CLK_PLL_DE (add CLK_SET_RATE_PARENT to it).
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 1729ff6a5aaed..7a222ff1ad0a9 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -439,7 +439,7 @@ static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram",
static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
- 0x104, 0, 4, 24, 3, BIT(31), 0);
+ 0x104, 0, 4, 24, 3, BIT(31), CLK_SET_RATE_PARENT);
static const char * const tcon_parents[] = { "pll-video" };
static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,

View file

@ -1,44 +0,0 @@
From 54c453465d296a98be67d6d758b564424952fc63 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Tue, 1 Aug 2017 21:12:57 +0800
Subject: [PATCH] clk: sunxi-ng: export CLK_PLL_DE for H3
The CLK_PLL_DE is needed to be referenced in device tree for H3, for
both forcing the parent of PLL_DE.
So export it to the device tree binding header.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/clk/sunxi-ng/ccu-sun8i-h3.h | 3 +--
include/dt-bindings/clock/sun8i-h3-ccu.h | 2 ++
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
index 1b4baea37d810..add3a7c182123 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
@@ -35,9 +35,8 @@
#define CLK_PLL_PERIPH0_2X 10
#define CLK_PLL_GPU 11
#define CLK_PLL_PERIPH1 12
-#define CLK_PLL_DE 13
-/* The CPUX clock is exported */
+/* The PLL_DE and CPUX clocks is exported */
#define CLK_AXI 15
#define CLK_AHB1 16
diff --git a/include/dt-bindings/clock/sun8i-h3-ccu.h b/include/dt-bindings/clock/sun8i-h3-ccu.h
index e139fe5c62ecd..5345957a8c2e6 100644
--- a/include/dt-bindings/clock/sun8i-h3-ccu.h
+++ b/include/dt-bindings/clock/sun8i-h3-ccu.h
@@ -45,6 +45,8 @@
#define CLK_PLL_PERIPH0 9
+#define CLK_PLL_DE 13
+
#define CLK_CPUX 14
#define CLK_BUS_CE 20

View file

@ -1,202 +0,0 @@
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 11240a83..ccde3a00 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -40,9 +40,11 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <dt-bindings/clock/sun8i-de2.h>
#include <dt-bindings/clock/sun8i-h3-ccu.h>
#include <dt-bindings/clock/sun8i-r-ccu.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/sun8i-de2.h>
#include <dt-bindings/reset/sun8i-h3-ccu.h>
#include <dt-bindings/reset/sun8i-r-ccu.h>
@@ -79,12 +81,98 @@
};
};
+ de: display-engine {
+ compatible = "allwinner,sun8i-h3-display-engine";
+ allwinner,pipelines = <&mixer0>,
+ <&mixer1>;
+ status = "disabled";
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
+ display_clocks: clock@1000000 {
+ /* compatible is in per SoC .dtsi file */
+ reg = <0x01000000 0x100000>;
+ clocks = <&ccu CLK_BUS_DE>,
+ <&ccu CLK_DE>;
+ clock-names = "bus",
+ "mod";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ assigned-clocks = <&ccu CLK_DE>;
+ assigned-clock-parents = <&ccu CLK_PLL_DE>;
+ assigned-clock-rates = <432000000>;
+ };
+
+ mixer0: mixer@1100000 {
+ compatible = "allwinner,sun8i-h3-de2-mixer0";
+ reg = <0x01100000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER0>,
+ <&display_clocks CLK_MIXER0>;
+ clock-names = "bus",
+ "mod";
+ resets = <&display_clocks RST_MIXER0>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ mixer0_out_tcon0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_in_mixer0>;
+ };
+
+ mixer0_out_tcon1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon1_in_mixer0>;
+ };
+ };
+ };
+ };
+
+ mixer1: mixer@1200000 {
+ compatible = "allwinner,sun8i-h3-de2-mixer1";
+ reg = <0x01200000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER1>,
+ <&display_clocks CLK_MIXER1>;
+ clock-names = "bus",
+ "mod";
+ /* resets is in per SoC .dtsi file */
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer1_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ mixer1_out_tcon0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_in_mixer1>;
+ };
+
+ mixer1_out_tcon1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon1_in_mixer1>;
+ };
+ };
+ };
+ };
+
syscon: syscon@1c00000 {
compatible = "allwinner,sun8i-h3-system-controller",
"syscon";
@@ -100,6 +188,86 @@
#dma-cells = <1>;
};
+ tcon0: lcd-controller@1c0c000 {
+ compatible = "allwinner,sun8i-h3-tcon";
+ reg = <0x01c0c000 0x1000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON0>,
+ <&ccu CLK_TCON0>;
+ clock-names = "ahb",
+ "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON0>;
+ reset-names = "lcd";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ tcon0_in_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&mixer0_out_tcon0>;
+ };
+
+ tcon0_in_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&mixer1_out_tcon0>;
+ };
+ };
+
+ tcon0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+ };
+
+ tcon1: lcd-controller@1c0d000 {
+ compatible = "allwinner,sun8i-h3-tcon";
+ reg = <0x01c0d000 0x1000>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON1>,
+ <&ccu CLK_TVE>;
+ clock-names = "ahb",
+ "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON1>;
+ reset-names = "lcd";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon1_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ tcon1_in_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&mixer0_out_tcon1>;
+ };
+
+ tcon1_in_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&mixer1_out_tcon1>;
+ };
+ };
+
+ tcon1_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+ };
+
mmc0: mmc@01c0f000 {
/* compatible and clocks are in per SoC .dtsi file */
reg = <0x01c0f000 0x1000>;

View file

@ -1,19 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index b36f9f42..b2896427 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -85,6 +85,14 @@
compatible = "allwinner,sun8i-h3-ccu";
};
+&display_clocks {
+ compatible = "allwinner,sun8i-a83t-de2-clk";
+};
+
+&mixer1 {
+ resets = <&display_clocks RST_WB>;
+};
+
&mmc0 {
compatible = "allwinner,sun7i-a20-mmc";
clocks = <&ccu CLK_BUS_MMC0>,

View file

@ -1,32 +0,0 @@
From d2259cb25f16b469b558d3b8d652862a7c5ddef5 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Tue, 15 Aug 2017 21:35:39 +0800
Subject: [PATCH] arm64: allwinner: h5: support display pipelines
As we have extracted the display pipelines to the H3/H5 common DTSI, we
can now support the display pipelines on H5.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
index d9a720bff05d3..305f7a28ba03c 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
@@ -98,6 +98,14 @@
compatible = "allwinner,sun50i-h5-ccu";
};
+&display_clocks {
+ compatible = "allwinner,sun50i-h5-de2-clk";
+};
+
+&mixer1 {
+ resets = <&display_clocks RST_MIXER1>;
+};
+
&mmc0 {
compatible = "allwinner,sun50i-h5-mmc",
"allwinner,sun50i-a64-mmc";

View file

@ -1,30 +0,0 @@
From 29510a43b7e3ff8249299e502661d3062ec8af4b Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 1 Jun 2017 20:29:06 +0200
Subject: [PATCH] drm: bridge: Enable polling hpd event in dw_hdmi
Some custom phys don't support hpd interrupts. Add support for polling
such events.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index bf14214fa4640..09cb5a3e4c718 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1954,7 +1954,11 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
struct drm_connector *connector = &hdmi->connector;
connector->interlace_allowed = 1;
- connector->polled = DRM_CONNECTOR_POLL_HPD;
+ if (hdmi->phy.ops->setup_hpd)
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+ else
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;
drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);

View file

@ -1,43 +0,0 @@
From 6e06b05d4d0128f3fcc32085f31c2b4add4c0ac7 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 2 Sep 2017 19:41:54 +0200
Subject: [PATCH] drm: bridge: Enable workaround in dw_hdmi for v1.32a
Allwinner SoCs have dw hdmi controller v1.32a which exhibits same
magenta line issue as i.MX6Q and i.MX6DL. Enable workaround for it.
Allwinner never released any kind of dw hdmi or errata documentation,
so it is not clear how many iterations need to be executed. One
iteration seems to be enough.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 09cb5a3e4c718..72969240a9d42 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1631,9 +1631,10 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
* then write one of the FC registers several times.
*
* The number of iterations matters and depends on the HDMI TX revision
- * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
- * i.MX6DL (v1.31a) have been identified as needing the workaround, with
- * 4 and 1 iterations respectively.
+ * (and possibly on the platform). So far i.MX6Q (v1.30a), i.MX6DL
+ * (v1.31a) and multiple Allwinner SoCs (v1.32a) have been identified
+ * as needing the workaround, with 4 iterations for v1.30a and 1
+ * iteration for others.
*/
switch (hdmi->version) {
@@ -1641,6 +1642,7 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
count = 4;
break;
case 0x131a:
+ case 0x132a:
count = 1;
break;
default:

View file

@ -1,28 +0,0 @@
From 7bdf732ba13e452e4ae2a717ea50d7e0f2d64ddd Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Tue, 11 Apr 2017 21:45:23 +0200
Subject: [PATCH] clk: sunxi: Add CLK_SET_RATE_PARENT flag for H3 HDMI clock
When setting the HDMI clock of H3, the PLL_VIDEO clock needs to be set.
Add CLK_SET_RATE_PARENT flag for H3 HDMI clock.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 7a222ff1ad0a9..36224ba93f9da 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -474,7 +474,7 @@ static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",
static const char * const hdmi_parents[] = { "pll-video" };
static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
- 0x150, 0, 4, 24, 2, BIT(31), 0);
+ 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M",
0x154, BIT(31), 0);

View file

@ -1,25 +0,0 @@
From 6f873f5d2d72a9a9779f0c26fc756ef5528ee2aa Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sat, 6 May 2017 16:03:20 +0800
Subject: [PATCH] drm/sun4i: allow to build for arm64
As the sun4i-drm driver already gained support for some AArch64-capable
Allwinner SoCs, allow it to be built on arm64 platform.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/gpu/drm/sun4i/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 6f860ece37754..369a31f834390 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -1,6 +1,6 @@
config DRM_SUN4I
tristate "DRM Support for Allwinner A10 Display Engine"
- depends on DRM && ARM && COMMON_CLK
+ depends on DRM && (ARM || ARM64) && COMMON_CLK
depends on ARCH_SUNXI || COMPILE_TEST
select DRM_GEM_CMA_HELPER
select DRM_KMS_HELPER

View file

@ -1,557 +0,0 @@
From 5de498da7efd4593976c4e41ca7367ac23352616 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Tue, 11 Apr 2017 21:46:33 +0200
Subject: [PATCH] drm: sun4i: Add a glue for the DesignWare HDMI controller in
H3
Allwinner H3 features DesignWare HDMI Transmitter paired with custom
PHY.
Add a glue driver for it.
For now, only video and CEC are supported. Audio will be supported at
a later time.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/sun4i/Kconfig | 9 +
drivers/gpu/drm/sun4i/Makefile | 1 +
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 500 ++++++++++++++++++++++++++++++++++
3 files changed, 510 insertions(+)
create mode 100644 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 06f05302ee75e..589502ffe31a9 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -40,6 +40,15 @@ config DRM_SUN4I_BACKEND
do some alpha blending and feed graphics to TCON. If M is
selected the module will be called sun4i-backend.
+config DRM_SUN8I_DW_HDMI
+ tristate "Support for Allwinner version of DesignWare HDMI"
+ depends on DRM_SUN4I
+ select DRM_DW_HDMI
+ help
+ Choose this option if you have an Allwinner SoC with the
+ DesignWare HDMI controller with custom HDMI PHY. If M is
+ selected the module will be called sun8i_dw_hdmi.
+
config DRM_SUN8I_MIXER
tristate "Support for Allwinner Display Engine 2.0 Mixer"
default MACH_SUN8I
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 43c753cafc884..9c56173bf1403 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o
obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
+obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i_dw_hdmi.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
new file mode 100644
index 0000000000000..65db3e10e311d
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2017, Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * Based on hdmi_bsp_sun8iw7.c which is:
+ * Copyright (c) 2016 Allwinnertech Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drm_of.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/bridge/dw_hdmi.h>
+
+#include "sun4i_crtc.h"
+#include "sun4i_tcon.h"
+
+#define SUN8I_HDMI_PHY_REG_POL 0x0000
+
+#define SUN8I_HDMI_PHY_REG_READ_EN 0x0010
+#define SUN8I_HDMI_PHY_REG_READ_EN_MAGIC 0x54524545
+
+#define SUN8I_HDMI_PHY_REG_UNSCRAMBLE 0x0014
+#define SUN8I_HDMI_PHY_REG_UNSCRAMBLE_MAGIC 0x42494E47
+
+#define SUN8I_HDMI_PHY_REG_CTRL 0x0020
+#define SUN8I_HDMI_PHY_REG_UNK1 0x0024
+#define SUN8I_HDMI_PHY_REG_UNK2 0x0028
+#define SUN8I_HDMI_PHY_REG_PLL 0x002c
+#define SUN8I_HDMI_PHY_REG_CLK 0x0030
+#define SUN8I_HDMI_PHY_REG_UNK3 0x0034
+
+#define SUN8I_HDMI_PHY_REG_STATUS 0x0038
+#define SUN8I_HDMI_PHY_REG_STATUS_READY BIT(7)
+#define SUN8I_HDMI_PHY_REG_STATUS_HPD BIT(19)
+
+#define SUN8I_HDMI_PHY_REG_CEC 0x003c
+
+#define to_sun8i_dw_hdmi(x) container_of(x, struct sun8i_dw_hdmi, x)
+#define set_bits(p, v) writel(readl(p) | (v), p)
+
+struct sun8i_dw_hdmi {
+ struct clk *clk_ahb;
+ struct clk *clk_ddc;
+ struct clk *clk_sfr;
+ struct device *dev;
+ struct drm_encoder encoder;
+ void __iomem *phy_base;
+ struct dw_hdmi_plat_data plat_data;
+ struct reset_control *rst_ddc;
+ struct reset_control *rst_hdmi;
+};
+
+static u32 sun8i_dw_hdmi_get_divider(int clk_khz)
+{
+ /*
+ * Due to missing documentation of HDMI PHY, we know correct
+ * settings only for following four PHY dividers. Select one
+ * based on pixel clock.
+ */
+ if (clk_khz <= 27000)
+ return 11;
+ else if (clk_khz <= 74250)
+ return 4;
+ else if (clk_khz <= 148500)
+ return 2;
+ else
+ return 1;
+}
+
+static void sun8i_dw_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+ struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+ struct sun4i_tcon *tcon = crtc->tcon;
+
+ DRM_DEBUG_DRIVER("Disabling HDMI Output\n");
+
+ sun4i_tcon_channel_disable(tcon, 1);
+}
+
+static void sun8i_dw_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+ struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+ struct sun4i_tcon *tcon = crtc->tcon;
+
+ DRM_DEBUG_DRIVER("Enabling HDMI Output\n");
+
+ sun4i_tcon_channel_enable(tcon, 1);
+}
+
+static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ struct sun8i_dw_hdmi *hdmi = to_sun8i_dw_hdmi(encoder);
+ struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+ struct sun4i_tcon *tcon = crtc->tcon;
+ u32 div;
+
+ sun4i_tcon1_mode_set(tcon, mode);
+
+ div = sun8i_dw_hdmi_get_divider(mode->crtc_clock);
+ clk_set_rate(hdmi->clk_sfr, mode->crtc_clock * 1000 * div);
+ clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
+}
+
+static const struct drm_encoder_helper_funcs
+ sun8i_dw_hdmi_encoder_helper_funcs = {
+ .mode_set = sun8i_dw_hdmi_encoder_mode_set,
+ .enable = sun8i_dw_hdmi_encoder_enable,
+ .disable = sun8i_dw_hdmi_encoder_disable,
+};
+
+static int sun8i_dw_hdmi_phy_init(struct dw_hdmi *hdmi_data, void *data,
+ struct drm_display_mode *mode)
+{
+ struct sun8i_dw_hdmi *hdmi = (struct sun8i_dw_hdmi *)data;
+ u32 div = sun8i_dw_hdmi_get_divider(mode->crtc_clock);
+ u32 val;
+
+ /*
+ * Unfortunately, we don't know much about those magic
+ * numbers. They are taken from Allwinner BSP driver.
+ */
+
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(val & ~0xf000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+
+ switch (div) {
+ case 1:
+ writel(0x30dc5fc0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x800863C0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(200);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ BIT(31) | BIT(30));
+ if (val < 0x3d)
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ val + 2);
+ else
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, 0x3f);
+ msleep(100);
+ writel(0x01FFFF7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x8063b000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F8246B5, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+ break;
+ case 2:
+ writel(0x39dc5040, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x80084381, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(100);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ BIT(31) | BIT(30));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, val);
+ writel(0x01FFFF7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x8063a800, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F81C485, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+ break;
+ case 4:
+ writel(0x39dc5040, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x80084343, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(100);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ BIT(31) | BIT(30));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, val);
+ writel(0x01FFFF7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x8063b000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F81C405, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+ break;
+ case 11:
+ writel(0x39dc5040, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x8008430a, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(100);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ BIT(31) | BIT(30));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, val);
+ writel(0x01FFFF7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x8063b000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F81C405, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+ break;
+ }
+
+ /* clear polarity bits */
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_POL);
+ val &= ~0x300;
+
+ /*
+ * Set polarity bits if necessary. Condition in original code
+ * is a bit weird. This is attempt to make it more reasonable
+ * and it works. It could be that bits and conditions are
+ * related and should be separated.
+ */
+ if (!(mode->flags & DRM_MODE_FLAG_PHSYNC) ||
+ !(mode->flags & DRM_MODE_FLAG_PVSYNC)) {
+ val |= 0x300;
+ }
+
+ writel(val, hdmi->phy_base + SUN8I_HDMI_PHY_REG_POL);
+
+ return 0;
+}
+
+static void sun8i_dw_hdmi_phy_disable(struct dw_hdmi *hdmi_data, void *data)
+{
+ struct sun8i_dw_hdmi *hdmi = (struct sun8i_dw_hdmi *)data;
+
+ /* Disable output and stop PLL */
+ writel(7, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+}
+
+static enum drm_connector_status
+ sun8i_dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi_data,
+ void *data)
+{
+ struct sun8i_dw_hdmi *hdmi = (struct sun8i_dw_hdmi *)data;
+ u32 reg_val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+
+ return (reg_val & SUN8I_HDMI_PHY_REG_STATUS_HPD) ?
+ connector_status_connected : connector_status_disconnected;
+}
+
+static const struct dw_hdmi_phy_ops sun8i_dw_hdmi_phy_ops = {
+ .init = &sun8i_dw_hdmi_phy_init,
+ .disable = &sun8i_dw_hdmi_phy_disable,
+ .read_hpd = &sun8i_dw_hdmi_phy_read_hpd,
+};
+
+static void sun8i_dw_hdmi_init(struct sun8i_dw_hdmi *hdmi)
+{
+ u32 timeout = 20;
+ u32 val;
+
+ /*
+ * HDMI PHY settings are taken as-is from Allwinner BSP code.
+ * There is no documentation.
+ */
+ writel(0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(0));
+ udelay(5);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(16));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(1));
+ usleep_range(10, 20);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(2));
+ udelay(5);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(3));
+ usleep_range(40, 100);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(19));
+ usleep_range(100, 200);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(18));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, 7 << 4);
+
+ /* Note that Allwinner code doesn't fail in case of timeout */
+ while (!(readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS) &
+ SUN8I_HDMI_PHY_REG_STATUS_READY)) {
+ if (!timeout--) {
+ dev_warn(hdmi->dev, "HDMI PHY init timeout!\n");
+ break;
+ }
+ usleep_range(100, 200);
+ }
+
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, 0xf << 8);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(7));
+
+ writel(0x39dc5040, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x80084343, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(100);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(31) | BIT(30));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, val);
+ writel(0x01FF0F7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x80639000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F81C405, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+
+ /* enable read access to HDMI controller */
+ writel(SUN8I_HDMI_PHY_REG_READ_EN_MAGIC,
+ hdmi->phy_base + SUN8I_HDMI_PHY_REG_READ_EN);
+
+ /* unscramble register offsets */
+ writel(SUN8I_HDMI_PHY_REG_UNSCRAMBLE_MAGIC,
+ hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNSCRAMBLE);
+
+ /* Reset PHY CEC settings. This gives dw hdmi total control over CEC. */
+ writel(0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CEC);
+}
+
+static const struct drm_encoder_funcs sun8i_dw_hdmi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dw_hdmi_plat_data *plat_data;
+ struct drm_device *drm = data;
+ struct drm_encoder *encoder;
+ struct sun8i_dw_hdmi *hdmi;
+ struct resource *res;
+ int ret;
+
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ plat_data = &hdmi->plat_data;
+ hdmi->dev = &pdev->dev;
+ encoder = &hdmi->encoder;
+
+ encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+ /*
+ * If we failed to find the CRTC(s) which this encoder is
+ * supposed to be connected to, it's because the CRTC has
+ * not been registered yet. Defer probing, and hope that
+ * the required CRTC is added later.
+ */
+ if (encoder->possible_crtcs == 0)
+ return -EPROBE_DEFER;
+
+ /* resource 0 is the memory region for the core controller */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ hdmi->phy_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(hdmi->phy_base))
+ return PTR_ERR(hdmi->phy_base);
+
+ hdmi->clk_ahb = devm_clk_get(dev, "iahb");
+ if (IS_ERR(hdmi->clk_ahb)) {
+ dev_err(dev, "Could not get iahb clock\n");
+ return PTR_ERR(hdmi->clk_ahb);
+ }
+
+ hdmi->clk_sfr = devm_clk_get(dev, "isfr");
+ if (IS_ERR(hdmi->clk_sfr)) {
+ dev_err(dev, "Could not get isfr clock\n");
+ return PTR_ERR(hdmi->clk_sfr);
+ }
+
+ hdmi->clk_ddc = devm_clk_get(dev, "ddc");
+ if (IS_ERR(hdmi->clk_ddc)) {
+ dev_err(dev, "Could not get ddc clock\n");
+ return PTR_ERR(hdmi->clk_ddc);
+ }
+
+ hdmi->rst_hdmi = devm_reset_control_get(dev, "hdmi");
+ if (IS_ERR(hdmi->rst_hdmi)) {
+ dev_err(dev, "Could not get hdmi reset control\n");
+ return PTR_ERR(hdmi->rst_hdmi);
+ }
+
+ hdmi->rst_ddc = devm_reset_control_get(dev, "ddc");
+ if (IS_ERR(hdmi->rst_ddc)) {
+ dev_err(dev, "Could not get ddc reset control\n");
+ return PTR_ERR(hdmi->rst_ddc);
+ }
+
+ ret = clk_prepare_enable(hdmi->clk_ahb);
+ if (ret) {
+ dev_err(dev, "Cannot enable ahb clock: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(hdmi->clk_sfr);
+ if (ret) {
+ dev_err(dev, "Cannot enable isfr clock: %d\n", ret);
+ goto err_ahb_clk;
+ }
+
+ ret = clk_prepare_enable(hdmi->clk_ddc);
+ if (ret) {
+ dev_err(dev, "Cannot enable ddc clock: %d\n", ret);
+ goto err_sfr_clk;
+ }
+
+ ret = reset_control_deassert(hdmi->rst_hdmi);
+ if (ret) {
+ dev_err(dev, "Could not deassert hdmi reset control\n");
+ goto err_ddc_clk;
+ }
+
+ ret = reset_control_deassert(hdmi->rst_ddc);
+ if (ret) {
+ dev_err(dev, "Could not deassert ddc reset control\n");
+ goto err_assert_hdmi_reset;
+ }
+
+ drm_encoder_helper_add(encoder, &sun8i_dw_hdmi_encoder_helper_funcs);
+ drm_encoder_init(drm, encoder, &sun8i_dw_hdmi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+
+ sun8i_dw_hdmi_init(hdmi);
+
+ plat_data->phy_ops = &sun8i_dw_hdmi_phy_ops,
+ plat_data->phy_name = "sun8i_dw_hdmi_phy",
+ plat_data->phy_data = hdmi;
+
+ ret = dw_hdmi_bind(pdev, encoder, plat_data);
+
+ /*
+ * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
+ * which would have called the encoder cleanup. Do it manually.
+ */
+ if (ret)
+ goto cleanup_encoder;
+
+ return 0;
+
+cleanup_encoder:
+ drm_encoder_cleanup(encoder);
+ reset_control_assert(hdmi->rst_ddc);
+err_assert_hdmi_reset:
+ reset_control_assert(hdmi->rst_hdmi);
+err_ddc_clk:
+ clk_disable_unprepare(hdmi->clk_ddc);
+err_sfr_clk:
+ clk_disable_unprepare(hdmi->clk_sfr);
+err_ahb_clk:
+ clk_disable_unprepare(hdmi->clk_ahb);
+
+ return ret;
+}
+
+static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ return dw_hdmi_unbind(dev);
+}
+
+static const struct component_ops sun8i_dw_hdmi_ops = {
+ .bind = sun8i_dw_hdmi_bind,
+ .unbind = sun8i_dw_hdmi_unbind,
+};
+
+static int sun8i_dw_hdmi_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &sun8i_dw_hdmi_ops);
+}
+
+static int sun8i_dw_hdmi_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &sun8i_dw_hdmi_ops);
+
+ return 0;
+}
+
+static const struct of_device_id sun8i_dw_hdmi_dt_ids[] = {
+ { .compatible = "allwinner,sun8i-h3-dw-hdmi" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, sun8i_dw_hdmi_dt_ids);
+
+struct platform_driver sun8i_dw_hdmi_pltfm_driver = {
+ .probe = sun8i_dw_hdmi_probe,
+ .remove = sun8i_dw_hdmi_remove,
+ .driver = {
+ .name = "sun8i-dw-hdmi",
+ .of_match_table = sun8i_dw_hdmi_dt_ids,
+ },
+};
+module_platform_driver(sun8i_dw_hdmi_pltfm_driver);
+
+MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
+MODULE_DESCRIPTION("Allwinner H3 DW HDMI bridge");
+MODULE_LICENSE("GPL");

View file

@ -1,59 +0,0 @@
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index ccde3a00..44ae22a9 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -109,6 +109,42 @@
assigned-clock-rates = <432000000>;
};
+ hdmi: hdmi@1ee0000 {
+ compatible = "allwinner,sun8i-h3-dw-hdmi";
+ reg = <0x01ee0000 0x10000>,
+ <0x01ef0000 0x10000>;
+ reg-io-width = <1>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI>,
+ <&ccu CLK_HDMI_DDC>;
+ clock-names = "iahb", "isfr", "ddc";
+ resets = <&ccu RST_BUS_HDMI0>, <&ccu RST_BUS_HDMI1>;
+ reset-names = "hdmi", "ddc";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ hdmi_in_tcon0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_out_hdmi>;
+ };
+ };
+
+ hdmi_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+ };
+
mixer0: mixer@1100000 {
compatible = "allwinner,sun8i-h3-de2-mixer0";
reg = <0x01100000 0x100000>;
@@ -224,6 +260,11 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
+
+ tcon0_out_hdmi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&hdmi_in_tcon0>;
+ };
};
};
};

View file

@ -1,89 +0,0 @@
From c19926638d14b39bba73461f7e4750fb1926d03e Mon Sep 17 00:00:00 2001
From: Marcus Cooper <codekipper@gmail.com>
Date: Tue, 5 Sep 2017 09:50:31 +0200
Subject: [PATCH] ASoC: sun4i-i2s: Add regmap field to sign extend sample
On the newer SoCs this is set by default to transfer a 0 after
each sample in each slot. Add the regmap field to configure this
and set it so that it pads the sample with 0s.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
---
sound/soc/sunxi/sun4i-i2s.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 04f92583a9696..7826fb3523c1b 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -138,6 +138,7 @@
* @field_fmt_bclk: regmap field to set clk polarity.
* @field_fmt_lrclk: regmap field to set frame polarity.
* @field_fmt_mode: regmap field to set the operational mode.
+ * @field_fmt_sext: regmap field to set the sign extension.
* @field_txchanmap: location of the tx channel mapping register.
* @field_rxchanmap: location of the rx channel mapping register.
* @field_txchansel: location of the tx channel select bit fields.
@@ -163,6 +164,7 @@ struct sun4i_i2s_quirks {
struct reg_field field_fmt_bclk;
struct reg_field field_fmt_lrclk;
struct reg_field field_fmt_mode;
+ struct reg_field field_fmt_sext;
struct reg_field field_txchanmap;
struct reg_field field_rxchanmap;
struct reg_field field_txchansel;
@@ -187,6 +189,7 @@ struct sun4i_i2s {
struct regmap_field *field_fmt_bclk;
struct regmap_field *field_fmt_lrclk;
struct regmap_field *field_fmt_mode;
+ struct regmap_field *field_fmt_sext;
struct regmap_field *field_txchanmap;
struct regmap_field *field_rxchanmap;
struct regmap_field *field_txchansel;
@@ -337,6 +340,9 @@ static int sun4i_i2s_set_clk_rate(struct sun4i_i2s *i2s,
SUN8I_I2S_FMT0_LRCK_PERIOD_MASK,
SUN8I_I2S_FMT0_LRCK_PERIOD(32));
+ /* Set sign extension to pad out LSB with 0 */
+ regmap_field_write(i2s->field_fmt_sext, 0);
+
return 0;
}
@@ -874,6 +880,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.has_slave_select_bit = true,
.field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1),
+ .field_fmt_sext = REG_FIELD(SUN4I_I2S_FMT1_REG, 8, 8),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -891,6 +898,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.has_slave_select_bit = true,
.field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1),
+ .field_fmt_sext = REG_FIELD(SUN4I_I2S_FMT1_REG, 8, 8),
.field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -914,6 +922,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19),
.field_fmt_mode = REG_FIELD(SUN4I_I2S_CTRL_REG, 4, 5),
+ .field_fmt_sext = REG_FIELD(SUN4I_I2S_FMT1_REG, 4, 5),
.field_txchanmap = REG_FIELD(SUN8I_I2S_TX_CHAN_MAP_REG, 0, 31),
.field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31),
.field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2),
@@ -959,6 +968,12 @@ static int sun4i_i2s_init_regmap_fields(struct device *dev,
if (IS_ERR(i2s->field_fmt_mode))
return PTR_ERR(i2s->field_fmt_mode);
+ i2s->field_fmt_sext =
+ devm_regmap_field_alloc(dev, i2s->regmap,
+ i2s->variant->field_fmt_sext);
+ if (IS_ERR(i2s->field_fmt_sext))
+ return PTR_ERR(i2s->field_fmt_sext);
+
i2s->field_txchanmap =
devm_regmap_field_alloc(dev, i2s->regmap,
i2s->variant->field_txchanmap);

View file

@ -1,95 +0,0 @@
From 9878125eb4b4ffe64f39bb4db431f2a69dad418b Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sun, 3 Sep 2017 11:52:11 +0200
Subject: [PATCH] clk: sunxi-ng: Fix crash during boot
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 36224ba93f9da..864dac96733b2 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -37,7 +37,7 @@ static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux",
16, 2, /* P */
BIT(31), /* gate */
BIT(28), /* lock */
- 0);
+ CLK_SET_RATE_UNGATE);
/*
* The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
@@ -55,7 +55,7 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
0, 5, /* M */
BIT(31), /* gate */
BIT(28), /* lock */
- 0);
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video",
"osc24M", 0x0010,
@@ -67,7 +67,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video",
297000000, /* frac rate 1 */
BIT(31), /* gate */
BIT(28), /* lock */
- 0);
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
"osc24M", 0x0018,
@@ -79,7 +79,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
297000000, /* frac rate 1 */
BIT(31), /* gate */
BIT(28), /* lock */
- 0);
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr",
"osc24M", 0x020,
@@ -88,7 +88,7 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr",
0, 2, /* M */
BIT(31), /* gate */
BIT(28), /* lock */
- 0);
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0",
"osc24M", 0x028,
@@ -97,7 +97,7 @@ static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0",
BIT(31), /* gate */
BIT(28), /* lock */
2, /* post-div */
- 0);
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
"osc24M", 0x0038,
@@ -109,7 +109,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
297000000, /* frac rate 1 */
BIT(31), /* gate */
BIT(28), /* lock */
- 0);
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1",
"osc24M", 0x044,
@@ -118,7 +118,7 @@ static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1",
BIT(31), /* gate */
BIT(28), /* lock */
2, /* post-div */
- 0);
+ CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
"osc24M", 0x0048,
@@ -130,7 +130,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
297000000, /* frac rate 1 */
BIT(31), /* gate */
BIT(28), /* lock */
- 0);
+ CLK_SET_RATE_UNGATE);
static const char * const cpux_parents[] = { "osc32k", "osc24M",
"pll-cpux" , "pll-cpux" };

View file

@ -1,55 +0,0 @@
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 8aa2befc..d3d70eac 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -53,6 +53,22 @@
#address-cells = <1>;
#size-cells = <1>;
+ sound_hdmi: sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "allwinner,hdmi";
+ simple-audio-card,mclk-fs = <256>;
+ status = "disabled";
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s2>;
+ };
+ };
+
clocks {
#address-cells = <1>;
#size-cells = <1>;
@@ -110,6 +126,7 @@
};
hdmi: hdmi@1ee0000 {
+ #sound-dai-cells = <0>;
compatible = "allwinner,sun8i-h3-dw-hdmi";
reg = <0x01ee0000 0x10000>,
<0x01ef0000 0x10000>;
@@ -685,6 +702,19 @@
status = "disabled";
};
+ i2s2: i2s@1c22800 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-h3-i2s";
+ reg = <0x01c22800 0x400>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 27>;
+ resets = <&ccu RST_BUS_I2S2>;
+ dma-names = "tx";
+ status = "disabled";
+ };
+
codec: codec@01c22c00 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun8i-h3-codec";

View file

@ -1,340 +0,0 @@
From 8797b952feb45f68b955645c4958878463f2be70 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Tue, 11 Apr 2017 21:48:20 +0200
Subject: [PATCH] ARM: sun8i: h3: Enable HDMI output on Orange Pi 2 board
The Orange Pi 2 board features a HDMI port that is connected to the HDMI
controller of H3 SoC.
Enable it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 33 +++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
index 17cdeae19c6f0..586181c4ce8b5 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
@@ -62,6 +62,17 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -114,6 +125,10 @@
status = "okay";
};
+&de {
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -125,12 +140,26 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -188,6 +217,10 @@
status = "okay";
};
+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
From 9bd1fdb163a632ba29bd435cb7ea513f1c723a96 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sun, 16 Apr 2017 23:35:58 +0800
Subject: [PATCH] ARM: sun8i: h3: Enable HDMI output for Orange Pi PC board
The Orange Pi PC board features a HDMI port that is connected to the
HDMI controller of H3 SoC.
Enable it.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 33 ++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
index 998b60f8d295e..24ec7376f4796 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
@@ -60,6 +60,17 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -98,6 +109,10 @@
status = "okay";
};
+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -121,12 +136,26 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -177,6 +206,10 @@
status = "okay";
};
+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
From 23255a79d972d434e4abca4390dec01d876a7296 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sun, 11 Jun 2017 22:39:47 +0200
Subject: [PATCH] ARM: sun8i: h3: Enable HDMI output on Orange Pi Lite
The Orange Pi Lite board features a HDMI port that is connected to the
HDMI controller of H3 SoC.
Enable it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts | 33 ++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
index 9b47a0def740c..cecf4af1b7433 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
@@ -61,6 +61,17 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -91,6 +102,10 @@
};
};
+&de {
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -99,12 +114,26 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -159,6 +188,10 @@
};
};
+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
From 957eec3e02059fb60138d8e44d12effb4d572c11 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sun, 11 Jun 2017 22:40:40 +0200
Subject: [PATCH] ARM: sun8i: h3: Enable HDMI output on Orange Pi One board
The Orange Pi One board features a HDMI port that is connected to the HDMI
controller of H3 SoC.
Enable it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 33 +++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
index 6880268e8b87b..ad1739e1d01d0 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
@@ -60,6 +60,17 @@
stdout-path = "serial0:115200n8";
};
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -90,6 +101,10 @@
};
};
+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -105,6 +120,20 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -147,6 +176,10 @@
status = "okay";
};
+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;

View file

@ -1,126 +0,0 @@
From ffa650ca191b8acbe70bf26b10080ab7c73a6908 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sat, 6 May 2017 16:13:47 +0800
Subject: [PATCH] arm64: allwinner: h5: enable HDMI output on Orange Pi PC2
Orange Pi PC2 features a HDMI connector connected to the HDMI controller
on H5 SoC.
Enable the HDMI output.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
index a8296feee8841..5a1443911d760 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
@@ -121,6 +121,10 @@
status = "okay";
};
+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -146,6 +150,10 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
@@ -159,6 +167,10 @@
};
};
+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -184,6 +196,10 @@
status = "okay";
};
+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
From 3acaae324e966dd769ec1a3fd297d0fb12082a78 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sat, 6 May 2017 16:14:36 +0800
Subject: [PATCH] arm64: allwinner: h5: enable HDMI output on Orange Pi Prime
Orange Pi Prime features a HDMI connector connected to the HDMI controller
on H5 SoC.
Enable the HDMI output.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
.../boot/dts/allwinner/sun50i-h5-orangepi-prime.dts | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
index d906b302cbcdc..e21567d7fc7f0 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
@@ -128,6 +128,10 @@
status = "okay";
};
+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -153,6 +157,10 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
@@ -166,6 +174,10 @@
};
};
+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -201,6 +213,10 @@
status = "okay";
};
+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;

View file

@ -1,117 +0,0 @@
From 23829558b10e69f4962474849c3f4b173c5ef009 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Tue, 5 Sep 2017 22:06:32 +0200
Subject: [PATCH] ARM: sun8i: h3: Enable HDMI audio on H3 boards
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 8 ++++++++
arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts | 8 ++++++++
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 8 ++++++++
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 8 ++++++++
7 files changed, 56 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
index 586181c4ce8b5..ef98e28e12137 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
@@ -150,6 +150,10 @@
};
};
+&i2s2 {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
@@ -217,6 +221,10 @@
status = "okay";
};
+&sound_hdmi {
+ status = "okay";
+};
+
&tcon0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
index cecf4af1b7433..01540419a0ca6 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
@@ -124,6 +124,10 @@
};
};
+&i2s2 {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
@@ -188,6 +192,10 @@
};
};
+&sound_hdmi {
+ status = "okay";
+};
+
&tcon0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
index ad1739e1d01d0..d3277f5d921b9 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
@@ -130,6 +130,10 @@
};
};
+&i2s2 {
+ status = "okay";
+};
+
&mixer0 {
status = "okay";
};
@@ -176,6 +180,10 @@
status = "okay";
};
+&sound_hdmi {
+ status = "okay";
+};
+
&tcon0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
index 24ec7376f4796..1d567ccd76d16 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
@@ -146,6 +146,10 @@
};
};
+&i2s2 {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
@@ -206,6 +210,10 @@
status = "okay";
};
+&sound_hdmi {
+ status = "okay";
+};
+
&tcon0 {
status = "okay";
};

View file

@ -1,52 +0,0 @@
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
index 2503d333..9d41a9d5 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
@@ -144,6 +144,10 @@
status = "okay";
};
+&i2s2 {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
@@ -179,6 +183,10 @@
status = "okay";
};
+&sound_hdmi {
+ status = "okay";
+};
+
&tcon0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
index 16c004b4..623014f2 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
@@ -151,6 +151,10 @@
status = "okay";
};
+&i2s2 {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
@@ -196,6 +200,10 @@
status = "okay";
};
+&sound_hdmi {
+ status = "okay";
+};
+
&tcon0 {
status = "okay";
};

View file

@ -1,55 +0,0 @@
From 35fbec685e9ccdcf154f00a93b46eafb9d0cc87a Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sun, 3 Sep 2017 11:32:34 +0200
Subject: [PATCH] drm: bridge: Add audio workaround for dw_hdmi v1.32a
Allwinner SoCs with dw hdmi v1.32a seems to have an issue with manual
setting CTS value. BSP driver sets it to auto mode and that works
here too.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 72969240a9d42..984fab8b658b5 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -424,16 +424,26 @@ static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
unsigned int n)
{
- /* Must be set/cleared first */
- hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
-
- /* nshift factor = 0 */
- hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
-
- hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
- HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
- hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
- hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
+ /*
+ * Manual CTS setting doesn't work correctly on Allwinner SoCs with
+ * dw hdmi v1.32a.
+ */
+ if (hdmi->version != 0x132a) {
+ /* Must be set/cleared first */
+ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+
+ /* nshift factor = 0 */
+ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
+
+ hdmi_writeb(hdmi,
+ ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
+ HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+ hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
+ hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
+ } else {
+ /* set automatic CTS calculation */
+ hdmi_writeb(hdmi, 0x00, HDMI_AUD_CTS3);
+ }
hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);

View file

@ -1,108 +0,0 @@
From e84b8d75ac116e67ac3bdb23cafbd03430aa50b9 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Mon, 31 Jul 2017 15:29:41 +0100
Subject: drm/bridge: dw-hdmi: add cec notifier support
Add CEC notifier support to the HDMI bridge driver, so that the CEC
part of the IP can receive its physical address.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Archit Taneja <architt@codeaurora.org>
Link: https://patchwork.freedesktop.org/patch/msgid/E1dcBhV-00088e-8x@rmk-PC.armlinux.org.uk
---
drivers/gpu/drm/bridge/synopsys/Kconfig | 1 +
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 22 +++++++++++++++++++++-
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
index a2fb939..7281681 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -2,6 +2,7 @@ config DRM_DW_HDMI
tristate
select DRM_KMS_HELPER
select REGMAP_MMIO
+ select CEC_CORE if CEC_NOTIFIER
config DRM_DW_HDMI_AHB_AUDIO
tristate "Synopsys Designware AHB Audio interface"
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 60faf2d..67b4af0 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -36,7 +36,10 @@
#include "dw-hdmi.h"
#include "dw-hdmi-audio.h"
+#include <media/cec-notifier.h>
+
#define DDC_SEGMENT_ADDR 0x30
+
#define HDMI_EDID_LEN 512
enum hdmi_datamap {
@@ -175,6 +178,8 @@ struct dw_hdmi {
struct regmap *regm;
void (*enable_audio)(struct dw_hdmi *hdmi);
void (*disable_audio)(struct dw_hdmi *hdmi);
+
+ struct cec_notifier *cec_notifier;
};
#define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -1896,6 +1901,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
drm_mode_connector_update_edid_property(connector, edid);
+ cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
ret = drm_add_edid_modes(connector, edid);
/* Store the ELD */
drm_edid_to_eld(connector, edid);
@@ -2119,11 +2125,16 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
* ask the source to re-read the EDID.
*/
if (intr_stat &
- (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD))
+ (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
__dw_hdmi_setup_rx_sense(hdmi,
phy_stat & HDMI_PHY_HPD,
phy_stat & HDMI_PHY_RX_SENSE);
+ if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0)
+ cec_notifier_set_phys_addr(hdmi->cec_notifier,
+ CEC_PHYS_ADDR_INVALID);
+ }
+
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
dev_dbg(hdmi->dev, "EVENT=%s\n",
phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
@@ -2376,6 +2387,12 @@ __dw_hdmi_probe(struct platform_device *pdev,
if (ret)
goto err_iahb;
+ hdmi->cec_notifier = cec_notifier_get(dev);
+ if (!hdmi->cec_notifier) {
+ ret = -ENOMEM;
+ goto err_iahb;
+ }
+
/*
* To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
* N and cts values before enabling phy
@@ -2452,6 +2469,9 @@ err_iahb:
hdmi->ddc = NULL;
}
+ if (hdmi->cec_notifier)
+ cec_notifier_put(hdmi->cec_notifier);
+
clk_disable_unprepare(hdmi->iahb_clk);
err_isfr:
clk_disable_unprepare(hdmi->isfr_clk);
--
cgit v1.1

View file

@ -1,96 +0,0 @@
From 7cc4ab225ae30bd9ec9239e7dba5b2937f526ccc Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Mon, 31 Jul 2017 15:29:46 +0100
Subject: drm/bridge: dw-hdmi: add better clock disable control
The video setup path aways sets the clock disable register to a specific
value, which has the effect of disabling the CEC engine. When we add the
CEC driver, this becomes a problem.
Fix this by only setting/clearing the bits that the video path needs to.
Reviewed-by: Jose Abreu <joabreu@synopsys.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Archit Taneja <architt@codeaurora.org>
Link: https://patchwork.freedesktop.org/patch/msgid/E1dcBha-00088l-DE@rmk-PC.armlinux.org.uk
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 67b4af0..f8171cd 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -166,6 +166,7 @@ struct dw_hdmi {
bool bridge_is_on; /* indicates the bridge is on */
bool rxsense; /* rxsense state */
u8 phy_mask; /* desired phy int mask settings */
+ u8 mc_clkdis; /* clock disable register */
spinlock_t audio_lock;
struct mutex audio_mutex;
@@ -551,8 +552,11 @@ EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable)
{
- hdmi_modb(hdmi, enable ? 0 : HDMI_MC_CLKDIS_AUDCLK_DISABLE,
- HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
+ if (enable)
+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
+ else
+ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_AUDCLK_DISABLE;
+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
}
static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi)
@@ -1574,8 +1578,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
/* HDMI Initialization Step B.4 */
static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
{
- u8 clkdis;
-
/* control period minimum duration */
hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
@@ -1587,17 +1589,21 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
/* Enable pixel clock and tmds data path */
- clkdis = 0x7F;
- clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
- hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE |
+ HDMI_MC_CLKDIS_CSCCLK_DISABLE |
+ HDMI_MC_CLKDIS_AUDCLK_DISABLE |
+ HDMI_MC_CLKDIS_PREPCLK_DISABLE |
+ HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
- clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
- hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
/* Enable csc path */
if (is_color_space_conversion(hdmi)) {
- clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
- hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
}
/* Enable color space conversion if needed */
@@ -2272,6 +2278,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->disabled = true;
hdmi->rxsense = true;
hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
+ hdmi->mc_clkdis = 0x7f;
mutex_init(&hdmi->mutex);
mutex_init(&hdmi->audio_mutex);
--
cgit v1.1

View file

@ -1,32 +0,0 @@
From e383bf85d32b5953f34fa0e3d619886ec49413b1 Mon Sep 17 00:00:00 2001
From: Hans Verkuil <hverkuil@xs4all.nl>
Date: Mon, 7 Aug 2017 09:20:35 +0200
Subject: drm/bridge: dw-hdmi: add missing cec_notifier_put
The __dw_hdmi_remove() function was missing a call to cec_notifier_put
to balance the cec_notifier_get in the probe function.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Archit Taneja <architt@codeaurora.org>
Link: https://patchwork.freedesktop.org/patch/msgid/a7688d13-2d61-ed16-f2df-28cbb5007f38@xs4all.nl
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index f8171cd..a24ec4a 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2496,6 +2496,9 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
/* Disable all interrupts */
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+ if (hdmi->cec_notifier)
+ cec_notifier_put(hdmi->cec_notifier);
+
clk_disable_unprepare(hdmi->iahb_clk);
clk_disable_unprepare(hdmi->isfr_clk);
--
cgit v1.1

View file

@ -1,522 +0,0 @@
From a616e63c56ef35365b781f08c7d437840f56940f Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Wed, 2 Aug 2017 20:41:07 +0200
Subject: drm/bridge: dw-hdmi: add cec driver
Add a CEC driver for the dw-hdmi hardware.
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
[hans.verkuil: unsigned -> unsigned int]
[hans.verkuil: cec_transmit_done -> cec_transmit_attempt_done]
[hans.verkuil: add missing CEC_CAP_PASSTHROUGH]
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Archit Taneja <architt@codeaurora.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20170802184108.7913-4-hverkuil@xs4all.nl
---
drivers/gpu/drm/bridge/synopsys/Kconfig | 9 +
drivers/gpu/drm/bridge/synopsys/Makefile | 1 +
drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 327 ++++++++++++++++++++++++++
drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h | 19 ++
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 42 +++-
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
6 files changed, 398 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
index 7281681..3cc53b4 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -22,3 +22,12 @@ config DRM_DW_HDMI_I2S_AUDIO
help
Support the I2S Audio interface which is part of the Synopsys
Designware HDMI block.
+
+config DRM_DW_HDMI_CEC
+ tristate "Synopsis Designware CEC interface"
+ depends on DRM_DW_HDMI
+ select CEC_CORE
+ select CEC_NOTIFIER
+ help
+ Support the CE interface which is part of the Synopsys
+ Designware HDMI block.
diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile
index 5f57d36..5dad97d 100644
--- a/drivers/gpu/drm/bridge/synopsys/Makefile
+++ b/drivers/gpu/drm/bridge/synopsys/Makefile
@@ -3,3 +3,4 @@
obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_CEC) += dw-hdmi-cec.o
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
new file mode 100644
index 0000000..6c32351
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -0,0 +1,327 @@
+/*
+ * Designware HDMI CEC driver
+ *
+ * Copyright (C) 2015-2017 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <drm/drm_edid.h>
+
+#include <media/cec.h>
+#include <media/cec-notifier.h>
+
+#include "dw-hdmi-cec.h"
+
+enum {
+ HDMI_IH_CEC_STAT0 = 0x0106,
+ HDMI_IH_MUTE_CEC_STAT0 = 0x0186,
+
+ HDMI_CEC_CTRL = 0x7d00,
+ CEC_CTRL_START = BIT(0),
+ CEC_CTRL_FRAME_TYP = 3 << 1,
+ CEC_CTRL_RETRY = 0 << 1,
+ CEC_CTRL_NORMAL = 1 << 1,
+ CEC_CTRL_IMMED = 2 << 1,
+
+ HDMI_CEC_STAT = 0x7d01,
+ CEC_STAT_DONE = BIT(0),
+ CEC_STAT_EOM = BIT(1),
+ CEC_STAT_NACK = BIT(2),
+ CEC_STAT_ARBLOST = BIT(3),
+ CEC_STAT_ERROR_INIT = BIT(4),
+ CEC_STAT_ERROR_FOLL = BIT(5),
+ CEC_STAT_WAKEUP = BIT(6),
+
+ HDMI_CEC_MASK = 0x7d02,
+ HDMI_CEC_POLARITY = 0x7d03,
+ HDMI_CEC_INT = 0x7d04,
+ HDMI_CEC_ADDR_L = 0x7d05,
+ HDMI_CEC_ADDR_H = 0x7d06,
+ HDMI_CEC_TX_CNT = 0x7d07,
+ HDMI_CEC_RX_CNT = 0x7d08,
+ HDMI_CEC_TX_DATA0 = 0x7d10,
+ HDMI_CEC_RX_DATA0 = 0x7d20,
+ HDMI_CEC_LOCK = 0x7d30,
+ HDMI_CEC_WKUPCTRL = 0x7d31,
+};
+
+struct dw_hdmi_cec {
+ struct dw_hdmi *hdmi;
+ const struct dw_hdmi_cec_ops *ops;
+ u32 addresses;
+ struct cec_adapter *adap;
+ struct cec_msg rx_msg;
+ unsigned int tx_status;
+ bool tx_done;
+ bool rx_done;
+ struct cec_notifier *notify;
+ int irq;
+};
+
+static void dw_hdmi_write(struct dw_hdmi_cec *cec, u8 val, int offset)
+{
+ cec->ops->write(cec->hdmi, val, offset);
+}
+
+static u8 dw_hdmi_read(struct dw_hdmi_cec *cec, int offset)
+{
+ return cec->ops->read(cec->hdmi, offset);
+}
+
+static int dw_hdmi_cec_log_addr(struct cec_adapter *adap, u8 logical_addr)
+{
+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap);
+
+ if (logical_addr == CEC_LOG_ADDR_INVALID)
+ cec->addresses = 0;
+ else
+ cec->addresses |= BIT(logical_addr) | BIT(15);
+
+ dw_hdmi_write(cec, cec->addresses & 255, HDMI_CEC_ADDR_L);
+ dw_hdmi_write(cec, cec->addresses >> 8, HDMI_CEC_ADDR_H);
+
+ return 0;
+}
+
+static int dw_hdmi_cec_transmit(struct cec_adapter *adap, u8 attempts,
+ u32 signal_free_time, struct cec_msg *msg)
+{
+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap);
+ unsigned int i, ctrl;
+
+ switch (signal_free_time) {
+ case CEC_SIGNAL_FREE_TIME_RETRY:
+ ctrl = CEC_CTRL_RETRY;
+ break;
+ case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR:
+ default:
+ ctrl = CEC_CTRL_NORMAL;
+ break;
+ case CEC_SIGNAL_FREE_TIME_NEXT_XFER:
+ ctrl = CEC_CTRL_IMMED;
+ break;
+ }
+
+ for (i = 0; i < msg->len; i++)
+ dw_hdmi_write(cec, msg->msg[i], HDMI_CEC_TX_DATA0 + i);
+
+ dw_hdmi_write(cec, msg->len, HDMI_CEC_TX_CNT);
+ dw_hdmi_write(cec, ctrl | CEC_CTRL_START, HDMI_CEC_CTRL);
+
+ return 0;
+}
+
+static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data)
+{
+ struct cec_adapter *adap = data;
+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap);
+ unsigned int stat = dw_hdmi_read(cec, HDMI_IH_CEC_STAT0);
+ irqreturn_t ret = IRQ_HANDLED;
+
+ if (stat == 0)
+ return IRQ_NONE;
+
+ dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0);
+
+ if (stat & CEC_STAT_ERROR_INIT) {
+ cec->tx_status = CEC_TX_STATUS_ERROR;
+ cec->tx_done = true;
+ ret = IRQ_WAKE_THREAD;
+ } else if (stat & CEC_STAT_DONE) {
+ cec->tx_status = CEC_TX_STATUS_OK;
+ cec->tx_done = true;
+ ret = IRQ_WAKE_THREAD;
+ } else if (stat & CEC_STAT_NACK) {
+ cec->tx_status = CEC_TX_STATUS_NACK;
+ cec->tx_done = true;
+ ret = IRQ_WAKE_THREAD;
+ }
+
+ if (stat & CEC_STAT_EOM) {
+ unsigned int len, i;
+
+ len = dw_hdmi_read(cec, HDMI_CEC_RX_CNT);
+ if (len > sizeof(cec->rx_msg.msg))
+ len = sizeof(cec->rx_msg.msg);
+
+ for (i = 0; i < len; i++)
+ cec->rx_msg.msg[i] =
+ dw_hdmi_read(cec, HDMI_CEC_RX_DATA0 + i);
+
+ dw_hdmi_write(cec, 0, HDMI_CEC_LOCK);
+
+ cec->rx_msg.len = len;
+ smp_wmb();
+ cec->rx_done = true;
+
+ ret = IRQ_WAKE_THREAD;
+ }
+
+ return ret;
+}
+
+static irqreturn_t dw_hdmi_cec_thread(int irq, void *data)
+{
+ struct cec_adapter *adap = data;
+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap);
+
+ if (cec->tx_done) {
+ cec->tx_done = false;
+ cec_transmit_attempt_done(adap, cec->tx_status);
+ }
+ if (cec->rx_done) {
+ cec->rx_done = false;
+ smp_rmb();
+ cec_received_msg(adap, &cec->rx_msg);
+ }
+ return IRQ_HANDLED;
+}
+
+static int dw_hdmi_cec_enable(struct cec_adapter *adap, bool enable)
+{
+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap);
+
+ if (!enable) {
+ dw_hdmi_write(cec, ~0, HDMI_CEC_MASK);
+ dw_hdmi_write(cec, ~0, HDMI_IH_MUTE_CEC_STAT0);
+ dw_hdmi_write(cec, 0, HDMI_CEC_POLARITY);
+
+ cec->ops->disable(cec->hdmi);
+ } else {
+ unsigned int irqs;
+
+ dw_hdmi_write(cec, 0, HDMI_CEC_CTRL);
+ dw_hdmi_write(cec, ~0, HDMI_IH_CEC_STAT0);
+ dw_hdmi_write(cec, 0, HDMI_CEC_LOCK);
+
+ dw_hdmi_cec_log_addr(cec->adap, CEC_LOG_ADDR_INVALID);
+
+ cec->ops->enable(cec->hdmi);
+
+ irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM |
+ CEC_STAT_DONE;
+ dw_hdmi_write(cec, irqs, HDMI_CEC_POLARITY);
+ dw_hdmi_write(cec, ~irqs, HDMI_CEC_MASK);
+ dw_hdmi_write(cec, ~irqs, HDMI_IH_MUTE_CEC_STAT0);
+ }
+ return 0;
+}
+
+static const struct cec_adap_ops dw_hdmi_cec_ops = {
+ .adap_enable = dw_hdmi_cec_enable,
+ .adap_log_addr = dw_hdmi_cec_log_addr,
+ .adap_transmit = dw_hdmi_cec_transmit,
+};
+
+static void dw_hdmi_cec_del(void *data)
+{
+ struct dw_hdmi_cec *cec = data;
+
+ cec_delete_adapter(cec->adap);
+}
+
+static int dw_hdmi_cec_probe(struct platform_device *pdev)
+{
+ struct dw_hdmi_cec_data *data = dev_get_platdata(&pdev->dev);
+ struct dw_hdmi_cec *cec;
+ int ret;
+
+ if (!data)
+ return -ENXIO;
+
+ /*
+ * Our device is just a convenience - we want to link to the real
+ * hardware device here, so that userspace can see the association
+ * between the HDMI hardware and its associated CEC chardev.
+ */
+ cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
+ if (!cec)
+ return -ENOMEM;
+
+ cec->irq = data->irq;
+ cec->ops = data->ops;
+ cec->hdmi = data->hdmi;
+
+ platform_set_drvdata(pdev, cec);
+
+ dw_hdmi_write(cec, 0, HDMI_CEC_TX_CNT);
+ dw_hdmi_write(cec, ~0, HDMI_CEC_MASK);
+ dw_hdmi_write(cec, ~0, HDMI_IH_MUTE_CEC_STAT0);
+ dw_hdmi_write(cec, 0, HDMI_CEC_POLARITY);
+
+ cec->adap = cec_allocate_adapter(&dw_hdmi_cec_ops, cec, "dw_hdmi",
+ CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT |
+ CEC_CAP_RC | CEC_CAP_PASSTHROUGH,
+ CEC_MAX_LOG_ADDRS);
+ if (IS_ERR(cec->adap))
+ return PTR_ERR(cec->adap);
+
+ /* override the module pointer */
+ cec->adap->owner = THIS_MODULE;
+
+ ret = devm_add_action(&pdev->dev, dw_hdmi_cec_del, cec);
+ if (ret) {
+ cec_delete_adapter(cec->adap);
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, cec->irq,
+ dw_hdmi_cec_hardirq,
+ dw_hdmi_cec_thread, IRQF_SHARED,
+ "dw-hdmi-cec", cec->adap);
+ if (ret < 0)
+ return ret;
+
+ cec->notify = cec_notifier_get(pdev->dev.parent);
+ if (!cec->notify)
+ return -ENOMEM;
+
+ ret = cec_register_adapter(cec->adap, pdev->dev.parent);
+ if (ret < 0) {
+ cec_notifier_put(cec->notify);
+ return ret;
+ }
+
+ /*
+ * CEC documentation says we must not call cec_delete_adapter
+ * after a successful call to cec_register_adapter().
+ */
+ devm_remove_action(&pdev->dev, dw_hdmi_cec_del, cec);
+
+ cec_register_cec_notifier(cec->adap, cec->notify);
+
+ return 0;
+}
+
+static int dw_hdmi_cec_remove(struct platform_device *pdev)
+{
+ struct dw_hdmi_cec *cec = platform_get_drvdata(pdev);
+
+ cec_unregister_adapter(cec->adap);
+ cec_notifier_put(cec->notify);
+
+ return 0;
+}
+
+static struct platform_driver dw_hdmi_cec_driver = {
+ .probe = dw_hdmi_cec_probe,
+ .remove = dw_hdmi_cec_remove,
+ .driver = {
+ .name = "dw-hdmi-cec",
+ },
+};
+module_platform_driver(dw_hdmi_cec_driver);
+
+MODULE_AUTHOR("Russell King <rmk+kernel@armlinux.org.uk>");
+MODULE_DESCRIPTION("Synopsys Designware HDMI CEC driver for i.MX");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(PLATFORM_MODULE_PREFIX "dw-hdmi-cec");
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h
new file mode 100644
index 0000000..cf4dc12
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.h
@@ -0,0 +1,19 @@
+#ifndef DW_HDMI_CEC_H
+#define DW_HDMI_CEC_H
+
+struct dw_hdmi;
+
+struct dw_hdmi_cec_ops {
+ void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
+ u8 (*read)(struct dw_hdmi *hdmi, int offset);
+ void (*enable)(struct dw_hdmi *hdmi);
+ void (*disable)(struct dw_hdmi *hdmi);
+};
+
+struct dw_hdmi_cec_data {
+ struct dw_hdmi *hdmi;
+ const struct dw_hdmi_cec_ops *ops;
+ int irq;
+};
+
+#endif
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a24ec4a..6aae581 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -35,6 +35,7 @@
#include "dw-hdmi.h"
#include "dw-hdmi-audio.h"
+#include "dw-hdmi-cec.h"
#include <media/cec-notifier.h>
@@ -133,6 +134,7 @@ struct dw_hdmi {
unsigned int version;
struct platform_device *audio;
+ struct platform_device *cec;
struct device *dev;
struct clk *isfr_clk;
struct clk *iahb_clk;
@@ -1794,7 +1796,6 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK);
hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK);
hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK);
- hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK);
hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT);
hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT);
@@ -2236,6 +2237,29 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
return -ENODEV;
}
+static void dw_hdmi_cec_enable(struct dw_hdmi *hdmi)
+{
+ mutex_lock(&hdmi->mutex);
+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ mutex_unlock(&hdmi->mutex);
+}
+
+static void dw_hdmi_cec_disable(struct dw_hdmi *hdmi)
+{
+ mutex_lock(&hdmi->mutex);
+ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ mutex_unlock(&hdmi->mutex);
+}
+
+static const struct dw_hdmi_cec_ops dw_hdmi_cec_ops = {
+ .write = hdmi_writeb,
+ .read = hdmi_readb,
+ .enable = dw_hdmi_cec_enable,
+ .disable = dw_hdmi_cec_disable,
+};
+
static const struct regmap_config hdmi_regmap_8bit_config = {
.reg_bits = 32,
.val_bits = 8,
@@ -2258,6 +2282,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
struct device_node *np = dev->of_node;
struct platform_device_info pdevinfo;
struct device_node *ddc_node;
+ struct dw_hdmi_cec_data cec;
struct dw_hdmi *hdmi;
struct resource *iores = NULL;
int irq;
@@ -2462,6 +2487,19 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->audio = platform_device_register_full(&pdevinfo);
}
+ if (config0 & HDMI_CONFIG0_CEC) {
+ cec.hdmi = hdmi;
+ cec.ops = &dw_hdmi_cec_ops;
+ cec.irq = irq;
+
+ pdevinfo.name = "dw-hdmi-cec";
+ pdevinfo.data = &cec;
+ pdevinfo.size_data = sizeof(cec);
+ pdevinfo.dma_mask = 0;
+
+ hdmi->cec = platform_device_register_full(&pdevinfo);
+ }
+
/* Reset HDMI DDC I2C master controller and mute I2CM interrupts */
if (hdmi->i2c)
dw_hdmi_i2c_init(hdmi);
@@ -2492,6 +2530,8 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
{
if (hdmi->audio && !IS_ERR(hdmi->audio))
platform_device_unregister(hdmi->audio);
+ if (!IS_ERR(hdmi->cec))
+ platform_device_unregister(hdmi->cec);
/* Disable all interrupts */
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
index c59f87e..69644c8 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
@@ -555,6 +555,7 @@ enum {
/* CONFIG0_ID field values */
HDMI_CONFIG0_I2S = 0x10,
+ HDMI_CONFIG0_CEC = 0x02,
/* CONFIG1_ID field values */
HDMI_CONFIG1_AHB = 0x01,
--
cgit v1.1

View file

@ -1,76 +0,0 @@
From 2356c573ba0eca736ec156b82ca6a6b37b8fe609 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Wed, 2 Aug 2017 20:41:08 +0200
Subject: drm/bridge: dw-hdmi: remove CEC engine register definitions
We don't need the CEC engine register definitions, so let's remove them.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Archit Taneja <architt@codeaurora.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20170802184108.7913-5-hverkuil@xs4all.nl
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 45 -------------------------------
1 file changed, 45 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
index 69644c8..9d90eb9 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
@@ -478,51 +478,6 @@
#define HDMI_A_PRESETUP 0x501A
#define HDMI_A_SRM_BASE 0x5020
-/* CEC Engine Registers */
-#define HDMI_CEC_CTRL 0x7D00
-#define HDMI_CEC_STAT 0x7D01
-#define HDMI_CEC_MASK 0x7D02
-#define HDMI_CEC_POLARITY 0x7D03
-#define HDMI_CEC_INT 0x7D04
-#define HDMI_CEC_ADDR_L 0x7D05
-#define HDMI_CEC_ADDR_H 0x7D06
-#define HDMI_CEC_TX_CNT 0x7D07
-#define HDMI_CEC_RX_CNT 0x7D08
-#define HDMI_CEC_TX_DATA0 0x7D10
-#define HDMI_CEC_TX_DATA1 0x7D11
-#define HDMI_CEC_TX_DATA2 0x7D12
-#define HDMI_CEC_TX_DATA3 0x7D13
-#define HDMI_CEC_TX_DATA4 0x7D14
-#define HDMI_CEC_TX_DATA5 0x7D15
-#define HDMI_CEC_TX_DATA6 0x7D16
-#define HDMI_CEC_TX_DATA7 0x7D17
-#define HDMI_CEC_TX_DATA8 0x7D18
-#define HDMI_CEC_TX_DATA9 0x7D19
-#define HDMI_CEC_TX_DATA10 0x7D1a
-#define HDMI_CEC_TX_DATA11 0x7D1b
-#define HDMI_CEC_TX_DATA12 0x7D1c
-#define HDMI_CEC_TX_DATA13 0x7D1d
-#define HDMI_CEC_TX_DATA14 0x7D1e
-#define HDMI_CEC_TX_DATA15 0x7D1f
-#define HDMI_CEC_RX_DATA0 0x7D20
-#define HDMI_CEC_RX_DATA1 0x7D21
-#define HDMI_CEC_RX_DATA2 0x7D22
-#define HDMI_CEC_RX_DATA3 0x7D23
-#define HDMI_CEC_RX_DATA4 0x7D24
-#define HDMI_CEC_RX_DATA5 0x7D25
-#define HDMI_CEC_RX_DATA6 0x7D26
-#define HDMI_CEC_RX_DATA7 0x7D27
-#define HDMI_CEC_RX_DATA8 0x7D28
-#define HDMI_CEC_RX_DATA9 0x7D29
-#define HDMI_CEC_RX_DATA10 0x7D2a
-#define HDMI_CEC_RX_DATA11 0x7D2b
-#define HDMI_CEC_RX_DATA12 0x7D2c
-#define HDMI_CEC_RX_DATA13 0x7D2d
-#define HDMI_CEC_RX_DATA14 0x7D2e
-#define HDMI_CEC_RX_DATA15 0x7D2f
-#define HDMI_CEC_LOCK 0x7D30
-#define HDMI_CEC_WKUPCTRL 0x7D31
-
/* I2C Master Registers (E-DDC) */
#define HDMI_I2CM_SLAVE 0x7E00
#define HDMI_I2CM_ADDRESS 0x7E01
--
cgit v1.1

View file

@ -1,30 +0,0 @@
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 81d4c39e414a..41769bc6a429 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -88,7 +88,7 @@ static const struct gpadc_data sun6i_gpadc_data = {
static const struct gpadc_data sun8i_a33_gpadc_data = {
.temp_offset = -1662,
.temp_scale = 162,
- .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN,
+ .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN,
};
struct sun4i_gpadc_iio {
diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
index 139872c2e0fe..d31d962bb7d8 100644
--- a/include/linux/mfd/sun4i-gpadc.h
+++ b/include/linux/mfd/sun4i-gpadc.h
@@ -38,9 +38,9 @@
#define SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(x) (GENMASK(3, 0) & BIT(x))
#define SUN6I_GPADC_CTRL1_ADC_CHAN_MASK GENMASK(3, 0)
-/* TP_CTRL1 bits for sun8i SoCs */
-#define SUN8I_GPADC_CTRL1_CHOP_TEMP_EN BIT(8)
-#define SUN8I_GPADC_CTRL1_GPADC_CALI_EN BIT(7)
+/* TP_CTRL1 bits for sun8i A23/A33 SoCs */
+#define SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN BIT(8)
+#define SUN8I_A23_GPADC_CTRL1_GPADC_CALI_EN BIT(7)
#define SUN4I_GPADC_CTRL2 0x08

View file

@ -1,397 +0,0 @@
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 41769bc6a429..5c79ba4d5ef5 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -22,6 +22,7 @@
* shutdown for not being used.
*/
+#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -31,6 +32,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/thermal.h>
#include <linux/delay.h>
@@ -49,6 +51,8 @@ static unsigned int sun6i_gpadc_chan_select(unsigned int chan)
return SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(chan);
}
+struct sun4i_gpadc_iio;
+
struct gpadc_data {
int temp_offset;
int temp_scale;
@@ -56,39 +60,12 @@ struct gpadc_data {
unsigned int tp_adc_select;
unsigned int (*adc_chan_select)(unsigned int chan);
unsigned int adc_chan_mask;
-};
-
-static const struct gpadc_data sun4i_gpadc_data = {
- .temp_offset = -1932,
- .temp_scale = 133,
- .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,
- .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
- .adc_chan_select = &sun4i_gpadc_chan_select,
- .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
-};
-
-static const struct gpadc_data sun5i_gpadc_data = {
- .temp_offset = -1447,
- .temp_scale = 100,
- .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,
- .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
- .adc_chan_select = &sun4i_gpadc_chan_select,
- .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
-};
-
-static const struct gpadc_data sun6i_gpadc_data = {
- .temp_offset = -1623,
- .temp_scale = 167,
- .tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN,
- .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT,
- .adc_chan_select = &sun6i_gpadc_chan_select,
- .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK,
-};
-
-static const struct gpadc_data sun8i_a33_gpadc_data = {
- .temp_offset = -1662,
- .temp_scale = 162,
- .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN,
+ unsigned int temp_data;
+ int (*sample_start)(struct sun4i_gpadc_iio *info);
+ int (*sample_end)(struct sun4i_gpadc_iio *info);
+ bool has_bus_clk;
+ bool has_bus_rst;
+ bool has_mod_clk;
};
struct sun4i_gpadc_iio {
@@ -103,6 +80,9 @@ struct sun4i_gpadc_iio {
atomic_t ignore_temp_data_irq;
const struct gpadc_data *data;
bool no_irq;
+ struct clk *ths_bus_clk;
+ struct clk *mod_clk;
+ struct reset_control *reset;
/* prevents concurrent reads of temperature and ADC */
struct mutex mutex;
struct thermal_zone_device *tzd;
@@ -276,7 +256,7 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)
if (info->no_irq) {
pm_runtime_get_sync(indio_dev->dev.parent);
- regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val);
+ regmap_read(info->regmap, info->data->temp_data, val);
pm_runtime_mark_last_busy(indio_dev->dev.parent);
pm_runtime_put_autosuspend(indio_dev->dev.parent);
@@ -384,10 +364,8 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int sun4i_gpadc_runtime_suspend(struct device *dev)
+static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info)
{
- struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
-
/* Disable the ADC on IP */
regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0);
/* Disable temperature sensor on IP */
@@ -396,10 +374,23 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev)
return 0;
}
-static int sun4i_gpadc_runtime_resume(struct device *dev)
+static int sun8i_h3_gpadc_sample_end(struct sun4i_gpadc_iio *info)
+{
+ /* Disable temperature sensor */
+ regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL2, 0);
+
+ return 0;
+}
+
+static int sun4i_gpadc_runtime_suspend(struct device *dev)
{
struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
+ return info->data->sample_end(info);
+}
+
+static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info)
+{
/* clkin = 6MHz */
regmap_write(info->regmap, SUN4I_GPADC_CTRL0,
SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) |
@@ -417,6 +408,29 @@ static int sun4i_gpadc_runtime_resume(struct device *dev)
return 0;
}
+static int sun8i_h3_gpadc_sample_start(struct sun4i_gpadc_iio *info)
+{
+ regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL2,
+ SUN8I_H3_GPADC_CTRL2_TEMP_SENSE_EN |
+ SUN8I_H3_GPADC_CTRL2_T_ACQ1(31));
+ regmap_write(info->regmap, SUN4I_GPADC_CTRL0,
+ SUN4I_GPADC_CTRL0_T_ACQ(31));
+ regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL3,
+ SUN4I_GPADC_CTRL3_FILTER_EN |
+ SUN4I_GPADC_CTRL3_FILTER_TYPE(1));
+ regmap_write(info->regmap, SUN8I_H3_GPADC_INTC,
+ SUN8I_H3_GPADC_INTC_TEMP_PERIOD(800));
+
+ return 0;
+}
+
+static int sun4i_gpadc_runtime_resume(struct device *dev)
+{
+ struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
+
+ return info->data->sample_start(info);
+}
+
static int sun4i_gpadc_get_temp(void *data, int *temp)
{
struct sun4i_gpadc_iio *info = data;
@@ -491,11 +505,78 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
return 0;
}
+static const struct gpadc_data sun4i_gpadc_data = {
+ .temp_offset = -1932,
+ .temp_scale = 133,
+ .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,
+ .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
+ .adc_chan_select = &sun4i_gpadc_chan_select,
+ .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
+ .temp_data = SUN4I_GPADC_TEMP_DATA,
+ .sample_start = sun4i_gpadc_sample_start,
+ .sample_end = sun4i_gpadc_sample_end,
+};
+
+static const struct gpadc_data sun5i_gpadc_data = {
+ .temp_offset = -1447,
+ .temp_scale = 100,
+ .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,
+ .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
+ .adc_chan_select = &sun4i_gpadc_chan_select,
+ .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,
+ .temp_data = SUN4I_GPADC_TEMP_DATA,
+ .sample_start = sun4i_gpadc_sample_start,
+ .sample_end = sun4i_gpadc_sample_end,
+};
+
+static const struct gpadc_data sun6i_gpadc_data = {
+ .temp_offset = -1623,
+ .temp_scale = 167,
+ .tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN,
+ .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT,
+ .adc_chan_select = &sun6i_gpadc_chan_select,
+ .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK,
+ .temp_data = SUN4I_GPADC_TEMP_DATA,
+ .sample_start = sun4i_gpadc_sample_start,
+ .sample_end = sun4i_gpadc_sample_end,
+};
+
+static const struct gpadc_data sun8i_a33_gpadc_data = {
+ .temp_offset = -1662,
+ .temp_scale = 162,
+ .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN,
+ .temp_data = SUN4I_GPADC_TEMP_DATA,
+ .sample_start = sun4i_gpadc_sample_start,
+ .sample_end = sun4i_gpadc_sample_end,
+};
+
+static const struct gpadc_data sun8i_h3_gpadc_data = {
+ /*
+ * The original formula on the datasheet seems to be wrong.
+ * These factors are calculated based on the formula in the BSP
+ * kernel, which is originally Tem = 217 - (T / 8.253), in which Tem
+ * is the temperature in Celsius degree and T is the raw value
+ * from the sensor.
+ */
+ .temp_offset = -1791,
+ .temp_scale = -121,
+ .temp_data = SUN8I_H3_GPADC_TEMP_DATA,
+ .sample_start = sun8i_h3_gpadc_sample_start,
+ .sample_end = sun8i_h3_gpadc_sample_end,
+ .has_bus_clk = true,
+ .has_bus_rst = true,
+ .has_mod_clk = true,
+};
+
static const struct of_device_id sun4i_gpadc_of_id[] = {
{
.compatible = "allwinner,sun8i-a33-ths",
.data = &sun8i_a33_gpadc_data,
},
+ {
+ .compatible = "allwinner,sun8i-h3-ths",
+ .data = &sun8i_h3_gpadc_data,
+ },
{ /* sentinel */ }
};
@@ -530,17 +611,75 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
return ret;
}
+ if (info->data->has_bus_rst) {
+ info->reset = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(info->reset)) {
+ ret = PTR_ERR(info->reset);
+ return ret;
+ }
+
+ ret = reset_control_deassert(info->reset);
+ if (ret)
+ return ret;
+ }
+
+ if (info->data->has_bus_clk) {
+ info->ths_bus_clk = devm_clk_get(&pdev->dev, "bus");
+ if (IS_ERR(info->ths_bus_clk)) {
+ ret = PTR_ERR(info->ths_bus_clk);
+ goto assert_reset;
+ }
+
+ ret = clk_prepare_enable(info->ths_bus_clk);
+ if (ret)
+ goto assert_reset;
+ }
+
+ if (info->data->has_mod_clk) {
+ info->mod_clk = devm_clk_get(&pdev->dev, "mod");
+ if (IS_ERR(info->mod_clk)) {
+ ret = PTR_ERR(info->mod_clk);
+ goto disable_bus_clk;
+ }
+
+ /* Running at 6MHz */
+ ret = clk_set_rate(info->mod_clk, 6000000);
+ if (ret)
+ goto disable_bus_clk;
+
+ ret = clk_prepare_enable(info->mod_clk);
+ if (ret)
+ goto disable_bus_clk;
+ }
+
if (!IS_ENABLED(CONFIG_THERMAL_OF))
return 0;
info->sensor_device = &pdev->dev;
info->tzd = thermal_zone_of_sensor_register(info->sensor_device, 0,
info, &sun4i_ts_tz_ops);
- if (IS_ERR(info->tzd))
+ if (IS_ERR(info->tzd)) {
dev_err(&pdev->dev, "could not register thermal sensor: %ld\n",
PTR_ERR(info->tzd));
+ ret = PTR_ERR(info->tzd);
+ goto disable_mod_clk;
+ }
+
+ return 0;
+
+disable_mod_clk:
+ if (info->data->has_mod_clk)
+ clk_disable_unprepare(info->mod_clk);
+
+disable_bus_clk:
+ if (info->data->has_bus_clk)
+ clk_disable_unprepare(info->ths_bus_clk);
+
+assert_reset:
+ if (info->data->has_bus_rst)
+ reset_control_assert(info->reset);
- return PTR_ERR_OR_ZERO(info->tzd);
+ return ret;
}
static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
@@ -699,6 +838,15 @@ static int sun4i_gpadc_remove(struct platform_device *pdev)
if (!info->no_irq)
iio_map_array_unregister(indio_dev);
+ if (info->data->has_mod_clk)
+ clk_disable_unprepare(info->mod_clk);
+
+ if (info->data->has_bus_clk)
+ clk_disable_unprepare(info->ths_bus_clk);
+
+ if (info->data->has_bus_rst)
+ reset_control_assert(info->reset);
+
return 0;
}
diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
index d31d962bb7d8..f794a2988a93 100644
--- a/include/linux/mfd/sun4i-gpadc.h
+++ b/include/linux/mfd/sun4i-gpadc.h
@@ -42,6 +42,9 @@
#define SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN BIT(8)
#define SUN8I_A23_GPADC_CTRL1_GPADC_CALI_EN BIT(7)
+/* TP_CTRL1 bits for SoCs after H3 */
+#define SUN8I_H3_GPADC_CTRL1_GPADC_CALI_EN BIT(17)
+
#define SUN4I_GPADC_CTRL2 0x08
#define SUN4I_GPADC_CTRL2_TP_SENSITIVE_ADJUST(x) ((GENMASK(3, 0) & (x)) << 28)
@@ -49,7 +52,17 @@
#define SUN4I_GPADC_CTRL2_PRE_MEA_EN BIT(24)
#define SUN4I_GPADC_CTRL2_PRE_MEA_THRE_CNT(x) (GENMASK(23, 0) & (x))
+#define SUN8I_H3_GPADC_CTRL2 0x40
+
+#define SUN8I_H3_GPADC_CTRL2_TEMP_SENSE_EN BIT(0)
+#define SUN8I_H3_GPADC_CTRL2_T_ACQ1(x) ((GENMASK(15, 0) * (x)) << 16)
+
#define SUN4I_GPADC_CTRL3 0x0c
+/*
+ * This register is named "Average filter Control Register" in H3 Datasheet,
+ * but the register's definition is the same as the old CTRL3 register.
+ */
+#define SUN8I_H3_GPADC_CTRL3 0x70
#define SUN4I_GPADC_CTRL3_FILTER_EN BIT(2)
#define SUN4I_GPADC_CTRL3_FILTER_TYPE(x) (GENMASK(1, 0) & (x))
@@ -71,6 +84,13 @@
#define SUN4I_GPADC_INT_FIFOC_TP_UP_IRQ_EN BIT(1)
#define SUN4I_GPADC_INT_FIFOC_TP_DOWN_IRQ_EN BIT(0)
+#define SUN8I_H3_GPADC_INTC 0x44
+
+#define SUN8I_H3_GPADC_INTC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12)
+#define SUN8I_H3_GPADC_INTC_TEMP_DATA BIT(8)
+#define SUN8I_H3_GPADC_INTC_TEMP_SHUT BIT(4)
+#define SUN8I_H3_GPADC_INTC_TEMP_ALARM BIT(0)
+
#define SUN4I_GPADC_INT_FIFOS 0x14
#define SUN4I_GPADC_INT_FIFOS_TEMP_DATA_PENDING BIT(18)
@@ -80,9 +100,16 @@
#define SUN4I_GPADC_INT_FIFOS_TP_UP_PENDING BIT(1)
#define SUN4I_GPADC_INT_FIFOS_TP_DOWN_PENDING BIT(0)
+#define SUN8I_H3_GPADC_INTS 0x44
+
+#define SUN8I_H3_GPADC_INTS_TEMP_DATA BIT(8)
+#define SUN8I_H3_GPADC_INTS_TEMP_SHUT BIT(4)
+#define SUN8I_H3_GPADC_INTS_TEMP_ALARM BIT(0)
+
#define SUN4I_GPADC_CDAT 0x1c
#define SUN4I_GPADC_TEMP_DATA 0x20
#define SUN4I_GPADC_DATA 0x24
+#define SUN8I_H3_GPADC_TEMP_DATA 0x80
#define SUN4I_GPADC_IRQ_FIFO_DATA 0
#define SUN4I_GPADC_IRQ_TEMP_DATA 1

View file

@ -1,28 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index a0cee17fe44b..efe3a8e4f2af 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -108,6 +108,23 @@
};
};
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&ths>;
+ };
+
+ soc {
+ ths: thermal-sensor@1c25000 {
+ compatible = "allwinner,sun8i-h3-ths";
+ reg = <0x01c25000 0x100>;
+ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_THS>;
+ #thermal-sensor-cells = <0>;
+ #io-channel-cells = <0>;
+ };
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,

View file

@ -1,93 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index b36f9f423..0ad8e3e80 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -41,6 +41,7 @@
*/
#include "sunxi-h3-h5.dtsi"
+#include <dt-bindings/thermal/thermal.h>
/ {
cpus {
@@ -72,6 +73,80 @@
};
};
+ thermal-zones {
+ cpu-thermal {
+ /* milliseconds */
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&ths>;
+
+ trips {
+ cpu_warm: cpu_warm {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_hot_pre: cpu_hot_pre {
+ temperature = <70000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_hot: cpu_hot {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_very_hot_pre: cpu_very_hot_pre {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_very_hot: cpu_very_hot {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_crit: cpu_crit {
+ temperature = <105000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ cpu_warm_limit_cpu {
+ trip = <&cpu_warm>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT 2>;
+ };
+
+ cpu_hot_pre_limit_cpu {
+ trip = <&cpu_hot_pre>;
+ cooling-device = <&cpu0 2 3>;
+ };
+
+ cpu_hot_limit_cpu {
+ trip = <&cpu_hot>;
+ cooling-device = <&cpu0 3 4>;
+ };
+
+ cpu_very_hot_pre_limit_cpu {
+ trip = <&cpu_very_hot>;
+ cooling-device = <&cpu0 5 6>;
+ };
+
+ cpu_very_hot_limit_cpu {
+ trip = <&cpu_very_hot>;
+ cooling-device = <&cpu0 7 THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,

View file

@ -1,34 +0,0 @@
From e42ea77a5f2b389eed2c9004eab80bf6589ebf5a Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Tue, 1 Aug 2017 23:42:12 +0800
Subject: [PATCH] iio: adc: sun4i-gpadc: workaroud bogus THS raw value 0
readout
When booting the system, the THS may read out a bogus false value which
is raw value 0.
On H3 it represents a extremely high temperature and can shutdown the
system immediately.
Workaround it by make it return -EINVAL when the raw value is 0 (which
is unlikely to happen).
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/iio/adc/sun4i-gpadc-iio.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index f378ca0bc0b30..a89dcb6fba4ec 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -262,6 +262,9 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)
pm_runtime_mark_last_busy(indio_dev->dev.parent);
pm_runtime_put_autosuspend(indio_dev->dev.parent);
+ if (!*val)
+ return -EINVAL;
+
return 0;
}

View file

@ -1,153 +0,0 @@
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index a89dcb6fb..dbe41fdf2 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -56,6 +56,7 @@ struct sun4i_gpadc_iio;
struct gpadc_data {
int temp_offset;
int temp_scale;
+ int temp_divider;
unsigned int tp_mode_en;
unsigned int tp_adc_select;
unsigned int (*adc_chan_select)(unsigned int chan);
@@ -63,6 +64,7 @@ struct gpadc_data {
unsigned int temp_data;
int (*sample_start)(struct sun4i_gpadc_iio *info);
int (*sample_end)(struct sun4i_gpadc_iio *info);
+ void (*reg_to_temp)(int val, int *temp);
bool has_bus_clk;
bool has_bus_rst;
bool has_mod_clk;
@@ -289,6 +291,15 @@ static int sun4i_gpadc_temp_scale(struct iio_dev *indio_dev, int *val)
return 0;
}
+static int sun4i_gpadc_temp_divider(struct iio_dev *indio_dev, int *val)
+{
+ struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+
+ *val = info->data->temp_divider;
+
+ return 0;
+}
+
static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -436,19 +447,32 @@ static int sun4i_gpadc_runtime_resume(struct device *dev)
static int sun4i_gpadc_get_temp(void *data, int *temp)
{
struct sun4i_gpadc_iio *info = data;
- int val, scale, offset;
+ int val, scale, offset, divider;
if (sun4i_gpadc_temp_read(info->indio_dev, &val))
return -ETIMEDOUT;
sun4i_gpadc_temp_scale(info->indio_dev, &scale);
sun4i_gpadc_temp_offset(info->indio_dev, &offset);
+ sun4i_gpadc_temp_divider(info->indio_dev, &divider);
- *temp = (val + offset) * scale;
+ if (info->data->reg_to_temp)
+ info->data->reg_to_temp(val, temp);
+ else
+ *temp = ((val + offset) * scale) / divider;
return 0;
}
+void sun50i_h5_reg_to_temp(int val, int *temp)
+{
+ u32 data = (u32)val;
+ if (data <= 0x500)
+ *temp = (2590000 - 1452 * data) / 10000;
+ else
+ *temp = (2230000 - 1191 * data) / 10000;
+}
+
static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = {
.get_temp = &sun4i_gpadc_get_temp,
};
@@ -510,6 +534,7 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
static const struct gpadc_data sun4i_gpadc_data = {
.temp_offset = -1932,
.temp_scale = 133,
+ .temp_divider = 1,
.tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,
.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = &sun4i_gpadc_chan_select,
@@ -522,6 +547,7 @@ static const struct gpadc_data sun4i_gpadc_data = {
static const struct gpadc_data sun5i_gpadc_data = {
.temp_offset = -1447,
.temp_scale = 100,
+ .temp_divider = 1,
.tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,
.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = &sun4i_gpadc_chan_select,
@@ -534,6 +560,7 @@ static const struct gpadc_data sun5i_gpadc_data = {
static const struct gpadc_data sun6i_gpadc_data = {
.temp_offset = -1623,
.temp_scale = 167,
+ .temp_divider = 1,
.tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN,
.tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT,
.adc_chan_select = &sun6i_gpadc_chan_select,
@@ -546,6 +573,7 @@ static const struct gpadc_data sun6i_gpadc_data = {
static const struct gpadc_data sun8i_a33_gpadc_data = {
.temp_offset = -1662,
.temp_scale = 162,
+ .temp_divider = 1,
.tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN,
.temp_data = SUN4I_GPADC_TEMP_DATA,
.sample_start = sun4i_gpadc_sample_start,
@@ -562,6 +590,34 @@ static const struct gpadc_data sun8i_h3_gpadc_data = {
*/
.temp_offset = -1791,
.temp_scale = -121,
+ .temp_divider = 1,
+ .temp_data = SUN8I_H3_GPADC_TEMP_DATA,
+ .sample_start = sun8i_h3_gpadc_sample_start,
+ .sample_end = sun8i_h3_gpadc_sample_end,
+ .has_bus_clk = true,
+ .has_bus_rst = true,
+ .has_mod_clk = true,
+};
+
+static const struct gpadc_data sun50i_a64_gpadc_data = {
+ .temp_offset = -2170,
+ .temp_scale = -1000,
+ .temp_divider = 8560,
+ .temp_data = SUN8I_H3_GPADC_TEMP_DATA,
+ .sample_start = sun8i_h3_gpadc_sample_start,
+ .sample_end = sun8i_h3_gpadc_sample_end,
+ .has_bus_clk = true,
+ .has_bus_rst = true,
+ .has_mod_clk = true,
+};
+
+static const struct gpadc_data sun50i_h5_gpadc_data = {
+ /* Not done for now since requires 3 extra fields
+ and/or a custom temperature conversion function
+ */
+ .temp_offset = -1791,
+ .temp_scale = -121,
+ .temp_divider = 1,
.temp_data = SUN8I_H3_GPADC_TEMP_DATA,
.sample_start = sun8i_h3_gpadc_sample_start,
.sample_end = sun8i_h3_gpadc_sample_end,
@@ -579,6 +635,14 @@ static const struct of_device_id sun4i_gpadc_of_id[] = {
.compatible = "allwinner,sun8i-h3-ths",
.data = &sun8i_h3_gpadc_data,
},
+ {
+ .compatible = "allwinner,sun50i-a64-ths",
+ .data = &sun50i_a64_gpadc_data,
+ },
+ {
+ .compatible = "allwinner,sun50i-h5-ths",
+ .data = &sun50i_h5_gpadc_data,
+ },
{ /* sentinel */ }
};

View file

@ -1,28 +0,0 @@
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
index d9a720bf..55b95569 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
@@ -76,6 +76,23 @@
};
};
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&ths>;
+ };
+
+ soc {
+ ths: thermal-sensor@1c25000 {
+ compatible = "allwinner,sun50i-h5-ths";
+ reg = <0x01c25000 0x100>;
+ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_THS>;
+ #thermal-sensor-cells = <0>;
+ #io-channel-cells = <0>;
+ };
+ };
+
psci {
compatible = "arm,psci-0.2";
method = "smc";

View file

@ -1,93 +0,0 @@
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
index 55b95569..422589b3 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
@@ -41,6 +41,7 @@
*/
#include <arm/sunxi-h3-h5.dtsi>
+#include <dt-bindings/thermal/thermal.h>
/ {
cpus {
@@ -98,6 +99,80 @@
method = "smc";
};
+ thermal-zones {
+ cpu-thermal {
+ /* milliseconds */
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&ths>;
+
+ trips {
+ cpu_warm: cpu_warm {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_hot_pre: cpu_hot_pre {
+ temperature = <70000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_hot: cpu_hot {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_very_hot_pre: cpu_very_hot_pre {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_very_hot: cpu_very_hot {
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_crit: cpu_crit {
+ temperature = <105000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ cpu_warm_limit_cpu {
+ trip = <&cpu_warm>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT 2>;
+ };
+
+ cpu_hot_pre_limit_cpu {
+ trip = <&cpu_hot_pre>;
+ cooling-device = <&cpu0 2 3>;
+ };
+
+ cpu_hot_limit_cpu {
+ trip = <&cpu_hot>;
+ cooling-device = <&cpu0 3 4>;
+ };
+
+ cpu_very_hot_pre_limit_cpu {
+ trip = <&cpu_very_hot>;
+ cooling-device = <&cpu0 5 6>;
+ };
+
+ cpu_very_hot_limit_cpu {
+ trip = <&cpu_very_hot>;
+ cooling-device = <&cpu0 7 THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 13

View file

@ -1,99 +0,0 @@
From 98b373a7c4b0b634979ff646d8aa40ea0ab96c1a Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Mon, 7 Dec 2015 09:47:34 +0100
Subject: [PATCH] drm/sun4i: Add GEM allocator
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/gpu/drm/sun4i/sun4i_drv.c | 27 +++++++++++++++++++++++++++
include/uapi/drm/sun4i_drm.h | 29 +++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
create mode 100644 include/uapi/drm/sun4i_drm.h
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index a45a627283a14..52991511ccd48 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -21,6 +21,8 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_of.h>
+#include <uapi/drm/sun4i_drm.h>
+
#include "sun4i_drv.h"
#include "sun4i_framebuffer.h"
#include "sun4i_tcon.h"
@@ -34,6 +36,27 @@ static void sun4i_drv_lastclose(struct drm_device *dev)
DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
+static int sun4i_gem_create_ioctl(struct drm_device *drm, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_sun4i_gem_create *args = data;
+ struct drm_gem_cma_object *cma_obj;
+ size_t size;
+
+ /* The Mali requires a 64 bytes alignment */
+ size = ALIGN(args->size, 64);
+
+ cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, size,
+ &args->handle);
+
+ return PTR_ERR_OR_ZERO(cma_obj);
+}
+
+static const struct drm_ioctl_desc sun4i_drv_ioctls[] = {
+ DRM_IOCTL_DEF_DRV(SUN4I_GEM_CREATE, sun4i_gem_create_ioctl,
+ DRM_UNLOCKED | DRM_AUTH),
+};
+
static struct drm_driver sun4i_drv_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
@@ -46,6 +69,10 @@ static struct drm_driver sun4i_drv_driver = {
.major = 1,
.minor = 0,
+ /* Custom ioctls */
+ .ioctls = sun4i_drv_ioctls,
+ .num_ioctls = ARRAY_SIZE(sun4i_drv_ioctls),
+
/* GEM Operations */
.dumb_create = drm_gem_cma_dumb_create,
.dumb_destroy = drm_gem_dumb_destroy,
diff --git a/include/uapi/drm/sun4i_drm.h b/include/uapi/drm/sun4i_drm.h
new file mode 100644
index 0000000000000..67b9dd4ee594b
--- /dev/null
+++ b/include/uapi/drm/sun4i_drm.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * 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.
+ */
+
+#ifndef _UAPI_SUN4I_DRM_H_
+#define _UAPI_SUN4I_DRM_H_
+
+#include <drm/drm.h>
+
+struct drm_sun4i_gem_create {
+ __u64 size;
+ __u32 flags;
+ __u32 handle;
+};
+
+#define DRM_SUN4I_GEM_CREATE 0x00
+
+#define DRM_IOCTL_SUN4I_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_SUN4I_GEM_CREATE, \
+ struct drm_sun4i_gem_create)
+
+#endif

View file

@ -1,47 +0,0 @@
From f684ef84935674e3234b88fab6856d218616947c Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Mon, 7 Dec 2015 09:33:28 +0100
Subject: [PATCH] drm: gem: cma: Export with handle allocator
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/gpu/drm/drm_gem_cma_helper.c | 3 ++-
include/drm/drm_gem_cma_helper.h | 4 ++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index bc28e75752546..cff1ae4b255c9 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -142,7 +142,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_create);
* A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
* error code on failure.
*/
-static struct drm_gem_cma_object *
+struct drm_gem_cma_object *
drm_gem_cma_create_with_handle(struct drm_file *file_priv,
struct drm_device *drm, size_t size,
uint32_t *handle)
@@ -169,6 +169,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
return cma_obj;
}
+EXPORT_SYMBOL_GPL(drm_gem_cma_create_with_handle);
/**
* drm_gem_cma_free_object - free resources associated with a CMA GEM object
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index b42529e0fae0c..28fc26e359b5b 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -84,6 +84,10 @@ int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma);
/* allocate physical memory */
struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
size_t size);
+struct drm_gem_cma_object *
+drm_gem_cma_create_with_handle(struct drm_file *file_priv,
+ struct drm_device *drm, size_t size,
+ uint32_t *handle);
extern const struct vm_operations_struct drm_gem_cma_vm_ops;

View file

@ -1,54 +0,0 @@
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index b36f9f42..f2973669 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -72,6 +72,49 @@
};
};
+ soc {
+ mali: gpu@1c40000 {
+ compatible = "allwinner,sun8i-h3-mali",
+ "allwinner,sun7i-a20-mali", "arm,mali-400";
+ reg = <0x01c40000 0x10000>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "gp",
+ "gpmmu",
+ "pp0",
+ "ppmmu0",
+ "pp1",
+ "ppmmu1",
+ "pmu";
+ clocks = <&ccu CLK_BUS_GPU>, <&ccu CLK_GPU>;
+ clock-names = "bus", "core";
+ resets = <&ccu RST_BUS_GPU>;
+ memory-region = <&cma>;
+
+ assigned-clocks = <&ccu CLK_GPU>;
+ assigned-clock-rates = <384000000>;
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ cma: linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x4000000>;
+ alignment = <0x2000>;
+ linux,cma-default;
+ };
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,

View file

@ -1,28 +0,0 @@
The GPU clock on H3 has only one parent, PLL-GPU, and the PLL is only
the parent of the GPU clock. The GPU clock can be tweaked by tweaking
the PLL-GPU clock.
Add CLK_SET_RATE_PARENT flag to allow tweaking the GPU clock via
tweaking PLL-GPU.
Fixes: 0577e4853bfb ("clk: sunxi-ng: Add H3 clocks")
Signed-off-by: Icenowy Zheng <icenowy at aosc.io>
---
drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 7a81c4885836..543c46d0e045 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -484,7 +484,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
- 0x1a0, 0, 3, BIT(31), 0);
+ 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);
static struct ccu_common *sun8i_h3_ccu_clks[] = {
&pll_cpux_clk.common,
--
2.13.5

View file

@ -1,83 +0,0 @@
From 059b07989e091f003f2d6adea37a54cd377471d4 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sun, 30 Jul 2017 13:36:18 +0800
Subject: pinctrl: sunxi: rename R_PIO i2c pin function name
The I2C pin functions in R_PIO used to be named "s_twi".
As we usually use the name "i2c" instead of "twi" in the mainline
kernel, change these names to "s_i2c" for consistency.
The "s_twi" functions are not yet referenced by any device trees in
mainline kernel so I think it's safe to change the name.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c | 4 ++--
drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c | 4 ++--
drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
index a22bd88..c96a361 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
@@ -25,12 +25,12 @@ static const struct sunxi_desc_pin sun6i_a31_r_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "s_twi"), /* SCK */
+ SUNXI_FUNCTION(0x2, "s_i2c"), /* SCK */
SUNXI_FUNCTION(0x3, "s_p2wi")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "s_twi"), /* SDA */
+ SUNXI_FUNCTION(0x2, "s_i2c"), /* SDA */
SUNXI_FUNCTION(0x3, "s_p2wi")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
index 2292e05..5789e9e 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
@@ -29,13 +29,13 @@ static const struct sunxi_desc_pin sun8i_a23_r_pins[] = {
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "s_rsb"), /* SCK */
- SUNXI_FUNCTION(0x3, "s_twi"), /* SCK */
+ SUNXI_FUNCTION(0x3, "s_i2c"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 0)), /* PL_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "s_rsb"), /* SDA */
- SUNXI_FUNCTION(0x3, "s_twi"), /* SDA */
+ SUNXI_FUNCTION(0x3, "s_i2c"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 1)), /* PL_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c
index 686ec21..ebfd9a2 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c
@@ -20,12 +20,12 @@ static const struct sunxi_desc_pin sun8i_h3_r_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "s_twi"), /* SCK */
+ SUNXI_FUNCTION(0x2, "s_i2c"), /* SCK */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PL_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "s_twi"), /* SDA */
+ SUNXI_FUNCTION(0x2, "s_i2c"), /* SDA */
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PL_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
--
cgit v1.1

View file

@ -1,236 +0,0 @@
From e9807e63fec81bab15b2e8be714d802966ea6425 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 25 Jun 2016 02:13:50 +0200
Subject: [PATCH 39/87] regulator: add support for SY8106A regulator
SY8106A is an I2C attached single output regulator made by Silergy Corp,
which is used on several Allwinner H3/H5 SBCs to control the power
supply of the ARM cores.
Add a driver for it.
Signed-off-by: Ondrej Jirman <megous@megous.com>
[Icenowy: Change commit message, remove enable/disable code, add default
ramp_delay]
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/regulator/Kconfig | 8 +-
drivers/regulator/Makefile | 2 +-
drivers/regulator/sy8106a-regulator.c | 164 ++++++++++++++++++++++++++++++++++
3 files changed, 172 insertions(+), 2 deletions(-)
create mode 100644 drivers/regulator/sy8106a-regulator.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 99b9362331b5..1efa73e18d07 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -764,6 +764,13 @@ config REGULATOR_STW481X_VMMC
This driver supports the internal VMMC regulator in the STw481x
PMIC chips.
+config REGULATOR_SY8106A
+ tristate "Silergy SY8106A regulator"
+ depends on I2C && (OF || COMPILE_TEST)
+ select REGMAP_I2C
+ help
+ This driver supports SY8106A single output regulator.
+
config REGULATOR_TPS51632
tristate "TI TPS51632 Power Regulator"
depends on I2C
@@ -938,4 +945,3 @@ config REGULATOR_WM8994
WM8994 CODEC.
endif
-
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 95b1e86ae692..f5120252f86a 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -95,6 +95,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
@@ -120,5 +121,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 000000000000..4babc95894e7
--- /dev/null
+++ b/drivers/regulator/sy8106a-regulator.c
@@ -0,0 +1,164 @@
+/*
+ * sy8106a-regulator.c - Regulator device driver for SY8106A
+ *
+ * Copyright (C) 2016 Ondřej Jirman <megous@megous.com>
+ *
+ * This program 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 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
+ * Library General Public License for more details.
+ */
+
+#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 int 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 = {
+ .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,
+ /* Enabling/disabling the regulator is not yet implemented */
+};
+
+/* 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,
+ /*
+ * This ramp_delay is a conservative default value which works on
+ * H3/H5 boards VDD-CPUX situations.
+ */
+ .ramp_delay = 200,
+ .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");
--
2.13.5

View file

@ -1,45 +0,0 @@
From cb4faa1940f5a33c2406c03476cf37ccc32f1997 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 26 Feb 2017 16:09:28 +0100
Subject: [PATCH 41/87] ARM: sunxi: h3/h5: Add r_i2c I2C controller
Allwinner H3/H5 SoCs have an I2C controller at PL GPIO bank.
Add support for it in the device tree.
Signed-off-by: Ondrej Jirman <megous@megous.com>
[Icenowy: Change to use r_ccu and change pinmux node name]
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 3a5f2aad7449..19fb71d29159 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -624,6 +624,20 @@
status = "disabled";
};
+ r_i2c: i2c@01f02400 {
+ compatible = "allwinner,sun6i-a31-i2c";
+ reg = <0x01f02400 0x400>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_i2c_pins>;
+ clocks = <&r_ccu CLK_APB0_I2C>;
+ clock-frequency = <100000>;
+ resets = <&r_ccu RST_APB0_I2C>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
r_pio: pinctrl@01f02c00 {
compatible = "allwinner,sun8i-h3-r-pinctrl";
reg = <0x01f02c00 0x400>;
--
2.13.5

Some files were not shown because too many files have changed in this diff Show more