mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
[AR-1313] Move mvebu edge to 6.1 (#4652)
* Initial work on bringing mvebu to 6.0 * Switch mvebu edge to 6.1 * Remove link leftover * Update kernel config Co-authored-by: Igor <igor@armbian.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ case $BRANCH in
|
||||
|
||||
edge)
|
||||
|
||||
KERNELBRANCH='branch:linux-5.17.y'
|
||||
KERNELBRANCH='branch:linux-6.1.y'
|
||||
|
||||
LINUXCONFIG='linux-mvebu-edge'
|
||||
KERNELPATCHDIR="mvebu-edge"
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Subject: [PATCH 01/30] cpuidle: mvebu: indicate failure to enter deeper sleep
|
||||
states
|
||||
MIME-Version: 1.0
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
|
||||
The cpuidle ->enter method expects the return value to be the sleep
|
||||
state we entered. Returning negative numbers or other codes is not
|
||||
permissible since coupled CPU idle was merged.
|
||||
|
||||
At least some of the mvebu_v7_cpu_suspend() implementations return the
|
||||
value from cpu_suspend(), which returns zero if the CPU vectors back
|
||||
into the kernel via cpu_resume() (the success case), or the non-zero
|
||||
return value of the suspend actor, or one (failure cases).
|
||||
|
||||
We do not want to be returning the failure case value back to CPU idle
|
||||
as that indicates that we successfully entered one of the deeper idle
|
||||
states. Always return zero instead, indicating that we slept for the
|
||||
shortest amount of time.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
---
|
||||
drivers/cpuidle/cpuidle-mvebu-v7.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpuidle/cpuidle-mvebu-v7.c
|
||||
+++ b/drivers/cpuidle/cpuidle-mvebu-v7.c
|
||||
@@ -39,8 +39,12 @@ static int mvebu_v7_enter_idle(struct cp
|
||||
ret = mvebu_v7_cpu_suspend(deepidle);
|
||||
cpu_pm_exit();
|
||||
|
||||
+ /*
|
||||
+ * If we failed to enter the desired state, indicate that we
|
||||
+ * slept lightly.
|
||||
+ */
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ return 0;
|
||||
|
||||
return index;
|
||||
}
|
||||
219
patch/kernel/archive/mvebu-6.1/09-pci-link-retraining.patch
Normal file
219
patch/kernel/archive/mvebu-6.1/09-pci-link-retraining.patch
Normal file
@@ -0,0 +1,219 @@
|
||||
Subject: [PATCH v3] PCI: Disallow retraining link for Atheros chips on non-Gen1 PCIe bridges
|
||||
Atheros AR9xxx and QCA9xxx chips have behaviour issues not only after a
|
||||
bus reset, but also after doing retrain link, if PCIe bridge is not in
|
||||
GEN1 mode (at 2.5 GT/s speed):
|
||||
|
||||
- QCA9880 and QCA9890 chips throw a Link Down event and completely
|
||||
disappear from the bus and their config space is not accessible
|
||||
afterwards.
|
||||
|
||||
- QCA9377 chip throws a Link Down event followed by Link Up event, the
|
||||
config space is accessible and PCI device ID is correct. But trying to
|
||||
access chip's I/O space causes Uncorrected (Non-Fatal) AER error,
|
||||
followed by Synchronous external abort 96000210 and Segmentation fault
|
||||
of insmod while loading ath10k_pci.ko module.
|
||||
|
||||
- AR9390 chip throws a Link Down event followed by Link Up event, config
|
||||
space is accessible, but contains nonsense values. PCI device ID is
|
||||
0xABCD which indicates HW bug that chip itself was not able to read
|
||||
values from internal EEPROM/OTP.
|
||||
|
||||
- AR9287 chip throws also Link Down and Link Up events, also has
|
||||
accessible config space containing correct values. But ath9k driver
|
||||
fails to initialize card from this state as it is unable to access HW
|
||||
registers. This also indicates that the chip iself is not able to read
|
||||
values from internal EEPROM/OTP.
|
||||
|
||||
These issues related to PCI device ID 0xABCD and to reading internal
|
||||
EEPROM/OTP were previously discussed at ath9k-devel mailing list in
|
||||
following thread:
|
||||
|
||||
https://www.mail-archive.com/ath9k-devel@lists.ath9k.org/msg07529.html
|
||||
|
||||
After experiments we've come up with a solution: it seems that Retrain
|
||||
link can be called only when using GEN1 PCIe bridge or when PCIe bridge
|
||||
link speed is forced to 2.5 GT/s. Applying this workaround fixes all
|
||||
mentioned cards.
|
||||
|
||||
This issue was reproduced with more cards:
|
||||
- Compex WLE900VX (QCA9880 based / device ID 0x003c)
|
||||
- QCNFA435 (QCA9377 based / device ID 0x0042)
|
||||
- Compex WLE200NX (AR9287 based / device ID 0x002e)
|
||||
- "noname" card (QCA9890 based / device ID 0x003c)
|
||||
- Wistron NKR-DNXAH1 (AR9390 based / device ID 0x0030)
|
||||
on Armada 385 with pci-mvebu.c driver and also on Armada 3720 with
|
||||
pci-aardvark.c driver.
|
||||
|
||||
To workaround this issue, this change introduces a new PCI quirk called
|
||||
PCI_DEV_FLAGS_NO_RETRAIN_LINK_WHEN_NOT_GEN1, which is enabled for all
|
||||
Atheros chips with PCI_DEV_FLAGS_NO_BUS_RESET quirk, and also for Atheros
|
||||
chip AR9287.
|
||||
|
||||
When this quirk is set, kernel disallows triggering PCI_EXP_LNKCTL_RL
|
||||
bit in config space of PCIe Bridge in the case when PCIe Bridge is
|
||||
capable of higher speed than 2.5 GT/s and this higher speed is already
|
||||
allowed. When PCIe Bridge has accessible LNKCTL2 register, we try to
|
||||
force target link speed to 2.5 GT/s. After this change it is possible
|
||||
to trigger PCI_EXP_LNKCTL_RL bit without issues.
|
||||
|
||||
Currently only PCIe ASPM kernel code triggers this PCI_EXP_LNKCTL_RL bit,
|
||||
so quirk check is added only into pcie/aspm.c file.
|
||||
|
||||
Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
Reported-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Tested-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Tested-by: Marek Behún <kabel@kernel.org>
|
||||
BugLink: https://lore.kernel.org/linux-pci/87h7l8axqp.fsf@toke.dk/
|
||||
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=84821
|
||||
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=192441
|
||||
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=209833
|
||||
Cc: stable@vger.kernel.org # c80851f6ce63a ("PCI: Add PCI_EXP_LNKCTL2_TLS* macros")
|
||||
|
||||
---
|
||||
Changes since v1:
|
||||
* Move whole quirk code into pcie_downgrade_link_to_gen1() function
|
||||
* Reformat to 80 chars per line where possible
|
||||
* Add quirk also for cards with AR9287 chip (PCI ID 0x002e)
|
||||
* Extend commit message description and add information about 0xABCD
|
||||
|
||||
Changes since v2:
|
||||
* Add quirk also for Atheros QCA9377 chip
|
||||
---
|
||||
drivers/pci/pcie/aspm.c | 44 +++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/pci/quirks.c | 39 ++++++++++++++++++++++++++++--------
|
||||
include/linux/pci.h | 2 ++
|
||||
3 files changed, 77 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
|
||||
index ac0557a305af..729b0389562b 100644
|
||||
--- a/drivers/pci/pcie/aspm.c
|
||||
+++ b/drivers/pci/pcie/aspm.c
|
||||
@@ -192,12 +192,56 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
|
||||
link->clkpm_disable = blacklist ? 1 : 0;
|
||||
}
|
||||
|
||||
+static int pcie_downgrade_link_to_gen1(struct pci_dev *parent)
|
||||
+{
|
||||
+ u16 reg16;
|
||||
+ u32 reg32;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Check if link is capable of higher speed than 2.5 GT/s */
|
||||
+ pcie_capability_read_dword(parent, PCI_EXP_LNKCAP, ®32);
|
||||
+ if ((reg32 & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Check if link speed can be downgraded to 2.5 GT/s */
|
||||
+ pcie_capability_read_dword(parent, PCI_EXP_LNKCAP2, ®32);
|
||||
+ if (!(reg32 & PCI_EXP_LNKCAP2_SLS_2_5GB)) {
|
||||
+ pci_err(parent, "ASPM: Bridge does not support changing Link Speed to 2.5 GT/s\n");
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
+ /* Force link speed to 2.5 GT/s */
|
||||
+ ret = pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL2,
|
||||
+ PCI_EXP_LNKCTL2_TLS,
|
||||
+ PCI_EXP_LNKCTL2_TLS_2_5GT);
|
||||
+ if (!ret) {
|
||||
+ /* Verify that new value was really set */
|
||||
+ pcie_capability_read_word(parent, PCI_EXP_LNKCTL2, ®16);
|
||||
+ if ((reg16 & PCI_EXP_LNKCTL2_TLS) != PCI_EXP_LNKCTL2_TLS_2_5GT)
|
||||
+ ret = -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (ret) {
|
||||
+ pci_err(parent, "ASPM: Changing Target Link Speed to 2.5 GT/s failed: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ pci_info(parent, "ASPM: Target Link Speed changed to 2.5 GT/s due to quirk\n");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static bool pcie_retrain_link(struct pcie_link_state *link)
|
||||
{
|
||||
struct pci_dev *parent = link->pdev;
|
||||
unsigned long end_jiffies;
|
||||
u16 reg16;
|
||||
|
||||
+ if ((link->downstream->dev_flags & PCI_DEV_FLAGS_NO_RETRAIN_LINK_WHEN_NOT_GEN1) &&
|
||||
+ pcie_downgrade_link_to_gen1(parent)) {
|
||||
+ pci_err(parent, "ASPM: Retrain Link at higher speed is disallowed by quirk\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16);
|
||||
reg16 |= PCI_EXP_LNKCTL_RL;
|
||||
pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
|
||||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
||||
index 5d2acebc3..91d675e0d 100644
|
||||
--- a/drivers/pci/quirks.c
|
||||
+++ b/drivers/pci/quirks.c
|
||||
@@ -3572,19 +3572,46 @@ static void quirk_nvidia_no_bus_reset(struct pci_dev *dev)
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
|
||||
quirk_nvidia_no_bus_reset);
|
||||
|
||||
+
|
||||
+static void quirk_no_bus_reset_and_no_retrain_link(struct pci_dev *dev)
|
||||
+{
|
||||
+ dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET |
|
||||
+ PCI_DEV_FLAGS_NO_RETRAIN_LINK_WHEN_NOT_GEN1;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Some Atheros AR9xxx and QCA988x chips do not behave after a bus reset.
|
||||
+ * Atheros AR9xxx and QCA9xxx chips do not behave after a bus reset and also
|
||||
+ * after retrain link when PCIe bridge is not in GEN1 mode at 2.5 GT/s speed.
|
||||
* The device will throw a Link Down error on AER-capable systems and
|
||||
* regardless of AER, config space of the device is never accessible again
|
||||
* and typically causes the system to hang or reset when access is attempted.
|
||||
+ * Or if config space is accessible again then it contains only dummy values
|
||||
+ * like fixed PCI device ID 0xABCD or values not initialized at all.
|
||||
+ * Retrain link can be called only when using GEN1 PCIe bridge or when
|
||||
+ * PCIe bridge has forced link speed to 2.5 GT/s via PCI_EXP_LNKCTL2 register.
|
||||
+ * To reset these cards it is required to do PCIe Warm Reset via PERST# pin.
|
||||
* https://lore.kernel.org/r/20140923210318.498dacbd@dualc.maya.org/
|
||||
+ * https://lore.kernel.org/r/87h7l8axqp.fsf@toke.dk/
|
||||
+ * https://www.mail-archive.com/ath9k-devel@lists.ath9k.org/msg07529.html
|
||||
*/
|
||||
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
|
||||
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
|
||||
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
|
||||
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset);
|
||||
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset);
|
||||
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x002e,
|
||||
+ quirk_no_bus_reset_and_no_retrain_link);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030,
|
||||
+ quirk_no_bus_reset_and_no_retrain_link);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032,
|
||||
+ quirk_no_bus_reset_and_no_retrain_link);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033,
|
||||
+ quirk_no_bus_reset_and_no_retrain_link);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034,
|
||||
+ quirk_no_bus_reset_and_no_retrain_link);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e,
|
||||
+ quirk_no_bus_reset_and_no_retrain_link);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c,
|
||||
+ quirk_no_bus_reset_and_no_retrain_link);
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0042,
|
||||
+ quirk_no_bus_reset_and_no_retrain_link);
|
||||
+
|
||||
|
||||
/*
|
||||
* Root port on some Cavium CN8xxx chips do not successfully complete a bus
|
||||
diff --git a/include/linux/pci.h b/include/linux/pci.h
|
||||
index 86c799c97b77..fdbf7254e4ab 100644
|
||||
--- a/include/linux/pci.h
|
||||
+++ b/include/linux/pci.h
|
||||
@@ -227,6 +227,8 @@ enum pci_dev_flags {
|
||||
PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11),
|
||||
/* Device does honor MSI masking despite saying otherwise */
|
||||
PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12),
|
||||
+ /* Don't Retrain Link for device when bridge is not in GEN1 mode */
|
||||
+ PCI_DEV_FLAGS_NO_RETRAIN_LINK_WHEN_NOT_GEN1 = (__force pci_dev_flags_t) (1 << 12),
|
||||
};
|
||||
|
||||
enum pci_irq_reroute_variant {
|
||||
--
|
||||
2.20.1
|
||||
@@ -0,0 +1,196 @@
|
||||
From 4d73779886194072ecbfea4e0232d10232b5709f Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Tue, 29 Nov 2016 10:13:46 +0000
|
||||
Subject: mvebu/clearfog pcie updates
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
---
|
||||
drivers/pci/controller/pci-mvebu.c | 76 ++++++++++++++++++++++++++++++++++++++
|
||||
drivers/pci/pci-bridge-emul.c | 2 +
|
||||
drivers/pci/pcie/aspm.c | 6 +++
|
||||
drivers/pci/pcie/portdrv_core.c | 2 +
|
||||
4 files changed, 86 insertions(+)
|
||||
|
||||
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
|
||||
index c1ffdb06c971..dba5baa2c1ed 100644
|
||||
--- a/drivers/pci/controller/pci-mvebu.c
|
||||
+++ b/drivers/pci/controller/pci-mvebu.c
|
||||
@@ -59,6 +59,12 @@
|
||||
#define PCIE_INT_INTX(i) BIT(24+i)
|
||||
#define PCIE_INT_PM_PME BIT(28)
|
||||
#define PCIE_INT_ALL_MASK GENMASK(31, 0)
|
||||
+#define PCIE_MASK_ERR_COR BIT(18)
|
||||
+#define PCIE_MASK_ERR_NONFATAL BIT(17)
|
||||
+#define PCIE_MASK_ERR_FATAL BIT(16)
|
||||
+#define PCIE_MASK_FERR_DET BIT(10)
|
||||
+#define PCIE_MASK_NFERR_DET BIT(9)
|
||||
+#define PCIE_MASK_CORERR_DET BIT(8)
|
||||
#define PCIE_CTRL_OFF 0x1a00
|
||||
#define PCIE_CTRL_X1_MODE 0x0001
|
||||
#define PCIE_CTRL_RC_MODE BIT(1)
|
||||
@@ -618,6 +624,54 @@ mvebu_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
|
||||
return PCI_BRIDGE_EMUL_HANDLED;
|
||||
}
|
||||
|
||||
+static void mvebu_pcie_handle_irq_change(struct mvebu_pcie_port *port)
|
||||
+{
|
||||
+ u32 reg, old;
|
||||
+ u16 devctl, rtctl;
|
||||
+
|
||||
+ /*
|
||||
+ * Errors from downstream devices:
|
||||
+ * bridge control register SERR: enables reception of errors
|
||||
+ * Errors from this device, or received errors:
|
||||
+ * command SERR: enables ERR_NONFATAL and ERR_FATAL messages
|
||||
+ * => when enabled, these conditions also flag SERR in status register
|
||||
+ * devctl CERE: enables ERR_CORR messages
|
||||
+ * devctl NFERE: enables ERR_NONFATAL messages
|
||||
+ * devctl FERE: enables ERR_FATAL messages
|
||||
+ * Enabled messages then have three paths:
|
||||
+ * 1. rtctl: enables system error indication
|
||||
+ * 2. root error status register updated
|
||||
+ * 3. root error command register: forwarding via MSI
|
||||
+ */
|
||||
+ old = mvebu_readl(port, PCIE_INT_UNMASK_OFF);
|
||||
+ reg = old & ~(PCIE_INT_PM_PME | PCIE_MASK_FERR_DET |
|
||||
+ PCIE_MASK_NFERR_DET | PCIE_MASK_CORERR_DET |
|
||||
+ PCIE_MASK_ERR_COR | PCIE_MASK_ERR_NONFATAL |
|
||||
+ PCIE_MASK_ERR_FATAL);
|
||||
+
|
||||
+ devctl = port->bridge.pcie_conf.devctl;
|
||||
+ if (devctl & PCI_EXP_DEVCTL_FERE)
|
||||
+ reg |= PCIE_MASK_FERR_DET | PCIE_MASK_ERR_FATAL;
|
||||
+ if (devctl & PCI_EXP_DEVCTL_NFERE)
|
||||
+ reg |= PCIE_MASK_NFERR_DET | PCIE_MASK_ERR_NONFATAL;
|
||||
+ if (devctl & PCI_EXP_DEVCTL_CERE)
|
||||
+ reg |= PCIE_MASK_CORERR_DET | PCIE_MASK_ERR_COR;
|
||||
+ if (port->bridge.conf.command & PCI_COMMAND_SERR)
|
||||
+ reg |= PCIE_MASK_FERR_DET | PCIE_MASK_NFERR_DET |
|
||||
+ PCIE_MASK_ERR_FATAL | PCIE_MASK_ERR_NONFATAL;
|
||||
+
|
||||
+ if (!(port->bridge.conf.bridgectrl & PCI_BRIDGE_CTL_SERR))
|
||||
+ reg &= ~(PCIE_MASK_ERR_COR | PCIE_MASK_ERR_NONFATAL |
|
||||
+ PCIE_MASK_ERR_FATAL);
|
||||
+
|
||||
+ rtctl = port->bridge.pcie_conf.rootctl;
|
||||
+ if (rtctl & PCI_EXP_RTCTL_PMEIE)
|
||||
+ reg |= PCIE_INT_PM_PME;
|
||||
+
|
||||
+ if (old != reg)
|
||||
+ mvebu_writel(port, reg, PCIE_INT_UNMASK_OFF);
|
||||
+}
|
||||
+
|
||||
static pci_bridge_emul_read_status_t
|
||||
mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
|
||||
int reg, u32 *value)
|
||||
@@ -734,6 +788,9 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
|
||||
switch (reg) {
|
||||
case PCI_COMMAND:
|
||||
mvebu_writel(port, new, PCIE_CMD_OFF);
|
||||
+
|
||||
+ if ((old ^ new) & PCI_COMMAND_SERR)
|
||||
+ mvebu_pcie_handle_irq_change(port);
|
||||
break;
|
||||
|
||||
case PCI_IO_BASE:
|
||||
@@ -775,6 +832,8 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
|
||||
break;
|
||||
|
||||
case PCI_INTERRUPT_LINE:
|
||||
+ if (((old ^ new) >> 16) & PCI_BRIDGE_CTL_SERR)
|
||||
+ mvebu_pcie_handle_irq_change(port);
|
||||
if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) {
|
||||
u32 ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
|
||||
if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16))
|
||||
@@ -798,7 +857,18 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
|
||||
|
||||
switch (reg) {
|
||||
case PCI_EXP_DEVCTL:
|
||||
+ /*
|
||||
+ * Armada370 data says these bits must always
|
||||
+ * be zero when in root complex mode.
|
||||
+ */
|
||||
+ new &= ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE |
|
||||
+ PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE);
|
||||
+
|
||||
mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL);
|
||||
+
|
||||
+ if ((new ^ old) & (PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_NFERE |
|
||||
+ PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_URRE))
|
||||
+ mvebu_pcie_handle_irq_change(port);
|
||||
break;
|
||||
|
||||
case PCI_EXP_LNKCTL:
|
||||
@@ -849,6 +919,12 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
|
||||
|
||||
default:
|
||||
break;
|
||||
+
|
||||
+ case PCI_EXP_RTCTL:
|
||||
+ if ((new ^ old) & (PCI_EXP_RTCTL_SECEE | PCI_EXP_RTCTL_SENFEE |
|
||||
+ PCI_EXP_RTCTL_SEFEE | PCI_EXP_RTCTL_PMEIE))
|
||||
+ mvebu_pcie_handle_irq_change(port);
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
|
||||
index 8e429766838c..33868afb5d05 100644
|
||||
--- a/drivers/pci/pci-bridge-emul.c
|
||||
+++ b/drivers/pci/pci-bridge-emul.c
|
||||
@@ -161,6 +161,7 @@ struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = {
|
||||
.rw = (GENMASK(7, 0) |
|
||||
((PCI_BRIDGE_CTL_PARITY |
|
||||
PCI_BRIDGE_CTL_SERR |
|
||||
+ /* NOTE: PCIe does not allow ISA, VGA, MASTER_ABORT */
|
||||
PCI_BRIDGE_CTL_ISA |
|
||||
PCI_BRIDGE_CTL_VGA |
|
||||
PCI_BRIDGE_CTL_MASTER_ABORT |
|
||||
@@ -359,6 +360,7 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
|
||||
bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE;
|
||||
bridge->conf.cache_line_size = 0x10;
|
||||
bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST);
|
||||
+ bridge->conf.bridgectrl = cpu_to_le16(PCI_BRIDGE_CTL_SERR);
|
||||
bridge->pci_regs_behavior = kmemdup(pci_regs_behavior,
|
||||
sizeof(pci_regs_behavior),
|
||||
GFP_KERNEL);
|
||||
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
|
||||
index a96b7424c9bc..72888e25c0d8 100644
|
||||
--- a/drivers/pci/pcie/aspm.c
|
||||
+++ b/drivers/pci/pcie/aspm.c
|
||||
@@ -586,6 +586,12 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
|
||||
pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &child_lnkcap);
|
||||
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &parent_lnkctl);
|
||||
pcie_capability_read_word(child, PCI_EXP_LNKCTL, &child_lnkctl);
|
||||
+dev_info(&parent->dev, "up support %x enabled %x\n",
|
||||
+ (parent_lnkcap & PCI_EXP_LNKCAP_ASPMS) >> 10,
|
||||
+ !!(parent_lnkctl & PCI_EXP_LNKCTL_ASPMC));
|
||||
+dev_info(&parent->dev, "dn support %x enabled %x\n",
|
||||
+ (child_lnkcap & PCI_EXP_LNKCAP_ASPMS) >> 10,
|
||||
+ !!(child_lnkctl & PCI_EXP_LNKCTL_ASPMC));
|
||||
|
||||
/*
|
||||
* Setup L0s state
|
||||
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
|
||||
index 604feeb84ee4..09f1ec9f5acb 100644
|
||||
--- a/drivers/pci/pcie/portdrv_core.c
|
||||
+++ b/drivers/pci/pcie/portdrv_core.c
|
||||
@@ -327,6 +327,7 @@ int pcie_port_device_register(struct pci_dev *dev)
|
||||
|
||||
/* Get and check PCI Express port services */
|
||||
capabilities = get_port_device_capability(dev);
|
||||
+dev_info(&dev->dev, "PCIe capabilities: 0x%x\n", capabilities);
|
||||
if (!capabilities)
|
||||
return 0;
|
||||
|
||||
@@ -339,6 +340,7 @@ int pcie_port_device_register(struct pci_dev *dev)
|
||||
* if that is to be used.
|
||||
*/
|
||||
status = pcie_init_service_irqs(dev, irqs, capabilities);
|
||||
+dev_info(&dev->dev, "init_service_irqs: %d\n", status);
|
||||
if (status) {
|
||||
capabilities &= PCIE_PORT_SERVICE_HP;
|
||||
if (!capabilities)
|
||||
--
|
||||
cgit
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
From e6a83c8b624052022b8212beabee6e4c40c6d8b2 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Tue, 29 Nov 2016 10:13:48 +0000
|
||||
Subject: implement slot capabilities (SSPL)
|
||||
|
||||
---
|
||||
drivers/pci/controller/pci-mvebu.c | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
|
||||
index dba5baa2c1ed..c817cc5b2206 100644
|
||||
--- a/drivers/pci/controller/pci-mvebu.c
|
||||
+++ b/drivers/pci/controller/pci-mvebu.c
|
||||
@@ -78,6 +78,7 @@
|
||||
#define PCIE_SSPL_VALUE_MASK GENMASK(7, 0)
|
||||
#define PCIE_SSPL_SCALE_SHIFT 8
|
||||
#define PCIE_SSPL_SCALE_MASK GENMASK(9, 8)
|
||||
+#define PCIE_SSPL_MSGEN BIT(14)
|
||||
#define PCIE_SSPL_ENABLE BIT(16)
|
||||
#define PCIE_RC_RTSTA 0x1a14
|
||||
#define PCIE_DEBUG_CTRL 0x1a60
|
||||
@@ -705,6 +706,14 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
|
||||
(PCI_EXP_LNKSTA_DLLLA << 16) : 0);
|
||||
break;
|
||||
|
||||
+ case PCI_EXP_SLTCAP:
|
||||
+ {
|
||||
+ u32 tmp = mvebu_readl(port, PCIE_SSPL_OFF);
|
||||
+ *value = FIELD_GET(PCIE_SSPL_SCALE_MASK, tmp) << 15 |
|
||||
+ FIELD_GET(PCIE_SSPL_VALUE_MASK, tmp) << 7;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
case PCI_EXP_SLTCTL: {
|
||||
u16 slotctl = le16_to_cpu(bridge->pcie_conf.slotctl);
|
||||
u16 slotsta = le16_to_cpu(bridge->pcie_conf.slotsta);
|
||||
@@ -882,6 +891,17 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
|
||||
mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL);
|
||||
break;
|
||||
|
||||
+ case PCI_EXP_SLTCAP:
|
||||
+ {
|
||||
+ u32 sspl = FIELD_PREP(PCIE_SSPL_VALUE_MASK,
|
||||
+ FIELD_GET(PCI_EXP_SLTCAP_SPLV, new)) |
|
||||
+ FIELD_PREP(PCIE_SSPL_SCALE_MASK,
|
||||
+ FIELD_GET(PCI_EXP_SLTCAP_SPLS, new)) |
|
||||
+ PCIE_SSPL_MSGEN;
|
||||
+ mvebu_writel(port, sspl, PCIE_SSPL_OFF);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
case PCI_EXP_SLTCTL:
|
||||
/*
|
||||
* Allow to change PCIE_SSPL_ENABLE bit only when slot power
|
||||
--
|
||||
cgit
|
||||
|
||||
1323
patch/kernel/archive/mvebu-6.1/12-net-dsa-mv88e6xxx.patch
Normal file
1323
patch/kernel/archive/mvebu-6.1/12-net-dsa-mv88e6xxx.patch
Normal file
File diff suppressed because it is too large
Load Diff
55
patch/kernel/archive/mvebu-6.1/20-pcie-bridge-emul.patch
Normal file
55
patch/kernel/archive/mvebu-6.1/20-pcie-bridge-emul.patch
Normal file
@@ -0,0 +1,55 @@
|
||||
From f1149effc7fd438ac5925a8e58ee2da294033ec5 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 2 Feb 2021 13:45:28 +0000
|
||||
Subject: PCI: pci-bridge-emul: re-arrange register tests
|
||||
|
||||
Re-arrange the tests for which sets of registers are being accessed
|
||||
so that it is easier to add further regions later. No functional
|
||||
change.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/pci/pci-bridge-emul.c | 15 ++++++++++-----
|
||||
1 file changed, 10 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c
|
||||
index 9334b2dd4764..d746116104c6 100644
|
||||
--- a/drivers/pci/pci-bridge-emul.c
|
||||
+++ b/drivers/pci/pci-bridge-emul.c
|
||||
@@ -477,8 +477,11 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
|
||||
read_op = pci_bridge_emul_read_ssid;
|
||||
cfgspace = NULL;
|
||||
behavior = NULL;
|
||||
- } else if (reg >= bridge->pcie_start && reg < bridge->pcie_start + PCI_CAP_PCIE_SIZEOF &&
|
||||
- bridge->has_pcie) {
|
||||
+ } else if (!bridge->has_pcie) {
|
||||
+ /* PCIe space is not implemented, and no PCI capabilities */
|
||||
+ *value = 0;
|
||||
+ return PCIBIOS_SUCCESSFUL;
|
||||
+ } else if (reg >= bridge->pcie_start && reg < bridge->pcie_start + PCI_CAP_PCIE_SIZEOF) {
|
||||
/* Our emulated PCIe capability */
|
||||
reg -= bridge->pcie_start;
|
||||
read_op = bridge->ops->read_pcie;
|
||||
@@ -551,14 +554,16 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
|
||||
write_op = bridge->ops->write_base;
|
||||
cfgspace = (__le32 *) &bridge->conf;
|
||||
behavior = bridge->pci_regs_behavior;
|
||||
- } else if (reg >= bridge->pcie_start && reg < bridge->pcie_start + PCI_CAP_PCIE_SIZEOF &&
|
||||
- bridge->has_pcie) {
|
||||
+ } else if (!bridge->has_pcie) {
|
||||
+ /* PCIe space is not implemented, and no PCI capabilities */
|
||||
+ return PCIBIOS_SUCCESSFUL;
|
||||
+ } else if (reg >= bridge->pcie_start && reg < bridge->pcie_start + PCI_CAP_PCIE_SIZEOF) {
|
||||
/* Our emulated PCIe capability */
|
||||
reg -= bridge->pcie_start;
|
||||
write_op = bridge->ops->write_pcie;
|
||||
cfgspace = (__le32 *) &bridge->pcie_conf;
|
||||
behavior = bridge->pcie_cap_regs_behavior;
|
||||
- } else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) {
|
||||
+ } else if (reg >= PCI_CFG_SPACE_SIZE) {
|
||||
/* PCIe extended capability space */
|
||||
reg -= PCI_CFG_SPACE_SIZE;
|
||||
write_op = bridge->ops->write_ext;
|
||||
--
|
||||
cgit
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
From 8137da20701c776ad3481115305a5e8e410871ba Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 29 Nov 2016 10:15:45 +0000
|
||||
Subject: ARM: dts: armada388-clearfog: emmc on clearfog base
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
arch/arm/boot/dts/armada-388-clearfog-base.dts | 1 +
|
||||
.../dts/armada-38x-solidrun-microsom-emmc.dtsi | 62 ++++++++++++++++++++++
|
||||
2 files changed, 63 insertions(+)
|
||||
create mode 100644 arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi
|
||||
|
||||
--- a/arch/arm/boot/dts/armada-388-clearfog-base.dts
|
||||
+++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
/dts-v1/;
|
||||
#include "armada-388-clearfog.dtsi"
|
||||
+#include "armada-38x-solidrun-microsom-emmc.dtsi"
|
||||
|
||||
/ {
|
||||
model = "SolidRun Clearfog Base A1";
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi
|
||||
@@ -0,0 +1,62 @@
|
||||
+/*
|
||||
+ * Device Tree file for SolidRun Armada 38x Microsom add-on for eMMC
|
||||
+ *
|
||||
+ * Copyright (C) 2015 Russell King
|
||||
+ *
|
||||
+ * This board is in development; the contents of this file work with
|
||||
+ * the A1 rev 2.0 of the board, which does not represent final
|
||||
+ * production board. Things will change, don't expect this file to
|
||||
+ * remain compatible info the future.
|
||||
+ *
|
||||
+ * This file is dual-licensed: you can use it either under the terms
|
||||
+ * of the GPL or the X11 license, at your option. Note that this dual
|
||||
+ * licensing only applies to this file, and not this project as a
|
||||
+ * whole.
|
||||
+ *
|
||||
+ * a) This file is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * version 2 as published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This file is distributed in the hope that it will be useful
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * Or, alternatively
|
||||
+ *
|
||||
+ * b) Permission is hereby granted, free of charge, to any person
|
||||
+ * obtaining a copy of this software and associated documentation
|
||||
+ * files (the "Software"), to deal in the Software without
|
||||
+ * restriction, including without limitation the rights to use
|
||||
+ * copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
+ * sell copies of the Software, and to permit persons to whom the
|
||||
+ * Software is furnished to do so, subject to the following
|
||||
+ * conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
|
||||
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
+ * OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+/ {
|
||||
+ soc {
|
||||
+ internal-regs {
|
||||
+ sdhci@d8000 {
|
||||
+ bus-width = <4>;
|
||||
+ no-1-8-v;
|
||||
+ non-removable;
|
||||
+ pinctrl-0 = <µsom_sdhci_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+ wp-inverted;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
@@ -0,0 +1,149 @@
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Subject: libata: add ledtrig support
|
||||
|
||||
This adds a LED trigger for each ATA port indicating disk activity.
|
||||
|
||||
As this is needed only on specific platforms (NAS SoCs and such),
|
||||
these platforms should define ARCH_WANTS_LIBATA_LEDS if there
|
||||
are boards with LED(s) intended to indicate ATA disk activity and
|
||||
need the OS to take care of that.
|
||||
In that way, if not selected, LED trigger support not will be
|
||||
included in libata-core and both, codepaths and structures remain
|
||||
untouched.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/ata/Kconfig | 16 ++++++++++++++++
|
||||
drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/libata.h | 9 +++++++++
|
||||
3 files changed, 66 insertions(+)
|
||||
|
||||
--- a/drivers/ata/Kconfig
|
||||
+++ b/drivers/ata/Kconfig
|
||||
@@ -67,6 +67,22 @@ config ATA_FORCE
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
+config ARCH_WANT_LIBATA_LEDS
|
||||
+ bool
|
||||
+
|
||||
+config ATA_LEDS
|
||||
+ bool "support ATA port LED triggers"
|
||||
+ depends on ARCH_WANT_LIBATA_LEDS
|
||||
+ select NEW_LEDS
|
||||
+ select LEDS_CLASS
|
||||
+ select LEDS_TRIGGERS
|
||||
+ default y
|
||||
+ help
|
||||
+ This option adds a LED trigger for each registered ATA port.
|
||||
+ It is used to drive disk activity leds connected via GPIO.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config ATA_ACPI
|
||||
bool "ATA ACPI Support"
|
||||
depends on ACPI
|
||||
--- a/drivers/ata/libata-core.c
|
||||
+++ b/drivers/ata/libata-core.c
|
||||
@@ -650,6 +650,19 @@ u64 ata_tf_read_block(const struct ata_t
|
||||
return block;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+#define LIBATA_BLINK_DELAY 20 /* ms */
|
||||
+static inline void ata_led_act(struct ata_port *ap)
|
||||
+{
|
||||
+ unsigned long led_delay = LIBATA_BLINK_DELAY;
|
||||
+
|
||||
+ if (unlikely(!ap->ledtrig))
|
||||
+ return;
|
||||
+
|
||||
+ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* ata_build_rw_tf - Build ATA taskfile for given read/write request
|
||||
* @tf: Target ATA taskfile
|
||||
@@ -4513,6 +4526,9 @@ struct ata_queued_cmd *ata_qc_new_init(s
|
||||
if (tag < 0)
|
||||
return NULL;
|
||||
}
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ ata_led_act(ap);
|
||||
+#endif
|
||||
|
||||
qc = __ata_qc_from_tag(ap, tag);
|
||||
qc->tag = qc->hw_tag = tag;
|
||||
@@ -5291,6 +5307,9 @@ struct ata_port *ata_port_alloc(struct a
|
||||
ap->stats.unhandled_irq = 1;
|
||||
ap->stats.idle_irq = 1;
|
||||
#endif
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
|
||||
+#endif
|
||||
ata_sff_port_init(ap);
|
||||
|
||||
return ap;
|
||||
@@ -5326,6 +5345,12 @@ static void ata_host_release(struct kref
|
||||
|
||||
kfree(ap->pmp_link);
|
||||
kfree(ap->slave_link);
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ if (ap->ledtrig) {
|
||||
+ led_trigger_unregister(ap->ledtrig);
|
||||
+ kfree(ap->ledtrig);
|
||||
+ };
|
||||
+#endif
|
||||
kfree(ap);
|
||||
host->ports[i] = NULL;
|
||||
}
|
||||
@@ -5732,7 +5757,23 @@ int ata_host_register(struct ata_host *h
|
||||
host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
|
||||
host->ports[i]->local_port_no = i + 1;
|
||||
}
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ for (i = 0; i < host->n_ports; i++) {
|
||||
+ if (unlikely(!host->ports[i]->ledtrig))
|
||||
+ continue;
|
||||
|
||||
+ snprintf(host->ports[i]->ledtrig_name,
|
||||
+ sizeof(host->ports[i]->ledtrig_name), "ata%u",
|
||||
+ host->ports[i]->print_id);
|
||||
+
|
||||
+ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name;
|
||||
+
|
||||
+ if (led_trigger_register(host->ports[i]->ledtrig)) {
|
||||
+ kfree(host->ports[i]->ledtrig);
|
||||
+ host->ports[i]->ledtrig = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
/* Create associated sysfs transport objects */
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
rc = ata_tport_add(host->dev,host->ports[i]);
|
||||
--- a/include/linux/libata.h
|
||||
+++ b/include/linux/libata.h
|
||||
@@ -23,6 +23,9 @@
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/async.h>
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+#include <linux/leds.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* Define if arch has non-standard setup. This is a _PCI_ standard
|
||||
@@ -882,6 +885,12 @@ struct ata_port {
|
||||
#ifdef CONFIG_ATA_ACPI
|
||||
struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */
|
||||
#endif
|
||||
+
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+ struct led_trigger *ledtrig;
|
||||
+ char ledtrig_name[8];
|
||||
+#endif
|
||||
+
|
||||
/* owned by EH */
|
||||
u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
From 9ee6345ef82f7af5f98e17a40e667f8ad6b2fa1b Mon Sep 17 00:00:00 2001
|
||||
From: aprayoga <adit.prayoga@gmail.com>
|
||||
Date: Sun, 3 Sep 2017 18:10:12 +0800
|
||||
Subject: Enable ATA port LED trigger
|
||||
|
||||
---
|
||||
arch/arm/configs/mvebu_v7_defconfig | 1 +
|
||||
arch/arm/mach-mvebu/Kconfig | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
--- a/arch/arm/configs/mvebu_v7_defconfig
|
||||
+++ b/arch/arm/configs/mvebu_v7_defconfig
|
||||
@@ -58,6 +58,7 @@ CONFIG_MTD_UBI=y
|
||||
CONFIG_EEPROM_AT24=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_ATA=y
|
||||
+CONFIG_ATA_LEDS=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_SATA_MV=y
|
||||
--- a/arch/arm/mach-mvebu/Kconfig
|
||||
+++ b/arch/arm/mach-mvebu/Kconfig
|
||||
@@ -56,6 +56,7 @@ config MACH_ARMADA_375
|
||||
config MACH_ARMADA_38X
|
||||
bool "Marvell Armada 380/385 boards"
|
||||
depends on ARCH_MULTI_V7
|
||||
+ select ARCH_WANT_LIBATA_LEDS
|
||||
select ARM_ERRATA_720789
|
||||
select PL310_ERRATA_753970
|
||||
select ARM_GIC
|
||||
@@ -0,0 +1,88 @@
|
||||
--- a/drivers/gpio/gpio-mvebu.c
|
||||
+++ b/drivers/gpio/gpio-mvebu.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/init.h>
|
||||
+#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
@@ -111,7 +112,7 @@ struct mvebu_gpio_chip {
|
||||
struct regmap *regs;
|
||||
u32 offset;
|
||||
struct regmap *percpu_regs;
|
||||
- int irqbase;
|
||||
+ int bank_irq[4];
|
||||
struct irq_domain *domain;
|
||||
int soc_variant;
|
||||
|
||||
@@ -601,6 +602,33 @@ static void mvebu_gpio_irq_handler(struc
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
|
||||
+ * While system is running, all registered GPIO interrupts need to have
|
||||
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
|
||||
+ * need to have wake-up enabled.
|
||||
+ * @param irq interrupt source number
|
||||
+ * @param enable enable as wake-up if equal to non-zero
|
||||
+ * @return This function returns 0 on success.
|
||||
+ */
|
||||
+static int mvebu_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
|
||||
+{
|
||||
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||
+ struct mvebu_gpio_chip *mvchip = gc->private;
|
||||
+ int irq;
|
||||
+ int bank;
|
||||
+
|
||||
+ bank = d->hwirq % 8;
|
||||
+ irq = mvchip->bank_irq[bank];
|
||||
+
|
||||
+ if (enable)
|
||||
+ enable_irq_wake(irq);
|
||||
+ else
|
||||
+ disable_irq_wake(irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* Functions implementing the pwm_chip methods
|
||||
*/
|
||||
static struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip)
|
||||
@@ -1219,7 +1247,7 @@ static int mvebu_gpio_probe(struct platf
|
||||
|
||||
err = irq_alloc_domain_generic_chips(
|
||||
mvchip->domain, ngpios, 2, np->name, handle_level_irq,
|
||||
- IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
|
||||
+ IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, IRQ_GC_INIT_NESTED_LOCK);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
|
||||
mvchip->chip.label);
|
||||
@@ -1237,6 +1265,8 @@ static int mvebu_gpio_probe(struct platf
|
||||
ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
|
||||
ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
|
||||
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
|
||||
+ ct->chip.irq_set_wake = mvebu_gpio_set_wake_irq;
|
||||
+ ct->chip.flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
|
||||
ct->chip.name = mvchip->chip.label;
|
||||
|
||||
ct = &gc->chip_types[1];
|
||||
@@ -1245,6 +1275,8 @@ static int mvebu_gpio_probe(struct platf
|
||||
ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
|
||||
ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
|
||||
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
|
||||
+ ct->chip.irq_set_wake = mvebu_gpio_set_wake_irq;
|
||||
+ ct->chip.flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
|
||||
ct->handler = handle_edge_irq;
|
||||
ct->chip.name = mvchip->chip.label;
|
||||
|
||||
@@ -1260,6 +1292,7 @@ static int mvebu_gpio_probe(struct platf
|
||||
continue;
|
||||
irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
|
||||
mvchip);
|
||||
+ mvchip->bank_irq[i] = irq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -0,0 +1,417 @@
|
||||
From e4728fcf779c37d1bcbd4b6505c9b40d4bb9ff48 Mon Sep 17 00:00:00 2001
|
||||
From: Heisath <jannis@imserv.org>
|
||||
Date: Thu, 03 Jun 2021 10:56:53 +0200
|
||||
Subject: [PATCH] Removes the hardcoded timer assignment of timers to pwm controllers
|
||||
This allows to use more than one pwm per gpio bank.
|
||||
|
||||
Original patch by helios4 team, updated to work on LK5.11+
|
||||
|
||||
Signed-off-by: Heisath <jannis@imserv.org>
|
||||
---
|
||||
|
||||
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
|
||||
index bad399e3f..d3fdaf177 100644
|
||||
--- a/drivers/gpio/gpio-mvebu.c
|
||||
+++ b/drivers/gpio/gpio-mvebu.c
|
||||
@@ -97,21 +97,42 @@
|
||||
|
||||
#define MVEBU_MAX_GPIO_PER_BANK 32
|
||||
|
||||
-struct mvebu_pwm {
|
||||
+enum mvebu_pwm_ctrl {
|
||||
+ MVEBU_PWM_CTRL_SET_A = 0,
|
||||
+ MVEBU_PWM_CTRL_SET_B,
|
||||
+ MVEBU_PWM_CTRL_MAX
|
||||
+};
|
||||
+
|
||||
+struct mvebu_pwmchip {
|
||||
struct regmap *regs;
|
||||
u32 offset;
|
||||
unsigned long clk_rate;
|
||||
- struct gpio_desc *gpiod;
|
||||
- struct pwm_chip chip;
|
||||
spinlock_t lock;
|
||||
- struct mvebu_gpio_chip *mvchip;
|
||||
+ bool in_use;
|
||||
|
||||
/* Used to preserve GPIO/PWM registers across suspend/resume */
|
||||
- u32 blink_select;
|
||||
u32 blink_on_duration;
|
||||
u32 blink_off_duration;
|
||||
};
|
||||
|
||||
+struct mvebu_pwm_chip_drv {
|
||||
+ enum mvebu_pwm_ctrl ctrl;
|
||||
+ struct gpio_desc *gpiod;
|
||||
+ bool master;
|
||||
+};
|
||||
+
|
||||
+struct mvebu_pwm {
|
||||
+ struct pwm_chip chip;
|
||||
+ struct mvebu_gpio_chip *mvchip;
|
||||
+ struct mvebu_pwmchip controller;
|
||||
+ enum mvebu_pwm_ctrl default_counter;
|
||||
+
|
||||
+ /* Used to preserve GPIO/PWM registers across suspend/resume */
|
||||
+ u32 blink_select;
|
||||
+};
|
||||
+
|
||||
+static struct mvebu_pwmchip *mvebu_pwm_list[MVEBU_PWM_CTRL_MAX];
|
||||
+
|
||||
struct mvebu_gpio_chip {
|
||||
struct gpio_chip chip;
|
||||
struct regmap *regs;
|
||||
@@ -288,12 +309,12 @@ mvebu_gpio_write_level_mask(struct mvebu_gpio_chip *mvchip, u32 val)
|
||||
* Functions returning offsets of individual registers for a given
|
||||
* PWM controller.
|
||||
*/
|
||||
-static unsigned int mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm)
|
||||
+static unsigned int mvebu_pwmreg_blink_on_duration(struct mvebu_pwmchip *mvpwm)
|
||||
{
|
||||
return mvpwm->offset + PWM_BLINK_ON_DURATION_OFF;
|
||||
}
|
||||
|
||||
-static unsigned int mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm)
|
||||
+static unsigned int mvebu_pwmreg_blink_off_duration(struct mvebu_pwmchip *mvpwm)
|
||||
{
|
||||
return mvpwm->offset + PWM_BLINK_OFF_DURATION_OFF;
|
||||
}
|
||||
@@ -653,39 +674,84 @@ static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
|
||||
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
|
||||
struct gpio_desc *desc;
|
||||
+ enum mvebu_pwm_ctrl id;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
+ struct mvebu_pwm_chip_drv *chip_data;
|
||||
|
||||
- spin_lock_irqsave(&mvpwm->lock, flags);
|
||||
+ spin_lock_irqsave(&mvpwm->controller.lock, flags);
|
||||
|
||||
- if (mvpwm->gpiod) {
|
||||
+ if (pwm->chip_data || (mvchip->blink_en_reg & BIT(pwm->hwpwm))) {
|
||||
ret = -EBUSY;
|
||||
- } else {
|
||||
- desc = gpiochip_request_own_desc(&mvchip->chip,
|
||||
- pwm->hwpwm, "mvebu-pwm",
|
||||
- GPIO_ACTIVE_HIGH,
|
||||
- GPIOD_OUT_LOW);
|
||||
- if (IS_ERR(desc)) {
|
||||
- ret = PTR_ERR(desc);
|
||||
- goto out;
|
||||
- }
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+
|
||||
+ desc = gpiochip_request_own_desc(&mvchip->chip,
|
||||
+ pwm->hwpwm, "mvebu-pwm",
|
||||
+ GPIO_ACTIVE_HIGH,
|
||||
+ GPIOD_OUT_LOW);
|
||||
+
|
||||
+ if (IS_ERR(desc)) {
|
||||
+ ret = PTR_ERR(desc);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ ret = gpiod_direction_output(desc, 0);
|
||||
+ if (ret) {
|
||||
+ gpiochip_free_own_desc(desc);
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- mvpwm->gpiod = desc;
|
||||
+ chip_data = kzalloc(sizeof(struct mvebu_pwm_chip_drv), GFP_KERNEL);
|
||||
+ if (!chip_data) {
|
||||
+ gpiochip_free_own_desc(desc);
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ for (id = MVEBU_PWM_CTRL_SET_A; id < MVEBU_PWM_CTRL_MAX; id++) {
|
||||
+ if (!mvebu_pwm_list[id]->in_use) {
|
||||
+ chip_data->ctrl = id;
|
||||
+ chip_data->master = true;
|
||||
+ mvebu_pwm_list[id]->in_use = true;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ if (!chip_data->master)
|
||||
+ chip_data->ctrl = mvpwm->default_counter;
|
||||
+
|
||||
+ regmap_update_bits(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset,
|
||||
+ BIT(pwm->hwpwm), chip_data->ctrl ? BIT(pwm->hwpwm) : 0);
|
||||
+
|
||||
+ chip_data->gpiod = desc;
|
||||
+ pwm->chip_data = chip_data;
|
||||
+
|
||||
+ regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset,
|
||||
+ &mvpwm->blink_select);
|
||||
+
|
||||
out:
|
||||
- spin_unlock_irqrestore(&mvpwm->lock, flags);
|
||||
+ spin_unlock_irqrestore(&mvpwm->controller.lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
|
||||
+ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data;
|
||||
unsigned long flags;
|
||||
|
||||
- spin_lock_irqsave(&mvpwm->lock, flags);
|
||||
- gpiochip_free_own_desc(mvpwm->gpiod);
|
||||
- mvpwm->gpiod = NULL;
|
||||
- spin_unlock_irqrestore(&mvpwm->lock, flags);
|
||||
+ spin_lock_irqsave(&mvpwm->controller.lock, flags);
|
||||
+ if (chip_data->master)
|
||||
+ mvebu_pwm_list[chip_data->ctrl]->in_use = false;
|
||||
+
|
||||
+
|
||||
+ gpiochip_free_own_desc(chip_data->gpiod);
|
||||
+ kfree(chip_data);
|
||||
+ pwm->chip_data = NULL;
|
||||
+ spin_unlock_irqrestore(&mvpwm->controller.lock, flags);
|
||||
}
|
||||
|
||||
static void mvebu_pwm_get_state(struct pwm_chip *chip,
|
||||
@@ -693,29 +759,36 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
|
||||
struct pwm_state *state) {
|
||||
|
||||
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
|
||||
+ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data;
|
||||
+ struct mvebu_pwmchip *controller;
|
||||
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
|
||||
unsigned long long val;
|
||||
unsigned long flags;
|
||||
u32 u;
|
||||
|
||||
- spin_lock_irqsave(&mvpwm->lock, flags);
|
||||
+ if (chip_data)
|
||||
+ controller = mvebu_pwm_list[chip_data->ctrl];
|
||||
+ else
|
||||
+ controller = &mvpwm->controller;
|
||||
+
|
||||
+ spin_lock_irqsave(&controller->lock, flags);
|
||||
|
||||
- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), &u);
|
||||
+ regmap_read(controller->regs, mvebu_pwmreg_blink_on_duration(controller), &u);
|
||||
/* Hardware treats zero as 2^32. See mvebu_pwm_apply(). */
|
||||
if (u > 0)
|
||||
val = u;
|
||||
else
|
||||
val = UINT_MAX + 1ULL;
|
||||
state->duty_cycle = DIV_ROUND_UP_ULL(val * NSEC_PER_SEC,
|
||||
- mvpwm->clk_rate);
|
||||
+ controller->clk_rate);
|
||||
|
||||
- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
|
||||
+ regmap_read(controller->regs, mvebu_pwmreg_blink_off_duration(controller), &u);
|
||||
/* period = on + off duration */
|
||||
if (u > 0)
|
||||
val += u;
|
||||
else
|
||||
val += UINT_MAX + 1ULL;
|
||||
- state->period = DIV_ROUND_UP_ULL(val * NSEC_PER_SEC, mvpwm->clk_rate);
|
||||
+ state->period = DIV_ROUND_UP_ULL(val * NSEC_PER_SEC, controller->clk_rate);
|
||||
|
||||
regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u);
|
||||
if (u)
|
||||
@@ -796,13 +796,15 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
|
||||
else
|
||||
state->enabled = false;
|
||||
|
||||
- spin_unlock_irqrestore(&mvpwm->lock, flags);
|
||||
+ spin_unlock_irqrestore(&controller->lock, flags);
|
||||
}
|
||||
|
||||
static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
const struct pwm_state *state)
|
||||
{
|
||||
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
|
||||
+ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data;
|
||||
+ struct mvebu_pwmchip *controller;
|
||||
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
|
||||
unsigned long long val;
|
||||
unsigned long flags;
|
||||
@@ -811,7 +813,12 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
if (state->polarity != PWM_POLARITY_NORMAL)
|
||||
return -EINVAL;
|
||||
|
||||
- val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle;
|
||||
+ if (chip_data)
|
||||
+ controller = mvebu_pwm_list[chip_data->ctrl];
|
||||
+ else
|
||||
+ controller = &mvpwm->controller;
|
||||
+
|
||||
+ val = (unsigned long long) controller->clk_rate * state->duty_cycle;
|
||||
do_div(val, NSEC_PER_SEC);
|
||||
if (val > UINT_MAX + 1ULL)
|
||||
return -EINVAL;
|
||||
@@ -750,7 +830,7 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
else
|
||||
on = 1;
|
||||
|
||||
- val = (unsigned long long) mvpwm->clk_rate * state->period;
|
||||
+ val = (unsigned long long) controller->clk_rate * state->period;
|
||||
do_div(val, NSEC_PER_SEC);
|
||||
val -= on;
|
||||
if (val > UINT_MAX + 1ULL)
|
||||
@@ -762,16 +842,16 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
else
|
||||
off = 1;
|
||||
|
||||
- spin_lock_irqsave(&mvpwm->lock, flags);
|
||||
+ spin_lock_irqsave(&controller->lock, flags);
|
||||
|
||||
- regmap_write(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), on);
|
||||
- regmap_write(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), off);
|
||||
+ regmap_write(controller->regs, mvebu_pwmreg_blink_on_duration(controller), on);
|
||||
+ regmap_write(controller->regs, mvebu_pwmreg_blink_off_duration(controller), off);
|
||||
if (state->enabled)
|
||||
mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1);
|
||||
else
|
||||
mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0);
|
||||
|
||||
- spin_unlock_irqrestore(&mvpwm->lock, flags);
|
||||
+ spin_unlock_irqrestore(&controller->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -787,25 +867,27 @@ static const struct pwm_ops mvebu_pwm_ops = {
|
||||
static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
|
||||
{
|
||||
struct mvebu_pwm *mvpwm = mvchip->mvpwm;
|
||||
+ struct mvebu_pwmchip *controller = &mvpwm->controller;
|
||||
|
||||
regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset,
|
||||
&mvpwm->blink_select);
|
||||
- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm),
|
||||
- &mvpwm->blink_on_duration);
|
||||
- regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm),
|
||||
- &mvpwm->blink_off_duration);
|
||||
+ regmap_read(controller->regs, mvebu_pwmreg_blink_on_duration(controller),
|
||||
+ &controller->blink_on_duration);
|
||||
+ regmap_read(controller->regs, mvebu_pwmreg_blink_off_duration(controller),
|
||||
+ &controller->blink_off_duration);
|
||||
}
|
||||
|
||||
static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
|
||||
{
|
||||
struct mvebu_pwm *mvpwm = mvchip->mvpwm;
|
||||
+ struct mvebu_pwmchip *controller = &mvpwm->controller;
|
||||
|
||||
regmap_write(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset,
|
||||
mvpwm->blink_select);
|
||||
- regmap_write(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm),
|
||||
- mvpwm->blink_on_duration);
|
||||
- regmap_write(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm),
|
||||
- mvpwm->blink_off_duration);
|
||||
+ regmap_write(controller->regs, mvebu_pwmreg_blink_on_duration(controller),
|
||||
+ controller->blink_on_duration);
|
||||
+ regmap_write(controller->regs, mvebu_pwmreg_blink_off_duration(controller),
|
||||
+ controller->blink_off_duration);
|
||||
}
|
||||
|
||||
static int mvebu_pwm_probe(struct platform_device *pdev,
|
||||
@@ -902,6 +902,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
|
||||
void __iomem *base;
|
||||
u32 offset;
|
||||
u32 set;
|
||||
+ enum mvebu_pwm_ctrl ctrl_set;
|
||||
|
||||
if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
|
||||
int ret = of_property_read_u32(dev->of_node,
|
||||
@@ -844,54 +920,39 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
|
||||
mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
|
||||
if (!mvpwm)
|
||||
return -ENOMEM;
|
||||
+
|
||||
mvchip->mvpwm = mvpwm;
|
||||
mvpwm->mvchip = mvchip;
|
||||
- mvpwm->offset = offset;
|
||||
+
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource_byname(pdev, "pwm");
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
|
||||
- if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
|
||||
- mvpwm->regs = mvchip->regs;
|
||||
+ mvpwm->controller.regs = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
+ &mvebu_gpio_regmap_config);
|
||||
+ if (IS_ERR(mvpwm->controller.regs))
|
||||
+ return PTR_ERR(mvpwm->controller.regs);
|
||||
|
||||
- switch (mvchip->offset) {
|
||||
- case AP80X_GPIO0_OFF_A8K:
|
||||
- case CP11X_GPIO0_OFF_A8K:
|
||||
- /* Blink counter A */
|
||||
- set = 0;
|
||||
- break;
|
||||
- case CP11X_GPIO1_OFF_A8K:
|
||||
- /* Blink counter B */
|
||||
- set = U32_MAX;
|
||||
- mvpwm->offset += PWM_BLINK_COUNTER_B_OFF;
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
+ /*
|
||||
+ * Use set A for lines of GPIO chip with id 0, B for GPIO chip
|
||||
+ * with id 1. Don't allow further GPIO chips to be used for PWM.
|
||||
+ */
|
||||
+ if (id == 0) {
|
||||
+ set = 0;
|
||||
+ ctrl_set = MVEBU_PWM_CTRL_SET_A;
|
||||
+ } else if (id == 1) {
|
||||
+ set = U32_MAX;
|
||||
+ ctrl_set = MVEBU_PWM_CTRL_SET_B;
|
||||
} else {
|
||||
- base = devm_platform_ioremap_resource_byname(pdev, "pwm");
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
-
|
||||
- mvpwm->regs = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
- &mvebu_gpio_regmap_config);
|
||||
- if (IS_ERR(mvpwm->regs))
|
||||
- return PTR_ERR(mvpwm->regs);
|
||||
-
|
||||
- /*
|
||||
- * Use set A for lines of GPIO chip with id 0, B for GPIO chip
|
||||
- * with id 1. Don't allow further GPIO chips to be used for PWM.
|
||||
- */
|
||||
- if (id == 0)
|
||||
- set = 0;
|
||||
- else if (id == 1)
|
||||
- set = U32_MAX;
|
||||
- else
|
||||
- return -EINVAL;
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_write(mvchip->regs,
|
||||
GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set);
|
||||
|
||||
- mvpwm->clk_rate = clk_get_rate(mvchip->clk);
|
||||
- if (!mvpwm->clk_rate) {
|
||||
+ mvpwm->controller.clk_rate = clk_get_rate(mvchip->clk);
|
||||
+ if (!mvpwm->controller.clk_rate) {
|
||||
dev_err(dev, "failed to get clock rate\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -907,7 +968,10 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
|
||||
*/
|
||||
mvpwm->chip.base = -1;
|
||||
|
||||
- spin_lock_init(&mvpwm->lock);
|
||||
+ spin_lock_init(&mvpwm->controller.lock);
|
||||
+
|
||||
+ mvpwm->default_counter = ctrl_set;
|
||||
+ mvebu_pwm_list[ctrl_set] = &mvpwm->controller;
|
||||
|
||||
return pwmchip_add(&mvpwm->chip);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
--- a/arch/arm/boot/dts/armada-388-helios4.dts
|
||||
+++ b/arch/arm/boot/dts/armada-388-helios4.dts
|
||||
@@ -84,6 +84,18 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys";
|
||||
+ pinctrl-0 = <µsom_phy0_int_pins>;
|
||||
+
|
||||
+ wol {
|
||||
+ label = "Wake-On-LAN";
|
||||
+ linux,code = <KEY_WAKEUP>;
|
||||
+ gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
|
||||
+ wakeup-source;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
io-leds {
|
||||
compatible = "gpio-leds";
|
||||
sata1-led {
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/scripts/Makefile.lib
|
||||
+++ b/scripts/Makefile.lib
|
||||
@@ -277,6 +277,9 @@ quiet_cmd_gzip = GZIP $@
|
||||
DTC ?= $(objtree)/scripts/dtc/dtc
|
||||
DTC_FLAGS += -Wno-interrupt_provider
|
||||
|
||||
+# Enable overlay support
|
||||
+DTC_FLAGS += -@
|
||||
+
|
||||
# Disable noisy checks by default
|
||||
ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
|
||||
DTC_FLAGS += -Wno-unit_address_vs_reg \
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi
|
||||
+++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi
|
||||
@@ -107,6 +107,7 @@
|
||||
compatible = "w25q32", "jedec,spi-nor";
|
||||
reg = <0>; /* Chip select 0 */
|
||||
spi-max-frequency = <3000000>;
|
||||
+ status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/arch/arm/mm/dma-mapping.c
|
||||
+++ b/arch/arm/mm/dma-mapping.c
|
||||
@@ -315,7 +315,7 @@ static void *__alloc_remap_buffer(struct
|
||||
pgprot_t prot, struct page **ret_page,
|
||||
const void *caller, bool want_vaddr);
|
||||
|
||||
-#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
|
||||
+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_2M
|
||||
static struct gen_pool *atomic_pool __ro_after_init;
|
||||
|
||||
static size_t atomic_pool_size __initdata = DEFAULT_DMA_COHERENT_POOL_SIZE;
|
||||
@@ -0,0 +1,70 @@
|
||||
--- a/drivers/net/wireless/ath/regd.c
|
||||
+++ b/drivers/net/wireless/ath/regd.c
|
||||
@@ -50,12 +50,9 @@ static int __ath_regd_init(struct ath_re
|
||||
#define ATH_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\
|
||||
NL80211_RRF_NO_IR)
|
||||
|
||||
-#define ATH_2GHZ_ALL ATH_2GHZ_CH01_11, \
|
||||
- ATH_2GHZ_CH12_13, \
|
||||
- ATH_2GHZ_CH14
|
||||
+#define ATH_2GHZ_ALL REG_RULE(2400, 2483, 40, 0, 30, 0)
|
||||
|
||||
-#define ATH_5GHZ_ALL ATH_5GHZ_5150_5350, \
|
||||
- ATH_5GHZ_5470_5850
|
||||
+#define ATH_5GHZ_ALL REG_RULE(5140, 5860, 40, 0, 30, 0)
|
||||
|
||||
/* This one skips what we call "mid band" */
|
||||
#define ATH_5GHZ_NO_MIDBAND ATH_5GHZ_5150_5350, \
|
||||
@@ -77,9 +74,8 @@ static const struct ieee80211_regdomain
|
||||
.n_reg_rules = 4,
|
||||
.alpha2 = "99",
|
||||
.reg_rules = {
|
||||
- ATH_2GHZ_CH01_11,
|
||||
- ATH_2GHZ_CH12_13,
|
||||
- ATH_5GHZ_NO_MIDBAND,
|
||||
+ ATH_2GHZ_ALL,
|
||||
+ ATH_5GHZ_ALL,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,8 +84,8 @@ static const struct ieee80211_regdomain
|
||||
.n_reg_rules = 3,
|
||||
.alpha2 = "99",
|
||||
.reg_rules = {
|
||||
- ATH_2GHZ_CH01_11,
|
||||
- ATH_5GHZ_NO_MIDBAND,
|
||||
+ ATH_2GHZ_ALL,
|
||||
+ ATH_5GHZ_ALL,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,7 +94,7 @@ static const struct ieee80211_regdomain
|
||||
.n_reg_rules = 3,
|
||||
.alpha2 = "99",
|
||||
.reg_rules = {
|
||||
- ATH_2GHZ_CH01_11,
|
||||
+ ATH_2GHZ_ALL,
|
||||
ATH_5GHZ_ALL,
|
||||
}
|
||||
};
|
||||
@@ -108,8 +104,7 @@ static const struct ieee80211_regdomain
|
||||
.n_reg_rules = 4,
|
||||
.alpha2 = "99",
|
||||
.reg_rules = {
|
||||
- ATH_2GHZ_CH01_11,
|
||||
- ATH_2GHZ_CH12_13,
|
||||
+ ATH_2GHZ_ALL,
|
||||
ATH_5GHZ_ALL,
|
||||
}
|
||||
};
|
||||
@@ -258,9 +253,7 @@ static bool ath_is_radar_freq(u16 center
|
||||
struct ath_regulatory *reg)
|
||||
|
||||
{
|
||||
- if (reg->country_code == CTRY_INDIA)
|
||||
- return (center_freq >= 5500 && center_freq <= 5700);
|
||||
- return (center_freq >= 5260 && center_freq <= 5700);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
static void ath_force_clear_no_ir_chan(struct wiphy *wiphy,
|
||||
@@ -0,0 +1,39 @@
|
||||
From 219f80b5cc03dab87fd05210b95c0b1a5afa8d33 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 14 Jul 2016 15:31:42 +0100
|
||||
Subject: ARM: dts: armada388-clearfog: use 1000BaseX mode for 88e6176 switch
|
||||
|
||||
Use 1000BaseX mode for the 88e6176 switch, which allows mvneta to
|
||||
negotiate correctly without needing to be forced.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
arch/arm/boot/dts/armada-388-clearfog.dts | 10 ++--------
|
||||
1 file changed, 2 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/armada-388-clearfog.dts
|
||||
+++ b/arch/arm/boot/dts/armada-388-clearfog.dts
|
||||
@@ -47,10 +47,8 @@
|
||||
|
||||
ð1 {
|
||||
/* ethernet@30000 */
|
||||
- fixed-link {
|
||||
- speed = <1000>;
|
||||
- full-duplex;
|
||||
- };
|
||||
+ phy-mode = "1000base-x";
|
||||
+ managed = "in-band-status";
|
||||
};
|
||||
|
||||
&expander0 {
|
||||
@@ -131,10 +129,6 @@
|
||||
reg = <5>;
|
||||
label = "cpu";
|
||||
ethernet = <ð1>;
|
||||
- fixed-link {
|
||||
- speed = <1000>;
|
||||
- full-duplex;
|
||||
- };
|
||||
};
|
||||
|
||||
port@6 {
|
||||
@@ -1 +1 @@
|
||||
archive/mvebu-5.16
|
||||
archive/mvebu-6.1/
|
||||
Reference in New Issue
Block a user