From 0437a1df6bfecb09fe0ebaa066a0861d85ac170a Mon Sep 17 00:00:00 2001 From: ludiazv Date: Thu, 25 Apr 2024 23:35:48 +0200 Subject: [PATCH] add kernel patches for orangepi-3lts for 6.1 6.5 kernels(KMETA) --- recipes-kernel/linux/linux-mainline.inc | 3 +- ...oC-hdmi-codec-fix-channel-allocation.patch | 142 ++++++ .../HACK-h6-Add-HDMI-sound-card.patch | 53 +++ ...-pek-allow-wakeup-after-shutdown-6_1.patch | 52 +++ ...-pek-allow-wakeup-after-shutdown-6_5.patch | 36 ++ .../OrangePi-3-LTS-support.patch | 393 +++++++++++++++++ ...om-Support-protected-clocks-property.patch | 49 +++ ...ner-Enforce-consistent-MMC-numbering.patch | 67 +++ ...nner-h6-Add-AC200-EPHY-related-nodes.patch | 110 +++++ ...4-dts-allwinner-h6-Add-SCPI-protocol.patch | 46 ++ ...-allwinner-h6-Fix-Cedrus-IOMMU-again.patch | 26 ++ .../arm64-dts-h6-deinterlace.patch | 31 ++ ...otected-clocks-for-all-OF-clock-prov.patch | 197 +++++++++ ...i-Support-unidirectional-mailbox-cha.patch | 122 ++++++ ...-orange-pi-3lts-rtc-on-faulty-boards.patch | 29 ++ .../bsp/orange-pi-3lts/fix-rtc.scc | 3 + ...0i-Allow-page-sizes-multiple-of-4096.patch | 107 +++++ .../mfd-Add-support-for-AC200.patch | 406 ++++++++++++++++++ ...pport-for-X-Powers-AC200-EPHY-syscon.patch | 374 ++++++++++++++++ .../mfd-Add-support-for-X-Powers-AC200.patch | 265 ++++++++++++ ...usuable-eMMC-on-some-H6-boards-by-di.patch | 60 +++ .../net-phy-Add-support-for-AC200-EPHY.patch | 276 ++++++++++++ .../bsp/orange-pi-3lts/orange-pi-3lts-6_1.scc | 8 + .../bsp/orange-pi-3lts/orange-pi-3lts-6_5.scc | 8 + .../orange-pi-3lts/orange-pi-3lts-common.scc | 20 + .../bsp/orange-pi-3lts/orange-pi-3lts.cfg | 5 + ...un6i-Allow-RTC-wakeup-after-shutdown.patch | 62 +++ .../bsp/orange-pi-3lts/wip-fix-H6-4k-60.patch | 75 ++++ recipes-kernel/linux/linux-mainline_6.1.9.bb | 2 + recipes-kernel/linux/linux-mainline_6.5.11.bb | 4 + 30 files changed, 3030 insertions(+), 1 deletion(-) create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/ASoC-hdmi-codec-fix-channel-allocation.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/HACK-h6-Add-HDMI-sound-card.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Input-axp20x-pek-allow-wakeup-after-shutdown-6_1.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Input-axp20x-pek-allow-wakeup-after-shutdown-6_5.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/OrangePi-3-LTS-support.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Revert-clk-qcom-Support-protected-clocks-property.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-Enforce-consistent-MMC-numbering.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Add-SCPI-protocol.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-h6-deinterlace.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/clk-Implement-protected-clocks-for-all-OF-clock-prov.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/fix-orange-pi-3lts-rtc-on-faulty-boards.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/fix-rtc.scc create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-AC200.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-X-Powers-AC200-EPHY-syscon.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-X-Powers-AC200.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/net-phy-Add-support-for-AC200-EPHY.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-6_1.scc create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-6_5.scc create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-common.scc create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts.cfg create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/rtc-sun6i-Allow-RTC-wakeup-after-shutdown.patch create mode 100644 recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/wip-fix-H6-4k-60.patch diff --git a/recipes-kernel/linux/linux-mainline.inc b/recipes-kernel/linux/linux-mainline.inc index 7860c33..5537b6c 100644 --- a/recipes-kernel/linux/linux-mainline.inc +++ b/recipes-kernel/linux/linux-mainline.inc @@ -44,7 +44,8 @@ S = "${WORKDIR}/linux-${PV}" KRELEASE = "${@d.getVar('PV', True).split('.')[0]}" SRC_URI = "https://www.kernel.org/pub/linux/kernel/v${KRELEASE}.x/linux-${PV}.tar.xz \ - file://defconfig \ + file://defconfig \ + file://sunxi-kmeta;type=kmeta;name=sunxi-kmeta;destsuffix=sunxi-kmeta \ " # append patches for kernels before 6.5 and after based on version diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/ASoC-hdmi-codec-fix-channel-allocation.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/ASoC-hdmi-codec-fix-channel-allocation.patch new file mode 100644 index 0000000..83cb49c --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/ASoC-hdmi-codec-fix-channel-allocation.patch @@ -0,0 +1,142 @@ +From 91b69779e0875e58d8973b2938a1cc4b7a1c455b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 25 Mar 2018 22:17:06 +0200 +Subject: [PATCH 22/44] ASoC: hdmi-codec: fix channel allocation + +--- + sound/soc/codecs/hdmi-codec.c | 113 ++++++++++++++++------------------ + 1 file changed, 52 insertions(+), 61 deletions(-) + +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -194,78 +194,69 @@ static const struct snd_pcm_chmap_elem h + */ + static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { + { .ca_id = 0x00, .n_ch = 2, +- .mask = FL | FR}, +- /* 2.1 */ +- { .ca_id = 0x01, .n_ch = 4, +- .mask = FL | FR | LFE}, +- /* Dolby Surround */ ++ .mask = FL | FR }, ++ { .ca_id = 0x03, .n_ch = 4, ++ .mask = FL | FR | LFE | FC }, + { .ca_id = 0x02, .n_ch = 4, + .mask = FL | FR | FC }, +- /* surround51 */ ++ { .ca_id = 0x01, .n_ch = 4, ++ .mask = FL | FR | LFE }, + { .ca_id = 0x0b, .n_ch = 6, +- .mask = FL | FR | LFE | FC | RL | RR}, +- /* surround40 */ +- { .ca_id = 0x08, .n_ch = 6, +- .mask = FL | FR | RL | RR }, +- /* surround41 */ +- { .ca_id = 0x09, .n_ch = 6, +- .mask = FL | FR | LFE | RL | RR }, +- /* surround50 */ ++ .mask = FL | FR | LFE | FC | RL | RR }, + { .ca_id = 0x0a, .n_ch = 6, + .mask = FL | FR | FC | RL | RR }, +- /* 6.1 */ +- { .ca_id = 0x0f, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RL | RR | RC }, +- /* surround71 */ ++ { .ca_id = 0x09, .n_ch = 6, ++ .mask = FL | FR | LFE | RL | RR }, ++ { .ca_id = 0x08, .n_ch = 6, ++ .mask = FL | FR | RL | RR }, ++ { .ca_id = 0x07, .n_ch = 6, ++ .mask = FL | FR | LFE | FC | RC }, ++ { .ca_id = 0x06, .n_ch = 6, ++ .mask = FL | FR | FC | RC }, ++ { .ca_id = 0x05, .n_ch = 6, ++ .mask = FL | FR | LFE | RC }, ++ { .ca_id = 0x04, .n_ch = 6, ++ .mask = FL | FR | RC }, + { .ca_id = 0x13, .n_ch = 8, + .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, +- /* others */ +- { .ca_id = 0x03, .n_ch = 8, +- .mask = FL | FR | LFE | FC }, +- { .ca_id = 0x04, .n_ch = 8, +- .mask = FL | FR | RC}, +- { .ca_id = 0x05, .n_ch = 8, +- .mask = FL | FR | LFE | RC }, +- { .ca_id = 0x06, .n_ch = 8, +- .mask = FL | FR | FC | RC }, +- { .ca_id = 0x07, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RC }, +- { .ca_id = 0x0c, .n_ch = 8, +- .mask = FL | FR | RC | RL | RR }, +- { .ca_id = 0x0d, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | RC }, +- { .ca_id = 0x0e, .n_ch = 8, +- .mask = FL | FR | FC | RL | RR | RC }, +- { .ca_id = 0x10, .n_ch = 8, +- .mask = FL | FR | RL | RR | RLC | RRC }, +- { .ca_id = 0x11, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, + { .ca_id = 0x12, .n_ch = 8, + .mask = FL | FR | FC | RL | RR | RLC | RRC }, +- { .ca_id = 0x14, .n_ch = 8, +- .mask = FL | FR | FLC | FRC }, +- { .ca_id = 0x15, .n_ch = 8, +- .mask = FL | FR | LFE | FLC | FRC }, +- { .ca_id = 0x16, .n_ch = 8, +- .mask = FL | FR | FC | FLC | FRC }, +- { .ca_id = 0x17, .n_ch = 8, +- .mask = FL | FR | LFE | FC | FLC | FRC }, +- { .ca_id = 0x18, .n_ch = 8, +- .mask = FL | FR | RC | FLC | FRC }, +- { .ca_id = 0x19, .n_ch = 8, +- .mask = FL | FR | LFE | RC | FLC | FRC }, +- { .ca_id = 0x1a, .n_ch = 8, +- .mask = FL | FR | RC | FC | FLC | FRC }, +- { .ca_id = 0x1b, .n_ch = 8, +- .mask = FL | FR | LFE | RC | FC | FLC | FRC }, +- { .ca_id = 0x1c, .n_ch = 8, +- .mask = FL | FR | RL | RR | FLC | FRC }, +- { .ca_id = 0x1d, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | FLC | FRC }, + { .ca_id = 0x1e, .n_ch = 8, + .mask = FL | FR | FC | RL | RR | FLC | FRC }, +- { .ca_id = 0x1f, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, ++ { .ca_id = 0x11, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | FLC | FRC }, ++ { .ca_id = 0x10, .n_ch = 8, ++ .mask = FL | FR | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1c, .n_ch = 8, ++ .mask = FL | FR | RL | RR | FLC | FRC }, ++ { .ca_id = 0x0f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | RC }, ++ { .ca_id = 0x1b, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FC | FLC | FRC }, ++ { .ca_id = 0x0e, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | RC }, ++ { .ca_id = 0x1a, .n_ch = 8, ++ .mask = FL | FR | RC | FC | FLC | FRC }, ++ { .ca_id = 0x0d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RC }, ++ { .ca_id = 0x19, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FLC | FRC }, ++ { .ca_id = 0x0c, .n_ch = 8, ++ .mask = FL | FR | RC | RL | RR }, ++ { .ca_id = 0x18, .n_ch = 8, ++ .mask = FL | FR | RC | FLC | FRC }, ++ { .ca_id = 0x17, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | FLC | FRC }, ++ { .ca_id = 0x16, .n_ch = 8, ++ .mask = FL | FR | FC | FLC | FRC }, ++ { .ca_id = 0x15, .n_ch = 8, ++ .mask = FL | FR | LFE | FLC | FRC }, ++ { .ca_id = 0x14, .n_ch = 8, ++ .mask = FL | FR | FLC | FRC }, + }; + + struct hdmi_codec_priv { diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/HACK-h6-Add-HDMI-sound-card.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/HACK-h6-Add-HDMI-sound-card.patch new file mode 100644 index 0000000..dda3c2f --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/HACK-h6-Add-HDMI-sound-card.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 16 Jan 2021 10:58:14 +0100 +Subject: [PATCH] HACK: h6: Add HDMI sound card + +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -108,6 +108,24 @@ + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + }; + ++ sound_hdmi: sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "allwinner-hdmi"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,frame-inversion; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1>; ++ dai-tdm-slot-num = <2>; ++ dai-tdm-slot-width = <32>; ++ }; ++ }; ++ + soc { + compatible = "simple-bus"; + #address-cells = <1>; +@@ -664,7 +682,6 @@ + dmas = <&dma 4>, <&dma 4>; + resets = <&ccu RST_BUS_I2S1>; + dma-names = "rx", "tx"; +- status = "disabled"; + }; + + spdif: spdif@5093000 { +@@ -801,6 +818,7 @@ + }; + + hdmi: hdmi@6000000 { ++ #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-h6-dw-hdmi"; + reg = <0x06000000 0x10000>; + reg-io-width = <1>; diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Input-axp20x-pek-allow-wakeup-after-shutdown-6_1.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Input-axp20x-pek-allow-wakeup-after-shutdown-6_1.patch new file mode 100644 index 0000000..cb602d6 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Input-axp20x-pek-allow-wakeup-after-shutdown-6_1.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sat, 2 Jan 2021 15:52:27 -0600 +Subject: [PATCH] Input: axp20x-pek - allow wakeup after shutdown + +While the AXP20x PMIC handles the power button itself after shutting +down, it is not always possible to use the PMIC's built-in shutdown +feature, such as when other wakeup sources are needed (for example, an +IR remote or wake-on-LAN) that require firmware support. In that case, +the PMIC remains on, but suspended, until the board is powered back on. + +During this "fake" off state, IRQ configuration is similar to system +sleep, where enable_irq_wake() must be call on an IRQ for it to be +wakeup capable. Run the suspend callback to arm the power button IRQs +during the shutdown process, so the power button works in this state. + +Signed-off-by: Samuel Holland +--- + drivers/input/misc/axp20x-pek.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/input/misc/axp20x-pek.c ++++ b/drivers/input/misc/axp20x-pek.c +@@ -354,7 +354,7 @@ static int axp20x_pek_probe(struct platf + return 0; + } + +-static int __maybe_unused axp20x_pek_suspend(struct device *dev) ++static int axp20x_pek_suspend(struct device *dev) + { + struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev); + +@@ -413,6 +413,11 @@ static const struct dev_pm_ops axp20x_pe + #endif + }; + ++static void axp20x_pek_shutdown(struct platform_device *pdev) ++{ ++ axp20x_pek_suspend(&pdev->dev); ++} ++ + static const struct platform_device_id axp_pek_id_match[] = { + { + .name = "axp20x-pek", +@@ -428,6 +433,7 @@ MODULE_DEVICE_TABLE(platform, axp_pek_id + + static struct platform_driver axp20x_pek_driver = { + .probe = axp20x_pek_probe, ++ .shutdown = axp20x_pek_shutdown, + .id_table = axp_pek_id_match, + .driver = { + .name = "axp20x-pek", diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Input-axp20x-pek-allow-wakeup-after-shutdown-6_5.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Input-axp20x-pek-allow-wakeup-after-shutdown-6_5.patch new file mode 100644 index 0000000..bf011a3 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Input-axp20x-pek-allow-wakeup-after-shutdown-6_5.patch @@ -0,0 +1,36 @@ +From dbf607d6716dd0a314d734cfd9423601d6c5a99d Mon Sep 17 00:00:00 2001 +From: OpenEmbedded +Date: Wed, 6 Dec 2023 18:01:24 +0100 +Subject: [PATCH] Input: axp20x-pek - allow wakeup after shutdown + +--- + drivers/input/misc/axp20x-pek.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c +index 4581606a2..7217dc6ed 100644 +--- a/drivers/input/misc/axp20x-pek.c ++++ b/drivers/input/misc/axp20x-pek.c +@@ -393,6 +393,11 @@ static const struct dev_pm_ops axp20x_pek_pm_ops = { + .resume_noirq = pm_sleep_ptr(axp20x_pek_resume_noirq), + }; + ++static void axp20x_pek_shutdown(struct platform_device *pdev) ++{ ++ axp20x_pek_suspend(&pdev->dev); ++} ++ + static const struct platform_device_id axp_pek_id_match[] = { + { + .name = "axp20x-pek", +@@ -408,6 +413,7 @@ MODULE_DEVICE_TABLE(platform, axp_pek_id_match); + + static struct platform_driver axp20x_pek_driver = { + .probe = axp20x_pek_probe, ++ .shutdown = axp20x_pek_shutdown, + .id_table = axp_pek_id_match, + .driver = { + .name = "axp20x-pek", +-- +2.43.0 + diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/OrangePi-3-LTS-support.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/OrangePi-3-LTS-support.patch new file mode 100644 index 0000000..ca12528 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/OrangePi-3-LTS-support.patch @@ -0,0 +1,393 @@ +From 20d3d43d9daa82d5fa1e937e17b975974572d189 Mon Sep 17 00:00:00 2001 +From: Juliano Dorigão +Date: Fri, 3 Mar 2023 16:12:03 -0400 +Subject: [PATCH] OrangePi 3 LTS support + +--- + arch/arm64/boot/dts/allwinner/Makefile | 1 + + .../allwinner/sun50i-h6-orangepi-3-lts.dts | 361 ++++++++++++++++++ + 2 files changed, 362 insertions(+) + create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts + +diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile +index 6a96494a2..ace8159a6 100644 +--- a/arch/arm64/boot/dts/allwinner/Makefile ++++ b/arch/arm64/boot/dts/allwinner/Makefile +@@ -32,6 +32,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-beelink-gs1.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-3.dtb ++dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-3-lts.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-lite2.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts +new file mode 100644 +index 000000000..67f38b8a1 +--- /dev/null ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts +@@ -0,0 +1,361 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2023 Jernej Skrabec ++// Based on sun50i-h6-orangepi-3.dts, which is: ++// Copyright (C) 2019 Ondřej Jirman ++ ++/dts-v1/; ++ ++#include "sun50i-h6.dtsi" ++#include "sun50i-h6-cpu-opp.dtsi" ++ ++#include ++ ++/ { ++ model = "OrangePi 3 LTS"; ++ compatible = "xunlong,orangepi-3-lts", "allwinner,sun50i-h6"; ++ ++ aliases { ++ ethernet0 = &emac; ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ connector { ++ compatible = "hdmi-connector"; ++ ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ ++ ext_osc32k: ext_osc32k_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "ext_osc32k"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ label = "orangepi:red:power"; ++ gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */ ++ }; ++ ++ led-1 { ++ label = "orangepi:green:status"; ++ gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */ ++ default-state = "on"; ++ }; ++ }; ++ ++ reg_vcc5v: vcc5v { ++ /* board wide 5V supply directly from the DC jack */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ reg_gmac_3v3: gmac-3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "gmac-3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ startup-delay-us = <150000>; ++ enable-active-high; ++ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ ++ }; ++ ++ reg_vcc33_wifi: vcc33-wifi { ++ /* Always on 3.3V regulator for WiFi and BT */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc33-wifi"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ enable-active-high; ++ gpio = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */ ++ }; ++ ++ reg_vcc_wifi_io: vcc-wifi-io { ++ /* Always on 1.8V/300mA regulator for WiFi and BT IO */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-wifi-io"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ vin-supply = <®_vcc33_wifi>; ++ }; ++ ++ wifi_pwrseq: wifi-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ clocks = <&rtc 1>; ++ clock-names = "ext_clock"; ++ reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PM3 */ ++ post-power-on-delay-ms = <200>; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <®_dcdca>; ++}; ++ ++&de { ++ status = "okay"; ++}; ++ ++&dwc3 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ehci3 { ++ status = "okay"; ++}; ++ ++&emac { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ext_rgmii_pins>; ++ phy-mode = "rgmii"; ++ phy-handle = <&ext_rgmii_phy>; ++ phy-supply = <®_gmac_3v3>; ++ allwinner,rx-delay-ps = <1500>; ++ allwinner,tx-delay-ps = <700>; ++ status = "okay"; ++}; ++ ++&gpu { ++ mali-supply = <®_dcdcc>; ++ status = "okay"; ++}; ++ ++&hdmi { ++ hvcc-supply = <®_bldo2>; ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ ++&mdio { ++ ext_rgmii_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ ++ reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ ++ reset-assert-us = <15000>; ++ reset-deassert-us = <40000>; ++ }; ++}; ++ ++&mmc0 { ++ vmmc-supply = <®_cldo1>; ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&mmc1 { ++ vmmc-supply = <®_vcc33_wifi>; ++ vqmmc-supply = <®_vcc_wifi_io>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ bus-width = <4>; ++ non-removable; ++ status = "okay"; ++}; ++ ++&mmc2 { ++ vmmc-supply = <®_cldo1>; ++ vqmmc-supply = <®_bldo2>; ++ cap-mmc-hw-reset; ++ non-removable; ++ bus-width = <8>; ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&ohci3 { ++ status = "okay"; ++}; ++ ++&pio { ++ vcc-pc-supply = <®_bldo2>; ++ vcc-pd-supply = <®_cldo1>; ++ vcc-pg-supply = <®_bldo3>; ++}; ++ ++&r_ir { ++ status = "okay"; ++}; ++ ++&r_rsb { ++ clock-frequency = <100000>; ++ status = "okay"; ++ ++ axp805: pmic@745 { ++ compatible = "x-powers,axp805", "x-powers,axp806"; ++ reg = <0x745>; ++ interrupt-parent = <&r_intc>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ x-powers,self-working-mode; ++ vina-supply = <®_vcc5v>; ++ vinb-supply = <®_vcc5v>; ++ vinc-supply = <®_vcc5v>; ++ vind-supply = <®_vcc5v>; ++ vine-supply = <®_vcc5v>; ++ aldoin-supply = <®_vcc5v>; ++ bldoin-supply = <®_vcc5v>; ++ cldoin-supply = <®_vcc5v>; ++ ++ regulators { ++ reg_aldo1: aldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc-pl-led-ir"; ++ }; ++ ++ reg_aldo2: aldo2 { ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc33-audio-tv-ephy-mac"; ++ }; ++ ++ /* ALDO3 is shorted to CLDO1 */ ++ reg_aldo3: aldo3 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc33-io-pd-emmc-sd-usb-uart-1"; ++ }; ++ ++ reg_bldo1: bldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc18-dram-bias-pll"; ++ }; ++ ++ reg_bldo2: bldo2 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc-efuse-pcie-hdmi-pc"; ++ }; ++ ++ reg_bldo3: bldo3 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc-pm-pg-dcxoio-wifi"; ++ }; ++ ++ bldo4 { ++ /* unused */ ++ }; ++ ++ reg_cldo1: cldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc33-io-pd-emmc-sd-usb-uart-2"; ++ }; ++ ++ cldo2 { ++ /* unused */ ++ }; ++ ++ cldo3 { ++ /* unused */ ++ }; ++ ++ reg_dcdca: dcdca { ++ regulator-always-on; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1160000>; ++ regulator-ramp-delay = <2500>; ++ regulator-name = "vdd-cpu"; ++ }; ++ ++ reg_dcdcc: dcdcc { ++ regulator-enable-ramp-delay = <32000>; ++ regulator-min-microvolt = <810000>; ++ regulator-max-microvolt = <1080000>; ++ regulator-ramp-delay = <2500>; ++ regulator-name = "vdd-gpu"; ++ }; ++ ++ reg_dcdcd: dcdcd { ++ regulator-always-on; ++ regulator-min-microvolt = <980000>; ++ regulator-max-microvolt = <980000>; ++ regulator-name = "vdd-sys"; ++ }; ++ ++ reg_dcdce: dcdce { ++ regulator-always-on; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-name = "vcc-dram"; ++ }; ++ ++ sw { ++ /* unused */ ++ }; ++ }; ++ }; ++}; ++ ++&pwm { ++ status = "okay"; ++}; ++ ++&r_ir { ++ status = "okay"; ++}; ++ ++&rtc { ++ clocks = <&ext_osc32k>; ++}; ++ ++/delete-node/ &spi0; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_ph_pins>; ++ status = "okay"; ++}; ++ ++&usb2otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb2phy { ++ usb0_id_det-gpios = <&pio 2 15 GPIO_ACTIVE_HIGH>; /* PC15 */ ++ usb0_vbus-supply = <®_vcc5v>; ++ usb3_vbus-supply = <®_vcc5v>; ++ status = "okay"; ++}; ++ ++&usb3phy { ++ status = "okay"; ++}; +-- +2.39.2 + diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Revert-clk-qcom-Support-protected-clocks-property.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Revert-clk-qcom-Support-protected-clocks-property.patch new file mode 100644 index 0000000..98f48bc --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/Revert-clk-qcom-Support-protected-clocks-property.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Mon, 30 Dec 2019 12:39:31 -0600 +Subject: [PATCH] Revert "clk: qcom: Support 'protected-clocks' property" + +Now that protected-clocks is handled in the clk core, this +driver-specific implementation is redundant. + +This reverts commit b181b3b801da8893c8eb706e448dd5111b02de60. + +Signed-off-by: Samuel Holland +--- + drivers/clk/qcom/common.c | 18 ------------------ + 1 file changed, 18 deletions(-) + +--- a/drivers/clk/qcom/common.c ++++ b/drivers/clk/qcom/common.c +@@ -194,22 +194,6 @@ int qcom_cc_register_sleep_clk(struct de + } + EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk); + +-/* Drop 'protected-clocks' from the list of clocks to register */ +-static void qcom_cc_drop_protected(struct device *dev, struct qcom_cc *cc) +-{ +- struct device_node *np = dev->of_node; +- struct property *prop; +- const __be32 *p; +- u32 i; +- +- of_property_for_each_u32(np, "protected-clocks", prop, p, i) { +- if (i >= cc->num_rclks) +- continue; +- +- cc->rclks[i] = NULL; +- } +-} +- + static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec, + void *data) + { +@@ -272,8 +256,6 @@ int qcom_cc_really_probe(struct platform + cc->rclks = rclks; + cc->num_rclks = num_clks; + +- qcom_cc_drop_protected(dev, cc); +- + for (i = 0; i < num_clk_hws; i++) { + ret = devm_clk_hw_register(dev, clk_hws[i]); + if (ret) diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-Enforce-consistent-MMC-numbering.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-Enforce-consistent-MMC-numbering.patch new file mode 100644 index 0000000..fc75e6d --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-Enforce-consistent-MMC-numbering.patch @@ -0,0 +1,67 @@ +From ba3b30a80ac2c388d48c58fbee242466d51fbfd8 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sun, 6 Dec 2020 11:15:34 -0600 +Subject: [PATCH 177/389] arm64: dts: allwinner: Enforce consistent MMC + numbering + +Signed-off-by: Samuel Holland +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 ++++++ + arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 6 ++++++ + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 6 ++++++ + 3 files changed, 18 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index 77b5349f6087..9e0e17179839 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -18,6 +18,12 @@ / { + #address-cells = <1>; + #size-cells = <1>; + ++ aliases { ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; ++ mmc2 = &mmc2; ++ }; ++ + chosen { + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +index a56fae761a1f..2159fa336d75 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +@@ -6,6 +6,12 @@ + #include + + / { ++ aliases { ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; ++ mmc2 = &mmc2; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +index ca1d287a0a01..3feac99556f3 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -17,6 +17,12 @@ / { + #address-cells = <1>; + #size-cells = <1>; + ++ aliases { ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; ++ mmc2 = &mmc2; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +-- +2.35.3 + diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch new file mode 100644 index 0000000..51bc021 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:40:20 +0200 +Subject: [PATCH] arm64: dts: allwinner: h6: Add AC200 EPHY related nodes + +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 56 ++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -16,6 +16,16 @@ + #address-cells = <1>; + #size-cells = <1>; + ++ ac200_pwm_clk: ac200_clk { ++ compatible = "pwm-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm1_pin>; ++ pwms = <&pwm 1 42 0>; ++ status = "disabled"; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +@@ -319,6 +329,10 @@ + cpu_speed_grade: cpu-speed-grade@1c { + reg = <0x1c 0x4>; + }; ++ ++ ephy_calib: ephy_calib@2c { ++ reg = <0x2c 0x2>; ++ }; + }; + + timer@3009000 { +@@ -373,6 +387,13 @@ + drive-strength = <40>; + }; + ++ ext_rmii_pins: rmii_pins { ++ pins = "PA0", "PA1", "PA2", "PA3", "PA4", ++ "PA5", "PA6", "PA7", "PA8", "PA9"; ++ function = "emac"; ++ drive-strength = <40>; ++ }; ++ + hdmi_pins: hdmi-pins { + pins = "PH8", "PH9", "PH10"; + function = "hdmi"; +@@ -393,6 +414,11 @@ + function = "i2c2"; + }; + ++ i2c3_pins: i2c3-pins { ++ pins = "PB17", "PB18"; ++ function = "i2c3"; ++ }; ++ + mmc0_pins: mmc0-pins { + pins = "PF0", "PF1", "PF2", "PF3", + "PF4", "PF5"; +@@ -419,6 +445,11 @@ + bias-pull-up; + }; + ++ pwm1_pin: pwm1-pin { ++ pins = "PB19"; ++ function = "pwm1"; ++ }; ++ + /omit-if-no-ref/ + spi0_pins: spi0-pins { + pins = "PC0", "PC2", "PC3"; +@@ -652,6 +683,31 @@ + #size-cells = <0>; + }; + ++ i2c3: i2c@5002c00 { ++ compatible = "allwinner,sun6i-a31-i2c"; ++ reg = <0x05002c00 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2C3>; ++ resets = <&ccu RST_BUS_I2C3>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c3_pins>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ac200: mfd@10 { ++ compatible = "x-powers,ac200"; ++ reg = <0x10>; ++ clocks = <&ac200_pwm_clk>; ++ ++ ac200_ephy: phy { ++ compatible = "x-powers,ac200-ephy"; ++ nvmem-cells = <&ephy_calib>; ++ nvmem-cell-names = "ephy_calib"; ++ }; ++ }; ++ }; ++ + emac: ethernet@5020000 { + compatible = "allwinner,sun50i-h6-emac", + "allwinner,sun50i-a64-emac"; diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Add-SCPI-protocol.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Add-SCPI-protocol.patch new file mode 100644 index 0000000..0971c9d --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Add-SCPI-protocol.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sat, 14 Dec 2019 20:54:40 -0600 +Subject: [PATCH] arm64: dts: allwinner: h6: Add SCPI protocol + +Signed-off-by: Samuel Holland +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -88,6 +88,13 @@ + method = "smc"; + }; + ++ scpi_protocol: scpi { ++ compatible = "arm,scpi"; ++ mboxes = <&msgbox 2>, <&msgbox 3>; ++ mbox-names = "tx", "rx"; ++ shmem = <&scpi_sram>; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + arm,no-tick-in-suspend; +@@ -196,6 +203,19 @@ + #size-cells = <1>; + ranges; + ++ sram_a2: sram@100000 { ++ compatible = "mmio-sram"; ++ reg = <0x00100000 0x18000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0x00100000 0x18000>; ++ ++ scpi_sram: scpi-sram@17c00 { ++ compatible = "arm,scp-shmem"; ++ reg = <0x17c00 0x200>; ++ }; ++ }; ++ + sram_c: sram@28000 { + compatible = "mmio-sram"; + reg = <0x00028000 0x1e000>; diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch new file mode 100644 index 0000000..ec2153f --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 12 Oct 2022 23:01:04 +0200 +Subject: [PATCH] arm64: dts: allwinner: h6: Fix Cedrus IOMMU, again + +Cedrus actually uses two IOMMU channels. Add the second one. + +Fixes: 62a8ccf3a248 ("arm64: dts: allwinner: h6: Fix Cedrus IOMMU usage") +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +index e897559d9a89..436cc2a02d1a 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -172,7 +172,7 @@ video-codec@1c0e000 { + resets = <&ccu RST_BUS_VE>; + interrupts = ; + allwinner,sram = <&ve_sram 1>; +- iommus = <&iommu 3>; ++ iommus = <&iommu 1>, <&iommu 3>; + }; + + gpu: gpu@1800000 { diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-h6-deinterlace.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-h6-deinterlace.patch new file mode 100644 index 0000000..cfc7495 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/arm64-dts-h6-deinterlace.patch @@ -0,0 +1,31 @@ +From c009b3b707bbde30fa6ff49ca3075160524ea7b9 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 26 May 2020 20:08:27 +0200 +Subject: [PATCH 41/44] arm64: dts: h6 deinterlace + +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -160,6 +160,18 @@ + }; + }; + ++ deinterlace: deinterlace@1420000 { ++ compatible = "allwinner,sun50i-h6-deinterlace"; ++ reg = <0x01420000 0x2000>; ++ clocks = <&ccu CLK_BUS_DEINTERLACE>, ++ <&ccu CLK_DEINTERLACE>, ++ <&ccu CLK_MBUS_DEINTERLACE>; ++ clock-names = "bus", "mod", "ram"; ++ resets = <&ccu RST_BUS_DEINTERLACE>; ++ interrupts = ; ++ iommus = <&iommu 2>; ++ }; ++ + video-codec@1c0e000 { + compatible = "allwinner,sun50i-h6-video-engine"; + reg = <0x01c0e000 0x2000>; diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/clk-Implement-protected-clocks-for-all-OF-clock-prov.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/clk-Implement-protected-clocks-for-all-OF-clock-prov.patch new file mode 100644 index 0000000..8ac83e1 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/clk-Implement-protected-clocks-for-all-OF-clock-prov.patch @@ -0,0 +1,197 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sun, 29 Dec 2019 20:23:28 -0600 +Subject: [PATCH] clk: Implement protected-clocks for all OF clock providers + +This is a generic implementation of the "protected-clocks" property from +the common clock binding. It allows firmware to inform the OS about +clocks that must not be disabled while the OS is running. + +This implementation comes with some caveats: + +1) Clocks that have CLK_IS_CRITICAL in their init data are prepared/ +enabled before they are attached to the clock tree. protected-clocks are +only protected once the clock provider is added, which is generally +after all of the clocks it provides have been registered. This leaves a +window of opportunity where something could disable or modify the clock, +such as a driver running on another CPU, or the clock core itself. There +is a comment to this effect in __clk_core_init(): + + /* + * Enable CLK_IS_CRITICAL clocks so newly added critical clocks + * don't get accidentally disabled when walking the orphan tree and + * reparenting clocks + */ + +Similarly, these clocks will be enabled after they are first reparented, +unlike other CLK_IS_CRITICAL clocks. See the comment in +clk_core_reparent_orphans_nolock(): + + /* + * We need to use __clk_set_parent_before() and _after() to + * to properly migrate any prepare/enable count of the orphan + * clock. This is important for CLK_IS_CRITICAL clocks, which + * are enabled during init but might not have a parent yet. + */ + +Ideally we could detect protected clocks before they are reparented, but +there are two problems with that: + + a) From the clock core's perspective, hw->init is const. + + b) The clock core doesn't see the device_node until __clk_register is + called on the first clock. + +So the only "race-free" way to detect protected-clocks is to do it in +the middle of __clk_register, between when core->flags is initialized +and calling __clk_core_init(). That requires scanning the device tree +again for each clock, which is part of why I didn't do it that way. + +2) __clk_protect needs to be idempotent, for two reasons: + + a) Clocks with CLK_IS_CRITICAL in their init data are already + prepared/enabled, and we don't want to prepare/enable them again. + + b) of_clk_set_defaults() is called twice for (at least some) clock + controllers registered with CLK_OF_DECLARE. It is called first in + of_clk_add_provider()/of_clk_add_hw_provider() inside clk_init_cb, + and again afterward in of_clk_init(). The second call in + of_clk_init() may be unnecessary, but verifying that would require + auditing all users of CLK_OF_DECLARE to ensure they called one of + the of_clk_add{,_hw}_provider functions. + +Signed-off-by: Samuel Holland +--- + drivers/clk/clk-conf.c | 54 ++++++++++++++++++++++++++++++++++++++++++ + drivers/clk/clk.c | 31 ++++++++++++++++++++++++ + drivers/clk/clk.h | 2 ++ + 3 files changed, 87 insertions(+) + +--- a/drivers/clk/clk-conf.c ++++ b/drivers/clk/clk-conf.c +@@ -11,6 +11,54 @@ + #include + #include + ++#include "clk.h" ++ ++static int __set_clk_flags(struct device_node *node) ++{ ++ struct of_phandle_args clkspec; ++ struct property *prop; ++ int i, index = 0, rc; ++ const __be32 *cur; ++ struct clk *clk; ++ u32 nr_cells; ++ ++ rc = of_property_read_u32(node, "#clock-cells", &nr_cells); ++ if (rc < 0) { ++ pr_err("clk: missing #clock-cells property on %pOF\n", node); ++ return rc; ++ } ++ ++ clkspec.np = node; ++ clkspec.args_count = nr_cells; ++ ++ of_property_for_each_u32(node, "protected-clocks", prop, cur, clkspec.args[0]) { ++ /* read the remainder of the clock specifier */ ++ for (i = 1; i < nr_cells; ++i) { ++ cur = of_prop_next_u32(prop, cur, &clkspec.args[i]); ++ if (!cur) { ++ pr_err("clk: invalid value of protected-clocks" ++ " property at %pOF\n", node); ++ return -EINVAL; ++ } ++ } ++ clk = of_clk_get_from_provider(&clkspec); ++ if (IS_ERR(clk)) { ++ if (PTR_ERR(clk) != -EPROBE_DEFER) ++ pr_err("clk: couldn't get protected clock" ++ " %u for %pOF\n", index, node); ++ return PTR_ERR(clk); ++ } ++ ++ rc = __clk_protect(clk); ++ if (rc < 0) ++ pr_warn("clk: failed to protect %s: %d\n", ++ __clk_get_name(clk), rc); ++ clk_put(clk); ++ index++; ++ } ++ return 0; ++} ++ + static int __set_clk_parents(struct device_node *node, bool clk_supplier) + { + struct of_phandle_args clkspec; +@@ -135,6 +183,12 @@ int of_clk_set_defaults(struct device_no + if (!node) + return 0; + ++ if (clk_supplier) { ++ rc = __set_clk_flags(node); ++ if (rc < 0) ++ return rc; ++ } ++ + rc = __set_clk_parents(node, clk_supplier); + if (rc < 0) + return rc; +--- a/drivers/clk/clk.c ++++ b/drivers/clk/clk.c +@@ -4271,6 +4271,37 @@ struct clk *devm_clk_hw_get_clk(struct d + EXPORT_SYMBOL_GPL(devm_clk_hw_get_clk); + + /* ++ * clk-conf helpers ++ */ ++ ++int __clk_protect(struct clk *clk) ++{ ++ struct clk_core *core = clk->core; ++ int ret = 0; ++ ++ clk_prepare_lock(); ++ ++ /* ++ * If CLK_IS_CRITICAL was set in the clock's init data, then ++ * the clock was already prepared/enabled when it was added. ++ */ ++ if (core->flags & CLK_IS_CRITICAL) ++ goto out; ++ ++ core->flags |= CLK_IS_CRITICAL; ++ ret = clk_core_prepare(core); ++ if (ret) ++ goto out; ++ ++ ret = clk_core_enable_lock(core); ++ ++out: ++ clk_prepare_unlock(); ++ ++ return ret; ++} ++ ++/* + * clkdev helpers + */ + +--- a/drivers/clk/clk.h ++++ b/drivers/clk/clk.h +@@ -24,6 +24,7 @@ struct clk_hw *clk_find_hw(const char *d + #ifdef CONFIG_COMMON_CLK + struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, + const char *dev_id, const char *con_id); ++int __clk_protect(struct clk *clk); + void __clk_put(struct clk *clk); + #else + /* All these casts to avoid ifdefs in clkdev... */ +@@ -33,6 +34,7 @@ clk_hw_create_clk(struct device *dev, st + { + return (struct clk *)hw; + } ++static inline int __clk_protect(struct clk *clk) { return 0; } + static inline void __clk_put(struct clk *clk) { } + + #endif diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch new file mode 100644 index 0000000..e09d6d2 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch @@ -0,0 +1,122 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Tue, 5 Mar 2019 22:02:41 -0600 +Subject: [PATCH] firmware: arm_scpi: Support unidirectional mailbox channels + +Some mailbox controllers have only unidirectional channels, so we need a +pair of them for each SCPI channel. If a mbox-names property is present, +look for "rx" and "tx" mbox channels; otherwise, the existing behavior +is preserved, and a single mbox channel is used for each SCPI channel. + +Note that since the mailbox framework only supports a single phandle +with each name (mbox_request_channel_byname always returns the first +one), this new mode only supports a single SCPI channel. + +Signed-off-by: Samuel Holland +--- + drivers/firmware/arm_scpi.c | 58 +++++++++++++++++++++++++++++-------- + 1 file changed, 46 insertions(+), 12 deletions(-) + +--- a/drivers/firmware/arm_scpi.c ++++ b/drivers/firmware/arm_scpi.c +@@ -231,7 +231,8 @@ struct scpi_xfer { + + struct scpi_chan { + struct mbox_client cl; +- struct mbox_chan *chan; ++ struct mbox_chan *rx_chan; ++ struct mbox_chan *tx_chan; + void __iomem *tx_payload; + void __iomem *rx_payload; + struct list_head rx_pending; +@@ -505,7 +506,7 @@ static int scpi_send_message(u8 idx, voi + msg->rx_len = rx_len; + reinit_completion(&msg->done); + +- ret = mbox_send_message(scpi_chan->chan, msg); ++ ret = mbox_send_message(scpi_chan->tx_chan, msg); + if (ret < 0 || !rx_buf) + goto out; + +@@ -856,8 +857,13 @@ static void scpi_free_channels(void *dat + struct scpi_drvinfo *info = data; + int i; + +- for (i = 0; i < info->num_chans; i++) +- mbox_free_channel(info->channels[i].chan); ++ for (i = 0; i < info->num_chans; i++) { ++ struct scpi_chan *pchan = &info->channels[i]; ++ ++ if (pchan->tx_chan != pchan->rx_chan) ++ mbox_free_channel(pchan->tx_chan); ++ mbox_free_channel(pchan->rx_chan); ++ } + } + + static int scpi_remove(struct platform_device *pdev) +@@ -913,6 +919,7 @@ static int scpi_probe(struct platform_de + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct scpi_drvinfo *scpi_drvinfo; ++ bool use_mbox_names = false; + + scpi_drvinfo = devm_kzalloc(dev, sizeof(*scpi_drvinfo), GFP_KERNEL); + if (!scpi_drvinfo) +@@ -926,6 +933,14 @@ static int scpi_probe(struct platform_de + dev_err(dev, "no mboxes property in '%pOF'\n", np); + return -ENODEV; + } ++ if (of_get_property(dev->of_node, "mbox-names", NULL)) { ++ use_mbox_names = true; ++ if (count != 2) { ++ dev_err(dev, "need exactly 2 mboxes with mbox-names\n"); ++ return -ENODEV; ++ } ++ count /= 2; ++ } + + scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan), + GFP_KERNEL); +@@ -974,15 +989,34 @@ static int scpi_probe(struct platform_de + mutex_init(&pchan->xfers_lock); + + ret = scpi_alloc_xfer_list(dev, pchan); +- if (!ret) { +- pchan->chan = mbox_request_channel(cl, idx); +- if (!IS_ERR(pchan->chan)) +- continue; +- ret = PTR_ERR(pchan->chan); +- if (ret != -EPROBE_DEFER) +- dev_err(dev, "failed to get channel%d err %d\n", +- idx, ret); ++ if (ret) ++ return ret; ++ ++ if (use_mbox_names) { ++ pchan->rx_chan = mbox_request_channel_byname(cl, "rx"); ++ if (IS_ERR(pchan->rx_chan)) { ++ ret = PTR_ERR(pchan->rx_chan); ++ goto fail; ++ } ++ pchan->tx_chan = mbox_request_channel_byname(cl, "tx"); ++ if (IS_ERR(pchan->rx_chan)) { ++ ret = PTR_ERR(pchan->tx_chan); ++ goto fail; ++ } ++ } else { ++ pchan->rx_chan = mbox_request_channel(cl, idx); ++ if (IS_ERR(pchan->rx_chan)) { ++ ret = PTR_ERR(pchan->rx_chan); ++ goto fail; ++ } ++ pchan->tx_chan = pchan->rx_chan; + } ++ continue; ++ ++fail: ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to get channel%d err %d\n", ++ idx, ret); + return ret; + } + diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/fix-orange-pi-3lts-rtc-on-faulty-boards.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/fix-orange-pi-3lts-rtc-on-faulty-boards.patch new file mode 100644 index 0000000..3fda990 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/fix-orange-pi-3lts-rtc-on-faulty-boards.patch @@ -0,0 +1,29 @@ +From 791849a059cce08f238491b8cae1c3d452edcda5 Mon Sep 17 00:00:00 2001 +From: OpenEmbedded +Date: Wed, 6 Dec 2023 00:37:25 +0100 +Subject: [PATCH 1/2] fix orange pi 3lts rtc on faulty boards" + +--- + arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts +index 67f38b8a1..e3337c6f2 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts +@@ -331,10 +331,10 @@ &pwm { + &r_ir { + status = "okay"; + }; +- ++/* + &rtc { + clocks = <&ext_osc32k>; +-}; ++};*/ + + /delete-node/ &spi0; + +-- +2.43.0 + diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/fix-rtc.scc b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/fix-rtc.scc new file mode 100644 index 0000000..b859676 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/fix-rtc.scc @@ -0,0 +1,3 @@ +# Optional patch for 3 lts that deactivates external 32Khz crystals and fallback to internal clock +# This fix rtc problems at the cost of clock accuracy on faulty boards +patch fix-orange-pi-3lts-rtc-on-faulty-boards.patch diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch new file mode 100644 index 0000000..a6af506 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 14 Oct 2022 20:15:43 +0200 +Subject: [PATCH] iommu/sun50i: Allow page sizes multiple of 4096 + +While peripheral supports only 4K page sizes, we can easily emulate +support for bigger page sizes, up to 1M. This is done by making multiple +entries in map function or clearing multiple entries in unmap. + +This considerably lowers overhead. + +Signed-off-by: Jernej Skrabec +--- + drivers/iommu/sun50i-iommu.c | 44 +++++++++++++++++++++--------------- + 1 file changed, 26 insertions(+), 18 deletions(-) + +diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c +index d7c5e9b1a087..9944266c4f58 100644 +--- a/drivers/iommu/sun50i-iommu.c ++++ b/drivers/iommu/sun50i-iommu.c +@@ -593,10 +593,12 @@ static int sun50i_iommu_map(struct iommu_domain *domain, unsigned long iova, + { + struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain); + struct sun50i_iommu *iommu = sun50i_domain->iommu; +- u32 pte_index; ++ u32 pte_index, pages, i; + u32 *page_table, *pte_addr; + int ret = 0; + ++ pages = size / SPAGE_SIZE; ++ + page_table = sun50i_dte_get_page_table(sun50i_domain, iova, gfp); + if (IS_ERR(page_table)) { + ret = PTR_ERR(page_table); +@@ -604,18 +606,21 @@ static int sun50i_iommu_map(struct iommu_domain *domain, unsigned long iova, + } + + pte_index = sun50i_iova_get_pte_index(iova); +- pte_addr = &page_table[pte_index]; +- if (unlikely(sun50i_pte_is_page_valid(*pte_addr))) { +- phys_addr_t page_phys = sun50i_pte_get_page_address(*pte_addr); +- dev_err(iommu->dev, +- "iova %pad already mapped to %pa cannot remap to %pa prot: %#x\n", +- &iova, &page_phys, &paddr, prot); +- ret = -EBUSY; +- goto out; ++ for (i = 0; i < pages; i++) { ++ pte_addr = &page_table[pte_index + i]; ++ if (unlikely(sun50i_pte_is_page_valid(*pte_addr))) { ++ phys_addr_t page_phys = sun50i_pte_get_page_address(*pte_addr); ++ dev_err(iommu->dev, ++ "iova %pad already mapped to %pa cannot remap to %pa prot: %#x\n", ++ &iova, &page_phys, &paddr, prot); ++ ret = -EBUSY; ++ goto out; ++ } ++ *pte_addr = sun50i_mk_pte(paddr, prot); ++ paddr += SPAGE_SIZE; + } + +- *pte_addr = sun50i_mk_pte(paddr, prot); +- sun50i_table_flush(sun50i_domain, pte_addr, 1); ++ sun50i_table_flush(sun50i_domain, &page_table[pte_index], pages); + + out: + return ret; +@@ -626,8 +631,10 @@ static size_t sun50i_iommu_unmap(struct iommu_domain *domain, unsigned long iova + { + struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain); + phys_addr_t pt_phys; ++ u32 dte, pages, i; + u32 *pte_addr; +- u32 dte; ++ ++ pages = size / SPAGE_SIZE; + + dte = sun50i_domain->dt[sun50i_iova_get_dte_index(iova)]; + if (!sun50i_dte_is_pt_valid(dte)) +@@ -636,13 +643,14 @@ static size_t sun50i_iommu_unmap(struct iommu_domain *domain, unsigned long iova + pt_phys = sun50i_dte_get_pt_address(dte); + pte_addr = (u32 *)phys_to_virt(pt_phys) + sun50i_iova_get_pte_index(iova); + +- if (!sun50i_pte_is_page_valid(*pte_addr)) +- return 0; ++ for (i = 0; i < pages; i++) ++ if (!sun50i_pte_is_page_valid(pte_addr[i])) ++ return 0; + +- memset(pte_addr, 0, sizeof(*pte_addr)); +- sun50i_table_flush(sun50i_domain, pte_addr, 1); ++ memset(pte_addr, 0, sizeof(*pte_addr) * pages); ++ sun50i_table_flush(sun50i_domain, pte_addr, pages); + +- return SZ_4K; ++ return size; + } + + static phys_addr_t sun50i_iommu_iova_to_phys(struct iommu_domain *domain, +@@ -828,7 +836,7 @@ static int sun50i_iommu_of_xlate(struct device *dev, + } + + static const struct iommu_ops sun50i_iommu_ops = { +- .pgsize_bitmap = SZ_4K, ++ .pgsize_bitmap = 0x1ff000, + .device_group = sun50i_iommu_device_group, + .domain_alloc = sun50i_iommu_domain_alloc, + .of_xlate = sun50i_iommu_of_xlate, diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-AC200.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-AC200.patch new file mode 100644 index 0000000..53b7895 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-AC200.patch @@ -0,0 +1,406 @@ +From 59adceb6f34521c0f1a229f20ee9961269daa539 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:38:21 +0200 +Subject: [PATCH 38/44] mfd: Add support for AC200 + +Signed-off-by: Jernej Skrabec +--- + drivers/mfd/Kconfig | 9 ++ + drivers/mfd/Makefile | 1 + + drivers/mfd/ac200.c | 150 +++++++++++++++++++++++++++ + include/linux/mfd/ac200.h | 209 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 369 insertions(+) + create mode 100644 drivers/mfd/ac200.c + create mode 100644 include/linux/mfd/ac200.h + +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -178,6 +178,15 @@ config MFD_AC100 + This driver include only the core APIs. You have to select individual + components like codecs or RTC under the corresponding menus. + ++config MFD_AC200 ++ tristate "X-Powers AC200" ++ select MFD_CORE ++ depends on I2C ++ help ++ If you say Y here you get support for the X-Powers AC200 IC. ++ This driver include only the core APIs. You have to select individual ++ components like Ethernet PHY or RTC under the corresponding menus. ++ + config MFD_AXP20X + tristate + select MFD_CORE +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -142,6 +142,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-s + obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o + + obj-$(CONFIG_MFD_AC100) += ac100.o ++obj-$(CONFIG_MFD_AC200) += ac200.o + obj-$(CONFIG_MFD_AXP20X) += axp20x.o + obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o + obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o +--- /dev/null ++++ b/drivers/mfd/ac200.c +@@ -0,0 +1,148 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * MFD core driver for X-Powers' AC200 IC ++ * ++ * The AC200 is a chip which is co-packaged with Allwinner H6 SoC and ++ * includes analog audio codec, analog TV encoder, ethernet PHY, eFuse ++ * and RTC. ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ * ++ * Based on AC100 driver with following copyrights: ++ * Copyright (2016) Chen-Yu Tsai ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static const struct regmap_range_cfg ac200_range_cfg[] = { ++ { ++ .range_min = AC200_SYS_VERSION, ++ .range_max = AC200_IC_CHARA1, ++ .selector_reg = AC200_TWI_REG_ADDR_H, ++ .selector_mask = 0xff, ++ .selector_shift = 0, ++ .window_start = 0, ++ .window_len = 256, ++ } ++}; ++ ++static const struct regmap_config ac200_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 16, ++ .ranges = ac200_range_cfg, ++ .num_ranges = ARRAY_SIZE(ac200_range_cfg), ++ .max_register = AC200_IC_CHARA1, ++}; ++ ++static struct mfd_cell ac200_cells[] = { ++ { ++ .name = "ac200-codec", ++ .of_compatible = "x-powers,ac200-codec", ++ }, { ++ .name = "ac200-efuse", ++ .of_compatible = "x-powers,ac200-efuse", ++ }, { ++ .name = "ac200-ephy", ++ .of_compatible = "x-powers,ac200-ephy", ++ }, { ++ .name = "ac200-rtc", ++ .of_compatible = "x-powers,ac200-rtc", ++ }, { ++ .name = "ac200-tve", ++ .of_compatible = "x-powers,ac200-tve", ++ }, ++}; ++ ++static int ac200_i2c_probe(struct i2c_client *i2c, ++ const struct i2c_device_id *id) ++{ ++ struct device *dev = &i2c->dev; ++ struct ac200_dev *ac200; ++ int ret; ++ ++ ac200 = devm_kzalloc(dev, sizeof(*ac200), GFP_KERNEL); ++ if (!ac200) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(i2c, ac200); ++ ++ ac200->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(ac200->clk)) { ++ ret = PTR_ERR(ac200->clk); ++ dev_err(dev, "Can't obtain the clock: %d\n", ret); ++ return ret; ++ } ++ ++ ac200->regmap = devm_regmap_init_i2c(i2c, &ac200_regmap_config); ++ if (IS_ERR(ac200->regmap)) { ++ ret = PTR_ERR(ac200->regmap); ++ dev_err(dev, "Regmap init failed: %d\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(ac200->clk); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); ++ if (ret) ++ goto err; ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 1); ++ if (ret) ++ goto err; ++ ++ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, ac200_cells, ++ ARRAY_SIZE(ac200_cells), NULL, 0, NULL); ++ if (ret) { ++ dev_err(dev, "Failed to add MFD devices: %d\n", ret); ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ clk_disable_unprepare(ac200->clk); ++ return ret; ++} ++ ++void ac200_i2c_remove(struct i2c_client *i2c) ++{ ++ struct ac200_dev *ac200 = i2c_get_clientdata(i2c); ++ ++ regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); ++ ++ clk_disable_unprepare(ac200->clk); ++} ++ ++static const struct i2c_device_id ac200_ids[] = { ++ { "ac200", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(i2c, ac200_ids); ++ ++static const struct of_device_id ac200_of_match[] = { ++ { .compatible = "x-powers,ac200" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, ac200_of_match); ++ ++static struct i2c_driver ac200_i2c_driver = { ++ .driver = { ++ .name = "ac200", ++ .of_match_table = of_match_ptr(ac200_of_match), ++ }, ++ .probe = ac200_i2c_probe, ++ .remove = ac200_i2c_remove, ++ .id_table = ac200_ids, ++}; ++module_i2c_driver(ac200_i2c_driver); ++ ++MODULE_DESCRIPTION("MFD core driver for AC200"); ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/include/linux/mfd/ac200.h +@@ -0,0 +1,209 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * AC200 register list ++ * ++ * Copyright (C) 2019 Jernej Skrabec ++ */ ++ ++#ifndef __LINUX_MFD_AC200_H ++#define __LINUX_MFD_AC200_H ++ ++#include ++#include ++ ++/* interface registers (can be accessed from any page) */ ++#define AC200_TWI_CHANGE_TO_RSB 0x3E ++#define AC200_TWI_PAD_DELAY 0xC4 ++#define AC200_TWI_REG_ADDR_H 0xFE ++ ++/* General registers */ ++#define AC200_SYS_VERSION 0x0000 ++#define AC200_SYS_CONTROL 0x0002 ++#define AC200_SYS_IRQ_ENABLE 0x0004 ++#define AC200_SYS_IRQ_STATUS 0x0006 ++#define AC200_SYS_CLK_CTL 0x0008 ++#define AC200_SYS_DLDO_OSC_CTL 0x000A ++#define AC200_SYS_PLL_CTL0 0x000C ++#define AC200_SYS_PLL_CTL1 0x000E ++#define AC200_SYS_AUDIO_CTL0 0x0010 ++#define AC200_SYS_AUDIO_CTL1 0x0012 ++#define AC200_SYS_EPHY_CTL0 0x0014 ++#define AC200_SYS_EPHY_CTL1 0x0016 ++#define AC200_SYS_TVE_CTL0 0x0018 ++#define AC200_SYS_TVE_CTL1 0x001A ++ ++/* Audio Codec registers */ ++#define AC200_AC_SYS_CLK_CTL 0x2000 ++#define AC200_SYS_MOD_RST 0x2002 ++#define AC200_SYS_SAMP_CTL 0x2004 ++#define AC200_I2S_CTL 0x2100 ++#define AC200_I2S_CLK 0x2102 ++#define AC200_I2S_FMT0 0x2104 ++#define AC200_I2S_FMT1 0x2108 ++#define AC200_I2S_MIX_SRC 0x2114 ++#define AC200_I2S_MIX_GAIN 0x2116 ++#define AC200_I2S_DACDAT_DVC 0x2118 ++#define AC200_I2S_ADCDAT_DVC 0x211A ++#define AC200_AC_DAC_DPC 0x2200 ++#define AC200_AC_DAC_MIX_SRC 0x2202 ++#define AC200_AC_DAC_MIX_GAIN 0x2204 ++#define AC200_DACA_OMIXER_CTRL 0x2220 ++#define AC200_OMIXER_SR 0x2222 ++#define AC200_LINEOUT_CTRL 0x2224 ++#define AC200_AC_ADC_DPC 0x2300 ++#define AC200_MBIAS_CTRL 0x2310 ++#define AC200_ADC_MIC_CTRL 0x2320 ++#define AC200_ADCMIXER_SR 0x2322 ++#define AC200_ANALOG_TUNING0 0x232A ++#define AC200_ANALOG_TUNING1 0x232C ++#define AC200_AC_AGC_SEL 0x2480 ++#define AC200_ADC_DAPLCTRL 0x2500 ++#define AC200_ADC_DAPRCTRL 0x2502 ++#define AC200_ADC_DAPLSTA 0x2504 ++#define AC200_ADC_DAPRSTA 0x2506 ++#define AC200_ADC_DAPLTL 0x2508 ++#define AC200_ADC_DAPRTL 0x250A ++#define AC200_ADC_DAPLHAC 0x250C ++#define AC200_ADC_DAPLLAC 0x250E ++#define AC200_ADC_DAPRHAC 0x2510 ++#define AC200_ADC_DAPRLAC 0x2512 ++#define AC200_ADC_DAPLDT 0x2514 ++#define AC200_ADC_DAPLAT 0x2516 ++#define AC200_ADC_DAPRDT 0x2518 ++#define AC200_ADC_DAPRAT 0x251A ++#define AC200_ADC_DAPNTH 0x251C ++#define AC200_ADC_DAPLHNAC 0x251E ++#define AC200_ADC_DAPLLNAC 0x2520 ++#define AC200_ADC_DAPRHNAC 0x2522 ++#define AC200_ADC_DAPRLNAC 0x2524 ++#define AC200_AC_DAPHHPFC 0x2526 ++#define AC200_AC_DAPLHPFC 0x2528 ++#define AC200_AC_DAPOPT 0x252A ++#define AC200_AC_DAC_DAPCTRL 0x3000 ++#define AC200_AC_DRC_HHPFC 0x3002 ++#define AC200_AC_DRC_LHPFC 0x3004 ++#define AC200_AC_DRC_CTRL 0x3006 ++#define AC200_AC_DRC_LPFHAT 0x3008 ++#define AC200_AC_DRC_LPFLAT 0x300A ++#define AC200_AC_DRC_RPFHAT 0x300C ++#define AC200_AC_DRC_RPFLAT 0x300E ++#define AC200_AC_DRC_LPFHRT 0x3010 ++#define AC200_AC_DRC_LPFLRT 0x3012 ++#define AC200_AC_DRC_RPFHRT 0x3014 ++#define AC200_AC_DRC_RPFLRT 0x3016 ++#define AC200_AC_DRC_LRMSHAT 0x3018 ++#define AC200_AC_DRC_LRMSLAT 0x301A ++#define AC200_AC_DRC_RRMSHAT 0x301C ++#define AC200_AC_DRC_RRMSLAT 0x301E ++#define AC200_AC_DRC_HCT 0x3020 ++#define AC200_AC_DRC_LCT 0x3022 ++#define AC200_AC_DRC_HKC 0x3024 ++#define AC200_AC_DRC_LKC 0x3026 ++#define AC200_AC_DRC_HOPC 0x3028 ++#define AC200_AC_DRC_LOPC 0x302A ++#define AC200_AC_DRC_HLT 0x302C ++#define AC200_AC_DRC_LLT 0x302E ++#define AC200_AC_DRC_HKI 0x3030 ++#define AC200_AC_DRC_LKI 0x3032 ++#define AC200_AC_DRC_HOPL 0x3034 ++#define AC200_AC_DRC_LOPL 0x3036 ++#define AC200_AC_DRC_HET 0x3038 ++#define AC200_AC_DRC_LET 0x303A ++#define AC200_AC_DRC_HKE 0x303C ++#define AC200_AC_DRC_LKE 0x303E ++#define AC200_AC_DRC_HOPE 0x3040 ++#define AC200_AC_DRC_LOPE 0x3042 ++#define AC200_AC_DRC_HKN 0x3044 ++#define AC200_AC_DRC_LKN 0x3046 ++#define AC200_AC_DRC_SFHAT 0x3048 ++#define AC200_AC_DRC_SFLAT 0x304A ++#define AC200_AC_DRC_SFHRT 0x304C ++#define AC200_AC_DRC_SFLRT 0x304E ++#define AC200_AC_DRC_MXGHS 0x3050 ++#define AC200_AC_DRC_MXGLS 0x3052 ++#define AC200_AC_DRC_MNGHS 0x3054 ++#define AC200_AC_DRC_MNGLS 0x3056 ++#define AC200_AC_DRC_EPSHC 0x3058 ++#define AC200_AC_DRC_EPSLC 0x305A ++#define AC200_AC_DRC_HPFHGAIN 0x305E ++#define AC200_AC_DRC_HPFLGAIN 0x3060 ++#define AC200_AC_DRC_BISTCR 0x3100 ++#define AC200_AC_DRC_BISTST 0x3102 ++ ++/* TVE registers */ ++#define AC200_TVE_CTL0 0x4000 ++#define AC200_TVE_CTL1 0x4002 ++#define AC200_TVE_MOD0 0x4004 ++#define AC200_TVE_MOD1 0x4006 ++#define AC200_TVE_DAC_CFG0 0x4008 ++#define AC200_TVE_DAC_CFG1 0x400A ++#define AC200_TVE_YC_DELAY 0x400C ++#define AC200_TVE_YC_FILTER 0x400E ++#define AC200_TVE_BURST_FRQ0 0x4010 ++#define AC200_TVE_BURST_FRQ1 0x4012 ++#define AC200_TVE_FRONT_PORCH 0x4014 ++#define AC200_TVE_BACK_PORCH 0x4016 ++#define AC200_TVE_TOTAL_LINE 0x401C ++#define AC200_TVE_FIRST_ACTIVE 0x401E ++#define AC200_TVE_BLACK_LEVEL 0x4020 ++#define AC200_TVE_BLANK_LEVEL 0x4022 ++#define AC200_TVE_PLUG_EN 0x4030 ++#define AC200_TVE_PLUG_IRQ_EN 0x4032 ++#define AC200_TVE_PLUG_IRQ_STA 0x4034 ++#define AC200_TVE_PLUG_STA 0x4038 ++#define AC200_TVE_PLUG_DEBOUNCE 0x4040 ++#define AC200_TVE_DAC_TEST 0x4042 ++#define AC200_TVE_PLUG_PULSE_LEVEL 0x40F4 ++#define AC200_TVE_PLUG_PULSE_START 0x40F8 ++#define AC200_TVE_PLUG_PULSE_PERIOD 0x40FA ++#define AC200_TVE_IF_CTL 0x5000 ++#define AC200_TVE_IF_TIM0 0x5008 ++#define AC200_TVE_IF_TIM1 0x500A ++#define AC200_TVE_IF_TIM2 0x500C ++#define AC200_TVE_IF_TIM3 0x500E ++#define AC200_TVE_IF_SYNC0 0x5010 ++#define AC200_TVE_IF_SYNC1 0x5012 ++#define AC200_TVE_IF_SYNC2 0x5014 ++#define AC200_TVE_IF_TIM4 0x5016 ++#define AC200_TVE_IF_STATUS 0x5018 ++ ++/* EPHY registers */ ++#define AC200_EPHY_CTL 0x6000 ++#define AC200_EPHY_BIST 0x6002 ++ ++/* eFuse registers (0x8000 - 0x9FFF, layout unknown) */ ++ ++/* RTC registers */ ++#define AC200_LOSC_CTRL0 0xA000 ++#define AC200_LOSC_CTRL1 0xA002 ++#define AC200_LOSC_AUTO_SWT_STA 0xA004 ++#define AC200_INTOSC_CLK_PRESCAL 0xA008 ++#define AC200_RTC_YY_MM_DD0 0xA010 ++#define AC200_RTC_YY_MM_DD1 0xA012 ++#define AC200_RTC_HH_MM_SS0 0xA014 ++#define AC200_RTC_HH_MM_SS1 0xA016 ++#define AC200_ALARM0_CUR_VLU0 0xA024 ++#define AC200_ALARM0_CUR_VLU1 0xA026 ++#define AC200_ALARM0_ENABLE 0xA028 ++#define AC200_ALARM0_IRQ_EN 0xA02C ++#define AC200_ALARM0_IRQ_STA 0xA030 ++#define AC200_ALARM1_WK_HH_MM_SS0 0xA040 ++#define AC200_ALARM1_WK_HH_MM_SS1 0xA042 ++#define AC200_ALARM1_ENABLE 0xA044 ++#define AC200_ALARM1_IRQ_EN 0xA048 ++#define AC200_ALARM1_IRQ_STA 0xA04C ++#define AC200_ALARM_CONFIG 0xA050 ++#define AC200_LOSC_OUT_GATING 0xA060 ++#define AC200_GP_DATA(x) (0xA100 + (x) * 2) ++#define AC200_RTC_DEB 0xA170 ++#define AC200_GPL_HOLD_OUTPUT 0xA180 ++#define AC200_VDD_RTC 0xA190 ++#define AC200_IC_CHARA0 0xA1F0 ++#define AC200_IC_CHARA1 0xA1F2 ++ ++struct ac200_dev { ++ struct clk *clk; ++ struct regmap *regmap; ++}; ++ ++#endif /* __LINUX_MFD_AC200_H */ diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-X-Powers-AC200-EPHY-syscon.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-X-Powers-AC200-EPHY-syscon.patch new file mode 100644 index 0000000..9708dfc --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-X-Powers-AC200-EPHY-syscon.patch @@ -0,0 +1,374 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 13 Jun 2022 17:37:19 +0100 +Subject: mfd: Add support for X-Powers AC200 EPHY syscon + +The X-Powers AC200 mixed signal chip contains a 100Mbit/s Ethernet PHY. +While the PHY is using the standard MDIO and MII/RMII interfaces to +the MAC, there are some registers in the AC200 that need to be setup to +make the PHY functional: +- The MDIO PHY address needs to set. +- The LED polarity needs to be configured. +- The MII interface mode needs to be set (MII or RMII). +- There is a reset line that controls the PHY operation. +- There is a clock gate that blocks or forwards the AC200's internal clock + to the PHY. + +This driver here takes care of those setup needs, but does not cover the +actual PHY operation. Once the PHY is set up and enabled, it behaves like +a standard MDIO/MII controlled PHY, and can be driven by the IEEE802.3-C22 +driver. + +To some degree those parameters mimic the typical wired setup of a +physical PHY chip: the LED polarity, MII interface mode and PHY address +are typically configued via connecting certain pins. We use the +devicetree to learn those parameters, which depend on the board setup. + +This driver is a child of the AC200 MFD parent device, and uses its +regmap and input clock. It also provides a reset and clock controller, +which the actual PHY device (node) needs to refer to. This ensures that +this PHY control device is initialised before the PHY is expected to work. + +Signed-off-by: Andre Przywara +--- + drivers/phy/allwinner/Kconfig | 9 + + drivers/phy/allwinner/Makefile | 1 + + drivers/phy/allwinner/ac200-ephy-ctl.c | 301 ++++++++++ + 3 files changed, 311 insertions(+) + +diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig +index e93a53139460..d3614169de5c 100644 +--- a/drivers/phy/allwinner/Kconfig ++++ b/drivers/phy/allwinner/Kconfig +@@ -58,3 +58,12 @@ config PHY_SUN50I_USB3 + part of Allwinner H6 SoC. + + This driver controls each individual USB 2+3 host PHY combo. ++ ++config AC200_PHY_CTL ++ tristate "X-Power AC200 PHY control driver" ++ depends on MFD_AC200 ++ depends on RESET_CONTROLLER ++ help ++ Enable this to support the Ethernet PHY operation of the AC200 ++ mixed signal chip. This driver just enables and configures the ++ PHY, the PHY itself is supported by a standard driver. +diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile +index bd74901a1255..0eecec7a908a 100644 +--- a/drivers/phy/allwinner/Makefile ++++ b/drivers/phy/allwinner/Makefile +@@ -3,3 +3,4 @@ obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o + obj-$(CONFIG_PHY_SUN6I_MIPI_DPHY) += phy-sun6i-mipi-dphy.o + obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o + obj-$(CONFIG_PHY_SUN50I_USB3) += phy-sun50i-usb3.o ++obj-$(CONFIG_AC200_PHY_CTL) += ac200-ephy-ctl.o +diff --git a/drivers/phy/allwinner/ac200-ephy-ctl.c b/drivers/phy/allwinner/ac200-ephy-ctl.c +new file mode 100644 +index 000000000000..8efeaf18e42c +--- /dev/null ++++ b/drivers/phy/allwinner/ac200-ephy-ctl.c +@@ -0,0 +1,301 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/** ++ * syscon driver to control and configure AC200 Ethernet PHY ++ * Copyright (c) 2022 Arm Ltd. ++ * ++ * TODO's and questions: ++ * ========================= ++ * - This driver is something like a syscon driver, as it controls various ++ * bits and registers that effect other devices (the actual PHY). It's ++ * unclear where it should live, though: ++ * - it could be integrated into the MFD driver, but this looks messy ++ * - it could live at the current location (drivers/phy/allwinner), but that ++ * sounds wrong ++ * - it could be a separate file, but in drivers/mfd ++ * - anything else ++ * ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* macros for system ephy control 0 register */ ++#define AC200_SYS_EPHY_CTL0 0x0014 ++#define AC200_EPHY_RESET_INVALID BIT(0) ++#define AC200_EPHY_SYSCLK_GATING 1 ++ ++/* macros for system ephy control 1 register */ ++#define AC200_SYS_EPHY_CTL1 0x0016 ++#define AC200_EPHY_E_EPHY_MII_IO_EN BIT(0) ++#define AC200_EPHY_E_LNK_LED_IO_EN BIT(1) ++#define AC200_EPHY_E_SPD_LED_IO_EN BIT(2) ++#define AC200_EPHY_E_DPX_LED_IO_EN BIT(3) ++ ++/* macros for ephy control register */ ++#define AC200_EPHY_CTL 0x6000 ++#define AC200_EPHY_SHUTDOWN BIT(0) ++#define AC200_EPHY_LED_POL BIT(1) ++#define AC200_EPHY_CLK_SEL BIT(2) ++#define AC200_EPHY_ADDR(x) (((x) & 0x1F) << 4) ++#define AC200_EPHY_XMII_SEL BIT(11) ++#define AC200_EPHY_CALIB(x) (((x) & 0xF) << 12) ++ ++struct ac200_ephy_ctl_dev { ++ struct reset_controller_dev rcdev; ++ struct clk_hw *gate_clk; ++ struct regmap *regmap; ++}; ++ ++static struct ac200_ephy_ctl_dev *to_phy_dev(struct reset_controller_dev *rcdev) ++{ ++ return container_of(rcdev, struct ac200_ephy_ctl_dev, rcdev); ++} ++ ++static int ephy_ctl_reset(struct reset_controller_dev *rcdev, unsigned long id) ++{ ++ struct ac200_ephy_ctl_dev *ac200 = to_phy_dev(rcdev); ++ int ret; ++ ++ ret = regmap_clear_bits(ac200->regmap, AC200_SYS_EPHY_CTL0, ++ AC200_EPHY_RESET_INVALID); ++ if (ret) ++ return ret; ++ ++ /* This is going via I2C, so there is plenty of built-in delay. */ ++ return regmap_set_bits(ac200->regmap, AC200_SYS_EPHY_CTL0, ++ AC200_EPHY_RESET_INVALID); ++} ++ ++static int ephy_ctl_assert(struct reset_controller_dev *rcdev, unsigned long id) ++{ ++ struct ac200_ephy_ctl_dev *ac200 = to_phy_dev(rcdev); ++ ++ return regmap_clear_bits(ac200->regmap, AC200_SYS_EPHY_CTL0, ++ AC200_EPHY_RESET_INVALID); ++} ++ ++static int ephy_ctl_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct ac200_ephy_ctl_dev *ac200 = to_phy_dev(rcdev); ++ ++ return regmap_set_bits(ac200->regmap, AC200_SYS_EPHY_CTL0, ++ AC200_EPHY_RESET_INVALID); ++} ++ ++static int ephy_ctl_status(struct reset_controller_dev *rcdev, unsigned long id) ++{ ++ struct ac200_ephy_ctl_dev *ac200 = to_phy_dev(rcdev); ++ ++ return regmap_test_bits(ac200->regmap, AC200_SYS_EPHY_CTL0, ++ AC200_EPHY_RESET_INVALID); ++} ++ ++static int ephy_ctl_reset_of_xlate(struct reset_controller_dev *rcdev, ++ const struct of_phandle_args *reset_spec) ++{ ++ if (WARN_ON(reset_spec->args_count != 0)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++const struct reset_control_ops ephy_ctl_reset_ops = { ++ .assert = ephy_ctl_assert, ++ .deassert = ephy_ctl_deassert, ++ .reset = ephy_ctl_reset, ++ .status = ephy_ctl_status, ++}; ++ ++static void ac200_ephy_ctl_disable(struct ac200_ephy_ctl_dev *priv) ++{ ++ regmap_write(priv->regmap, AC200_EPHY_CTL, AC200_EPHY_SHUTDOWN); ++ regmap_write(priv->regmap, AC200_SYS_EPHY_CTL1, 0); ++ regmap_write(priv->regmap, AC200_SYS_EPHY_CTL0, 0); ++} ++ ++static int ac200_ephy_ctl_probe(struct platform_device *pdev) ++{ ++ struct reset_controller_dev *rcdev; ++ struct device *dev = &pdev->dev; ++ struct ac200_ephy_ctl_dev *priv; ++ struct nvmem_cell *calcell; ++ const char *parent_name; ++ phy_interface_t phy_if; ++ u16 *caldata, ephy_ctl; ++ struct clk *clk; ++ size_t callen; ++ u32 value; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, priv); ++ ++ priv->regmap = dev_get_regmap(dev->parent, NULL); ++ if (!priv->regmap) ++ return -EPROBE_DEFER; ++ ++ calcell = devm_nvmem_cell_get(dev, "calibration"); ++ if (IS_ERR(calcell)) ++ return dev_err_probe(dev, PTR_ERR(calcell), ++ "Unable to find calibration data!\n"); ++ ++ caldata = nvmem_cell_read(calcell, &callen); ++ if (IS_ERR(caldata)) { ++ dev_err(dev, "Unable to read calibration data!\n"); ++ return PTR_ERR(caldata); ++ } ++ ++ if (callen != 2) { ++ dev_err(dev, "Calibration data length must be 2 bytes!\n"); ++ kfree(caldata); ++ return -EINVAL; ++ } ++ ++ ephy_ctl = AC200_EPHY_CALIB(*caldata + 3); ++ kfree(caldata); ++ ++ ret = of_get_phy_mode(dev->of_node, &phy_if); ++ if (ret) { ++ dev_err(dev, "Unable to read PHY connection mode\n"); ++ return ret; ++ } ++ ++ switch (phy_if) { ++ case PHY_INTERFACE_MODE_MII: ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ ephy_ctl |= AC200_EPHY_XMII_SEL; ++ break; ++ default: ++ dev_err(dev, "Illegal PHY connection mode (%d), only RMII or MII supported\n", ++ phy_if); ++ return -EINVAL; ++ } ++ ++ ret = of_property_read_u32(dev->of_node, "x-powers,led-polarity", ++ &value); ++ if (ret) { ++ dev_err(dev, "Unable to read LED polarity setting\n"); ++ return ret; ++ } ++ ++ if (value == GPIO_ACTIVE_LOW) ++ ephy_ctl |= AC200_EPHY_LED_POL; ++ ++ ret = of_property_read_u32(dev->of_node, "phy-address", &value); ++ if (ret) { ++ dev_err(dev, "Unable to read PHY address value\n"); ++ return ret; ++ } ++ ++ ephy_ctl |= AC200_EPHY_ADDR(value); ++ ++ clk = clk_get(dev->parent, NULL); ++ if (IS_ERR(clk)) ++ return dev_err_probe(dev, PTR_ERR(clk), ++ "Unable to obtain the clock\n"); ++ ++ if (clk_get_rate(clk) == 24000000) ++ ephy_ctl |= AC200_EPHY_CLK_SEL; ++ ++ clk_put(clk); ++ ++ /* Assert reset and gate clock, to disable PHY for now */ ++ ret = regmap_write(priv->regmap, AC200_SYS_EPHY_CTL0, 0); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(priv->regmap, AC200_SYS_EPHY_CTL1, ++ AC200_EPHY_E_EPHY_MII_IO_EN | ++ AC200_EPHY_E_LNK_LED_IO_EN | ++ AC200_EPHY_E_SPD_LED_IO_EN | ++ AC200_EPHY_E_DPX_LED_IO_EN); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(priv->regmap, AC200_EPHY_CTL, ephy_ctl); ++ if (ret) ++ return ret; ++ ++ rcdev = &priv->rcdev; ++ rcdev->owner = dev->driver->owner; ++ rcdev->nr_resets = 1; ++ rcdev->ops = &ephy_ctl_reset_ops; ++ rcdev->of_node = dev->of_node; ++ rcdev->of_reset_n_cells = 0; ++ rcdev->of_xlate = ephy_ctl_reset_of_xlate; ++ ++ ret = devm_reset_controller_register(dev, rcdev); ++ if (ret) { ++ dev_err(dev, "Unable to register reset controller: %d\n", ret); ++ goto err_disable_ephy; ++ } ++ ++ parent_name = of_clk_get_parent_name(dev->parent->of_node, 0); ++ priv->gate_clk = devm_clk_hw_register_regmap_gate(dev, ++ "ac200-ephy-ctl-gate", parent_name, 0, ++ priv->regmap, AC200_SYS_EPHY_CTL0, ++ AC200_EPHY_SYSCLK_GATING, 0); ++ if (IS_ERR(priv->gate_clk)) { ++ ret = PTR_ERR(priv->gate_clk); ++ dev_err(dev, "Unable to register gate clock: %d\n", ret); ++ goto err_disable_ephy; ++ } ++ ++ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, ++ priv->gate_clk); ++ if (ret) { ++ dev_err(dev, "Unable to register clock provider: %d\n", ret); ++ goto err_disable_ephy; ++ } ++ ++ return 0; ++ ++err_disable_ephy: ++ ac200_ephy_ctl_disable(priv); ++ ++ return ret; ++} ++ ++static int ac200_ephy_ctl_remove(struct platform_device *pdev) ++{ ++ struct ac200_ephy_ctl_dev *priv = platform_get_drvdata(pdev); ++ ++ ac200_ephy_ctl_disable(priv); ++ ++ return 0; ++} ++ ++static const struct of_device_id ac200_ephy_ctl_match[] = { ++ { .compatible = "x-powers,ac200-ephy-ctl" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, ac200_ephy_ctl_match); ++ ++static struct platform_driver ac200_ephy_ctl_driver = { ++ .probe = ac200_ephy_ctl_probe, ++ .remove = ac200_ephy_ctl_remove, ++ .driver = { ++ .name = "ac200-ephy-ctl", ++ .of_match_table = ac200_ephy_ctl_match, ++ }, ++}; ++module_platform_driver(ac200_ephy_ctl_driver); ++ ++MODULE_AUTHOR("Andre Przywara "); ++MODULE_DESCRIPTION("AC200 Ethernet PHY control driver"); ++MODULE_LICENSE("GPL"); +-- +Armbian + diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-X-Powers-AC200.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-X-Powers-AC200.patch new file mode 100644 index 0000000..5c3c526 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mfd-Add-support-for-X-Powers-AC200.patch @@ -0,0 +1,265 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:38:21 +0200 +Subject: mfd: Add support for X-Powers AC200 + +The X-Powers AC200 is a mixed signal multi-purpose chip, which provides +audio DAC/ADCs, a CVBS video encoder, a 100Mbit/s Ethernet PHY and a +real-time clock. Its control registers can be accessed via I2C or +Allwinner's RSB bus. +Beside this chip being used on some older boards (for instance the Remix +Mini PC), it is quite wide spread due to its die being co-packaged on the +Allwinner H6 and H616 SoCs, which use its audio, video and PHY +functionality. + +Aside from the RTC, the other functions do not need constant +hand-holding via the I2C registers, but rather need to be configured and +enabled only once. + +We model the control side of this chip using the MFD subsystem. This +driver here just provides the parent device for the various subfunctions, +and takes care of enabling clocks and reset, but also provides the regmap, +which the respective child drivers will use. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Andre Przywara +--- + drivers/mfd/Kconfig | 12 + + drivers/mfd/Makefile | 1 + + drivers/mfd/ac200.c | 190 ++++++++++ + 3 files changed, 203 insertions(+) + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index f6b519eaaa71..39fef6420fe5 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -191,6 +191,18 @@ config MFD_AC100 + This driver include only the core APIs. You have to select individual + components like codecs or RTC under the corresponding menus. + ++config MFD_AC200 ++ tristate "X-Powers AC200" ++ select MFD_CORE ++ select REGMAP_I2C ++ depends on COMMON_CLK ++ depends on I2C ++ depends on OF ++ help ++ If you say Y here you get support for the X-Powers AC200 IC. ++ This driver include only the core APIs. You have to select individual ++ components like Ethernet PHY or codec under the corresponding menus. ++ + config MFD_AXP20X + tristate + select MFD_CORE +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index f3d1f1dc73b5..e2ba77bd1d51 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -137,6 +137,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o + obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o + + obj-$(CONFIG_MFD_AC100) += ac100.o ++obj-$(CONFIG_MFD_AC200) += ac200.o + obj-$(CONFIG_MFD_AXP20X) += axp20x.o + obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o + obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o +diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c +new file mode 100644 +index 000000000000..ad28c380c880 +--- /dev/null ++++ b/drivers/mfd/ac200.c +@@ -0,0 +1,190 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * MFD core driver for X-Powers' AC200 IC ++ * ++ * The AC200 is a chip which is co-packaged with Allwinner H6 SoC and ++ * includes analog audio codec, analog TV encoder, ethernet PHY, eFuse ++ * and RTC. ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ * ++ * Based on AC100 driver with following copyrights: ++ * Copyright (2016) Chen-Yu Tsai ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct ac200_dev { ++ struct clk *clk; ++ struct regmap *regmap; ++}; ++ ++#define AC200_SYS_CONTROL 0x0002 ++#define AC200_SYS_BG_CTL 0x0050 ++ ++/* interface register (can be accessed from any page) */ ++#define AC200_TWI_REG_ADDR_H 0xFE ++ ++#define AC200_MAX_REG 0xA1F2 ++ ++static const struct regmap_range_cfg ac200_range_cfg[] = { ++ { ++ .range_max = AC200_MAX_REG, ++ .selector_reg = AC200_TWI_REG_ADDR_H, ++ .selector_mask = 0xff, ++ .selector_shift = 0, ++ .window_start = 0, ++ .window_len = 256, ++ } ++}; ++ ++static const struct regmap_config ac200_regmap_config = { ++ .name = "AC200", ++ .reg_bits = 8, ++ .reg_stride = 2, ++ .val_bits = 16, ++ .ranges = ac200_range_cfg, ++ .num_ranges = ARRAY_SIZE(ac200_range_cfg), ++ .max_register = AC200_MAX_REG, ++}; ++ ++static struct mfd_cell ac200_cells[] = { ++ { ++ .name = "ac200-codec", ++ .of_compatible = "x-powers,ac200-codec", ++ }, { ++ .name = "ac200-ephy-ctl", ++ .of_compatible = "x-powers,ac200-ephy-ctl", ++ }, ++}; ++ ++static int ac200_i2c_probe(struct i2c_client *i2c) ++{ ++ struct device *dev = &i2c->dev; ++ struct nvmem_cell *bgcell; ++ struct ac200_dev *ac200; ++ u16 *bgdata, bgval; ++ size_t bglen; ++ int ret; ++ ++ ac200 = devm_kzalloc(dev, sizeof(*ac200), GFP_KERNEL); ++ if (!ac200) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(i2c, ac200); ++ ++ ac200->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(ac200->clk)) ++ return dev_err_probe(dev, PTR_ERR(ac200->clk), ++ "Can't obtain the clock\n"); ++ ++ ac200->regmap = devm_regmap_init_i2c(i2c, &ac200_regmap_config); ++ if (IS_ERR(ac200->regmap)) { ++ ret = PTR_ERR(ac200->regmap); ++ dev_err(dev, "Regmap init failed: %d\n", ret); ++ return ret; ++ } ++ ++ bgcell = devm_nvmem_cell_get(dev, "bandgap"); ++ if (IS_ERR(bgcell)) ++ return dev_err_probe(dev, PTR_ERR(bgcell), ++ "Unable to find bandgap data!\n"); ++ ++ bgdata = nvmem_cell_read(bgcell, &bglen); ++ if (IS_ERR(bgdata)) { ++ dev_err(dev, "Unable to read bandgap data!\n"); ++ return PTR_ERR(bgdata); ++ } ++ ++ if (bglen != 2) { ++ dev_err(dev, "Invalid nvmem bandgap length!\n"); ++ kfree(bgdata); ++ return -EINVAL; ++ } ++ ++ bgval = *bgdata; ++ kfree(bgdata); ++ ++ ret = clk_prepare_enable(ac200->clk); ++ if (ret) ++ return ret; ++ ++ /* ++ * There is no documentation on how long we have to wait before ++ * executing first operation. Vendor driver sleeps for 40 ms. ++ */ ++ msleep(40); ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); ++ if (ret) ++ goto err; ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_CONTROL, 1); ++ if (ret) ++ goto err; ++ ++ if (bgval) { ++ /* bandgap register is not documented */ ++ ret = regmap_write(ac200->regmap, AC200_SYS_BG_CTL, ++ 0x8280 | bgval); ++ if (ret) ++ goto err; ++ } ++ ++ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, ac200_cells, ++ ARRAY_SIZE(ac200_cells), NULL, 0, NULL); ++ if (ret) { ++ dev_err(dev, "Failed to add MFD devices: %d\n", ret); ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ clk_disable_unprepare(ac200->clk); ++ return ret; ++} ++ ++static void ac200_i2c_remove(struct i2c_client *i2c) ++{ ++ struct ac200_dev *ac200 = i2c_get_clientdata(i2c); ++ ++ regmap_write(ac200->regmap, AC200_SYS_CONTROL, 0); ++ ++ clk_disable_unprepare(ac200->clk); ++} ++ ++static const struct i2c_device_id ac200_ids[] = { ++ { "ac200", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ac200_ids); ++ ++static const struct of_device_id ac200_of_match[] = { ++ { .compatible = "x-powers,ac200" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ac200_of_match); ++ ++static struct i2c_driver ac200_i2c_driver = { ++ .driver = { ++ .name = "ac200", ++ .of_match_table = of_match_ptr(ac200_of_match), ++ }, ++ .probe = ac200_i2c_probe, ++ .remove = ac200_i2c_remove, ++ .id_table = ac200_ids, ++}; ++module_i2c_driver(ac200_i2c_driver); ++ ++MODULE_DESCRIPTION("MFD core driver for AC200"); ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_LICENSE("GPL v2"); +-- +Armbian + diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch new file mode 100644 index 0000000..bf3b0c5 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?= + +Date: Sun, 25 Aug 2019 17:05:58 +0200 +Subject: [PATCH] mmc: sunxi: fix unusuable eMMC on some H6 boards by disabling + DDR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some Allwinner H6 boards have timing problems when dealing with +DDR-capable eMMC cards. These boards include the Pine H64 and Tanix TX6. + +These timing problems result in out of sync communication between the +driver and the eMMC, which renders the memory unsuable for every +operation but some basic commmands, like reading the status register. + +The cause of these timing problems is not yet well known, but they go +away by disabling DDR mode operation in the driver. Like on some H5 +boards, it might be that the traces are not precise enough to support +these speeds. However, Jernej Skrabec compared the BSP driver with this +driver, and found that the BSP driver configures pinctrl to operate at +1.8 V when entering DDR mode (although 3.3 V operation is supported), while +the mainline kernel lacks any mechanism to switch voltages dynamically. +Finally, other possible cause might be some timing parameter that is +different on the H6 with respect to other SoCs. + +Therefore, as this fix works reliably, the kernel lacks the required +dynamic pinctrl control for now and a slow eMMC is better than a not +working eMMC, just disable DDR operation for now on H6-compatible +devices. + +Signed-off-by: Alejandro González +--- + drivers/mmc/host/sunxi-mmc.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/mmc/host/sunxi-mmc.c ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -1421,14 +1421,17 @@ static int sunxi_mmc_probe(struct platfo + + /* + * Some H5 devices do not have signal traces precise enough to +- * use HS DDR mode for their eMMC chips. ++ * use HS DDR mode for their eMMC chips. Other H6 devices operate ++ * unreliably on HS DDR mode, too. + * + * We still enable HS DDR modes for all the other controller +- * variants that support them. ++ * variants that support them properly. + */ + if ((host->cfg->clk_delays || host->use_new_timings) && + !of_device_is_compatible(pdev->dev.of_node, +- "allwinner,sun50i-h5-emmc")) ++ "allwinner,sun50i-h5-emmc") && ++ !of_device_is_compatible(pdev->dev.of_node, ++ "allwinner,sun50i-h6-emmc")) + mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR; + + ret = mmc_of_parse(mmc); diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/net-phy-Add-support-for-AC200-EPHY.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/net-phy-Add-support-for-AC200-EPHY.patch new file mode 100644 index 0000000..c5814cd --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/net-phy-Add-support-for-AC200-EPHY.patch @@ -0,0 +1,276 @@ +From cbf68fb141747879e2e6c43584c1e1e3b4d77683 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Fri, 16 Aug 2019 16:38:57 +0200 +Subject: [PATCH 39/44] net: phy: Add support for AC200 EPHY + +Signed-off-by: Jernej Skrabec +--- + drivers/net/phy/Kconfig | 7 ++ + drivers/net/phy/Makefile | 1 + + drivers/net/phy/ac200.c | 234 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 242 insertions(+) + create mode 100644 drivers/net/phy/ac200.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -63,6 +63,13 @@ config SFP + + comment "MII PHY device drivers" + ++config AC200_PHY ++ tristate "AC200 EPHY" ++ depends on NVMEM ++ depends on OF ++ help ++ Fast ethernet PHY as found in X-Powers AC200 multi-function device. ++ + config AMD_PHY + tristate "AMD PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -30,6 +30,7 @@ obj-$(CONFIG_SFP) += sfp.o + sfp-obj-$(CONFIG_SFP) += sfp-bus.o + obj-y += $(sfp-obj-y) $(sfp-obj-m) + ++obj-$(CONFIG_AC200_PHY) += ac200.o + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_AMD_PHY) += amd.o + aquantia-objs += aquantia_main.o +--- /dev/null ++++ b/drivers/net/phy/ac200.c +@@ -0,0 +1,234 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/** ++ * Driver for AC200 Ethernet PHY ++ * ++ * Copyright (c) 2019 Jernej Skrabec ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AC200_EPHY_ID 0x00441400 ++#define AC200_EPHY_ID_MASK 0x0ffffff0 ++ ++/* macros for system ephy control 0 register */ ++#define AC200_EPHY_RESET_INVALID BIT(0) ++#define AC200_EPHY_SYSCLK_GATING BIT(1) ++ ++/* macros for system ephy control 1 register */ ++#define AC200_EPHY_E_EPHY_MII_IO_EN BIT(0) ++#define AC200_EPHY_E_LNK_LED_IO_EN BIT(1) ++#define AC200_EPHY_E_SPD_LED_IO_EN BIT(2) ++#define AC200_EPHY_E_DPX_LED_IO_EN BIT(3) ++ ++/* macros for ephy control register */ ++#define AC200_EPHY_SHUTDOWN BIT(0) ++#define AC200_EPHY_LED_POL BIT(1) ++#define AC200_EPHY_CLK_SEL BIT(2) ++#define AC200_EPHY_ADDR(x) (((x) & 0x1F) << 4) ++#define AC200_EPHY_XMII_SEL BIT(11) ++#define AC200_EPHY_CALIB(x) (((x) & 0xF) << 12) ++ ++struct ac200_ephy_dev { ++ struct phy_driver *ephy; ++ struct regmap *regmap; ++}; ++ ++static char *ac200_phy_name = "AC200 EPHY"; ++ ++static void disable_intelligent_ieee(struct phy_device *phydev) ++{ ++ unsigned int value; ++ ++ phy_write(phydev, 0x1f, 0x0100); /* switch to page 1 */ ++ value = phy_read(phydev, 0x17); ++ value &= ~BIT(3); /* disable IEEE */ ++ phy_write(phydev, 0x17, value); ++ phy_write(phydev, 0x1f, 0x0000); /* switch to page 0 */ ++} ++ ++static void disable_802_3az_ieee(struct phy_device *phydev) ++{ ++ unsigned int value; ++ ++ phy_write(phydev, 0xd, 0x7); ++ phy_write(phydev, 0xe, 0x3c); ++ phy_write(phydev, 0xd, BIT(14) | 0x7); ++ value = phy_read(phydev, 0xe); ++ value &= ~BIT(1); ++ phy_write(phydev, 0xd, 0x7); ++ phy_write(phydev, 0xe, 0x3c); ++ phy_write(phydev, 0xd, BIT(14) | 0x7); ++ phy_write(phydev, 0xe, value); ++ ++ phy_write(phydev, 0x1f, 0x0200); /* switch to page 2 */ ++ phy_write(phydev, 0x18, 0x0000); ++} ++ ++static int ac200_ephy_config_init(struct phy_device *phydev) ++{ ++ const struct ac200_ephy_dev *priv = phydev->drv->driver_data; ++ unsigned int value; ++ int ret; ++ ++ phy_write(phydev, 0x1f, 0x0100); /* Switch to Page 1 */ ++ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ ++ ++ phy_write(phydev, 0x1f, 0x0200); /* Switch to Page 2 */ ++ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0600); /* Switch to Page 6 */ ++ phy_write(phydev, 0x14, 0x708f); /* PHYAFE TX optimization */ ++ phy_write(phydev, 0x13, 0xF000); /* PHYAFE RX optimization */ ++ phy_write(phydev, 0x15, 0x1530); ++ ++ phy_write(phydev, 0x1f, 0x0800); /* Switch to Page 6 */ ++ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ ++ ++ disable_intelligent_ieee(phydev); /* Disable Intelligent IEEE */ ++ disable_802_3az_ieee(phydev); /* Disable 802.3az IEEE */ ++ phy_write(phydev, 0x1f, 0x0000); /* Switch to Page 0 */ ++ ++ value = (phydev->interface == PHY_INTERFACE_MODE_RMII) ? ++ AC200_EPHY_XMII_SEL : 0; ++ ret = regmap_update_bits(priv->regmap, AC200_EPHY_CTL, ++ AC200_EPHY_XMII_SEL, value); ++ if (ret) ++ return ret; ++ ++ /* FIXME: This is probably H6 specific */ ++ value = phy_read(phydev, 0x13); ++ value |= BIT(12); ++ phy_write(phydev, 0x13, value); ++ ++ return 0; ++} ++ ++static const struct mdio_device_id __maybe_unused ac200_ephy_phy_tbl[] = { ++ { AC200_EPHY_ID, AC200_EPHY_ID_MASK }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(mdio, ac200_ephy_phy_tbl); ++ ++static int ac200_ephy_probe(struct platform_device *pdev) ++{ ++ struct ac200_dev *ac200 = dev_get_drvdata(pdev->dev.parent); ++ struct device *dev = &pdev->dev; ++ struct ac200_ephy_dev *priv; ++ struct nvmem_cell *calcell; ++ struct phy_driver *ephy; ++ u16 *caldata, calib; ++ size_t callen; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ ephy = devm_kzalloc(dev, sizeof(*ephy), GFP_KERNEL); ++ if (!ephy) ++ return -ENOMEM; ++ ++ calcell = devm_nvmem_cell_get(dev, "ephy_calib"); ++ if (IS_ERR(calcell)) { ++ dev_err(dev, "Unable to find calibration data!\n"); ++ return PTR_ERR(calcell); ++ } ++ ++ caldata = nvmem_cell_read(calcell, &callen); ++ if (IS_ERR(caldata)) { ++ dev_err(dev, "Unable to read calibration data!\n"); ++ return PTR_ERR(caldata); ++ } ++ ++ if (callen != 2) { ++ dev_err(dev, "Calibration data has wrong length: 2 != %lu\n", ++ callen); ++ kfree(caldata); ++ return -EINVAL; ++ } ++ ++ calib = *caldata + 3; ++ kfree(caldata); ++ ++ ephy->phy_id = AC200_EPHY_ID; ++ ephy->phy_id_mask = AC200_EPHY_ID_MASK; ++ ephy->name = ac200_phy_name; ++ ephy->driver_data = priv; ++ ephy->soft_reset = genphy_soft_reset; ++ ephy->config_init = ac200_ephy_config_init; ++ ephy->suspend = genphy_suspend; ++ ephy->resume = genphy_resume; ++ ++ priv->ephy = ephy; ++ priv->regmap = ac200->regmap; ++ platform_set_drvdata(pdev, priv); ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_EPHY_CTL0, ++ AC200_EPHY_RESET_INVALID | ++ AC200_EPHY_SYSCLK_GATING); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ac200->regmap, AC200_SYS_EPHY_CTL1, ++ AC200_EPHY_E_EPHY_MII_IO_EN | ++ AC200_EPHY_E_LNK_LED_IO_EN | ++ AC200_EPHY_E_SPD_LED_IO_EN | ++ AC200_EPHY_E_DPX_LED_IO_EN); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(ac200->regmap, AC200_EPHY_CTL, ++ AC200_EPHY_LED_POL | ++ AC200_EPHY_CLK_SEL | ++ AC200_EPHY_ADDR(1) | ++ AC200_EPHY_CALIB(calib)); ++ if (ret) ++ return ret; ++ ++ ret = phy_driver_register(priv->ephy, THIS_MODULE); ++ if (ret) { ++ dev_err(dev, "Unable to register phy\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ac200_ephy_remove(struct platform_device *pdev) ++{ ++ struct ac200_ephy_dev *priv = platform_get_drvdata(pdev); ++ ++ phy_driver_unregister(priv->ephy); ++ ++ regmap_write(priv->regmap, AC200_EPHY_CTL, AC200_EPHY_SHUTDOWN); ++ regmap_write(priv->regmap, AC200_SYS_EPHY_CTL1, 0); ++ regmap_write(priv->regmap, AC200_SYS_EPHY_CTL0, 0); ++ ++ return 0; ++} ++ ++static const struct of_device_id ac200_ephy_match[] = { ++ { .compatible = "x-powers,ac200-ephy" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, ac200_ephy_match); ++ ++static struct platform_driver ac200_ephy_driver = { ++ .probe = ac200_ephy_probe, ++ .remove = ac200_ephy_remove, ++ .driver = { ++ .name = "ac200-ephy", ++ .of_match_table = ac200_ephy_match, ++ }, ++}; ++module_platform_driver(ac200_ephy_driver); ++ ++MODULE_AUTHOR("Jernej Skrabec "); ++MODULE_DESCRIPTION("AC200 Ethernet PHY driver"); ++MODULE_LICENSE("GPL"); diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-6_1.scc b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-6_1.scc new file mode 100644 index 0000000..31c96a2 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-6_1.scc @@ -0,0 +1,8 @@ +# K metadata for orangepi lts +# version 6.1 + +patch Input-axp20x-pek-allow-wakeup-after-shutdown-6_1.patch +patch mfd-Add-support-for-AC200.patch +patch net-phy-Add-support-for-AC200-EPHY.patch + +include orange-pi-3lts-common.scc diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-6_5.scc b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-6_5.scc new file mode 100644 index 0000000..ad96b00 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-6_5.scc @@ -0,0 +1,8 @@ +# K metadata for orangepi lts +# version 6.5 + +patch Input-axp20x-pek-allow-wakeup-after-shutdown-6_5.patch +patch mfd-Add-support-for-X-Powers-AC200-EPHY-syscon.patch +patch mfd-Add-support-for-X-Powers-AC200.patch + +include orange-pi-3lts-common.scc diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-common.scc b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-common.scc new file mode 100644 index 0000000..22a5bea --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts-common.scc @@ -0,0 +1,20 @@ +# Kmeta common +# + +patch clk-Implement-protected-clocks-for-all-OF-clock-prov.patch +patch Revert-clk-qcom-Support-protected-clocks-property.patch +patch rtc-sun6i-Allow-RTC-wakeup-after-shutdown.patch +patch firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch +patch arm64-dts-allwinner-h6-Add-SCPI-protocol.patch +patch ASoC-hdmi-codec-fix-channel-allocation.patch +patch arm64-dts-h6-deinterlace.patch +patch HACK-h6-Add-HDMI-sound-card.patch +patch arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch +patch mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch +patch wip-fix-H6-4k-60.patch +patch arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch +patch iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch +patch OrangePi-3-LTS-support.patch +patch arm64-dts-allwinner-Enforce-consistent-MMC-numbering.patch + +kconf harware orange-pi-3lts.cfg diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts.cfg b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts.cfg new file mode 100644 index 0000000..e3bceda --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/orange-pi-3lts.cfg @@ -0,0 +1,5 @@ +CONFIG_NVMEM_SUNXI_SID=y +CONFIG_INIT_STACK_NONE=y +CONFIG_PHY_SUN50I_USB3=y +CONFIG_AC200_PHY=m +CONFIG_MFD_AC200=m diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/rtc-sun6i-Allow-RTC-wakeup-after-shutdown.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/rtc-sun6i-Allow-RTC-wakeup-after-shutdown.patch new file mode 100644 index 0000000..3abf3b5 --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/rtc-sun6i-Allow-RTC-wakeup-after-shutdown.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sat, 2 Jan 2021 15:52:27 -0600 +Subject: [PATCH] rtc: sun6i: Allow RTC wakeup after shutdown + +Only IRQs that have enable_irq_wake() called on them can wake the system +from sleep or after it has been shut down. Currently, the RTC alarm can +only wake the system from sleep. Run the suspend callback to arm the IRQ +during the shutdown process, so the RTC alarm also works after shutdown. + +Signed-off-by: Samuel Holland +--- + drivers/rtc/rtc-sun6i.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/rtc/rtc-sun6i.c ++++ b/drivers/rtc/rtc-sun6i.c +@@ -641,7 +641,6 @@ static const struct rtc_class_ops sun6i_ + .alarm_irq_enable = sun6i_rtc_alarm_irq_enable + }; + +-#ifdef CONFIG_PM_SLEEP + /* Enable IRQ wake on suspend, to wake up from RTC. */ + static int sun6i_rtc_suspend(struct device *dev) + { +@@ -654,7 +653,7 @@ static int sun6i_rtc_suspend(struct devi + } + + /* Disable IRQ wake on resume. */ +-static int sun6i_rtc_resume(struct device *dev) ++static int __maybe_unused sun6i_rtc_resume(struct device *dev) + { + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + +@@ -663,7 +662,6 @@ static int sun6i_rtc_resume(struct devic + + return 0; + } +-#endif + + static SIMPLE_DEV_PM_OPS(sun6i_rtc_pm_ops, + sun6i_rtc_suspend, sun6i_rtc_resume); +@@ -735,6 +733,11 @@ static int sun6i_rtc_probe(struct platfo + return 0; + } + ++static void sun6i_rtc_shutdown(struct platform_device *pdev) ++{ ++ sun6i_rtc_suspend(&pdev->dev); ++} ++ + /* + * As far as RTC functionality goes, all models are the same. The + * datasheets claim that different models have different number of +@@ -755,6 +758,7 @@ MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids + + static struct platform_driver sun6i_rtc_driver = { + .probe = sun6i_rtc_probe, ++ .shutdown = sun6i_rtc_shutdown, + .driver = { + .name = "sun6i-rtc", + .of_match_table = sun6i_rtc_dt_ids, diff --git a/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/wip-fix-H6-4k-60.patch b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/wip-fix-H6-4k-60.patch new file mode 100644 index 0000000..1b956fb --- /dev/null +++ b/recipes-kernel/linux/linux-mainline/sunxi-kmeta/bsp/orange-pi-3lts/wip-fix-H6-4k-60.patch @@ -0,0 +1,75 @@ +From edc858b1d62ce5ffd8b8d10cc62425af15d48a91 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 8 Dec 2021 20:42:45 +0100 +Subject: [PATCH] wip: fix H6 4k@60 + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 7 +++++++ + drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 4 ++++ + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 2 +- + 3 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index f08d0fded61f..bcd839a3ce80 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1488,6 +1488,8 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + /* Override and disable clock termination. */ + dw_hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE, + HDMI_3D_TX_PHY_CKCALCTRL); ++ if (mpixelclock == 594000000) ++ dw_hdmi_phy_i2c_write(hdmi, 0x8006, HDMI_3D_TX_PHY_MSM_CTRL); + + return 0; + } +@@ -2166,6 +2168,8 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, + hdmi->hdmi_data.hdcp_enable = 0; + hdmi->hdmi_data.video_mode.mdataenablepolarity = true; + ++ hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP); ++ + /* HDMI Initialization Step B.1 */ + hdmi_av_composer(hdmi, &connector->display_info, mode); + +@@ -2205,6 +2209,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, + hdmi_video_sample(hdmi); + hdmi_tx_hdcp_config(hdmi); + ++ msleep(100); ++ hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP); ++ + dw_hdmi_clear_overflow(hdmi); + + return 0; +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h +index 1999db05bc3b..05182418efbb 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h +@@ -842,6 +842,10 @@ enum { + HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00, + HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04, + ++/* HDMI_FC_GCP */ ++ HDMI_FC_GCP_SET_AVMUTE = 0x2, ++ HDMI_FC_GCP_CLEAR_AVMUTE = 0x1, ++ + /* FC_DBGFORCE field values */ + HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, + HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, +diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +index b64d93da651d..b70bc9de761f 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c ++++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +@@ -90,7 +90,7 @@ static const struct dw_hdmi_mpll_config sun50i_h6_mpll_cfg[] = { + }, + }, { + 594000000, { +- { 0x1a40, 0x0003 }, ++ { 0x1a7c, 0x0003 }, + { 0x3b4c, 0x0003 }, + { 0x5a64, 0x0003 }, + }, +-- +2.34.1 + diff --git a/recipes-kernel/linux/linux-mainline_6.1.9.bb b/recipes-kernel/linux/linux-mainline_6.1.9.bb index 40abfa6..f2704dc 100644 --- a/recipes-kernel/linux/linux-mainline_6.1.9.bb +++ b/recipes-kernel/linux/linux-mainline_6.1.9.bb @@ -21,3 +21,5 @@ SRC_URI:append:orange-pi-zero2 = " \ file://0011-dts-add-usb-to-h616.patch \ file://0012-dts-orange-pi-zero2.patch \ " +KERNEL_FEATURES:append:orange-pi-3lts = " bsp/orange-pi-3lts/orange-pi-3lts-6_1.scc bsp/uwe5622/uwe5622-6_1.scc" + diff --git a/recipes-kernel/linux/linux-mainline_6.5.11.bb b/recipes-kernel/linux/linux-mainline_6.5.11.bb index fcc7ae2..e1ac640 100644 --- a/recipes-kernel/linux/linux-mainline_6.5.11.bb +++ b/recipes-kernel/linux/linux-mainline_6.5.11.bb @@ -4,5 +4,9 @@ DESCRIPTION = "Mainline Longterm Linux kernel" LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46" +# Board Specific features +KERNEL_FEATURES:prepend:orange-pi-3lts = " bsp/orange-pi-3lts/orange-pi-3lts-6_5.scc bsp/uwe5622/uwe5622-6_5.scc" + + SRC_URI[sha256sum] = "2ee24af9282b80923b2da56b70aad7df2e8ee4e3f076452e05ba66be2059b519"