lede/target/linux/phytium/patches-5.10/001-add-phytium-support.patch
2024-05-05 14:25:06 +08:00

5103 lines
156 KiB
Diff

--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3919,6 +3919,10 @@
force Enable ASPM even on devices that claim not to support it.
WARNING: Forcing ASPM on may cause system lockups.
+ pcie_hp= [PCIE] PCI Express Hotplug driver options:
+ nomsi Do not use MSI for PCI Express Native Hotplug (this
+ makes all PCIe ports use INTx for hotplug services).
+
pcie_ports= [PCIE] PCIe port services handling:
native Use native PCIe services (PME, AER, DPC, PCIe hotplug)
even if the platform doesn't give the OS permission to
--- a/Documentation/devicetree/bindings/arm/cpus.yaml
+++ b/Documentation/devicetree/bindings/arm/cpus.yaml
@@ -162,6 +162,10 @@ properties:
- nvidia,tegra132-denver
- nvidia,tegra186-denver
- nvidia,tegra194-carmel
+ - phytium,ftc660
+ - phytium,ftc661
+ - phytium,ftc662
+ - phytium,ftc663
- qcom,krait
- qcom,kryo
- qcom,kryo260
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -16,6 +16,8 @@ Required properties:
Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
Use "sifive,fu540-c000-gem" for SiFive FU540-C000 SoC.
+ Use "cdns,phytium-gem-1.0" for GEM version 1.0 on Phytium SoCs
+ Use "cdns,phytium-gem-2.0" for GEM version 2.0 on Phytium SoCs
Or the generic form: "cdns,emac".
- reg: Address and length of the register set for the device
For "sifive,fu540-c000-gem", second range is required to specify the
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -56,6 +56,7 @@ properties:
- amlogic,meson8m2-dwmac
- amlogic,meson-gxbb-dwmac
- amlogic,meson-axg-dwmac
+ - phytium,gmac
- snps,dwmac
- snps,dwmac-3.50a
- snps,dwmac-3.610
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -7,6 +7,7 @@
#include <asm/hwcap.h>
#include <linux/clocksource.h>
#include <linux/init.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/types.h>
#include <clocksource/arm_arch_timer.h>
@@ -24,29 +25,35 @@ int arch_timer_arch_init(void);
* the code. At least it does so with a recent GCC (4.6.3).
*/
static __always_inline
-void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val)
+void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u64 val)
{
if (access == ARCH_TIMER_PHYS_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
- asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
+ asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" ((u32)val));
+ isb();
break;
- case ARCH_TIMER_REG_TVAL:
- asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
+ case ARCH_TIMER_REG_CVAL:
+ asm volatile("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val));
break;
+ default:
+ BUILD_BUG();
}
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
- asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
+ asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" ((u32)val));
+ isb();
break;
- case ARCH_TIMER_REG_TVAL:
- asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
+ case ARCH_TIMER_REG_CVAL:
+ asm volatile("mcrr p15, 3, %Q0, %R0, c14" : : "r" (val));
break;
+ default:
+ BUILD_BUG();
}
+ } else {
+ BUILD_BUG();
}
-
- isb();
}
static __always_inline
@@ -59,19 +66,19 @@ u32 arch_timer_reg_read_cp15(int access,
case ARCH_TIMER_REG_CTRL:
asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
break;
- case ARCH_TIMER_REG_TVAL:
- asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
- break;
+ default:
+ BUILD_BUG();
}
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
break;
- case ARCH_TIMER_REG_TVAL:
- asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
- break;
+ default:
+ BUILD_BUG();
}
+ } else {
+ BUILD_BUG();
}
return val;
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -327,4 +327,9 @@ config ARCH_ZYNQMP
help
This enables support for Xilinx ZynqMP Family
+config ARCH_PHYTIUM
+ bool "Phytium SoC Family"
+ help
+ This enables support for Phytium ARMv8 SoC family.
+
endmenu
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -30,3 +30,4 @@ subdir-y += ti
subdir-y += toshiba
subdir-y += xilinx
subdir-y += zte
+subdir-y += phytium
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -32,7 +32,7 @@
({ \
const struct arch_timer_erratum_workaround *__wa; \
__wa = __this_cpu_read(timer_unstable_counter_workaround); \
- (__wa && __wa->h) ? __wa->h : arch_timer_##h; \
+ (__wa && __wa->h) ? ({ isb(); __wa->h;}) : arch_timer_##h; \
})
#else
@@ -52,8 +52,6 @@ struct arch_timer_erratum_workaround {
enum arch_timer_erratum_match_type match_type;
const void *id;
const char *desc;
- u32 (*read_cntp_tval_el0)(void);
- u32 (*read_cntv_tval_el0)(void);
u64 (*read_cntpct_el0)(void);
u64 (*read_cntvct_el0)(void);
int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
@@ -64,25 +62,28 @@ struct arch_timer_erratum_workaround {
DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
timer_unstable_counter_workaround);
-/* inline sysreg accessors that make erratum_handler() work */
-static inline notrace u32 arch_timer_read_cntp_tval_el0(void)
+static inline notrace u64 arch_timer_read_cntpct_el0(void)
{
- return read_sysreg(cntp_tval_el0);
-}
+ u64 cnt;
-static inline notrace u32 arch_timer_read_cntv_tval_el0(void)
-{
- return read_sysreg(cntv_tval_el0);
-}
+ asm volatile(ALTERNATIVE("isb\n mrs %0, cntpct_el0",
+ "nop\n" __mrs_s("%0", SYS_CNTPCTSS_EL0),
+ ARM64_HAS_ECV)
+ : "=r" (cnt));
-static inline notrace u64 arch_timer_read_cntpct_el0(void)
-{
- return read_sysreg(cntpct_el0);
+ return cnt;
}
static inline notrace u64 arch_timer_read_cntvct_el0(void)
{
- return read_sysreg(cntvct_el0);
+ u64 cnt;
+
+ asm volatile(ALTERNATIVE("isb\n mrs %0, cntvct_el0",
+ "nop\n" __mrs_s("%0", SYS_CNTVCTSS_EL0),
+ ARM64_HAS_ECV)
+ : "=r" (cnt));
+
+ return cnt;
}
#define arch_timer_reg_read_stable(reg) \
@@ -102,51 +103,58 @@ static inline notrace u64 arch_timer_rea
* the code.
*/
static __always_inline
-void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val)
+void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u64 val)
{
if (access == ARCH_TIMER_PHYS_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
write_sysreg(val, cntp_ctl_el0);
+ isb();
break;
- case ARCH_TIMER_REG_TVAL:
- write_sysreg(val, cntp_tval_el0);
+ case ARCH_TIMER_REG_CVAL:
+ write_sysreg(val, cntp_cval_el0);
break;
+ default:
+ BUILD_BUG();
}
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
write_sysreg(val, cntv_ctl_el0);
+ isb();
break;
- case ARCH_TIMER_REG_TVAL:
- write_sysreg(val, cntv_tval_el0);
+ case ARCH_TIMER_REG_CVAL:
+ write_sysreg(val, cntv_cval_el0);
break;
+ default:
+ BUILD_BUG();
}
+ } else {
+ BUILD_BUG();
}
-
- isb();
}
static __always_inline
-u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
+u64 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
{
if (access == ARCH_TIMER_PHYS_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
return read_sysreg(cntp_ctl_el0);
- case ARCH_TIMER_REG_TVAL:
- return arch_timer_reg_read_stable(cntp_tval_el0);
+ default:
+ BUILD_BUG();
}
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
return read_sysreg(cntv_ctl_el0);
- case ARCH_TIMER_REG_TVAL:
- return arch_timer_reg_read_stable(cntv_tval_el0);
+ default:
+ BUILD_BUG();
}
}
- BUG();
+ BUILD_BUG();
+ unreachable();
}
static inline u32 arch_timer_get_cntfrq(void)
@@ -169,7 +177,6 @@ static __always_inline u64 __arch_counte
{
u64 cnt;
- isb();
cnt = arch_timer_reg_read_stable(cntpct_el0);
arch_counter_enforce_ordering(cnt);
return cnt;
@@ -179,8 +186,10 @@ static __always_inline u64 __arch_counte
{
u64 cnt;
- isb();
- cnt = read_sysreg(cntpct_el0);
+ asm volatile(ALTERNATIVE("isb\n mrs %0, cntpct_el0",
+ "nop\n" __mrs_s("%0", SYS_CNTPCTSS_EL0),
+ ARM64_HAS_ECV)
+ : "=r" (cnt));
arch_counter_enforce_ordering(cnt);
return cnt;
}
@@ -189,7 +198,6 @@ static __always_inline u64 __arch_counte
{
u64 cnt;
- isb();
cnt = arch_timer_reg_read_stable(cntvct_el0);
arch_counter_enforce_ordering(cnt);
return cnt;
@@ -199,8 +207,10 @@ static __always_inline u64 __arch_counte
{
u64 cnt;
- isb();
- cnt = read_sysreg(cntvct_el0);
+ asm volatile(ALTERNATIVE("isb\n mrs %0, cntvct_el0",
+ "nop\n" __mrs_s("%0", SYS_CNTVCTSS_EL0),
+ ARM64_HAS_ECV)
+ : "=r" (cnt));
arch_counter_enforce_ordering(cnt);
return cnt;
}
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -69,7 +69,7 @@
#define ARM64_SPECTRE_BHB 59
#define ARM64_WORKAROUND_2457168 60
#define ARM64_WORKAROUND_1742098 61
-
-#define ARM64_NCAPS 62
+#define ARM64_HAS_ECV 62
+#define ARM64_NCAPS 63
#endif /* __ASM_CPUCAPS_H */
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -227,6 +227,9 @@
#define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
ESR_ELx_SYS64_ISS_DIR_READ)
+#define ESR_ELx_SYS64_ISS_SYS_CNTVCTSS (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 6, 14, 0) | \
+ ESR_ELx_SYS64_ISS_DIR_READ)
+
#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \
ESR_ELx_SYS64_ISS_DIR_READ)
@@ -317,6 +320,9 @@
#define ESR_ELx_CP15_64_ISS_SYS_CNTVCT (ESR_ELx_CP15_64_ISS_SYS_VAL(1, 14) | \
ESR_ELx_CP15_64_ISS_DIR_READ)
+#define ESR_ELx_CP15_64_ISS_SYS_CNTVCTSS (ESR_ELx_CP15_64_ISS_SYS_VAL(9, 14) | \
+ ESR_ELx_CP15_64_ISS_DIR_READ)
+
#define ESR_ELx_CP15_32_ISS_SYS_CNTFRQ (ESR_ELx_CP15_32_ISS_SYS_VAL(0, 0, 14, 0) |\
ESR_ELx_CP15_32_ISS_DIR_READ)
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -453,6 +453,9 @@
#define SYS_CNTFRQ_EL0 sys_reg(3, 3, 14, 0, 0)
+#define SYS_CNTPCTSS_EL0 sys_reg(3, 3, 14, 0, 5)
+#define SYS_CNTVCTSS_EL0 sys_reg(3, 3, 14, 0, 6)
+
#define SYS_CNTP_TVAL_EL0 sys_reg(3, 3, 14, 2, 0)
#define SYS_CNTP_CTL_EL0 sys_reg(3, 3, 14, 2, 1)
#define SYS_CNTP_CVAL_EL0 sys_reg(3, 3, 14, 2, 2)
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1769,6 +1769,16 @@ static const struct arm64_cpu_capabiliti
.sign = FTR_UNSIGNED,
.min_field_value = 1,
},
+ {
+ .desc = "Enhanced Counter Virtualization",
+ .capability = ARM64_HAS_ECV,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .matches = has_cpuid_feature,
+ .sys_reg = SYS_ID_AA64MMFR0_EL1,
+ .field_pos = ID_AA64MMFR0_ECV_SHIFT,
+ .sign = FTR_UNSIGNED,
+ .min_field_value = 1,
+ },
#ifdef CONFIG_ARM64_PAN
{
.desc = "Privileged Access Never",
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -553,6 +553,12 @@ static const struct sys64_hook sys64_hoo
.handler = cntvct_read_handler,
},
{
+ /* Trap read access to CNTVCTSS_EL0 */
+ .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK,
+ .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTVCTSS,
+ .handler = cntvct_read_handler,
+ },
+ {
/* Trap read access to CNTFRQ_EL0 */
.esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK,
.esr_val = ESR_ELx_SYS64_ISS_SYS_CNTFRQ,
@@ -628,6 +634,11 @@ static const struct sys64_hook cp15_64_h
.esr_val = ESR_ELx_CP15_64_ISS_SYS_CNTVCT,
.handler = compat_cntvct_read_handler,
},
+ {
+ .esr_mask = ESR_ELx_CP15_64_ISS_SYS_MASK,
+ .esr_val = ESR_ELx_CP15_64_ISS_SYS_CNTVCTSS,
+ .handler = compat_cntvct_read_handler,
+ },
{},
};
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -78,6 +78,8 @@ EXPORT_SYMBOL(flush_dcache_page);
* Additional functions defined in assembly.
*/
EXPORT_SYMBOL(__flush_icache_range);
+EXPORT_SYMBOL(__flush_dcache_area);
+EXPORT_SYMBOL(__inval_dcache_area);
#ifdef CONFIG_ARCH_HAS_PMEM_API
void arch_wb_cache_pmem(void *addr, size_t size)
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -158,6 +158,16 @@ static const struct apd_device_desc hip0
.fixed_clk_rate = 125000000,
};
+static const struct apd_device_desc phytium_i2c_desc = {
+ .setup = acpi_apd_setup,
+ .fixed_clk_rate = 200000000,
+};
+
+static const struct apd_device_desc phytium_pe220x_i2c_desc = {
+ .setup = acpi_apd_setup,
+ .fixed_clk_rate = 50000000,
+};
+
static const struct apd_device_desc thunderx2_i2c_desc = {
.setup = acpi_apd_setup,
.fixed_clk_rate = 125000000,
@@ -240,6 +250,8 @@ static const struct acpi_device_id acpi_
{ "HISI02A2", APD_ADDR(hip08_i2c_desc) },
{ "HISI02A3", APD_ADDR(hip08_lite_i2c_desc) },
{ "HISI0173", APD_ADDR(hip08_spi_desc) },
+ { "PHYT0003", APD_ADDR(phytium_i2c_desc) },
+ { "PHYT0038", APD_ADDR(phytium_pe220x_i2c_desc) },
{ "NXP0001", APD_ADDR(nxp_i2c_desc) },
#endif
{ }
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -90,6 +90,18 @@ bool acpi_scan_is_offline(struct acpi_de
acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context);
void acpi_scan_table_handler(u32 event, void *table, void *context);
+#ifdef CONFIG_ACPI_GENERIC_GSI
+int acpi_register_irq(struct device *dev, u32 hwirq, int trigger,
+ int polarity, struct fwnode_handle *fwnode);
+#else
+static inline
+int acpi_register_irq(struct device *dev, u32 hwirq, int trigger,
+ int polarity, struct fwnode_handle *fwnode)
+{
+ return acpi_register_gsi(dev, hwirq, trigger, polarity);
+}
+#endif
+
/* --------------------------------------------------------------------------
Device Node Initialization / Removal
-------------------------------------------------------------------------- */
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -10,6 +10,8 @@
#include <linux/irqdomain.h>
#include <linux/of.h>
+#include "internal.h"
+
enum acpi_irq_model_id acpi_irq_model;
static struct fwnode_handle *acpi_gsi_domain_id;
@@ -38,29 +40,19 @@ int acpi_gsi_to_irq(u32 gsi, unsigned in
}
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
-/**
- * acpi_register_gsi() - Map a GSI to a linux IRQ number
- * @dev: device for which IRQ has to be mapped
- * @gsi: GSI IRQ number
- * @trigger: trigger type of the GSI number to be mapped
- * @polarity: polarity of the GSI to be mapped
- *
- * Returns: a valid linux IRQ number on success
- * -EINVAL on failure
- */
-int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
- int polarity)
+int acpi_register_irq(struct device *dev, u32 hwirq, int trigger,
+ int polarity, struct fwnode_handle *fwnode)
{
struct irq_fwspec fwspec;
unsigned int irq;
- if (WARN_ON(!acpi_gsi_domain_id)) {
- pr_warn("GSI: No registered irqchip, giving up\n");
+ if (!fwnode) {
+ dev_warn(dev, "No registered irqchip for hwirq %d\n", hwirq);
return -EINVAL;
}
- fwspec.fwnode = acpi_gsi_domain_id;
- fwspec.param[0] = gsi;
+ fwspec.fwnode = fwnode;
+ fwspec.param[0] = hwirq;
fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
fwspec.param_count = 2;
@@ -70,6 +62,22 @@ int acpi_register_gsi(struct device *dev
return irq;
}
+
+/**
+ * acpi_register_gsi() - Map a GSI to a linux IRQ number
+ * @dev: device for which IRQ has to be mapped
+ * @gsi: GSI IRQ number
+ * @trigger: trigger type of the GSI number to be mapped
+ * @polarity: polarity of the GSI to be mapped
+ *
+ * Returns: a valid linux IRQ number on success
+ * -EINVAL on failure
+ */
+int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity)
+{
+ return acpi_register_irq(dev, gsi, trigger, polarity, acpi_gsi_domain_id);
+}
EXPORT_SYMBOL_GPL(acpi_register_gsi);
/**
@@ -97,7 +105,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
* Return:
* The referenced device fwhandle or NULL on failure
*/
-static struct fwnode_handle *
+struct fwnode_handle *
acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
{
struct fwnode_handle *result;
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -22,6 +22,8 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
+#include "internal.h"
+
#define PREFIX "ACPI: "
#define _COMPONENT ACPI_PCI_COMPONENT
@@ -410,6 +412,7 @@ int acpi_pci_irq_enable(struct pci_dev *
char *link = NULL;
char link_desc[16];
int rc;
+ struct fwnode_handle *rs_fwnode;
pin = dev->pin;
if (!pin) {
@@ -438,7 +441,8 @@ int acpi_pci_irq_enable(struct pci_dev *
gsi = acpi_pci_link_allocate_irq(entry->link,
entry->index,
&triggering, &polarity,
- &link);
+ &link,
+ &rs_fwnode);
else
gsi = entry->index;
} else
@@ -462,7 +466,7 @@ int acpi_pci_irq_enable(struct pci_dev *
return 0;
}
- rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
+ rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, rs_fwnode);
if (rc < 0) {
dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
pin_name(pin));
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
u8 resource_type;
u8 possible_count;
u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+ struct acpi_resource_source resource_source;
u8 initialized:1;
u8 reserved:7;
};
@@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_p
{
struct acpi_resource_extended_irq *p =
&resource->data.extended_irq;
+ struct acpi_resource_source *rs =
+ &link->irq.resource_source;
if (!p || !p->interrupt_count) {
printk(KERN_WARNING PREFIX
"Blank _PRS EXT IRQ resource\n");
@@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_p
link->irq.triggering = p->triggering;
link->irq.polarity = p->polarity;
link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
+ if (p->resource_source.string_length) {
+ rs->index = p->resource_source.index;
+ rs->string_length = p->resource_source.string_length;
+ rs->string_ptr = kstrdup(p->resource_source.string_ptr,
+ GFP_KERNEL);
+ }
break;
}
default:
@@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi
resource->res.data.extended_irq.shareable = ACPI_SHARED;
resource->res.data.extended_irq.interrupt_count = 1;
resource->res.data.extended_irq.interrupts[0] = irq;
- /* ignore resource_source, it's optional */
+ resource->res.data.extended_irq.resource_source =
+ link->irq.resource_source;
break;
default:
printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
@@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct
* failure: return -1
*/
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
- int *polarity, char **name)
+ int *polarity, char **name, struct fwnode_handle **rs_fwnode)
{
int result;
struct acpi_device *device;
@@ -656,6 +666,8 @@ int acpi_pci_link_allocate_irq(acpi_hand
*polarity = link->irq.polarity;
if (name)
*name = acpi_device_bid(link->device);
+ if (rs_fwnode)
+ *rs_fwnode = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Link %s is referenced\n",
acpi_device_bid(link->device)));
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -536,6 +536,18 @@ config HW_RANDOM_XIPHERA
To compile this driver as a module, choose M here: the
module will be called xiphera-trng.
+config HW_RANDOM_PHYTIUM
+ tristate "Phytium Random Number Generator support"
+ depends on ARCH_PHYTIUM || COMPILE_TEST
+ help
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Phytium SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called phytium-rng.
+
+ If unsure, say Y.
+
endif # HW_RANDOM
config UML_RANDOM
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -46,3 +46,5 @@ obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-r
obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.o
obj-$(CONFIG_HW_RANDOM_CCTRNG) += cctrng.o
obj-$(CONFIG_HW_RANDOM_XIPHERA) += xiphera-trng.o
+
+obj-$(CONFIG_HW_RANDOM_PHYTIUM) += phytium-rng.o
\ No newline at end of file
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -109,6 +109,27 @@ config ASPEED_KCS_IPMI_BMC
The driver implements the BMC side of the KCS contorller, it
provides the access of KCS IO space for BMC side.
+config PHYTIUM_KCS_IPMI_BMC
+ depends on ARCH_PHYTIUM
+ select IPMI_KCS_BMC
+ select REGMAP_MMIO
+ tristate "PHYTIUM KCS IPMI BMC driver"
+ help
+ Provides a driver for the KCS (Kerboard Controller Style) IPMI
+ interface found on Phytium SOCs.
+
+ The driver implements the BMC side of the KCS controller, it
+ provides the access of KCS IO space for BMC side.
+
+config PHYTIUM_BT_IPMI_BMC
+ depends on ARCH_PHYTIUM
+ depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
+ tristate "PHYTIUM BT BMC driver"
+ help
+ Provides a driver for the BT (Block Transfer) IPMI interface
+ found on Phytium SOCs. The driver implements the BMC
+ side of the BT interface.
+
config NPCM7XX_KCS_IPMI_BMC
depends on ARCH_NPCM7XX || COMPILE_TEST
select IPMI_KCS_BMC
--- a/drivers/char/ipmi/Makefile
+++ b/drivers/char/ipmi/Makefile
@@ -27,3 +27,5 @@ obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-b
obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o
obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o
obj-$(CONFIG_IPMB_DEVICE_INTERFACE) += ipmb_dev_int.o
+obj-$(CONFIG_PHYTIUM_KCS_IPMI_BMC) += kcs_bmc_phytium.o
+obj-$(CONFIG_PHYTIUM_BT_IPMI_BMC) += bt_bmc_phytium.o
\ No newline at end of file
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -41,23 +41,29 @@
#define CNTACR_RWVT BIT(4)
#define CNTACR_RWPT BIT(5)
-#define CNTVCT_LO 0x08
-#define CNTVCT_HI 0x0c
+#define CNTVCT_LO 0x00
+#define CNTPCT_LO 0x08
#define CNTFRQ 0x10
-#define CNTP_TVAL 0x28
+#define CNTP_CVAL_LO 0x20
#define CNTP_CTL 0x2c
-#define CNTV_TVAL 0x38
+#define CNTV_CVAL_LO 0x30
#define CNTV_CTL 0x3c
-static unsigned arch_timers_present __initdata;
+/*
+ * The minimum amount of time a generic counter is guaranteed to not roll over
+ * (40 years)
+ */
+#define MIN_ROLLOVER_SECS (40ULL * 365 * 24 * 3600)
-static void __iomem *arch_counter_base;
+static unsigned arch_timers_present __initdata;
struct arch_timer {
void __iomem *base;
struct clock_event_device evt;
};
+static struct arch_timer *arch_timer_mem __ro_after_init;
+
#define to_arch_timer(e) container_of(e, struct arch_timer, evt)
static u32 arch_timer_rate;
@@ -85,32 +91,57 @@ static int __init early_evtstrm_cfg(char
early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg);
/*
+ * Makes an educated guess at a valid counter width based on the Generic Timer
+ * specification. Of note:
+ * 1) the system counter is at least 56 bits wide
+ * 2) a roll-over time of not less than 40 years
+ *
+ * See 'ARM DDI 0487G.a D11.1.2 ("The system counter")' for more details.
+ */
+static int arch_counter_get_width(void)
+{
+ u64 min_cycles = MIN_ROLLOVER_SECS * arch_timer_rate;
+
+ /* guarantee the returned width is within the valid range */
+ return clamp_val(ilog2(min_cycles - 1) + 1, 56, 64);
+}
+
+/*
* Architected system timer support.
*/
static __always_inline
-void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val,
+void arch_timer_reg_write(int access, enum arch_timer_reg reg, u64 val,
struct clock_event_device *clk)
{
if (access == ARCH_TIMER_MEM_PHYS_ACCESS) {
struct arch_timer *timer = to_arch_timer(clk);
switch (reg) {
case ARCH_TIMER_REG_CTRL:
- writel_relaxed(val, timer->base + CNTP_CTL);
+ writel_relaxed((u32)val, timer->base + CNTP_CTL);
break;
- case ARCH_TIMER_REG_TVAL:
- writel_relaxed(val, timer->base + CNTP_TVAL);
+ case ARCH_TIMER_REG_CVAL:
+ /*
+ * Not guaranteed to be atomic, so the timer
+ * must be disabled at this point.
+ */
+ writeq_relaxed(val, timer->base + CNTP_CVAL_LO);
break;
+ default:
+ BUILD_BUG();
}
} else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) {
struct arch_timer *timer = to_arch_timer(clk);
switch (reg) {
case ARCH_TIMER_REG_CTRL:
- writel_relaxed(val, timer->base + CNTV_CTL);
+ writel_relaxed((u32)val, timer->base + CNTV_CTL);
break;
- case ARCH_TIMER_REG_TVAL:
- writel_relaxed(val, timer->base + CNTV_TVAL);
+ case ARCH_TIMER_REG_CVAL:
+ /* Same restriction as above */
+ writeq_relaxed(val, timer->base + CNTV_CVAL_LO);
break;
+ default:
+ BUILD_BUG();
}
} else {
arch_timer_reg_write_cp15(access, reg, val);
@@ -129,9 +160,8 @@ u32 arch_timer_reg_read(int access, enum
case ARCH_TIMER_REG_CTRL:
val = readl_relaxed(timer->base + CNTP_CTL);
break;
- case ARCH_TIMER_REG_TVAL:
- val = readl_relaxed(timer->base + CNTP_TVAL);
- break;
+ default:
+ BUILD_BUG();
}
} else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) {
struct arch_timer *timer = to_arch_timer(clk);
@@ -139,9 +169,8 @@ u32 arch_timer_reg_read(int access, enum
case ARCH_TIMER_REG_CTRL:
val = readl_relaxed(timer->base + CNTV_CTL);
break;
- case ARCH_TIMER_REG_TVAL:
- val = readl_relaxed(timer->base + CNTV_TVAL);
- break;
+ default:
+ BUILD_BUG();
}
} else {
val = arch_timer_reg_read_cp15(access, reg);
@@ -193,13 +222,11 @@ static struct clocksource clocksource_co
.name = "arch_sys_counter",
.rating = 400,
.read = arch_counter_read,
- .mask = CLOCKSOURCE_MASK(56),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static struct cyclecounter cyclecounter __ro_after_init = {
.read = arch_counter_read_cc,
- .mask = CLOCKSOURCE_MASK(56),
};
struct ate_acpi_oem_info {
@@ -227,16 +254,6 @@ struct ate_acpi_oem_info {
_new; \
})
-static u32 notrace fsl_a008585_read_cntp_tval_el0(void)
-{
- return __fsl_a008585_read_reg(cntp_tval_el0);
-}
-
-static u32 notrace fsl_a008585_read_cntv_tval_el0(void)
-{
- return __fsl_a008585_read_reg(cntv_tval_el0);
-}
-
static u64 notrace fsl_a008585_read_cntpct_el0(void)
{
return __fsl_a008585_read_reg(cntpct_el0);
@@ -273,16 +290,6 @@ static u64 notrace fsl_a008585_read_cntv
_new; \
})
-static u32 notrace hisi_161010101_read_cntp_tval_el0(void)
-{
- return __hisi_161010101_read_reg(cntp_tval_el0);
-}
-
-static u32 notrace hisi_161010101_read_cntv_tval_el0(void)
-{
- return __hisi_161010101_read_reg(cntv_tval_el0);
-}
-
static u64 notrace hisi_161010101_read_cntpct_el0(void)
{
return __hisi_161010101_read_reg(cntpct_el0);
@@ -367,16 +374,6 @@ static u64 notrace sun50i_a64_read_cntvc
{
return __sun50i_a64_read_reg(cntvct_el0);
}
-
-static u32 notrace sun50i_a64_read_cntp_tval_el0(void)
-{
- return read_sysreg(cntp_cval_el0) - sun50i_a64_read_cntpct_el0();
-}
-
-static u32 notrace sun50i_a64_read_cntv_tval_el0(void)
-{
- return read_sysreg(cntv_cval_el0) - sun50i_a64_read_cntvct_el0();
-}
#endif
#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
@@ -385,7 +382,7 @@ EXPORT_SYMBOL_GPL(timer_unstable_counter
static atomic_t timer_unstable_counter_workaround_in_use = ATOMIC_INIT(0);
-static void erratum_set_next_event_tval_generic(const int access, unsigned long evt,
+static void erratum_set_next_event_generic(const int access, unsigned long evt,
struct clock_event_device *clk)
{
unsigned long ctrl;
@@ -406,17 +403,17 @@ static void erratum_set_next_event_tval_
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
}
-static __maybe_unused int erratum_set_next_event_tval_virt(unsigned long evt,
+static __maybe_unused int erratum_set_next_event_virt(unsigned long evt,
struct clock_event_device *clk)
{
- erratum_set_next_event_tval_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk);
+ erratum_set_next_event_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk);
return 0;
}
-static __maybe_unused int erratum_set_next_event_tval_phys(unsigned long evt,
+static __maybe_unused int erratum_set_next_event_phys(unsigned long evt,
struct clock_event_device *clk)
{
- erratum_set_next_event_tval_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk);
+ erratum_set_next_event_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk);
return 0;
}
@@ -426,12 +423,10 @@ static const struct arch_timer_erratum_w
.match_type = ate_match_dt,
.id = "fsl,erratum-a008585",
.desc = "Freescale erratum a005858",
- .read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0,
- .read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0,
.read_cntpct_el0 = fsl_a008585_read_cntpct_el0,
.read_cntvct_el0 = fsl_a008585_read_cntvct_el0,
- .set_next_event_phys = erratum_set_next_event_tval_phys,
- .set_next_event_virt = erratum_set_next_event_tval_virt,
+ .set_next_event_phys = erratum_set_next_event_phys,
+ .set_next_event_virt = erratum_set_next_event_virt,
},
#endif
#ifdef CONFIG_HISILICON_ERRATUM_161010101
@@ -439,23 +434,19 @@ static const struct arch_timer_erratum_w
.match_type = ate_match_dt,
.id = "hisilicon,erratum-161010101",
.desc = "HiSilicon erratum 161010101",
- .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0,
- .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0,
.read_cntpct_el0 = hisi_161010101_read_cntpct_el0,
.read_cntvct_el0 = hisi_161010101_read_cntvct_el0,
- .set_next_event_phys = erratum_set_next_event_tval_phys,
- .set_next_event_virt = erratum_set_next_event_tval_virt,
+ .set_next_event_phys = erratum_set_next_event_phys,
+ .set_next_event_virt = erratum_set_next_event_virt,
},
{
.match_type = ate_match_acpi_oem_info,
.id = hisi_161010101_oem_info,
.desc = "HiSilicon erratum 161010101",
- .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0,
- .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0,
.read_cntpct_el0 = hisi_161010101_read_cntpct_el0,
.read_cntvct_el0 = hisi_161010101_read_cntvct_el0,
- .set_next_event_phys = erratum_set_next_event_tval_phys,
- .set_next_event_virt = erratum_set_next_event_tval_virt,
+ .set_next_event_phys = erratum_set_next_event_phys,
+ .set_next_event_virt = erratum_set_next_event_virt,
},
#endif
#ifdef CONFIG_ARM64_ERRATUM_858921
@@ -472,12 +463,10 @@ static const struct arch_timer_erratum_w
.match_type = ate_match_dt,
.id = "allwinner,erratum-unknown1",
.desc = "Allwinner erratum UNKNOWN1",
- .read_cntp_tval_el0 = sun50i_a64_read_cntp_tval_el0,
- .read_cntv_tval_el0 = sun50i_a64_read_cntv_tval_el0,
.read_cntpct_el0 = sun50i_a64_read_cntpct_el0,
.read_cntvct_el0 = sun50i_a64_read_cntvct_el0,
- .set_next_event_phys = erratum_set_next_event_tval_phys,
- .set_next_event_virt = erratum_set_next_event_tval_virt,
+ .set_next_event_phys = erratum_set_next_event_phys,
+ .set_next_event_virt = erratum_set_next_event_virt,
},
#endif
#ifdef CONFIG_ARM64_ERRATUM_1418040
@@ -715,10 +704,18 @@ static __always_inline void set_next_eve
struct clock_event_device *clk)
{
unsigned long ctrl;
+ u64 cnt;
+
ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
ctrl |= ARCH_TIMER_CTRL_ENABLE;
ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
- arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk);
+
+ if (access == ARCH_TIMER_PHYS_ACCESS)
+ cnt = __arch_counter_get_cntpct();
+ else
+ cnt = __arch_counter_get_cntvct();
+
+ arch_timer_reg_write(access, ARCH_TIMER_REG_CVAL, evt + cnt, clk);
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
}
@@ -736,23 +733,79 @@ static int arch_timer_set_next_event_phy
return 0;
}
+static u64 arch_counter_get_cnt_mem(struct arch_timer *t, int offset_lo)
+{
+ u32 cnt_lo, cnt_hi, tmp_hi;
+
+ do {
+ cnt_hi = readl_relaxed(t->base + offset_lo + 4);
+ cnt_lo = readl_relaxed(t->base + offset_lo);
+ tmp_hi = readl_relaxed(t->base + offset_lo + 4);
+ } while (cnt_hi != tmp_hi);
+
+ return ((u64) cnt_hi << 32) | cnt_lo;
+}
+
+static __always_inline void set_next_event_mem(const int access, unsigned long evt,
+ struct clock_event_device *clk)
+{
+ struct arch_timer *timer = to_arch_timer(clk);
+ unsigned long ctrl;
+ u64 cnt;
+
+ ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
+ ctrl |= ARCH_TIMER_CTRL_ENABLE;
+ ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
+
+ if (access == ARCH_TIMER_MEM_VIRT_ACCESS)
+ cnt = arch_counter_get_cnt_mem(timer, CNTVCT_LO);
+ else
+ cnt = arch_counter_get_cnt_mem(timer, CNTPCT_LO);
+
+ arch_timer_reg_write(access, ARCH_TIMER_REG_CVAL, evt + cnt, clk);
+ arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
+}
+
static int arch_timer_set_next_event_virt_mem(unsigned long evt,
struct clock_event_device *clk)
{
- set_next_event(ARCH_TIMER_MEM_VIRT_ACCESS, evt, clk);
+ set_next_event_mem(ARCH_TIMER_MEM_VIRT_ACCESS, evt, clk);
return 0;
}
static int arch_timer_set_next_event_phys_mem(unsigned long evt,
struct clock_event_device *clk)
{
- set_next_event(ARCH_TIMER_MEM_PHYS_ACCESS, evt, clk);
+ set_next_event_mem(ARCH_TIMER_MEM_PHYS_ACCESS, evt, clk);
return 0;
}
+static u64 __arch_timer_check_delta(void)
+{
+#ifdef CONFIG_ARM64
+ const struct midr_range broken_cval_midrs[] = {
+ /*
+ * XGene-1 implements CVAL in terms of TVAL, meaning
+ * that the maximum timer range is 32bit. Shame on them.
+ */
+ MIDR_ALL_VERSIONS(MIDR_CPU_MODEL(ARM_CPU_IMP_APM,
+ APM_CPU_PART_POTENZA)),
+ {},
+ };
+
+ if (is_midr_in_range_list(read_cpuid_id(), broken_cval_midrs)) {
+ pr_warn_once("Broken CNTx_CVAL_EL1, limiting width to 32bits");
+ return CLOCKSOURCE_MASK(32);
+ }
+#endif
+ return CLOCKSOURCE_MASK(arch_counter_get_width());
+}
+
static void __arch_timer_setup(unsigned type,
struct clock_event_device *clk)
{
+ u64 max_delta;
+
clk->features = CLOCK_EVT_FEAT_ONESHOT;
if (type == ARCH_TIMER_TYPE_CP15) {
@@ -784,6 +837,7 @@ static void __arch_timer_setup(unsigned
}
clk->set_next_event = sne;
+ max_delta = __arch_timer_check_delta();
} else {
clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
clk->name = "arch_mem_timer";
@@ -800,11 +854,13 @@ static void __arch_timer_setup(unsigned
clk->set_next_event =
arch_timer_set_next_event_phys_mem;
}
+
+ max_delta = CLOCKSOURCE_MASK(56);
}
clk->set_state_shutdown(clk);
- clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
+ clockevents_config_and_register(clk, arch_timer_rate, 0xf, max_delta);
}
static void arch_timer_evtstrm_enable(int divider)
@@ -974,15 +1030,7 @@ bool arch_timer_evtstrm_available(void)
static u64 arch_counter_get_cntvct_mem(void)
{
- u32 vct_lo, vct_hi, tmp_hi;
-
- do {
- vct_hi = readl_relaxed(arch_counter_base + CNTVCT_HI);
- vct_lo = readl_relaxed(arch_counter_base + CNTVCT_LO);
- tmp_hi = readl_relaxed(arch_counter_base + CNTVCT_HI);
- } while (vct_hi != tmp_hi);
-
- return ((u64) vct_hi << 32) | vct_lo;
+ return arch_counter_get_cnt_mem(arch_timer_mem, CNTVCT_LO);
}
static struct arch_timer_kvm_info arch_timer_kvm_info;
@@ -995,6 +1043,7 @@ struct arch_timer_kvm_info *arch_timer_g
static void __init arch_counter_register(unsigned type)
{
u64 start_count;
+ int width;
/* Register the CP15 based counter if we have one */
if (type & ARCH_TIMER_TYPE_CP15) {
@@ -1019,6 +1068,10 @@ static void __init arch_counter_register
arch_timer_read_counter = arch_counter_get_cntvct_mem;
}
+ width = arch_counter_get_width();
+ clocksource_counter.mask = CLOCKSOURCE_MASK(width);
+ cyclecounter.mask = CLOCKSOURCE_MASK(width);
+
if (!arch_counter_suspend_stop)
clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
start_count = arch_timer_read_counter();
@@ -1028,8 +1081,7 @@ static void __init arch_counter_register
timecounter_init(&arch_timer_kvm_info.timecounter,
&cyclecounter, start_count);
- /* 56 bits minimum, so we assume worst case rollover */
- sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
+ sched_clock_register(arch_timer_read_counter, width, arch_timer_rate);
}
static void arch_timer_stop(struct clock_event_device *clk)
@@ -1170,25 +1222,25 @@ static int __init arch_timer_mem_registe
{
int ret;
irq_handler_t func;
- struct arch_timer *t;
- t = kzalloc(sizeof(*t), GFP_KERNEL);
- if (!t)
+ arch_timer_mem = kzalloc(sizeof(*arch_timer_mem), GFP_KERNEL);
+ if (!arch_timer_mem)
return -ENOMEM;
- t->base = base;
- t->evt.irq = irq;
- __arch_timer_setup(ARCH_TIMER_TYPE_MEM, &t->evt);
+ arch_timer_mem->base = base;
+ arch_timer_mem->evt.irq = irq;
+ __arch_timer_setup(ARCH_TIMER_TYPE_MEM, &arch_timer_mem->evt);
if (arch_timer_mem_use_virtual)
func = arch_timer_handler_virt_mem;
else
func = arch_timer_handler_phys_mem;
- ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt);
+ ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &arch_timer_mem->evt);
if (ret) {
pr_err("Failed to request mem timer irq\n");
- kfree(t);
+ kfree(arch_timer_mem);
+ arch_timer_mem = NULL;
}
return ret;
@@ -1436,7 +1488,6 @@ arch_timer_mem_frame_register(struct arc
return ret;
}
- arch_counter_base = base;
arch_timers_present |= ARCH_TIMER_TYPE_MEM;
return 0;
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -21,7 +21,7 @@ config CRYPTO_DEV_PADLOCK
(so called VIA PadLock ACE, Advanced Cryptography Engine)
that provides instructions for very fast cryptographic
operations with supported algorithms.
-
+
The instructions are used only when the CPU supports them.
Otherwise software encryption is used.
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -712,6 +712,13 @@ config ZX_DMA
help
Support the DMA engine for ZTE ZX family platform devices.
+config PHYTIUM_DDMA
+ bool "Phytium PE220x DDMA support"
+ depends on (ARCH_PHYTIUM || COMPILE_TEST)
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Enable support for Phytium PE220x DDMA controller.
# driver files
source "drivers/dma/bestcomm/Kconfig"
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -87,3 +87,4 @@ obj-y += mediatek/
obj-y += qcom/
obj-y += ti/
obj-y += xilinx/
+obj-y += phytium/
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -537,4 +537,11 @@ config EDAC_DMC520
Support for error detection and correction on the
SoCs with ARM DMC-520 DRAM controller.
+config EDAC_PHYTIUM
+ tristate "Phytium Pe220x SoC"
+ depends on (ARM64)
+ help
+ Support for error detection and correction on the
+ Phytium Pe220x family of SOCs.
+
endif # EDAC
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -89,3 +89,4 @@ obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o
obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o
obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o
obj-$(CONFIG_EDAC_DMC520) += dmc520_edac.o
+obj-$(CONFIG_EDAC_PHYTIUM) += phytium_edac.o
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -27,6 +27,18 @@ config ARM_SCMI_PROTOCOL
This protocol library provides interface for all the client drivers
making use of the features offered by the SCMI.
+if ARM_SCMI_PROTOCOL
+config ARM_SCMI_TRANSPORT_FORCE_POLLING
+ bool "Support force polling mode for SCMI Mailbox"
+ help
+ Support force polling mode for SCMI Mailbox transports.
+
+ If you want to configure SCMI Mailbox transport to use polling mode
+ on the TX path and do not use any completion IRQ facility even when
+ available through kernel parameter, answer Y. If unsure, say N.
+
+endif #ARM_SCMI_PROTOCOL
+
config ARM_SCMI_POWER_DOMAIN
tristate "SCMI power domain driver"
depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -98,6 +98,10 @@ struct scmi_info {
int users;
};
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_FORCE_POLLING
+static bool scmi_force_polling;
+#endif
+
#define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle)
static const int scmi_linux_errmap[] = {
@@ -344,6 +348,15 @@ static bool scmi_xfer_done_no_timeout(st
ktime_after(ktime_get(), stop);
}
+
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_FORCE_POLLING
+static int __init scmi_set_force_polling(char *str)
+{
+ return kstrtobool(str, &scmi_force_polling);
+}
+early_param("scmi.force_polling", scmi_set_force_polling);
+#endif
+
/**
* scmi_do_xfer() - Do one transfer
*
@@ -366,6 +379,11 @@ int scmi_do_xfer(const struct scmi_handl
if (unlikely(!cinfo))
return -EINVAL;
+#ifdef CONFIG_ARM_SCMI_TRANSPORT_FORCE_POLLING
+ if (scmi_force_polling)
+ xfer->hdr.poll_completion = true;
+#endif
+
trace_scmi_xfer_begin(xfer->transfer_id, xfer->hdr.id,
xfer->hdr.protocol_id, xfer->hdr.seq,
xfer->hdr.poll_completion);
--- a/drivers/firmware/arm_scmi/shmem.c
+++ b/drivers/firmware/arm_scmi/shmem.c
@@ -32,6 +32,14 @@ struct scmi_shared_mem {
void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer)
{
+#ifdef CONFIG_ARCH_PHYTIUM
+ /* callee not set cahnnel free when init, caller set it */
+ static int is_init = 0;
+ if(unlikely(is_init == 0)) {
+ iowrite32(0x1, &shmem->channel_status);
+ is_init = 1;
+ }
+#endif
/*
* Ideally channel must be free by now unless OS timeout last
* request and platform continued to process the same, wait
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -108,6 +108,10 @@ config GPIO_REGMAP
config GPIO_MAX730X
tristate
+# This symbol is selected by both MMIO and PCI expanders
+config GPIO_PHYTIUM_CORE
+ tristate
+
menu "Memory mapped GPIO drivers"
depends on HAS_IOMEM
@@ -739,6 +743,27 @@ config GPIO_AMD_FCH
Note: This driver doesn't registers itself automatically, as it
needs to be provided with platform specific configuration.
(See eg. CONFIG_PCENGINES_APU2.)
+
+config GPIO_PHYTIUM_PLAT
+ tristate "Phytium GPIO Platform support"
+ default y if ARCH_PHYTIUM
+ depends on ARM64
+ select GPIO_PHYTIUM_CORE
+ select IRQ_DOMAIN
+ select GENERIC_IRQ_CHIP
+ select GPIOLIB_IRQCHIP
+ help
+ Say yes here to enable GPIO support for Phytium SoCs.
+
+config GPIO_PHYTIUM_SGPIO
+ tristate "Phytium SGPIO support"
+ default y if ARCH_PHYTIUM
+ depends on ARM64
+ select IRQ_DOMAIN
+ select GENERIC_IRQ_CHIP
+ help
+ Say yes here to enable SGPIO support for Phytium SoCs.
+
endmenu
menu "Port-mapped I/O GPIO drivers"
@@ -1520,6 +1545,20 @@ config GPIO_SODAVILLE
help
Say Y here to support Intel Sodaville GPIO.
+
+config GPIO_PHYTIUM_PCI
+ tristate "Phytium GPIO PCI support"
+ select GPIO_PHYTIUM_CORE
+ select IRQ_DOMAIN
+ select GENERIC_IRQ_CHIP
+ select GPIOLIB_IRQCHIP
+ help
+ Say Y here to support Phytium PCI GPIO controller on px210 chipset.
+ An interrupt is generated when any of the inputs change state
+ (low to high or high to low).
+
+ This driver can be used for Phytium px210.
+
endmenu
menu "SPI GPIO expanders"
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -180,3 +180,8 @@ obj-$(CONFIG_GPIO_XTENSA) += gpio-xtens
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZX) += gpio-zx.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
+
+obj-$(CONFIG_GPIO_PHYTIUM_CORE) += gpio-phytium-core.o
+obj-$(CONFIG_GPIO_PHYTIUM_PCI) += gpio-phytium-pci.o
+obj-$(CONFIG_GPIO_PHYTIUM_PLAT) += gpio-phytium-platform.o
+obj-$(CONFIG_GPIO_PHYTIUM_SGPIO) += gpio-phytium-sgpio.o
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -393,6 +393,8 @@ source "drivers/gpu/drm/tidss/Kconfig"
source "drivers/gpu/drm/xlnx/Kconfig"
+source "drivers/gpu/drm/phytium/Kconfig"
+
# Keep legacy drivers last
menuconfig DRM_LEGACY
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -124,3 +124,4 @@ obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
obj-$(CONFIG_DRM_MCDE) += mcde/
obj-$(CONFIG_DRM_TIDSS) += tidss/
obj-y += xlnx/
+obj-$(CONFIG_DRM_PHYTIUM) += phytium/
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -2096,6 +2096,16 @@ config SENSORS_INTEL_M10_BMC_HWMON
sensors monitor various telemetry data of different components on the
card, e.g. board temperature, FPGA core temperature/voltage/current.
+
+config SENSORS_PHYTIUM
+ tristate "Phytium Fan tach and capture counter driver"
+ help
+ This driver provides support for Phytium Fan Tacho and capture
+ counter controllers.
+
+ This driver can also be built as a module. If so, the module
+ will be called tacho-phytium.
+
if ACPI
comment "ACPI drivers"
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -194,6 +194,8 @@ obj-$(CONFIG_SENSORS_WM831X) += wm831x-h
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
obj-$(CONFIG_SENSORS_XGENE) += xgene-hwmon.o
+obj-$(CONFIG_SENSORS_PHYTIUM) += tacho-phytium.o
+
obj-$(CONFIG_SENSORS_OCC) += occ/
obj-$(CONFIG_PMBUS) += pmbus/
--- a/drivers/hwspinlock/Kconfig
+++ b/drivers/hwspinlock/Kconfig
@@ -65,4 +65,13 @@ config HSEM_U8500
If unsure, say N.
+config HWSPINLOCK_PHYTIUM
+ tristate "Phytium Hardware Spinlock device"
+ depends on HWSPINLOCK
+ depends on ARCH_PHYTIUM
+ help
+ Say y here to support the Phytium Hardware Spinlock device.
+
+ If unsure, say N.
+
endif # HWSPINLOCK
--- a/drivers/hwspinlock/Makefile
+++ b/drivers/hwspinlock/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_HWSPINLOCK_SIRF) += sirf_h
obj-$(CONFIG_HWSPINLOCK_SPRD) += sprd_hwspinlock.o
obj-$(CONFIG_HWSPINLOCK_STM32) += stm32_hwspinlock.o
obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o
+
+obj-$(CONFIG_HWSPINLOCK_PHYTIUM) += phytium_hwspinlock.o
\ No newline at end of file
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -1206,6 +1206,34 @@ config I2C_RCAR
This driver can also be built as a module. If so, the module
will be called i2c-rcar.
+config I2C_PHYTIUM_CORE
+ tristate
+
+config I2C_PHYTIUM_PCI
+ tristate "Phytium I2C PCI"
+ depends on PCI && ARCH_PHYTIUM
+ select I2C_PHYTIUM_CORE
+ select I2C_SMBUS
+ help
+ If you say yes to this option, support will be included for the
+ Phytium I2C adapter. Only master mode is supported.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-phytium-pci.
+
+config I2C_PHYTIUM_PLATFORM
+ tristate "Phytium I2C Platform"
+ depends on (ACPI && COMMON_CLK) || !ACPI
+ select I2C_SLAVE
+ select I2C_PHYTIUM_CORE
+ select I2C_SMBUS
+ help
+ If you say yes to this option, support will be included for the
+ Phytium I2C adapter. Only master mode is supported.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-phytium-platform.
+
comment "External I2C/SMBus adapter drivers"
config I2C_DIOLAN_U2C
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -123,6 +123,10 @@ obj-$(CONFIG_I2C_XLR) += i2c-xlr.o
obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o
obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
obj-$(CONFIG_I2C_ZX2967) += i2c-zx2967.o
+obj-$(CONFIG_I2C_PHYTIUM_CORE) += i2c-phytium-core.o
+i2c-phytium-core-objs := i2c-phytium-common.o i2c-phytium-master.o i2c-phytium-slave.o
+obj-$(CONFIG_I2C_PHYTIUM_PCI) += i2c-phytium-pci.o
+obj-$(CONFIG_I2C_PHYTIUM_PLATFORM) += i2c-phytium-platform.o
# External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1226,4 +1226,16 @@ config XILINX_XADC
The driver can also be build as a module. If so, the module will be called
xilinx-xadc.
+config PHYTIUM_ADC
+ tristate "Phytium ADC driver"
+ depends on ARCH_PHYTIUM || COMPILE_TEST
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for Phytium analog to digital
+ converters (ADC).
+
+ To compile this driver as a module, choose M here: the module
+ will be called phytium-adc.
+
endmenu
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -111,3 +111,4 @@ obj-$(CONFIG_VIPERBOARD_ADC) += viperboa
xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o
obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o
obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o
+obj-$(CONFIG_PHYTIUM_ADC) += phytium-adc.o
\ No newline at end of file
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -788,4 +788,15 @@ config KEYBOARD_MTK_PMIC
To compile this driver as a module, choose M here: the
module will be called pmic-keys.
+config KEYBOARD_PHYTIUM
+ tristate "Phytium keypad support"
+ depends on ARCH_PHYTIUM
+ select INPUT_MATRIXKMAP
+ help
+ Say Y here if you want to enable support for Phytium keypad
+ port.
+
+ To compile this driver as a module, choose M here: the
+ module will be called phytium_keypad.
+
endif
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-k
obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY) += tm2-touchkey.o
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
+obj-$(CONFIG_KEYBOARD_PHYTIUM) += phytium-keypad.o
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -40,6 +40,18 @@ config SERIO_I8042
To compile this driver as a module, choose M here: the
module will be called i8042.
+config SERIO_PHYTIUM_PS2
+ depends on SERIO
+ tristate "PHYTIUM PS/2 (keyboard and mouse)"
+ default y if ARCH_PHYTIUM
+ depends on PCI
+ help
+ This selects support for the PS/2 Host Controller on
+ Phytium SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called phytium-ps2.
+
config SERIO_SERPORT
tristate "Serial port line discipline"
default y
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_SERIO) += serio.o
obj-$(CONFIG_SERIO_I8042) += i8042.o
+obj-$(CONFIG_SERIO_PHYTIUM_PS2) += phytium-ps2.o
obj-$(CONFIG_SERIO_PARKBD) += parkbd.o
obj-$(CONFIG_SERIO_SERPORT) += serport.o
obj-$(CONFIG_SERIO_CT82C710) += ct82c710.o
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2873,6 +2873,13 @@ static void arm_smmu_write_msi_msg(struc
doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo;
doorbell &= MSI_CFG0_ADDR_MASK;
+#ifdef CONFIG_PM_SLEEP
+ /* Saves the msg (base addr of msi irq) and restores it during resume */
+ desc->msg.address_lo = msg->address_lo;
+ desc->msg.address_hi = msg->address_hi;
+ desc->msg.data = msg->data;
+#endif
+
writeq_relaxed(doorbell, smmu->base + cfg[0]);
writel_relaxed(msg->data, smmu->base + cfg[1]);
writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]);
@@ -2928,11 +2935,51 @@ static void arm_smmu_setup_msis(struct a
devm_add_action(dev, arm_smmu_free_msis, dev);
}
-static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
+#ifdef CONFIG_PM_SLEEP
+static void arm_smmu_resume_msis(struct arm_smmu_device *smmu)
+{
+ struct msi_desc *desc;
+ struct device *dev = smmu->dev;
+
+ for_each_msi_entry(desc, dev) {
+ switch (desc->platform.msi_index) {
+ case EVTQ_MSI_INDEX:
+ case GERROR_MSI_INDEX:
+ case PRIQ_MSI_INDEX: {
+ phys_addr_t *cfg = arm_smmu_msi_cfg[desc->platform.msi_index];
+ struct msi_msg *msg = &desc->msg;
+ phys_addr_t doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo;
+
+ doorbell &= MSI_CFG0_ADDR_MASK;
+ writeq_relaxed(doorbell, smmu->base + cfg[0]);
+ writel_relaxed(msg->data, smmu->base + cfg[1]);
+ writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE,
+ smmu->base + cfg[2]);
+ break;
+ }
+ default:
+ continue;
+
+ }
+ }
+}
+#else
+static void arm_smmu_resume_msis(struct arm_smmu_device *smmu)
+{
+}
+#endif
+
+static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu, bool resume)
{
int irq, ret;
- arm_smmu_setup_msis(smmu);
+ if (!resume)
+ arm_smmu_setup_msis(smmu);
+ else {
+ /* The irq doesn't need to be re-requested during resume */
+ arm_smmu_resume_msis(smmu);
+ return;
+ }
/* Request interrupt lines */
irq = smmu->evtq.q.irq;
@@ -2974,7 +3021,7 @@ static void arm_smmu_setup_unique_irqs(s
}
}
-static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
+static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu, bool resume)
{
int ret, irq;
u32 irqen_flags = IRQ_CTRL_EVTQ_IRQEN | IRQ_CTRL_GERROR_IRQEN;
@@ -3001,7 +3048,7 @@ static int arm_smmu_setup_irqs(struct ar
if (ret < 0)
dev_warn(smmu->dev, "failed to enable combined irq\n");
} else
- arm_smmu_setup_unique_irqs(smmu);
+ arm_smmu_setup_unique_irqs(smmu, resume);
if (smmu->features & ARM_SMMU_FEAT_PRI)
irqen_flags |= IRQ_CTRL_PRIQ_IRQEN;
@@ -3026,7 +3073,7 @@ static int arm_smmu_device_disable(struc
return ret;
}
-static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
+static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool resume)
{
int ret;
u32 reg, enables;
@@ -3134,7 +3181,7 @@ static int arm_smmu_device_reset(struct
}
}
- ret = arm_smmu_setup_irqs(smmu);
+ ret = arm_smmu_setup_irqs(smmu, resume);
if (ret) {
dev_err(smmu->dev, "failed to setup irqs\n");
return ret;
@@ -3144,7 +3191,7 @@ static int arm_smmu_device_reset(struct
enables &= ~(CR0_EVTQEN | CR0_PRIQEN);
/* Enable the SMMU interface, or ensure bypass */
- if (!bypass || disable_bypass) {
+ if (!smmu->bypass || disable_bypass) {
enables |= CR0_SMMUEN;
} else {
ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT);
@@ -3492,6 +3539,26 @@ static void __iomem *arm_smmu_ioremap(st
return devm_ioremap_resource(dev, &res);
}
+#ifdef CONFIG_PM_SLEEP
+static int arm_smmu_suspend(struct device *dev)
+{
+ /*
+ * The smmu is powered off and related registers are automatically
+ * cleared when suspend. No need to do anything.
+ */
+ return 0;
+}
+
+static int arm_smmu_resume(struct device *dev)
+{
+ struct arm_smmu_device *smmu = dev_get_drvdata(dev);
+
+ arm_smmu_device_reset(smmu, true);
+
+ return 0;
+}
+#endif
+
static int arm_smmu_device_probe(struct platform_device *pdev)
{
int irq, ret;
@@ -3499,7 +3566,6 @@ static int arm_smmu_device_probe(struct
resource_size_t ioaddr;
struct arm_smmu_device *smmu;
struct device *dev = &pdev->dev;
- bool bypass;
smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
if (!smmu) {
@@ -3517,7 +3583,7 @@ static int arm_smmu_device_probe(struct
}
/* Set bypass mode according to firmware probing result */
- bypass = !!ret;
+ smmu->bypass = !!ret;
/* Base address */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -3578,7 +3644,7 @@ static int arm_smmu_device_probe(struct
platform_set_drvdata(pdev, smmu);
/* Reset the device */
- ret = arm_smmu_device_reset(smmu, bypass);
+ ret = arm_smmu_device_reset(smmu, false);
if (ret)
return ret;
@@ -3623,10 +3689,21 @@ static const struct of_device_id arm_smm
};
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
+#ifdef CONFIG_PM_SLEEP
+static const struct dev_pm_ops arm_smmu_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(arm_smmu_suspend,
+ arm_smmu_resume)
+};
+#define ARM_SMMU_PM_OPS (&arm_smmu_pm_ops)
+#else
+#define ARM_SMMU_PM_OPS NULL
+#endif
+
static struct platform_driver arm_smmu_driver = {
.driver = {
.name = "arm-smmu-v3",
.of_match_table = arm_smmu_of_match,
+ .pm = ARM_SMMU_PM_OPS,
.suppress_bind_attrs = true,
},
.probe = arm_smmu_device_probe,
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -636,6 +636,7 @@ struct arm_smmu_device {
/* IOMMU core code handle */
struct iommu_device iommu;
+ bool bypass;
};
/* SMMU private data for each master */
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -599,4 +599,12 @@ config MST_IRQ
help
Support MStar Interrupt Controller.
+config PHYTIUM_IXIC
+ bool "Phytium SoC PCI Legacy Interrupt Controller"
+ depends on ARCH_PHYTIUM
+ select IRQ_DOMAIN
+ select IRQ_DOMAIN_HIERARCHY
+ help
+ This enables support PCI Legacy Interrupt on Phytium SoC.
+
endmenu
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -114,3 +114,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-l
obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o
obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o
obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o
+obj-$(CONFIG_PHYTIUM_IXIC) += irq-phytium-ixic.o
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -4792,6 +4792,7 @@ static void its_restore_enable(void)
{
struct its_node *its;
int ret;
+ int cpu;
raw_spin_lock(&its_lock);
list_for_each_entry(its, &its_nodes, entry) {
@@ -4845,6 +4846,23 @@ static void its_restore_enable(void)
GITS_TYPER_HCC(gic_read_typer(base + GITS_TYPER)))
its_cpu_init_collection(its);
}
+
+ /*
+ * Enable LPIs:firmware just restore GICR_CTLR_ENABLE_LPIs of boot
+ * CPU, the other CPUs also should be restored.
+ */
+ for_each_possible_cpu(cpu) {
+ void __iomem *rbase = gic_data_rdist_cpu(cpu)->rd_base;
+ u32 val;
+
+ /*Enable LPIs*/
+ val = readl_relaxed(rbase + GICR_CTLR);
+ if (val & GICR_CTLR_ENABLE_LPIS)
+ continue;
+
+ val |= GICR_CTLR_ENABLE_LPIS;
+ writel_relaxed(val, rbase + GICR_CTLR);
+ }
raw_spin_unlock(&its_lock);
}
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -254,4 +254,13 @@ config QCOM_IPCC
acts as an interrupt controller for receiving interrupts from clients.
Say Y here if you want to build this driver.
+config PHYTIUM_MBOX
+ tristate "Phytium SoC Mailbox Support"
+ depends on ARCH_PHYTIUM || COMPILE_TEST
+ help
+ Mailbox driver implementation for the Phytium platform. It is used
+ to send message between application processors and on-chip management
+ firmware. Say Y here if you want to build this mailbox controller
+ driver.
+
endif
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -54,3 +54,5 @@ obj-$(CONFIG_SUN6I_MSGBOX) += sun6i-msgb
obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o
obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
+
+obj-$(CONFIG_PHYTIUM_MBOX) += phytium-mailbox.o
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -168,6 +168,15 @@ config VIDEO_TI_CAL
In TI Technical Reference Manual this module is referred as
Camera Interface Subsystem (CAMSS).
+config VIDEO_PHYTIUM_JPEG
+ tristate "Phytium JPEG Encoder driver"
+ depends on VIDEO_V4L2
+ select VIDEOBUF2_DMA_CONTIG
+ help
+ Support for the Phytium JPEG Encoder Engine embedded
+ in the Phytium SOCs. The engine can capture and
+ compress video data from digital or analog sources.
+
endif # V4L_PLATFORM_DRIVERS
menuconfig V4L_MEM2MEM_DRIVERS
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -80,3 +80,4 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
obj-y += sunxi/
+obj-$(CONFIG_VIDEO_PHYTIUM_JPEG) += phytium-jpeg/
\ No newline at end of file
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1035,6 +1035,21 @@ config UCB1400_CORE
To compile this driver as a module, choose M here: the
module will be called ucb1400_core.
+config MFD_PHYTIUM_I2S_LSD
+ tristate "PHYTIUM px210 I2S LSD MFD driver"
+ depends on (PCI && ARCH_PHYTIUM)
+ select MFD_CORE
+ help
+ This enables support for the Phytium px210 LSD I2S controller.
+
+config MFD_PHYTIUM_I2S_MMD
+ tristate "PHYTIUM px210 I2S MMD MFD driver"
+ depends on (PCI && ARCH_PHYTIUM)
+ select MFD_CORE
+ help
+ This enables support for the Phytium px210 MMD I2S controllers
+ for Display Port.
+
config MFD_PM8XXX
tristate "Qualcomm PM8xxx PMIC chips driver"
depends on (ARM || HEXAGON || COMPILE_TEST)
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -267,3 +267,6 @@ obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-
obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
+
+obj-$(CONFIG_MFD_PHYTIUM_I2S_LSD) += phytium_px210_i2s_lsd.o
+obj-$(CONFIG_MFD_PHYTIUM_I2S_MMD) += phytium_px210_i2s_mmd.o
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -1105,3 +1105,37 @@ config MMC_OWL
config MMC_SDHCI_EXTERNAL_DMA
bool
+
+config MMC_PHYTIUM_SDCI
+ tristate "Phytium SD Host Controller support"
+ depends on ARCH_PHYTIUM || COMPILE_TEST
+ default y if ARCH_PHYTIUM
+ help
+ This selects support for the SD/MMC Host Controller on
+ Phytium SoC family.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
+config MMC_PHYTIUM_MCI_PCI
+ tristate "Phytium octopus PCI MultiMedia Card Interface support"
+ depends on ARCH_PHYTIUM
+ default y if ARCH_PHYTIUM
+ help
+ This selects support for the PCI MultiMedia Card Interface on Phytium
+ px210 chipset.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
+config MMC_PHYTIUM_MCI_PLTFM
+ tristate "Phytium MultiMedia Card Interface support"
+ depends on ARCH_PHYTIUM && OF
+ default y if ARCH_PHYTIUM
+ help
+ This selects support for the MultiMedia Card Interface on Phytium SoCs.
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_MMC_USDHI6ROL0) += usdhi6ro
obj-$(CONFIG_MMC_TOSHIBA_PCI) += toshsd.o
obj-$(CONFIG_MMC_BCM2835) += bcm2835.o
obj-$(CONFIG_MMC_OWL) += owl-mmc.o
+obj-$(CONFIG_MMC_PHYTIUM_SDCI) += phytium-sdci.o
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o
@@ -112,3 +113,6 @@ endif
obj-$(CONFIG_MMC_SDHCI_XENON) += sdhci-xenon-driver.o
sdhci-xenon-driver-y += sdhci-xenon.o sdhci-xenon-phy.o
+
+obj-$(CONFIG_MMC_PHYTIUM_MCI_PCI) += phytium-mci-pci.o phytium-mci.o
+obj-$(CONFIG_MMC_PHYTIUM_MCI_PLTFM) += phytium-mci-plat.o phytium-mci.o
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -486,6 +486,25 @@ config MTD_NAND_RICOH
expermental, readwrite
'SmartMedia/xD new translation layer'
+config MTD_NAND_PHYTIUM
+ tristate
+
+config MTD_NAND_PHYTIUM_PCI
+ tristate "Support Phytium NAND controller as a PCI device"
+ select MTD_NAND_PHYTIUM
+ depends on PCI
+ help
+ Enable the driver for NAND flash controller of Phytium Px210 chipset,
+ using the Phytium NAND controller core.
+
+config MTD_NAND_PHYTIUM_PLAT
+ tristate "Support Phytium NAND controller as a platform device"
+ select MTD_NAND_PHYTIUM
+ depends on ARCH_PHYTIUM
+ help
+ Enable the driver for NAND flash controller of Phytium CPU chipset,
+ using the Phytium NAND controller core.
+
config MTD_NAND_DISKONCHIP
tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation)"
depends on HAS_IOMEM
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -59,6 +59,10 @@ obj-$(CONFIG_MTD_NAND_MESON) += meson_n
obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.o
obj-$(CONFIG_MTD_NAND_ARASAN) += arasan-nand-controller.o
+obj-$(CONFIG_MTD_NAND_PHYTIUM) += phytium_nand.o
+obj-$(CONFIG_MTD_NAND_PHYTIUM_PCI) += phytium_nand_pci.o
+obj-$(CONFIG_MTD_NAND_PHYTIUM_PLAT) += phytium_nand_plat.o
+
nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
nand-objs += nand_onfi.o
nand-objs += nand_jedec.o
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -17,6 +17,7 @@ spi-nor-objs += sst.o
spi-nor-objs += winbond.o
spi-nor-objs += xilinx.o
spi-nor-objs += xmc.o
+spi-nor-objs += boya.o
spi-nor-objs += xtx.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
--- a/drivers/mtd/spi-nor/controllers/Kconfig
+++ b/drivers/mtd/spi-nor/controllers/Kconfig
@@ -62,3 +62,12 @@ config SPI_INTEL_SPI_PLATFORM
To compile this driver as a module, choose M here: the module
will be called intel-spi-platform.
+
+config SPI_PHYTIUM_QUADSPI
+ tristate "Phytium Quad SPI Controller"
+ depends on ARCH_PHYTIUM || ARM
+ depends on OF && HAS_IOMEM
+ help
+ This enables support for the Quad SPI controller in master mode.
+ This driver does not support generic SPI. The implementation only
+ supports SPI NOR.
--- a/drivers/mtd/spi-nor/controllers/Makefile
+++ b/drivers/mtd/spi-nor/controllers/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi
obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o
obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o
+obj-$(CONFIG_SPI_PHYTIUM_QUADSPI) += phytium-quadspi.o
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2038,6 +2038,7 @@ static const struct spi_nor_manufacturer
&spi_nor_winbond,
&spi_nor_xilinx,
&spi_nor_xmc,
+ &spi_nor_boya,
&spi_nor_xtx,
};
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -398,6 +398,7 @@ extern const struct spi_nor_manufacturer
extern const struct spi_nor_manufacturer spi_nor_winbond;
extern const struct spi_nor_manufacturer spi_nor_xilinx;
extern const struct spi_nor_manufacturer spi_nor_xmc;
+extern const struct spi_nor_manufacturer spi_nor_boya;
extern const struct spi_nor_manufacturer spi_nor_xtx;
int spi_nor_write_enable(struct spi_nor *nor);
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -179,6 +179,8 @@ source "drivers/net/can/softing/Kconfig"
source "drivers/net/can/spi/Kconfig"
source "drivers/net/can/usb/Kconfig"
+source "drivers/net/can/phytium/Kconfig"
+
endif
config CAN_DEBUG_DEVICES
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -29,5 +29,6 @@ obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o
obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o
obj-$(CONFIG_PCH_CAN) += pch_can.o
+obj-$(CONFIG_CAN_PHYTIUM) += phytium/
subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -9,6 +9,7 @@
#include <linux/clk.h>
#include <linux/phylink.h>
+#include <linux/phy.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/net_tstamp.h>
#include <linux/interrupt.h>
@@ -17,6 +18,12 @@
#define MACB_EXT_DESC
#endif
+enum irq_type {
+ IRQ_TYPE_INTX = 1,
+ IRQ_TYPE_MSI = 2,
+ IRQ_TYPE_MAX = 3,
+};
+
#define MACB_GREGS_NBR 16
#define MACB_GREGS_VERSION 2
#define MACB_MAX_QUEUES 8
@@ -77,10 +84,13 @@
#define MACB_RBQPH 0x04D4
/* GEM register offsets. */
+#define GEM_NCR 0x0000 /* Network Control */
#define GEM_NCFGR 0x0004 /* Network Config */
#define GEM_USRIO 0x000c /* User IO */
#define GEM_DMACFG 0x0010 /* DMA Configuration */
#define GEM_JML 0x0048 /* Jumbo Max Length */
+#define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */
+#define GEM_AXI_PIPE 0x0054 /* Axi max pipeline register*/
#define GEM_HRB 0x0080 /* Hash Bottom */
#define GEM_HRT 0x0084 /* Hash Top */
#define GEM_SA1B 0x0088 /* Specific1 Bottom */
@@ -157,6 +167,7 @@
#define GEM_PEFTN 0x01f4 /* PTP Peer Event Frame Tx Ns */
#define GEM_PEFRSL 0x01f8 /* PTP Peer Event Frame Rx Sec Low */
#define GEM_PEFRN 0x01fc /* PTP Peer Event Frame Rx Ns */
+#define GEM_PCSCNTRL 0x0200 /* PCS Control */
#define GEM_DCFG1 0x0280 /* Design Config 1 */
#define GEM_DCFG2 0x0284 /* Design Config 2 */
#define GEM_DCFG3 0x0288 /* Design Config 3 */
@@ -166,6 +177,10 @@
#define GEM_DCFG7 0x0298 /* Design Config 7 */
#define GEM_DCFG8 0x029C /* Design Config 8 */
#define GEM_DCFG10 0x02A4 /* Design Config 10 */
+#define GEM_DCFG12 0x02AC /* Design Config 12 */
+#define GEM_USX_CONTROL 0x0A80 /* High speed PCS control register */
+#define GEM_USX_STATUS 0x0A88 /* High speed PCS status register */
+#define GEM_TAIL_ENABLE 0x0E7C /* Phytium: Enable tail */
#define GEM_TXBDCTRL 0x04cc /* TX Buffer Descriptor control register */
#define GEM_RXBDCTRL 0x04d0 /* RX Buffer Descriptor control register */
@@ -200,6 +215,37 @@
#define GEM_IER(hw_q) (0x0600 + ((hw_q) << 2))
#define GEM_IDR(hw_q) (0x0620 + ((hw_q) << 2))
#define GEM_IMR(hw_q) (0x0640 + ((hw_q) << 2))
+#define GEM_TAIL(hw_q) (0x0e80 + ((hw_q) << 2)) /* Phytium: tail register */
+#define GEM_SRC_SEL_LN 0x1C04
+#define GEM_DIV_SEL0_LN 0x1C08
+#define GEM_DIV_SEL1_LN 0x1C0C
+#define GEM_PMA_XCVR_POWER_STATE 0x1C10
+#define GEM_SPEED_MODE 0x1C14
+#define GEM_MII_SELECT 0x1C18
+#define GEM_SEL_MII_ON_RGMII 0x1C1C
+#define GEM_TX_CLK_SEL0 0x1C20
+#define GEM_TX_CLK_SEL1 0x1C24
+#define GEM_TX_CLK_SEL2 0x1C28
+#define GEM_TX_CLK_SEL3 0x1C2C
+#define GEM_RX_CLK_SEL0 0x1C30
+#define GEM_RX_CLK_SEL1 0x1C34
+#define GEM_CLK_250M_DIV10_DIV100_SEL 0x1C38
+#define GEM_TX_CLK_SEL5 0x1C3C
+#define GEM_TX_CLK_SEL6 0x1C40
+#define GEM_RX_CLK_SEL4 0x1C44
+#define GEM_RX_CLK_SEL5 0x1C48
+#define GEM_TX_CLK_SEL3_0 0x1C70
+#define GEM_TX_CLK_SEL4_0 0x1C74
+#define GEM_RX_CLK_SEL3_0 0x1C78
+#define GEM_RX_CLK_SEL4_0 0x1C7C
+#define GEM_RGMII_TX_CLK_SEL0 0x1C80
+#define GEM_RGMII_TX_CLK_SEL1 0x1C84
+
+#define GEM_PHY_INT_ENABLE 0x1C88
+#define GEM_PHY_INT_CLEAR 0x1C8C
+#define GEM_PHY_INT_STATE 0x1C90
+
+#define GEM_INTX_IRQ_MASK 0x1C7C /* Phytium: irq mask */
/* Bitfields in NCR */
#define MACB_LB_OFFSET 0 /* reserved */
@@ -231,6 +277,8 @@
#define MACB_SRTSM_OFFSET 15
#define MACB_OSSMODE_OFFSET 24 /* Enable One Step Synchro Mode */
#define MACB_OSSMODE_SIZE 1
+#define MACB_2PT5G_OFFSET 29 /* 2.5G operation selected */
+#define MACB_2PT5G_SIZE 1
/* Bitfields in NCFGR */
#define MACB_SPD_OFFSET 0 /* Speed */
@@ -272,11 +320,19 @@
#define MACB_IRXFCS_OFFSET 19
#define MACB_IRXFCS_SIZE 1
+/* GEM specific NCR bitfields. */
+#define GEM_ENABLE_HS_MAC_OFFSET 31
+#define GEM_ENABLE_HS_MAC_SIZE 1
+
/* GEM specific NCFGR bitfields. */
+#define GEM_FD_OFFSET 1 /* Full duplex */
+#define GEM_FD_SIZE 1
#define GEM_GBE_OFFSET 10 /* Gigabit mode enable */
#define GEM_GBE_SIZE 1
#define GEM_PCSSEL_OFFSET 11
#define GEM_PCSSEL_SIZE 1
+#define GEM_PAE_OFFSET 13 /* Pause enable */
+#define GEM_PAE_SIZE 1
#define GEM_CLK_OFFSET 18 /* MDC clock division */
#define GEM_CLK_SIZE 3
#define GEM_DBW_OFFSET 21 /* Data bus width */
@@ -461,11 +517,21 @@
#define MACB_REV_OFFSET 0
#define MACB_REV_SIZE 16
+/* Bitfield in HS_MAC_CONFIG */
+#define GEM_HS_MAC_SPEED_OFFSET 0
+#define GEM_HS_MAC_SPEED_SIZE 3
+
+/* Bitfields in PCSCNTRL */
+#define GEM_PCSAUTONEG_OFFSET 12
+#define GEM_PCSAUTONEG_SIZE 1
+
/* Bitfields in DCFG1. */
#define GEM_IRQCOR_OFFSET 23
#define GEM_IRQCOR_SIZE 1
#define GEM_DBWDEF_OFFSET 25
#define GEM_DBWDEF_SIZE 3
+#define GEM_NO_PCS_OFFSET 0
+#define GEM_NO_PCS_SIZE 1
/* Bitfields in DCFG2. */
#define GEM_RX_PKT_BUFF_OFFSET 20
@@ -500,6 +566,30 @@
#define GEM_RXBD_RDBUFF_OFFSET 8
#define GEM_RXBD_RDBUFF_SIZE 4
+/* Bitfields in DCFG12. */
+#define GEM_HIGH_SPEED_OFFSET 26
+#define GEM_HIGH_SPEED_SIZE 1
+
+/* Bitfields in USX_CONTROL. */
+#define GEM_USX_CTRL_SPEED_OFFSET 14
+#define GEM_USX_CTRL_SPEED_SIZE 3
+#define GEM_SERDES_RATE_OFFSET 12
+#define GEM_SERDES_RATE_SIZE 2
+#define GEM_RX_SCR_BYPASS_OFFSET 9
+#define GEM_RX_SCR_BYPASS_SIZE 1
+#define GEM_TX_SCR_BYPASS_OFFSET 8
+#define GEM_TX_SCR_BYPASS_SIZE 1
+#define GEM_RX_SYNC_RESET_OFFSET 2
+#define GEM_RX_SYNC_RESET_SIZE 1
+#define GEM_TX_EN_OFFSET 1
+#define GEM_TX_EN_SIZE 1
+#define GEM_SIGNAL_OK_OFFSET 0
+#define GEM_SIGNAL_OK_SIZE 1
+
+/* Bitfields in USX_STATUS. */
+#define GEM_USX_BLOCK_LOCK_OFFSET 0
+#define GEM_USX_BLOCK_LOCK_SIZE 1
+
/* Bitfields in TISUBN */
#define GEM_SUBNSINCR_OFFSET 0
#define GEM_SUBNSINCRL_OFFSET 24
@@ -658,11 +748,16 @@
#define MACB_CAPS_GEM_HAS_PTP 0x00000040
#define MACB_CAPS_BD_RD_PREFETCH 0x00000080
#define MACB_CAPS_NEEDS_RSTONUBR 0x00000100
+#define MACB_CAPS_SEL_CLK 0x00000200
+#define MACB_CAPS_TAILPTR 0x00001000 /* Phytium: tail register */
+#define MACB_CAPS_CLK_HW_CHG 0x04000000
#define MACB_CAPS_MACB_IS_EMAC 0x08000000
#define MACB_CAPS_FIFO_MODE 0x10000000
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
#define MACB_CAPS_SG_DISABLED 0x40000000
#define MACB_CAPS_MACB_IS_GEM 0x80000000
+#define MACB_CAPS_PCS 0x01000000
+#define MACB_CAPS_HIGH_SPEED 0x02000000
/* LSO settings */
#define MACB_LSO_UFO_ENABLE 0x01
@@ -1112,6 +1207,7 @@ struct macb_config {
struct clk **rx_clk, struct clk **tsu_clk);
int (*init)(struct platform_device *pdev);
int jumbo_max_len;
+ void (*sel_clk_hw)(struct macb *bp, int speed);
};
struct tsu_incr {
@@ -1132,6 +1228,7 @@ struct macb_queue {
unsigned int RBQS;
unsigned int RBQP;
unsigned int RBQPH;
+ unsigned int TAILADDR;
unsigned int tx_head, tx_tail;
struct macb_dma_desc *tx_ring;
@@ -1191,6 +1288,7 @@ struct macb {
struct clk *rx_clk;
struct clk *tsu_clk;
struct net_device *dev;
+ struct ncsi_dev *ndev;
union {
struct macb_stats macb;
struct gem_stats gem;
@@ -1201,7 +1299,13 @@ struct macb {
struct mii_bus *mii_bus;
struct phylink *phylink;
struct phylink_config phylink_config;
+ struct phylink_pcs phylink_pcs;
+ int link;
+ int speed;
+ int duplex;
+ int use_ncsi;
+ int force_phy_mode;
u32 caps;
unsigned int dma_burst_length;
@@ -1244,6 +1348,8 @@ struct macb {
u32 rx_intr_mask;
struct macb_pm_data pm_data;
+
+ void (*sel_clk_hw)(struct macb *bp, int speed);
};
#ifdef CONFIG_MACB_USE_HWSTAMP
@@ -1301,6 +1407,24 @@ static inline bool gem_has_ptp(struct ma
return !!(bp->caps & MACB_CAPS_GEM_HAS_PTP);
}
+enum phytium_type {
+ PHYTIUM_DEV_1P0 = 1,
+ PHYTIUM_DEV_2P0,
+ PHYTIUM_DEV_3P0,
+};
+
+struct phytium_platform_pdata {
+ int phytium_dev_type;
+ struct clk *txclk;
+ struct clk *rxclk;
+ struct clk *tsu_clk;
+ u32 caps;
+ int irq_type;
+ int irq[4];
+ phy_interface_t phy_interface;
+ const struct property_entry *properties;
+};
+
/**
* struct macb_platform_data - platform data for MACB Ethernet used for PCI registration
* @pclk: platform clock
@@ -1309,6 +1433,7 @@ static inline bool gem_has_ptp(struct ma
struct macb_platform_data {
struct clk *pclk;
struct clk *hclk;
+ struct phytium_platform_pdata phytium_macb_pdata;
};
#endif /* _MACB_H */
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -35,6 +35,8 @@
#include <linux/tcp.h>
#include <linux/iopoll.h>
#include <linux/pm_runtime.h>
+#include <linux/acpi.h>
+#include <net/ncsi.h>
#include "macb.h"
/* This structure is only used for MACB on SiFive FU540 devices */
@@ -84,6 +86,14 @@ struct sifive_fu540_macb_mgmt {
#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0)
#define MACB_WOL_ENABLED (0x1 << 1)
+#define HS_SPEED_100M 0
+#define HS_SPEED_1000M 1
+#define HS_SPEED_2500M 2
+#define HS_SPEED_5000M 3
+#define HS_SPEED_10000M 4
+#define MACB_SERDES_RATE_5G 0
+#define MACB_SERDES_RATE_10G 1
+
/* Graceful stop timeouts in us. We should allow up to
* 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
*/
@@ -513,6 +523,10 @@ static void macb_validate(struct phylink
state->interface != PHY_INTERFACE_MODE_RMII &&
state->interface != PHY_INTERFACE_MODE_GMII &&
state->interface != PHY_INTERFACE_MODE_SGMII &&
+ state->interface != PHY_INTERFACE_MODE_2500BASEX &&
+ state->interface != PHY_INTERFACE_MODE_5GBASER &&
+ state->interface != PHY_INTERFACE_MODE_10GBASER &&
+ state->interface != PHY_INTERFACE_MODE_USXGMII &&
!phy_interface_mode_is_rgmii(state->interface)) {
bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
return;
@@ -525,10 +539,47 @@ static void macb_validate(struct phylink
return;
}
+ if ((state->interface == PHY_INTERFACE_MODE_10GBASER ||
+ state->interface == PHY_INTERFACE_MODE_USXGMII ||
+ state->interface == PHY_INTERFACE_MODE_5GBASER) &&
+ !(bp->caps & MACB_CAPS_HIGH_SPEED &&
+ bp->caps & MACB_CAPS_PCS)) {
+ bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
+ return;
+ }
+
phylink_set_port_modes(mask);
phylink_set(mask, Autoneg);
phylink_set(mask, Asym_Pause);
+ if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE &&
+ (state->interface == PHY_INTERFACE_MODE_NA ||
+ state->interface == PHY_INTERFACE_MODE_10GBASER ||
+ state->interface == PHY_INTERFACE_MODE_USXGMII)) {
+ bp->speed = state->speed;
+ bp->link = 1;
+ bp->duplex = state->duplex;
+ if (bp->speed == SPEED_5000) {
+ phylink_set(mask, 5000baseT_Full);
+ } else {
+ phylink_set(mask, 10000baseCR_Full);
+ phylink_set(mask, 10000baseER_Full);
+ phylink_set(mask, 10000baseKR_Full);
+ phylink_set(mask, 10000baseLR_Full);
+ phylink_set(mask, 10000baseLRM_Full);
+ phylink_set(mask, 10000baseSR_Full);
+ phylink_set(mask, 10000baseT_Full);
+ }
+ if (state->interface != PHY_INTERFACE_MODE_NA)
+ goto out;
+ }
+
+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
+ phylink_set(mask, 2500baseX_Full);
+
+ if (state->interface == PHY_INTERFACE_MODE_5GBASER)
+ phylink_set(mask, 5000baseT_Full);
+
phylink_set(mask, 10baseT_Half);
phylink_set(mask, 10baseT_Full);
phylink_set(mask, 100baseT_Half);
@@ -545,23 +596,110 @@ static void macb_validate(struct phylink
if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
phylink_set(mask, 1000baseT_Half);
}
-
+out:
bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
bitmap_and(state->advertising, state->advertising, mask,
__ETHTOOL_LINK_MODE_MASK_NBITS);
}
-static void macb_mac_pcs_get_state(struct phylink_config *config,
+static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+ phy_interface_t interface, int speed,
+ int duplex)
+{
+ struct macb *bp = container_of(pcs, struct macb, phylink_pcs);
+ u32 config;
+
+ config = gem_readl(bp, USX_CONTROL);
+ if (speed == SPEED_10000) {
+ config = GEM_BFINS(SERDES_RATE, MACB_SERDES_RATE_10G, config);
+ config = GEM_BFINS(USX_CTRL_SPEED, HS_SPEED_10000M, config);
+ } else if (speed == SPEED_5000) {
+ config = GEM_BFINS(SERDES_RATE, MACB_SERDES_RATE_5G, config);
+ config = GEM_BFINS(USX_CTRL_SPEED, HS_SPEED_5000M, config);
+ }
+
+ config &= ~(GEM_BIT(TX_SCR_BYPASS) | GEM_BIT(RX_SCR_BYPASS));
+ /* reset */
+ config &= ~(GEM_BIT(SIGNAL_OK) | GEM_BIT(TX_EN));
+ config |= GEM_BIT(RX_SYNC_RESET);
+
+ gem_writel(bp, USX_CONTROL, config);
+
+ /* enable rx and tx */
+ config &= ~(GEM_BIT(RX_SYNC_RESET));
+ config |= GEM_BIT(SIGNAL_OK) | GEM_BIT(TX_EN);
+
+ gem_writel(bp, USX_CONTROL, config);
+}
+
+static void macb_usx_pcs_get_state(struct phylink_pcs *pcs,
struct phylink_link_state *state)
{
+ struct macb *bp = container_of(pcs, struct macb, phylink_pcs);
+ u32 val;
+
+ if (state->interface == PHY_INTERFACE_MODE_5GBASER)
+ state->speed = SPEED_5000;
+ else if (state->interface == PHY_INTERFACE_MODE_10GBASER ||
+ state->interface == PHY_INTERFACE_MODE_USXGMII)
+ state->speed = bp->speed;
+
+ state->duplex = 1;
+ state->an_complete = 1;
+
+ val = gem_readl(bp, USX_STATUS);
+ state->link = !!(val & GEM_BIT(USX_BLOCK_LOCK));
+ val = gem_readl(bp, NCFGR);
+ if (val & GEM_BIT(PAE))
+ state->pause = MLO_PAUSE_RX;
+}
+
+static int macb_usx_pcs_config(struct phylink_pcs *pcs,
+ unsigned int mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
+{
+ struct macb *bp = container_of(pcs, struct macb, phylink_pcs);
+
+ gem_writel(bp, USX_CONTROL, gem_readl(bp, USX_CONTROL) |
+ GEM_BIT(SIGNAL_OK));
+
+ return 0;
+}
+
+static void macb_pcs_get_state(struct phylink_pcs *pcs,
+ struct phylink_link_state *state)
+{
state->link = 0;
}
-static void macb_mac_an_restart(struct phylink_config *config)
+static void macb_pcs_an_restart(struct phylink_pcs *pcs)
{
/* Not supported */
}
+static int macb_pcs_config(struct phylink_pcs *pcs,
+ unsigned int mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
+{
+ return 0;
+}
+
+static const struct phylink_pcs_ops macb_phylink_usx_pcs_ops = {
+ .pcs_get_state = macb_usx_pcs_get_state,
+ .pcs_config = macb_usx_pcs_config,
+ .pcs_link_up = macb_usx_pcs_link_up,
+};
+
+static const struct phylink_pcs_ops macb_phylink_pcs_ops = {
+ .pcs_get_state = macb_pcs_get_state,
+ .pcs_an_restart = macb_pcs_an_restart,
+ .pcs_config = macb_pcs_config,
+};
+
static void macb_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
@@ -569,25 +707,57 @@ static void macb_mac_config(struct phyli
struct macb *bp = netdev_priv(ndev);
unsigned long flags;
u32 old_ctrl, ctrl;
+ u32 old_ncr, ncr;
spin_lock_irqsave(&bp->lock, flags);
- old_ctrl = ctrl = macb_or_gem_readl(bp, NCFGR);
+ ctrl = macb_or_gem_readl(bp, NCFGR);
+ old_ctrl = ctrl;
+ ncr = macb_or_gem_readl(bp, NCR);
+ old_ncr = ncr;
if (bp->caps & MACB_CAPS_MACB_IS_EMAC) {
if (state->interface == PHY_INTERFACE_MODE_RMII)
ctrl |= MACB_BIT(RM9200_RMII);
} else if (macb_is_gem(bp)) {
ctrl &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
+ ncr &= ~GEM_BIT(ENABLE_HS_MAC);
- if (state->interface == PHY_INTERFACE_MODE_SGMII)
+ if (state->interface == PHY_INTERFACE_MODE_SGMII ||
+ state->interface == PHY_INTERFACE_MODE_2500BASEX) {
ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
+ } else if (state->interface == PHY_INTERFACE_MODE_10GBASER ||
+ state->interface == PHY_INTERFACE_MODE_USXGMII ||
+ state->interface == PHY_INTERFACE_MODE_5GBASER) {
+ ctrl |= GEM_BIT(PCSSEL);
+ ncr |= GEM_BIT(ENABLE_HS_MAC);
+ }
}
/* Apply the new configuration, if any */
if (old_ctrl ^ ctrl)
macb_or_gem_writel(bp, NCFGR, ctrl);
+ if (old_ncr ^ ncr)
+ macb_or_gem_writel(bp, NCR, ncr);
+
+ /* Disable AN for SGMII fixed link configuration, enable otherwise.
+ * Must be written after PCSSEL is set in NCFGR,
+ * otherwise writes will not take effect.
+ */
+ if (macb_is_gem(bp) && (state->interface == PHY_INTERFACE_MODE_SGMII ||
+ PHY_INTERFACE_MODE_2500BASEX)) {
+ u32 pcsctrl, old_pcsctrl;
+
+ old_pcsctrl = gem_readl(bp, PCSCNTRL);
+ if (mode == MLO_AN_FIXED)
+ pcsctrl = old_pcsctrl & ~GEM_BIT(PCSAUTONEG);
+ else
+ pcsctrl = old_pcsctrl | GEM_BIT(PCSAUTONEG);
+ if (old_pcsctrl != pcsctrl)
+ gem_writel(bp, PCSCNTRL, pcsctrl);
+ }
+
spin_unlock_irqrestore(&bp->lock, flags);
}
@@ -600,18 +770,184 @@ static void macb_mac_link_down(struct ph
unsigned int q;
u32 ctrl;
+ if (bp->use_ncsi)
+ ncsi_stop_dev(bp->ndev);
+
if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC))
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
queue_writel(queue, IDR,
bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
/* Disable Rx and Tx */
- ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE));
+ ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE)) & ~(MACB_BIT(2PT5G));
macb_writel(bp, NCR, ctrl);
netif_tx_stop_all_queues(ndev);
}
+static void phytium_gem1p0_sel_clk(struct macb *bp, int speed)
+{
+ if (bp->phy_interface == PHY_INTERFACE_MODE_10GBASER ||
+ bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) {
+ gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/
+ if (speed == SPEED_5000) {
+ gem_writel(bp, DIV_SEL0_LN, 0x8); /*0x1c08*/
+ gem_writel(bp, DIV_SEL0_LN, 0x8); /*0x1c08*/
+ gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/
+ gem_writel(bp, PMA_XCVR_POWER_STATE, 0x0); /*0x1c10*/
+ } else {
+ gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/
+ gem_writel(bp, DIV_SEL1_LN, 0x1); /*0x1c0c*/
+ gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/
+ }
+ } else if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) {
+ gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/
+ gem_writel(bp, DIV_SEL0_LN, 0x8); /*0x1c08*/
+ gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/
+ gem_writel(bp, PMA_XCVR_POWER_STATE, 0x0); /*0x1c10*/
+ } else if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) {
+ gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/
+ gem_writel(bp, DIV_SEL0_LN, 0x1); /*0x1c08*/
+ gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/
+ gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/
+ gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/
+ gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/
+ gem_writel(bp, TX_CLK_SEL2, 0x1); /*0x1c28*/
+ gem_writel(bp, TX_CLK_SEL3, 0x1); /*0x1c2c*/
+ gem_writel(bp, RX_CLK_SEL0, 0x1); /*0x1c30*/
+ gem_writel(bp, RX_CLK_SEL1, 0x0); /*0x1c34*/
+ gem_writel(bp, TX_CLK_SEL3_0, 0x0); /*0x1c70*/
+ gem_writel(bp, TX_CLK_SEL4_0, 0x0); /*0x1c74*/
+ gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/
+ gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/
+ } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ if (speed == SPEED_1000) {
+ gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/
+ gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/
+ gem_writel(bp, DIV_SEL1_LN, 0x8); /*0x1c0c*/
+ gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/
+ gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/
+ gem_writel(bp, TX_CLK_SEL1, 0x0); /*0x1c24*/
+ gem_writel(bp, TX_CLK_SEL2, 0x0); /*0x1c28*/
+ gem_writel(bp, TX_CLK_SEL3, 0x1); /*0x1c2c*/
+ gem_writel(bp, RX_CLK_SEL0, 0x1); /*0x1c30*/
+ gem_writel(bp, RX_CLK_SEL1, 0x0); /*0x1c34*/
+ gem_writel(bp, TX_CLK_SEL3_0, 0x0); /*0x1c70*/
+ gem_writel(bp, TX_CLK_SEL4_0, 0x0); /*0x1c74*/
+ gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/
+ gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/
+ } else if (speed == SPEED_100 || speed == SPEED_10) {
+ gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/
+ gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/
+ gem_writel(bp, DIV_SEL1_LN, 0x8); /*0x1c0c*/
+ gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/
+ gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/
+ gem_writel(bp, TX_CLK_SEL1, 0x0); /*0x1c24*/
+ gem_writel(bp, TX_CLK_SEL2, 0x1); /*0x1c28*/
+ gem_writel(bp, TX_CLK_SEL3, 0x1); /*0x1c2c*/
+ gem_writel(bp, RX_CLK_SEL0, 0x1); /*0x1c30*/
+ gem_writel(bp, RX_CLK_SEL1, 0x0); /*0x1c34*/
+ gem_writel(bp, TX_CLK_SEL3_0, 0x1); /*0x1c70*/
+ gem_writel(bp, TX_CLK_SEL4_0, 0x0); /*0x1c74*/
+ gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/
+ gem_writel(bp, RX_CLK_SEL4_0, 0x1); /*0x1c7c*/
+ }
+ } else if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+ bp->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) {
+ if (speed == SPEED_1000) {
+ gem_writel(bp, MII_SELECT, 0x1); /*0x1c18*/
+ gem_writel(bp, SEL_MII_ON_RGMII, 0x0); /*0x1c1c*/
+ gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/
+ gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/
+ gem_writel(bp, TX_CLK_SEL2, 0x0); /*0x1c28*/
+ gem_writel(bp, TX_CLK_SEL3, 0x0); /*0x1c2c*/
+ gem_writel(bp, RX_CLK_SEL0, 0x0); /*0x1c30*/
+ gem_writel(bp, RX_CLK_SEL1, 0x1); /*0x1c34*/
+ gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x0); /*0x1c38*/
+ gem_writel(bp, RX_CLK_SEL5, 0x1); /*0x1c48*/
+ gem_writel(bp, RGMII_TX_CLK_SEL0, 0x1); /*0x1c80*/
+ gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); /*0x1c84*/
+ } else if (speed == SPEED_100) {
+ gem_writel(bp, MII_SELECT, 0x1); /*0x1c18*/
+ gem_writel(bp, SEL_MII_ON_RGMII, 0x0); /*0x1c1c*/
+ gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/
+ gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/
+ gem_writel(bp, TX_CLK_SEL2, 0x0); /*0x1c28*/
+ gem_writel(bp, TX_CLK_SEL3, 0x0); /*0x1c2c*/
+ gem_writel(bp, RX_CLK_SEL0, 0x0); /*0x1c30*/
+ gem_writel(bp, RX_CLK_SEL1, 0x1); /*0x1c34*/
+ gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x0); /*0x1c38*/
+ gem_writel(bp, RX_CLK_SEL5, 0x1); /*0x1c48*/
+ gem_writel(bp, RGMII_TX_CLK_SEL0, 0x0); /*0x1c80*/
+ gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); /*0x1c84*/
+ } else {
+ gem_writel(bp, MII_SELECT, 0x1); /*0x1c18*/
+ gem_writel(bp, SEL_MII_ON_RGMII, 0x0); /*0x1c1c*/
+ gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/
+ gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/
+ gem_writel(bp, TX_CLK_SEL2, 0x0); /*0x1c28*/
+ gem_writel(bp, TX_CLK_SEL3, 0x0); /*0x1c2c*/
+ gem_writel(bp, RX_CLK_SEL0, 0x0); /*0x1c30*/
+ gem_writel(bp, RX_CLK_SEL1, 0x1); /*0x1c34*/
+ gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x1); /*0x1c38*/
+ gem_writel(bp, RX_CLK_SEL5, 0x1); /*0x1c48*/
+ gem_writel(bp, RGMII_TX_CLK_SEL0, 0x0); /*0x1c80*/
+ gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); /*0x1c84*/
+ }
+ } else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII) {
+ gem_writel(bp, RX_CLK_SEL5, 0x1); /*0x1c48*/
+ }
+
+ if (speed == SPEED_100)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_100M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else if (speed == SPEED_1000)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_1000M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else if (speed == SPEED_2500)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_2500M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else if (speed == SPEED_5000)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_5000M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else if (speed == SPEED_10000)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_10000M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+}
+
+static void phytium_gem2p0_sel_clk(struct macb *bp, int speed)
+{
+ if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
+ if (speed == SPEED_100 || speed == SPEED_10) {
+ gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/
+ gem_writel(bp, DIV_SEL1_LN, 0x1); /*0x1c0c*/
+ }
+ }
+
+ if (speed == SPEED_100 || speed == SPEED_10)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_100M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else if (speed == SPEED_1000)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_1000M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else if (speed == SPEED_2500)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_2500M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+}
+
+static void phytium_gem3p0_sel_clk(struct macb *bp, int speed)
+{
+ if (speed == SPEED_100 || speed == SPEED_10)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_100M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else if (speed == SPEED_1000)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_1000M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else if (speed == SPEED_2500)
+ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_2500M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+}
+
static void macb_mac_link_up(struct phylink_config *config,
struct phy_device *phy,
unsigned int mode, phy_interface_t interface,
@@ -624,9 +960,13 @@ static void macb_mac_link_up(struct phyl
unsigned long flags;
unsigned int q;
u32 ctrl;
+ int err;
spin_lock_irqsave(&bp->lock, flags);
+ if (bp->caps & MACB_CAPS_SEL_CLK)
+ bp->sel_clk_hw(bp, speed);
+
ctrl = macb_or_gem_readl(bp, NCFGR);
ctrl &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
@@ -642,7 +982,7 @@ static void macb_mac_link_up(struct phyl
if (macb_is_gem(bp)) {
ctrl &= ~GEM_BIT(GBE);
- if (speed == SPEED_1000)
+ if (speed == SPEED_1000 || speed == SPEED_2500)
ctrl |= GEM_BIT(GBE);
}
@@ -664,18 +1004,71 @@ static void macb_mac_link_up(struct phyl
macb_or_gem_writel(bp, NCFGR, ctrl);
+ if (speed == SPEED_2500) {
+ u32 network_ctrl;
+
+ network_ctrl = macb_readl(bp, NCR);
+ network_ctrl |= MACB_BIT(2PT5G);
+ macb_writel(bp, NCR, network_ctrl);
+ }
+
+ if (bp->phy_interface == PHY_INTERFACE_MODE_10GBASER ||
+ bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) {
+ if (speed == SPEED_5000)
+ gem_writel(bp, HS_MAC_CONFIG,
+ GEM_BFINS(HS_MAC_SPEED, HS_SPEED_5000M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ else
+ gem_writel(bp, HS_MAC_CONFIG,
+ GEM_BFINS(HS_MAC_SPEED, HS_SPEED_10000M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+ } else if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER)
+ gem_writel(bp, HS_MAC_CONFIG,
+ GEM_BFINS(HS_MAC_SPEED, HS_SPEED_5000M,
+ gem_readl(bp, HS_MAC_CONFIG)));
+
spin_unlock_irqrestore(&bp->lock, flags);
/* Enable Rx and Tx */
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE));
+ if (bp->use_ncsi) {
+ /* Start the NCSI device */
+ err = ncsi_start_dev(bp->ndev);
+ if (err) {
+ netdev_err(bp->dev, "Ncsi start dev failed (error %d)\n", err);
+ return;
+ }
+ }
+
netif_tx_wake_all_queues(ndev);
}
+static int macb_mac_prepare(struct phylink_config *config, unsigned int mode,
+ phy_interface_t interface)
+{
+ struct net_device *ndev = to_net_dev(config->dev);
+ struct macb *bp = netdev_priv(ndev);
+
+ if (interface == PHY_INTERFACE_MODE_10GBASER ||
+ interface == PHY_INTERFACE_MODE_5GBASER ||
+ interface == PHY_INTERFACE_MODE_USXGMII)
+ bp->phylink_pcs.ops = &macb_phylink_usx_pcs_ops;
+ else if (interface == PHY_INTERFACE_MODE_SGMII ||
+ interface == PHY_INTERFACE_MODE_2500BASEX)
+ bp->phylink_pcs.ops = &macb_phylink_pcs_ops;
+ else
+ bp->phylink_pcs.ops = NULL;
+
+ if (bp->phylink_pcs.ops)
+ phylink_set_pcs(bp->phylink, &bp->phylink_pcs);
+
+ return 0;
+}
+
static const struct phylink_mac_ops macb_phylink_ops = {
.validate = macb_validate,
- .mac_pcs_get_state = macb_mac_pcs_get_state,
- .mac_an_restart = macb_mac_an_restart,
+ .mac_prepare = macb_mac_prepare,
.mac_config = macb_mac_config,
.mac_link_down = macb_mac_link_down,
.mac_link_up = macb_mac_link_up,
@@ -693,8 +1086,14 @@ static int macb_phylink_connect(struct m
struct device_node *dn = bp->pdev->dev.of_node;
struct net_device *dev = bp->dev;
struct phy_device *phydev;
+ struct macb_platform_data *pdata = dev_get_platdata(&bp->pdev->dev);
int ret;
+ if (pdata && pdata->phytium_macb_pdata.properties) {
+ phylink_start(bp->phylink);
+ return 0;
+ }
+
if (dn)
ret = phylink_of_phy_connect(bp->phylink, dn, 0);
@@ -704,6 +1103,7 @@ static int macb_phylink_connect(struct m
netdev_err(dev, "no PHY found\n");
return -ENXIO;
}
+ phydev->force_mode = bp->force_phy_mode;
/* attach the mac to the phy */
ret = phylink_connect_phy(bp->phylink, phydev);
@@ -719,6 +1119,29 @@ static int macb_phylink_connect(struct m
return 0;
}
+static void macb_get_pcs_fixed_state(struct phylink_config *config,
+ struct phylink_link_state *state)
+{
+ struct net_device *ndev = to_net_dev(config->dev);
+ struct macb *bp = netdev_priv(ndev);
+
+ state->link = (macb_readl(bp, NSR) & MACB_BIT(NSR_LINK)) != 0;
+}
+
+static void macb_get_usx_pcs_fixed_state(struct phylink_config *config,
+ struct phylink_link_state *state)
+{
+ u32 val;
+ struct net_device *ndev = to_net_dev(config->dev);
+ struct macb *bp = netdev_priv(ndev);
+
+ val = gem_readl(bp, USX_STATUS);
+ state->link = !!(val & GEM_BIT(USX_BLOCK_LOCK));
+ val = gem_readl(bp, NCFGR);
+ if (val & GEM_BIT(PAE))
+ state->pause = MLO_PAUSE_RX;
+}
+
/* based on au1000_eth. c*/
static int macb_mii_probe(struct net_device *dev)
{
@@ -727,8 +1150,19 @@ static int macb_mii_probe(struct net_dev
bp->phylink_config.dev = &dev->dev;
bp->phylink_config.type = PHYLINK_NETDEV;
+ if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII ||
+ bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) {
+ bp->phylink_config.poll_fixed_state = true;
+ bp->phylink_config.get_fixed_state = macb_get_pcs_fixed_state;
+ } else if (bp->phy_interface == PHY_INTERFACE_MODE_10GBASER ||
+ bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) {
+ bp->phylink_config.poll_fixed_state = true;
+ bp->phylink_config.get_fixed_state = macb_get_usx_pcs_fixed_state;
+ }
+
bp->phylink = phylink_create(&bp->phylink_config, bp->pdev->dev.fwnode,
bp->phy_interface, &macb_phylink_ops);
+
if (IS_ERR(bp->phylink)) {
netdev_err(dev, "Could not create a phylink instance (%ld)\n",
PTR_ERR(bp->phylink));
@@ -2097,6 +2531,8 @@ static netdev_tx_t macb_start_xmit(struc
wmb();
skb_tx_timestamp(skb);
+ if (bp->caps & MACB_CAPS_TAILPTR)
+ queue_writel(queue, TAILADDR, BIT(31) | macb_tx_ring_wrap(bp, queue->tx_head));
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)
@@ -2294,6 +2730,9 @@ static void gem_init_rings(struct macb *
queue->tx_head = 0;
queue->tx_tail = 0;
+ if (bp->caps & MACB_CAPS_TAILPTR)
+ queue_writel(queue, TAILADDR, BIT(31) | queue->tx_head);
+
queue->rx_tail = 0;
queue->rx_prepared_head = 0;
@@ -2463,6 +2902,45 @@ static void macb_configure_dma(struct ma
}
}
+static int phytium_mac_config(struct macb *bp)
+{
+ u32 old_ctrl, ctrl;
+ u32 old_ncr, ncr;
+
+ netdev_dbg(bp->dev, "phytium mac config");
+
+ ncr = macb_readl(bp, NCR);
+ old_ncr = ncr;
+ ctrl = macb_or_gem_readl(bp, NCFGR);
+ old_ctrl = ctrl;
+
+ ncr &= ~(GEM_BIT(ENABLE_HS_MAC) | MACB_BIT(2PT5G));
+ ctrl &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL) | MACB_BIT(SPD) | MACB_BIT(FD));
+ if (macb_is_gem(bp))
+ ctrl &= ~GEM_BIT(GBE);
+
+ if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) {
+ ctrl |= GEM_BIT(PCSSEL) | GEM_BIT(SGMIIEN);
+ ncr |= MACB_BIT(2PT5G);
+ } else if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
+ bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) {
+ ctrl |= GEM_BIT(PCSSEL);
+ ncr |= GEM_BIT(ENABLE_HS_MAC);
+ }
+
+ if (bp->duplex)
+ ctrl |= MACB_BIT(FD);
+
+ /* Apply the new configuration, if any */
+ if (old_ctrl ^ ctrl)
+ macb_or_gem_writel(bp, NCFGR, ctrl);
+
+ if (old_ncr ^ ncr)
+ macb_or_gem_writel(bp, NCR, ncr);
+
+ return 0;
+}
+
static void macb_init_hw(struct macb *bp)
{
u32 config;
@@ -2491,6 +2969,25 @@ static void macb_init_hw(struct macb *bp
if (bp->caps & MACB_CAPS_JUMBO)
bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK;
+ gem_writel(bp, AXI_PIPE, 0x1010);
+ if (bp->caps & MACB_CAPS_TAILPTR)
+ gem_writel(bp, TAIL_ENABLE, 0x80000001);
+
+ if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
+ bp->phy_interface == PHY_INTERFACE_MODE_5GBASER ||
+ bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) {
+ /* phytium need hwclock */
+ if (bp->caps & MACB_CAPS_SEL_CLK)
+ bp->sel_clk_hw(bp, bp->speed);
+ phytium_mac_config(bp);
+ if (bp->link)
+ macb_usx_pcs_link_up(&bp->phylink_pcs, 0,
+ bp->phy_interface, bp->speed, bp->duplex);
+ } else {
+ bp->speed = SPEED_10;
+ bp->duplex = DUPLEX_HALF;
+ }
+
macb_configure_dma(bp);
}
@@ -2615,7 +3112,10 @@ static void macb_set_rx_mode(struct net_
static int macb_open(struct net_device *dev)
{
- size_t bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;
+ /* adjust bufsz to be at least the size of a standard frame,
+ * to fix rx error when set small size mtu.
+ */
+ size_t bufsz = (dev->mtu < ETH_DATA_LEN ? ETH_DATA_LEN : dev->mtu) + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;
struct macb *bp = netdev_priv(dev);
struct macb_queue *queue;
unsigned int q;
@@ -3543,6 +4043,8 @@ static const struct net_device_ops macb_
#endif
.ndo_set_features = macb_set_features,
.ndo_features_check = macb_features_check,
+ .ndo_vlan_rx_add_vid = ncsi_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ncsi_vlan_rx_kill_vid,
};
/* Configure peripheral capabilities according to device tree
@@ -3552,16 +4054,26 @@ static void macb_configure_caps(struct m
const struct macb_config *dt_conf)
{
u32 dcfg;
+ struct macb_platform_data *pdata;
if (dt_conf)
bp->caps = dt_conf->caps;
+ pdata = dev_get_platdata(&bp->pdev->dev);
+ if (pdata && pdata->phytium_macb_pdata.phytium_dev_type == PHYTIUM_DEV_3P0)
+ bp->caps |= pdata->phytium_macb_pdata.caps;
+
if (hw_is_gem(bp->regs, bp->native_io)) {
bp->caps |= MACB_CAPS_MACB_IS_GEM;
dcfg = gem_readl(bp, DCFG1);
if (GEM_BFEXT(IRQCOR, dcfg) == 0)
bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
+ if (GEM_BFEXT(NO_PCS, dcfg) == 0)
+ bp->caps |= MACB_CAPS_PCS;
+ dcfg = gem_readl(bp, DCFG12);
+ if (GEM_BFEXT(HIGH_SPEED, dcfg) == 1)
+ bp->caps |= MACB_CAPS_HIGH_SPEED;
dcfg = gem_readl(bp, DCFG2);
if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
bp->caps |= MACB_CAPS_FIFO_MODE;
@@ -3603,6 +4115,165 @@ static void macb_probe_queues(void __iom
*num_queues = hweight32(*queue_mask);
}
+#ifdef CONFIG_ACPI
+static int phytium_clk_acpi_init(struct platform_device *pdev, struct clk **pclk,
+ struct clk **hclk, struct clk **tx_clk,
+ struct clk **rx_clk, struct clk **tsu_clk)
+{
+ struct macb_platform_data *pdata;
+ int err;
+
+ pdata = dev_get_platdata(&pdev->dev);
+ if (pdata) {
+ *pclk = pdata->pclk;
+ *hclk = pdata->hclk;
+ *tx_clk = pdata->phytium_macb_pdata.txclk;
+ *rx_clk = pdata->phytium_macb_pdata.rxclk;
+ *tsu_clk = pdata->phytium_macb_pdata.tsu_clk;
+ } else {
+ *pclk = NULL;
+ *hclk = NULL;
+ *tx_clk = NULL;
+ *rx_clk = NULL;
+ *tsu_clk = NULL;
+ }
+
+ err = clk_prepare_enable(*pclk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable pclk (%d)\n", err);
+ return err;
+ }
+
+ err = clk_prepare_enable(*hclk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable hclk (%d)\n", err);
+ goto err_disable_pclk;
+ }
+
+ err = clk_prepare_enable(*tx_clk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable tx_clk (%d)\n", err);
+ goto err_disable_hclk;
+ }
+
+ err = clk_prepare_enable(*rx_clk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable rx_clk (%d)\n", err);
+ goto err_disable_txclk;
+ }
+
+ err = clk_prepare_enable(*tsu_clk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable tsu_clk (%d)\n", err);
+ goto err_disable_rxclk;
+ }
+
+ return 0;
+
+err_disable_rxclk:
+ clk_disable_unprepare(*rx_clk);
+
+err_disable_txclk:
+ clk_disable_unprepare(*tx_clk);
+
+err_disable_hclk:
+ clk_disable_unprepare(*hclk);
+
+err_disable_pclk:
+ clk_disable_unprepare(*pclk);
+
+ return err;
+}
+#endif
+
+static int phytium_clk_init(struct platform_device *pdev, struct clk **pclk,
+ struct clk **hclk, struct clk **tx_clk,
+ struct clk **rx_clk, struct clk **tsu_clk)
+{
+ struct macb_platform_data *pdata;
+ int err;
+
+ pdata = dev_get_platdata(&pdev->dev);
+ if (pdata) {
+ *pclk = pdata->pclk;
+ *hclk = pdata->hclk;
+ *tx_clk = pdata->phytium_macb_pdata.txclk;
+ *rx_clk = pdata->phytium_macb_pdata.rxclk;
+ *tsu_clk = pdata->phytium_macb_pdata.tsu_clk;
+ } else {
+ *pclk = devm_clk_get(&pdev->dev, "pclk");
+ *hclk = devm_clk_get(&pdev->dev, "hclk");
+ *tx_clk = devm_clk_get_optional(&pdev->dev, "tx_clk");
+ *rx_clk = devm_clk_get_optional(&pdev->dev, "rx_clk");
+ *tsu_clk = devm_clk_get_optional(&pdev->dev, "tsu_clk");
+ }
+
+ if (IS_ERR_OR_NULL(*pclk))
+ return dev_err_probe(&pdev->dev,
+ IS_ERR(*pclk) ? PTR_ERR(*pclk) : -ENODEV,
+ "failed to get pclk\n");
+
+ if (IS_ERR_OR_NULL(*hclk))
+ return dev_err_probe(&pdev->dev,
+ IS_ERR(*hclk) ? PTR_ERR(*hclk) : -ENODEV,
+ "failed to get hclk\n");
+
+ if (IS_ERR(*tx_clk))
+ return PTR_ERR(*tx_clk);
+
+ if (IS_ERR(*rx_clk))
+ return PTR_ERR(*rx_clk);
+
+ if (IS_ERR(*tsu_clk))
+ return PTR_ERR(*tsu_clk);
+
+ err = clk_prepare_enable(*pclk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable pclk (%d)\n", err);
+ return err;
+ }
+
+ err = clk_prepare_enable(*hclk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable hclk (%d)\n", err);
+ goto err_disable_pclk;
+ }
+
+ err = clk_prepare_enable(*tx_clk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable tx_clk (%d)\n", err);
+ goto err_disable_hclk;
+ }
+
+ err = clk_prepare_enable(*rx_clk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable rx_clk (%d)\n", err);
+ goto err_disable_txclk;
+ }
+
+ err = clk_prepare_enable(*tsu_clk);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable tsu_clk (%d)\n", err);
+ goto err_disable_rxclk;
+ }
+
+ return 0;
+
+err_disable_rxclk:
+ clk_disable_unprepare(*rx_clk);
+
+err_disable_txclk:
+ clk_disable_unprepare(*tx_clk);
+
+err_disable_hclk:
+ clk_disable_unprepare(*hclk);
+
+err_disable_pclk:
+ clk_disable_unprepare(*pclk);
+
+ return err;
+}
+
static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
struct clk **hclk, struct clk **tx_clk,
struct clk **rx_clk, struct clk **tsu_clk)
@@ -3696,6 +4367,225 @@ err_disable_pclk:
return err;
}
+static irqreturn_t phytium_macb_interrupt_intx(int irq, void *dev_id)
+{
+ struct macb *bp = dev_id;
+ u32 irq_mask;
+ int i;
+
+ irq_mask = gem_readl(bp, INTX_IRQ_MASK);
+ if (unlikely(!irq_mask))
+ return IRQ_NONE;
+
+ gem_writel(bp, INTX_IRQ_MASK, irq_mask);
+
+ for (i = 0; i < bp->num_queues; i++) {
+ if ((irq_mask & bp->queue_mask) & BIT(i))
+ macb_interrupt(irq, &bp->queues[i]);
+ }
+ return IRQ_HANDLED;
+}
+
+static int phytium_queue_request_irq(struct platform_device *pdev, unsigned int q)
+{
+ int err;
+ struct macb_queue *queue;
+ struct macb_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct macb *bp = netdev_priv(dev);
+
+ queue = &bp->queues[q];
+ if (q == 0 && pdata->phytium_macb_pdata.irq_type == IRQ_TYPE_INTX) {
+ dev->irq = pdata->phytium_macb_pdata.irq[q];
+ err = devm_request_irq(&pdev->dev, dev->irq, phytium_macb_interrupt_intx,
+ IRQF_SHARED, dev->name, bp);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Unable to request dev %d (error %d)\n",
+ dev->irq, err);
+ }
+ }
+
+ if (pdata->phytium_macb_pdata.irq_type == IRQ_TYPE_MSI) {
+ queue->irq = pdata->phytium_macb_pdata.irq[q];
+ err = devm_request_irq(&pdev->dev, queue->irq, macb_interrupt,
+ 0, dev->name, queue);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Unable to request IRQ %d (error %d)\n",
+ queue->irq, err);
+ }
+ }
+
+ return err;
+}
+
+static int phytium_init(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ unsigned int hw_q, q;
+ struct macb *bp = netdev_priv(dev);
+ struct macb_queue *queue;
+ int err;
+ u32 val, reg;
+ struct macb_platform_data *pdata;
+
+ bp->tx_ring_size = DEFAULT_TX_RING_SIZE;
+ bp->rx_ring_size = DEFAULT_RX_RING_SIZE;
+
+ pdata = dev_get_platdata(&pdev->dev);
+
+ /* set the queue register mapping once for all: queue0 has a special
+ * register mapping but we don't want to test the queue index then
+ * compute the corresponding register offset at run time.
+ */
+ for (hw_q = 0, q = 0; hw_q < MACB_MAX_QUEUES; ++hw_q) {
+ if (!(bp->queue_mask & (1 << hw_q)))
+ continue;
+
+ queue = &bp->queues[q];
+ queue->bp = bp;
+ netif_napi_add(dev, &queue->napi, macb_poll, NAPI_POLL_WEIGHT);
+ if (hw_q) {
+ queue->ISR = GEM_ISR(hw_q - 1);
+ queue->IER = GEM_IER(hw_q - 1);
+ queue->IDR = GEM_IDR(hw_q - 1);
+ queue->IMR = GEM_IMR(hw_q - 1);
+ queue->TBQP = GEM_TBQP(hw_q - 1);
+ queue->RBQP = GEM_RBQP(hw_q - 1);
+ queue->RBQS = GEM_RBQS(hw_q - 1);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ if (bp->hw_dma_cap & HW_DMA_CAP_64B) {
+ queue->TBQPH = GEM_TBQPH(hw_q - 1);
+ queue->RBQPH = GEM_RBQPH(hw_q - 1);
+ }
+#endif
+ } else {
+ /* queue0 uses legacy registers */
+ queue->ISR = MACB_ISR;
+ queue->IER = MACB_IER;
+ queue->IDR = MACB_IDR;
+ queue->IMR = MACB_IMR;
+ queue->TBQP = MACB_TBQP;
+ queue->RBQP = MACB_RBQP;
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ if (bp->hw_dma_cap & HW_DMA_CAP_64B) {
+ queue->TBQPH = MACB_TBQPH;
+ queue->RBQPH = MACB_RBQPH;
+ }
+#endif
+ }
+
+ if (bp->caps & MACB_CAPS_TAILPTR)
+ queue->TAILADDR = GEM_TAIL(hw_q);
+ /* get irq: here we use the linux queue index, not the hardware
+ * queue index. the queue irq definitions in the device tree
+ * must remove the optional gaps that could exist in the
+ * hardware queue mask.
+ */
+ if (pdata && pdata->phytium_macb_pdata.phytium_dev_type == PHYTIUM_DEV_3P0) {
+ err = phytium_queue_request_irq(pdev, q);
+ } else {
+ queue->irq = platform_get_irq(pdev, q);
+ err = devm_request_irq(&pdev->dev, queue->irq, macb_interrupt,
+ IRQF_SHARED, dev->name, queue);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Unable to request IRQ %d (error %d)\n",
+ queue->irq, err);
+ return err;
+ }
+ }
+
+ INIT_WORK(&queue->tx_error_task, macb_tx_error_task);
+ q++;
+ }
+
+ dev->netdev_ops = &macb_netdev_ops;
+
+ /* setup appropriated routines according to adapter type */
+ if (macb_is_gem(bp)) {
+ bp->max_tx_length = GEM_MAX_TX_LEN;
+ bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;
+ bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;
+ bp->macbgem_ops.mog_init_rings = gem_init_rings;
+ bp->macbgem_ops.mog_rx = gem_rx;
+ dev->ethtool_ops = &gem_ethtool_ops;
+ } else {
+ bp->max_tx_length = MACB_MAX_TX_LEN;
+ bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers;
+ bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers;
+ bp->macbgem_ops.mog_init_rings = macb_init_rings;
+ bp->macbgem_ops.mog_rx = macb_rx;
+ dev->ethtool_ops = &macb_ethtool_ops;
+ }
+
+ /* Set features */
+ dev->hw_features = NETIF_F_SG;
+
+ /* Check LSO capability */
+ if (GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))
+ dev->hw_features |= MACB_NETIF_LSO;
+
+ /* Checksum offload is only available on gem with packet buffer */
+ if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
+ dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+ if (bp->caps & MACB_CAPS_SG_DISABLED)
+ dev->hw_features &= ~NETIF_F_SG;
+ dev->features = dev->hw_features;
+
+ /* Check RX Flow Filters support.
+ * Max Rx flows set by availability of screeners & compare regs:
+ * each 4-tuple define requires 1 T2 screener reg + 3 compare regs
+ */
+ reg = gem_readl(bp, DCFG8);
+ bp->max_tuples = min((GEM_BFEXT(SCR2CMP, reg) / 3),
+ GEM_BFEXT(T2SCR, reg));
+ INIT_LIST_HEAD(&bp->rx_fs_list.list);
+ if (bp->max_tuples > 0) {
+ /* also needs one ethtype match to check IPv4 */
+ if (GEM_BFEXT(SCR2ETH, reg) > 0) {
+ /* program this reg now */
+ reg = 0;
+ reg = GEM_BFINS(ETHTCMP, (uint16_t)ETH_P_IP, reg);
+ gem_writel_n(bp, ETHT, SCRT2_ETHT, reg);
+ /* Filtering is supported in hw but don't enable it in kernel now */
+ dev->hw_features |= NETIF_F_NTUPLE;
+ /* init Rx flow definitions */
+ bp->rx_fs_list.count = 0;
+ spin_lock_init(&bp->rx_fs_lock);
+ } else {
+ bp->max_tuples = 0;
+ }
+ }
+
+ if (!(bp->caps & MACB_CAPS_USRIO_DISABLED)) {
+ val = 0;
+ if (phy_interface_mode_is_rgmii(bp->phy_interface))
+ val = GEM_BIT(RGMII);
+ else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
+ (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
+ val = MACB_BIT(RMII);
+ else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
+ val = MACB_BIT(MII);
+
+ if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN)
+ val |= MACB_BIT(CLKEN);
+
+ macb_or_gem_writel(bp, USRIO, val);
+ }
+
+ /* Set MII management clock divider */
+ val = macb_mdc_clk_div(bp);
+ val |= macb_dbw(bp);
+ if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII ||
+ bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX)
+ val |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
+ macb_writel(bp, NCFGR, val);
+
+ return 0;
+}
+
static int macb_init(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
@@ -4436,6 +5326,75 @@ static const struct macb_config zynq_con
.init = macb_init,
};
+static const struct macb_config phytium_gem1p0_config = {
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP |
+ MACB_CAPS_BD_RD_PREFETCH |
+ MACB_CAPS_SEL_CLK,
+ .dma_burst_length = 16,
+ .clk_init = phytium_clk_init,
+ .init = phytium_init,
+ .jumbo_max_len = 16360,
+ .sel_clk_hw = phytium_gem1p0_sel_clk,
+};
+
+static const struct macb_config phytium_gem2p0_config = {
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP |
+ MACB_CAPS_BD_RD_PREFETCH |
+ MACB_CAPS_SEL_CLK,
+ .dma_burst_length = 16,
+ .clk_init = macb_clk_init,
+ .init = macb_init,
+ .jumbo_max_len = 10240,
+ .sel_clk_hw = phytium_gem2p0_sel_clk,
+};
+
+static const struct macb_config phytium_gem3p0_config = {
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP |
+ MACB_CAPS_BD_RD_PREFETCH |
+ MACB_CAPS_SEL_CLK |
+ MACB_CAPS_TAILPTR,
+ .dma_burst_length = 16,
+ .clk_init = phytium_clk_init,
+ .init = phytium_init,
+ .jumbo_max_len = 10240,
+ .sel_clk_hw = phytium_gem3p0_sel_clk,
+};
+
+#ifdef CONFIG_ACPI
+static const struct macb_config phytium_gem1p0_acpi_config = {
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP |
+ MACB_CAPS_BD_RD_PREFETCH |
+ MACB_CAPS_SEL_CLK,
+ .dma_burst_length = 16,
+ .clk_init = phytium_clk_acpi_init,
+ .init = phytium_init,
+ .jumbo_max_len = 10240,
+ .sel_clk_hw = phytium_gem1p0_sel_clk,
+};
+
+static const struct macb_config phytium_gem3p0_acpi_config = {
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP |
+ MACB_CAPS_BD_RD_PREFETCH |
+ MACB_CAPS_SEL_CLK |
+ MACB_CAPS_TAILPTR,
+ .dma_burst_length = 16,
+ .clk_init = phytium_clk_acpi_init,
+ .init = phytium_init,
+ .jumbo_max_len = 10240,
+ .sel_clk_hw = phytium_gem3p0_sel_clk,
+};
+#endif
+
static const struct of_device_id macb_dt_ids[] = {
{ .compatible = "cdns,at32ap7000-macb" },
{ .compatible = "cdns,at91sam9260-macb", .data = &at91sam9260_config },
@@ -4453,11 +5412,26 @@ static const struct of_device_id macb_dt
{ .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
{ .compatible = "cdns,zynq-gem", .data = &zynq_config },
{ .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
+ { .compatible = "cdns,phytium-gem-1.0", .data = &phytium_gem1p0_config },
+ { .compatible = "cdns,phytium-gem-2.0", .data = &phytium_gem2p0_config },
+ { .compatible = "cdns,phytium-gem-3.0", .data = &phytium_gem3p0_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, macb_dt_ids);
#endif /* CONFIG_OF */
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id macb_acpi_ids[] = {
+ { .id = "PHYT0036", .driver_data = (kernel_ulong_t)&phytium_gem1p0_acpi_config },
+ { .id = "PHYT0046", .driver_data = (kernel_ulong_t)&phytium_gem3p0_acpi_config },
+ { }
+};
+
+MODULE_DEVICE_TABLE(acpi, macb_acpi_ids);
+#else
+#define macb_acpi_ids NULL
+#endif
+
static const struct macb_config default_gem_config = {
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
MACB_CAPS_JUMBO |
@@ -4468,6 +5442,32 @@ static const struct macb_config default_
.jumbo_max_len = 10240,
};
+static void gem_ncsi_handler(struct ncsi_dev *nd)
+{
+ if (unlikely(nd->state != ncsi_dev_state_functional))
+ return;
+
+ netdev_dbg(nd->dev, "NCSI interface %s\n",
+ nd->link_up ? "up" : "down");
+}
+
+static int macb_get_phy_mode(struct platform_device *pdev)
+{
+ const char *pm;
+ int err, i;
+
+ err = device_property_read_string(&pdev->dev, "phy-mode", &pm);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
+ if (!strcasecmp(pm, phy_modes(i)))
+ return i;
+ }
+
+ return -ENODEV;
+}
+
static int macb_probe(struct platform_device *pdev)
{
const struct macb_config *macb_config = &default_gem_config;
@@ -4476,17 +5476,26 @@ static int macb_probe(struct platform_de
struct clk **) = macb_config->clk_init;
int (*init)(struct platform_device *) = macb_config->init;
struct device_node *np = pdev->dev.of_node;
- struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL;
+ struct clk *pclk = NULL, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL;
struct clk *tsu_clk = NULL;
unsigned int queue_mask, num_queues;
+ struct macb_platform_data *pdata;
bool native_io;
- phy_interface_t interface;
struct net_device *dev;
struct resource *regs;
void __iomem *mem;
struct macb *bp;
int err, val;
+ pdata = dev_get_platdata(&pdev->dev);
+ if (pdata) {
+ if (pdata->phytium_macb_pdata.phytium_dev_type == PHYTIUM_DEV_3P0) {
+ macb_config = &phytium_gem3p0_config;
+ clk_init = macb_config->clk_init;
+ init = macb_config->init;
+ }
+ }
+
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mem = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(mem))
@@ -4501,6 +5510,15 @@ static int macb_probe(struct platform_de
clk_init = macb_config->clk_init;
init = macb_config->init;
}
+ } else if (has_acpi_companion(&pdev->dev)) {
+ const struct acpi_device_id *match;
+
+ match = acpi_match_device(macb_acpi_ids, &pdev->dev);
+ if (match && match->driver_data) {
+ macb_config = (void *)match->driver_data;
+ clk_init = macb_config->clk_init;
+ init = macb_config->init;
+ }
}
err = clk_init(pdev, &pclk, &hclk, &tx_clk, &rx_clk, &tsu_clk);
@@ -4549,8 +5567,11 @@ static int macb_probe(struct platform_de
if (macb_config)
bp->jumbo_max_len = macb_config->jumbo_max_len;
+ if (macb_config)
+ bp->sel_clk_hw = macb_config->sel_clk_hw;
+
bp->wol = 0;
- if (of_get_property(np, "magic-packet", NULL))
+ if (device_property_read_bool(&pdev->dev, "magic-packet"))
bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
@@ -4602,22 +5623,47 @@ static int macb_probe(struct platform_de
else if (err)
macb_get_hwaddr(bp);
- err = of_get_phy_mode(np, &interface);
- if (err)
- /* not found in DT, MII by default */
- bp->phy_interface = PHY_INTERFACE_MODE_MII;
- else
- bp->phy_interface = interface;
+ err = macb_get_phy_mode(pdev);
+ if (err < 0) {
+ if (pdata && pdata->phytium_macb_pdata.phytium_dev_type == PHYTIUM_DEV_3P0)
+ bp->phy_interface = pdata->phytium_macb_pdata.phy_interface;
+ else
+ bp->phy_interface = PHY_INTERFACE_MODE_MII;
+ } else {
+ bp->phy_interface = err;
+ }
+
+ bp->link = 0;
+ bp->duplex = DUPLEX_UNKNOWN;
+ bp->speed = SPEED_UNKNOWN;
/* IP specific init */
err = init(pdev);
if (err)
goto err_out_free_netdev;
+ if (device_property_read_bool(&pdev->dev, "force-phy-mode")) {
+ bp->force_phy_mode = 1;
+ }
+
err = macb_mii_init(bp);
if (err)
goto err_out_free_netdev;
+ if (device_property_read_bool(&pdev->dev, "use-ncsi")) {
+ if (!IS_ENABLED(CONFIG_NET_NCSI)) {
+ dev_err(&pdev->dev, "NCSI stack not enabled\n");
+ goto err_out_free_netdev;
+ }
+ dev_notice(&pdev->dev, "Using NCSI interface\n");
+ bp->use_ncsi = 1;
+ bp->ndev = ncsi_register_dev(dev, gem_ncsi_handler);
+ if (!bp->ndev)
+ goto err_out_free_netdev;
+ } else {
+ bp->use_ncsi = 0;
+ }
+
netif_carrier_off(dev);
err = register_netdev(dev);
@@ -4661,6 +5707,7 @@ static int macb_remove(struct platform_d
{
struct net_device *dev;
struct macb *bp;
+ struct macb_platform_data *pdata = dev_get_platdata(&pdev->dev);
dev = platform_get_drvdata(pdev);
@@ -4669,16 +5716,21 @@ static int macb_remove(struct platform_d
mdiobus_unregister(bp->mii_bus);
mdiobus_free(bp->mii_bus);
+ if (bp->ndev)
+ ncsi_unregister_dev(bp->ndev);
unregister_netdev(dev);
tasklet_kill(&bp->hresp_err_tasklet);
pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
if (!pm_runtime_suspended(&pdev->dev)) {
- clk_disable_unprepare(bp->tx_clk);
- clk_disable_unprepare(bp->hclk);
- clk_disable_unprepare(bp->pclk);
- clk_disable_unprepare(bp->rx_clk);
- clk_disable_unprepare(bp->tsu_clk);
+ if (!pdata) {
+ clk_disable_unprepare(bp->tx_clk);
+ clk_disable_unprepare(bp->hclk);
+ clk_disable_unprepare(bp->pclk);
+ clk_disable_unprepare(bp->rx_clk);
+ clk_disable_unprepare(bp->tsu_clk);
+ }
+
pm_runtime_set_suspended(&pdev->dev);
}
phylink_destroy(bp->phylink);
@@ -4895,6 +5947,7 @@ static struct platform_driver macb_drive
.driver = {
.name = "macb",
.of_match_table = of_match_ptr(macb_dt_ids),
+ .acpi_match_table = ACPI_PTR(macb_acpi_ids),
.pm = &macb_pm_ops,
},
};
--- a/drivers/net/ethernet/cadence/macb_pci.c
+++ b/drivers/net/ethernet/cadence/macb_pci.c
@@ -21,17 +21,166 @@
#define CDNS_VENDOR_ID 0x17cd
#define CDNS_DEVICE_ID 0xe007
+#define PCI_DEVICE_ID_GMAC_3P0 0xdc3b
+#define PCI_SUBDEVICE_ID_SGMII 0x1000
+#define PCI_SUBDEVICE_ID_1000BASEX 0x1001
+#define PCI_SUBDEVICE_ID_USXGMII 0x1004
+#define PCI_SUBDEVICE_ID_10GBASER 0x1005
#define GEM_PCLK_RATE 50000000
#define GEM_HCLK_RATE 50000000
+#define GEM_TXCLK_RATE 25000000
+#define GEM_RXCLK_RATE 25000000
+#define GEM_TSUCLK_RATE 300000000
+
+static const u32 fixedlink[][5] = {
+ {0, 1, 1000, 1, 0},
+ {0, 1, 2500, 1, 0},
+ {0, 1, 5000, 1, 0},
+ {0, 1, 10000, 1, 0},
+};
+
+static const struct property_entry fl_properties[][2] = {
+ {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[0]), {}},
+ {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[1]), {}},
+ {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[2]), {}},
+ {PROPERTY_ENTRY_U32_ARRAY("fixed-link", fixedlink[3]), {}},
+};
+
+static const struct phytium_platform_pdata phytium_sgmii_pdata = {
+ .phytium_dev_type = PHYTIUM_DEV_3P0,
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP |
+ MACB_CAPS_BD_RD_PREFETCH |
+ MACB_CAPS_USRIO_DISABLED |
+ MACB_CAPS_TAILPTR,
+ .phy_interface = PHY_INTERFACE_MODE_SGMII,
+};
+
+static const struct phytium_platform_pdata phytium_1000basex_pdata = {
+ .phytium_dev_type = PHYTIUM_DEV_3P0,
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP |
+ MACB_CAPS_BD_RD_PREFETCH |
+ MACB_CAPS_USRIO_DISABLED |
+ MACB_CAPS_TAILPTR,
+ .phy_interface = PHY_INTERFACE_MODE_SGMII,
+ .properties = fl_properties[0],
+};
+
+static const struct phytium_platform_pdata phytium_usxgmii_pdata = {
+ .phytium_dev_type = PHYTIUM_DEV_3P0,
+ .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
+ MACB_CAPS_JUMBO |
+ MACB_CAPS_GEM_HAS_PTP |
+ MACB_CAPS_BD_RD_PREFETCH |
+ MACB_CAPS_USRIO_DISABLED |
+ MACB_CAPS_TAILPTR,
+ .phy_interface = PHY_INTERFACE_MODE_USXGMII,
+ .properties = fl_properties[3],
+};
+
+static int phytium_macb_pci_init(struct pci_dev *pdev, struct macb_platform_data *plat_data,
+ struct platform_device_info *plat_info,
+ struct phytium_platform_pdata *phytium_data)
+{
+ int i;
+ int err;
+ char clkname[20];
+
+ err = pci_alloc_irq_vectors(pdev, 4, 4, PCI_IRQ_MSI);
+ if (err < 0) {
+ dev_err(&pdev->dev, "err=%d, fialed to allocate MSI entry", err);
+ plat_data->phytium_macb_pdata.irq_type = IRQ_TYPE_INTX;
+ plat_data->phytium_macb_pdata.irq[0] = pdev->irq;
+
+ } else {
+ plat_data->phytium_macb_pdata.irq_type = IRQ_TYPE_MSI;
+ for (i = 0; i < 4; i++)
+ plat_data->phytium_macb_pdata.irq[i] = pci_irq_vector(pdev, i);
+ }
+
+ plat_data->phytium_macb_pdata.phytium_dev_type = phytium_data->phytium_dev_type;
+ plat_data->phytium_macb_pdata.caps = phytium_data->caps;
+ plat_data->phytium_macb_pdata.phy_interface = phytium_data->phy_interface;
+ if (phytium_data && phytium_data->properties) {
+ plat_info->fwnode = NULL;
+ plat_info->properties = phytium_data->properties;
+ plat_data->phytium_macb_pdata.properties = phytium_data->properties;
+ }
+
+ snprintf(clkname, 20, "txclk:%02x", plat_info->id);
+ plat_data->phytium_macb_pdata.txclk =
+ clk_register_fixed_rate(&pdev->dev, clkname, NULL, 0, GEM_TXCLK_RATE);
+ if (IS_ERR(plat_data->phytium_macb_pdata.txclk)) {
+ err = PTR_ERR(plat_data->phytium_macb_pdata.txclk);
+ goto err_txclk_register;
+ }
+
+ snprintf(clkname, 20, "rxclk:%02x", plat_info->id);
+ plat_data->phytium_macb_pdata.rxclk =
+ clk_register_fixed_rate(&pdev->dev, clkname, NULL, 0, GEM_RXCLK_RATE);
+ if (IS_ERR(plat_data->phytium_macb_pdata.rxclk)) {
+ err = PTR_ERR(plat_data->phytium_macb_pdata.rxclk);
+ goto err_rxclk_register;
+ }
+
+ snprintf(clkname, 20, "tsuclk:%02x", plat_info->id);
+ plat_data->phytium_macb_pdata.tsu_clk =
+ clk_register_fixed_rate(&pdev->dev, clkname, NULL, 0, GEM_TSUCLK_RATE);
+ if (IS_ERR(plat_data->phytium_macb_pdata.tsu_clk)) {
+ err = PTR_ERR(plat_data->phytium_macb_pdata.tsu_clk);
+ goto err_tsuclk_register;
+ }
+
+ return 0;
+
+err_tsuclk_register:
+ clk_unregister(plat_data->phytium_macb_pdata.rxclk);
+
+err_rxclk_register:
+ clk_unregister(plat_data->phytium_macb_pdata.txclk);
+
+err_txclk_register:
+
+ return err;
+}
+
+static void phytium_macb_pci_uninit(struct pci_dev *pdev)
+{
+ struct platform_device *plat_dev = pci_get_drvdata(pdev);
+ struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev);
+
+ plat_dev->dev.dma_ops = NULL;
+ plat_dev->dev.iommu = NULL;
+ plat_dev->dev.iommu_group = NULL;
+ plat_dev->dev.dma_range_map = NULL;
+
+ clk_unregister(plat_data->phytium_macb_pdata.txclk);
+ clk_unregister(plat_data->phytium_macb_pdata.rxclk);
+ clk_unregister(plat_data->phytium_macb_pdata.tsu_clk);
+
+ if (plat_data->phytium_macb_pdata.properties) {
+ struct fwnode_handle *fw_node = dev_fwnode(&plat_dev->dev);
+
+ if (fw_node)
+ fwnode_remove_software_node(fw_node);
+ fw_node = NULL;
+ }
+}
static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int err;
struct platform_device *plat_dev;
struct platform_device_info plat_info;
+ struct phytium_platform_pdata *phytium_data = NULL;
struct macb_platform_data plat_data;
struct resource res[2];
+ char pclk_name[20] = "pclk";
+ char hclk_name[20] = "hclk";
/* enable pci device */
err = pcim_enable_device(pdev);
@@ -48,9 +197,6 @@ static int macb_probe(struct pci_dev *pd
res[0].end = pci_resource_end(pdev, 0);
res[0].name = PCI_DRIVER_NAME;
res[0].flags = IORESOURCE_MEM;
- res[1].start = pci_irq_vector(pdev, 0);
- res[1].name = PCI_DRIVER_NAME;
- res[1].flags = IORESOURCE_IRQ;
dev_info(&pdev->dev, "EMAC physical base addr: %pa\n",
&res[0].start);
@@ -58,32 +204,48 @@ static int macb_probe(struct pci_dev *pd
/* set up macb platform data */
memset(&plat_data, 0, sizeof(plat_data));
+ /* set up platform device info */
+ memset(&plat_info, 0, sizeof(plat_info));
+ plat_info.parent = &pdev->dev;
+ plat_info.fwnode = pdev->dev.fwnode;
+ plat_info.name = PLAT_DRIVER_NAME;
+ plat_info.id = pdev->devfn;
+ plat_info.res = res;
+ plat_info.num_res = ARRAY_SIZE(res);
+ plat_info.data = &plat_data;
+ plat_info.size_data = sizeof(plat_data);
+ plat_info.dma_mask = pdev->dma_mask;
+ if (pdev->vendor == PCI_VENDOR_ID_PHYTIUM)
+ phytium_data = (struct phytium_platform_pdata *)id->driver_data;
+
/* initialize clocks */
- plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0,
+ if (pdev->device == PCI_DEVICE_ID_GMAC_3P0) {
+ plat_info.id = (pdev->bus->number << 8) | pdev->devfn;
+ snprintf(pclk_name, 20, "pclk:%02x", plat_info.id);
+ snprintf(hclk_name, 20, "hclk:%02x", plat_info.id);
+ }
+ plat_data.pclk = clk_register_fixed_rate(&pdev->dev, pclk_name, NULL, 0,
GEM_PCLK_RATE);
if (IS_ERR(plat_data.pclk)) {
err = PTR_ERR(plat_data.pclk);
goto err_pclk_register;
}
- plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0,
+ plat_data.hclk = clk_register_fixed_rate(&pdev->dev, hclk_name, NULL, 0,
GEM_HCLK_RATE);
if (IS_ERR(plat_data.hclk)) {
err = PTR_ERR(plat_data.hclk);
goto err_hclk_register;
}
- /* set up platform device info */
- memset(&plat_info, 0, sizeof(plat_info));
- plat_info.parent = &pdev->dev;
- plat_info.fwnode = pdev->dev.fwnode;
- plat_info.name = PLAT_DRIVER_NAME;
- plat_info.id = pdev->devfn;
- plat_info.res = res;
- plat_info.num_res = ARRAY_SIZE(res);
- plat_info.data = &plat_data;
- plat_info.size_data = sizeof(plat_data);
- plat_info.dma_mask = pdev->dma_mask;
+ if (pdev->device == PCI_DEVICE_ID_GMAC_3P0) {
+ if (phytium_macb_pci_init(pdev, &plat_data, &plat_info, phytium_data))
+ goto err_phytium_clk_register;
+ }
+
+ res[1].start = pci_irq_vector(pdev, 0);
+ res[1].name = PCI_DRIVER_NAME;
+ res[1].flags = IORESOURCE_IRQ;
/* register platform device */
plat_dev = platform_device_register_full(&plat_info);
@@ -92,11 +254,21 @@ static int macb_probe(struct pci_dev *pd
goto err_plat_dev_register;
}
+ if (pdev->device == PCI_DEVICE_ID_GMAC_3P0) {
+ plat_dev->dev.dma_ops = (&pdev->dev)->dma_ops;
+ plat_dev->dev.iommu = (&pdev->dev)->iommu;
+ plat_dev->dev.iommu_group = (&pdev->dev)->iommu_group;
+ plat_dev->dev.dma_range_map = (&pdev->dev)->dma_range_map;
+ }
pci_set_drvdata(pdev, plat_dev);
return 0;
err_plat_dev_register:
+ if (pdev->device == PCI_DEVICE_ID_GMAC_3P0)
+ clk_unregister(plat_data.phytium_macb_pdata.tsu_clk);
+
+err_phytium_clk_register:
clk_unregister(plat_data.hclk);
err_hclk_register:
@@ -113,11 +285,26 @@ static void macb_remove(struct pci_dev *
clk_unregister(plat_data->pclk);
clk_unregister(plat_data->hclk);
+
+ if (pdev->device == PCI_DEVICE_ID_GMAC_3P0)
+ phytium_macb_pci_uninit(pdev);
platform_device_unregister(plat_dev);
+
+ if (pdev->device == PCI_DEVICE_ID_GMAC_3P0)
+ pci_free_irq_vectors(pdev);
}
static const struct pci_device_id dev_id_table[] = {
{ PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHYTIUM, PCI_DEVICE_ID_GMAC_3P0,
+ PCI_VENDOR_ID_PHYTIUM, PCI_SUBDEVICE_ID_SGMII),
+ .driver_data = (kernel_ulong_t)&phytium_sgmii_pdata},
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHYTIUM, PCI_DEVICE_ID_GMAC_3P0,
+ PCI_VENDOR_ID_PHYTIUM, PCI_SUBDEVICE_ID_1000BASEX),
+ .driver_data = (kernel_ulong_t)&phytium_1000basex_pdata},
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHYTIUM, PCI_DEVICE_ID_GMAC_3P0,
+ PCI_VENDOR_ID_PHYTIUM, PCI_SUBDEVICE_ID_USXGMII),
+ .driver_data = (kernel_ulong_t)&phytium_usxgmii_pdata},
{ 0, }
};
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -117,6 +117,16 @@ config DWMAC_OXNAS
This selects the Oxford Semiconductor OXNASSoC glue layer support for
the stmmac device driver. This driver is used for OX820.
+config DWMAC_PHYTIUM
+ tristate "Phytium dwmac support"
+ default ARCH_PHYTIUM
+ depends on (OF || ACPI) && (ARCH_PHYTIUM || COMPILE_TEST)
+ help
+ Support for GMAC controller on Phytium SoCs.
+
+ This selects the Phytium GMAC glue layer support for the
+ stmmac device driver.
+
config DWMAC_QCOM_ETHQOS
tristate "Qualcomm ETHQOS support"
default ARCH_QCOM
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc
obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o
obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o
+obj-$(CONFIG_DWMAC_PHYTIUM) += dwmac-phytium.o
obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -394,6 +394,12 @@ config XILINX_GMII2RGMII
the Reduced Gigabit Media Independent Interface(RGMII) between
Ethernet physical media devices and the Gigabit Ethernet controller.
+config MOTORCOMM_PHY
+ tristate "Motorcomm PHYs"
+ help
+ Enables support for Motorcomm network PHYs.
+ Currently supports the YT8511 gigabit PHY.
+
endif # PHYLIB
config MICREL_KS8995MA
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -96,3 +96,5 @@ obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
+
+obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -103,6 +103,10 @@
#define AT803X_DEBUG_REG_GREEN 0x3D
#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6)
+#define AT803X_DEBUG_REG_B 0x0B
+#define AT803X_DEBUG_REG_B_HIBERNATION_ENABLE 0x1
+#define AT803X_DEBUG_REG_B_HIBERNATION_OFFSET 15
+
#define AT803X_DEBUG_REG_1F 0x1F
#define AT803X_DEBUG_PLL_ON BIT(2)
#define AT803X_DEBUG_RGMII_1V8 BIT(3)
@@ -284,6 +288,20 @@ static int at803x_enable_tx_delay(struct
AT803X_DEBUG_TX_CLK_DLY_EN);
}
+static inline int at803x_disable_hibernate(struct phy_device *phydev)
+{
+ int ret = 0;
+ u16 val = 0;
+
+ ret = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_B);
+ if (ret < 0)
+ return ret;
+
+ val = ret & 0xffff;
+ val &= (~(AT803X_DEBUG_REG_B_HIBERNATION_ENABLE << AT803X_DEBUG_REG_B_HIBERNATION_OFFSET));
+ return phy_write(phydev, AT803X_DEBUG_DATA, val);
+}
+
static int at803x_disable_rx_delay(struct phy_device *phydev)
{
return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
@@ -717,6 +735,10 @@ static int at803x_config_init(struct phy
{
int ret;
+ ret = at803x_disable_hibernate(phydev);
+ if (ret < 0)
+ return ret;
+
/* The RX and TX delay default is:
* after HW reset: RX delay enabled and TX delay disabled
* after SW reset: RX delay enabled, while TX delay retains the
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -306,6 +306,9 @@ static int phylink_parse_mode(struct phy
phylink_set(pl->supported, 2500baseX_Full);
break;
+ case PHY_INTERFACE_MODE_5GBASER:
+ phylink_set(pl->supported, 5000baseT_Full);
+ break;
case PHY_INTERFACE_MODE_USXGMII:
case PHY_INTERFACE_MODE_10GKR:
case PHY_INTERFACE_MODE_10GBASER:
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -109,6 +109,11 @@ struct controller {
unsigned int ist_running;
int request_result;
wait_queue_head_t requester;
+
+#ifdef CONFIG_ARCH_PHYTIUM
+ u32 buses;
+ u16 slot_ctrl_t;
+#endif
};
/**
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -226,6 +226,11 @@ void pciehp_handle_presence_or_link_chan
{
int present, link_active;
+#ifdef CONFIG_ARCH_PHYTIUM
+ struct pci_dev *pdev = ctrl->pcie->port;
+ u16 slot_ctrl_val;
+#endif
+
/*
* If the slot is on and presence or link has changed, turn it off.
* Even if it's occupied again, we cannot assume the card is the same.
@@ -244,6 +249,21 @@ void pciehp_handle_presence_or_link_chan
if (events & PCI_EXP_SLTSTA_PDC)
ctrl_info(ctrl, "Slot(%s): Card not present\n",
slot_name(ctrl));
+#ifdef CONFIG_ARCH_PHYTIUM
+ if ((ctrl->buses > 0) && (ctrl->slot_ctrl > 0)) {
+ pci_write_config_dword(pdev, PCI_PRIMARY_BUS, ctrl->buses);
+ slot_ctrl_val = ctrl->slot_ctrl_t | PCI_EXP_SLTCTL_ABPE |
+ PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
+ PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_CCIE |
+ PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_ATTN_IND_BLINK |
+ PCI_EXP_SLTCTL_PWR_IND_ON |
+ PCI_EXP_SLTCTL_DLLSCE;
+ slot_ctrl_val &= ~PCI_EXP_SLTCTL_PWR_OFF;
+ pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl_val);
+ ctrl_info(ctrl, "Ctrl buses=0x%x, slot_ctrl=0x%x\n",
+ ctrl->buses, slot_ctrl_val);
+ }
+#endif
pciehp_disable_slot(ctrl, SURPRISE_REMOVAL);
break;
default:
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -597,7 +597,7 @@ static irqreturn_t pciehp_isr(int irq, v
* in the Slot Control register (PCIe r4.0, sec 6.7.3.4).
*/
if (pdev->current_state == PCI_D3cold ||
- (!(ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE) && !pciehp_poll_mode))
+ (!(ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE) && !pciehp_poll_mode))
return IRQ_NONE;
/*
@@ -695,7 +695,13 @@ static irqreturn_t pciehp_ist(int irq, v
struct controller *ctrl = (struct controller *)dev_id;
struct pci_dev *pdev = ctrl_dev(ctrl);
irqreturn_t ret;
+#ifdef CONFIG_ARCH_PHYTIUM
+ u32 events, buses;
+ u16 slot_ctrl;
+ bool link_active;
+#else
u32 events;
+#endif
ctrl->ist_running = true;
pci_config_pm_runtime_get(pdev);
@@ -715,6 +721,23 @@ static irqreturn_t pciehp_ist(int irq, v
goto out;
}
+#ifdef CONFIG_ARCH_PHYTIUM
+ if(ctrl->state == ON_STATE) {
+ pci_read_config_dword(pdev, PCI_PRIMARY_BUS, &buses);
+ pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
+ ctrl->buses = buses;
+ ctrl->slot_ctrl_t = slot_ctrl;
+ ctrl_dbg(ctrl, "Ctrl buses=0x%x, slot_ctrl=0x%x\n",
+ ctrl->buses, ctrl->slot_ctrl_t);
+ }
+
+ mdelay(1000);
+
+ link_active = pciehp_check_link_active(ctrl);
+ if((ctrl->state == ON_STATE) && (link_active == false))
+ events |= PCI_EXP_SLTSTA_DLLSC;
+#endif
+
/* Check Attention Button Pressed */
if (events & PCI_EXP_SLTSTA_ABP) {
ctrl_info(ctrl, "Slot(%s): Attention button pressed\n",
@@ -749,7 +772,6 @@ static irqreturn_t pciehp_ist(int irq, v
else if (events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC))
pciehp_handle_presence_or_link_change(ctrl, events);
up_read(&ctrl->reset_lock);
-
ret = IRQ_HANDLED;
out:
pci_config_pm_runtime_put(pdev);
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -123,6 +123,19 @@ void pcie_port_bus_unregister(void);
struct pci_dev;
+#ifdef CONFIG_HOTPLUG_PCI_PCIE
+extern bool pciehp_msi_disabled;
+
+static inline bool pciehp_no_msi(void)
+{
+ return pciehp_msi_disabled;
+}
+
+#else /* !CONFIG_HOTPLUG_PCI_PCIE */
+static inline bool pciehp_no_msi(void) { return false; }
+#endif /* !CONFIG_HOTPLUG_PCI_PCIE */
+
+
#ifdef CONFIG_PCIE_PME
extern bool pcie_pme_msi_disabled;
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -25,6 +25,17 @@ struct portdrv_service_data {
u32 service;
};
+bool pciehp_msi_disabled;
+
+static int __init pciehp_setup(char *str)
+{
+ if (!strncmp(str, "nomsi", 5))
+ pciehp_msi_disabled = true;
+
+ return 1;
+}
+__setup("pcie_hp=", pciehp_setup);
+
/**
* release_pcie_device - free PCI Express port service device structure
* @dev: Port service device to release
@@ -177,6 +188,9 @@ static int pcie_init_service_irqs(struct
if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi())
goto legacy_irq;
+ if ((mask & PCIE_PORT_SERVICE_HP) && pciehp_no_msi())
+ goto legacy_irq;
+
/* Try to use MSI-X or MSI if supported */
if (pcie_port_enable_irq_vec(dev, irqs, mask) == 0)
return 0;
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -31,6 +31,7 @@
#include <linux/suspend.h>
#include <linux/switchtec.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
+#include <linux/crash_dump.h>
#include "pci.h"
static ktime_t fixup_debug_start(struct pci_dev *dev,
@@ -3902,12 +3903,12 @@ static int nvme_disable_and_flr(struct p
void __iomem *bar;
u16 cmd;
u32 cfg;
-
+ printk("%s began\n", __func__);
if (dev->class != PCI_CLASS_STORAGE_EXPRESS ||
!pcie_has_flr(dev) || !pci_resource_start(dev, 0))
return -ENOTTY;
- if (probe)
+ if (probe & !is_kdump_kernel())
return 0;
bar = pci_iomap(dev, 0, NVME_REG_CC + sizeof(cfg));
@@ -3961,7 +3962,7 @@ static int nvme_disable_and_flr(struct p
pci_iounmap(dev, bar);
pcie_flr(dev);
-
+ printk("%s finished\n", __func__);
return 0;
}
@@ -4057,6 +4058,7 @@ static const struct pci_dev_reset_method
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA,
reset_ivb_igd },
{ PCI_VENDOR_ID_SAMSUNG, 0xa804, nvme_disable_and_flr },
+ { PCI_VENDOR_ID_SAMSUNG, 0xa809, nvme_disable_and_flr },
{ PCI_VENDOR_ID_INTEL, 0x0953, delay_250ms_after_flr },
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
reset_chelsio_generic_dev },
@@ -4996,6 +4998,10 @@ static const struct pci_dev_acs_enabled
{ PCI_VENDOR_ID_ZHAOXIN, PCI_ANY_ID, pci_quirk_zhaoxin_pcie_ports_acs },
/* Wangxun nics */
{ PCI_VENDOR_ID_WANGXUN, PCI_ANY_ID, pci_quirk_wangxun_nic_acs },
+ /* Phytium Technology */
+ { 0x10b5, PCI_ANY_ID, pci_quirk_xgene_acs },
+ { 0x17cd, PCI_ANY_ID, pci_quirk_xgene_acs },
+ { 0x1db7, PCI_ANY_ID, pci_quirk_xgene_acs },
{ 0 }
};
@@ -5380,6 +5386,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SE
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0144, quirk_no_ext_tags);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0420, quirk_no_ext_tags);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0422, quirk_no_ext_tags);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PHYTIUM, 0xdc3a, quirk_no_ext_tags);
#ifdef CONFIG_PCI_ATS
static void quirk_no_ats(struct pci_dev *pdev)
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -570,4 +570,14 @@ config PWM_ZX
To compile this driver as a module, choose M here: the module
will be called pwm-zx.
+config PWM_PHYTIUM
+ tristate "Phytium PWM support"
+ depends on ARCH_PHYTIUM
+ help
+ Generic PWM framework driver for the PWM controller found on
+ Phytium SoCs.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-phytium.
+
endif
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -55,3 +55,5 @@ obj-$(CONFIG_PWM_TWL) += pwm-twl.o
obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o
obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o
obj-$(CONFIG_PWM_ZX) += pwm-zx.o
+
+obj-$(CONFIG_PWM_PHYTIUM) += pwm-phytium.o
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -260,7 +260,7 @@ static int pwm_export_child(struct devic
export->child.parent = parent;
export->child.devt = MKDEV(0, 0);
export->child.groups = pwm_groups;
- dev_set_name(&export->child, "pwm%u", pwm->hwpwm);
+ dev_set_name(&export->child, "pwm%u", pwm->pwm);
ret = device_register(&export->child);
if (ret) {
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -288,6 +288,12 @@ config TI_K3_R5_REMOTEPROC
It's safe to say N here if you're not interested in utilizing
a slave processor.
+config HOMO_REMOTEPROC
+ bool "homogeneous remoteproc support"
+ select RPMSG_VIRTIO
+ help
+ Say y here to support homogeneous processors via the remote processor framework.
+
endif # REMOTEPROC
endmenu
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_s
obj-$(CONFIG_STM32_RPROC) += stm32_rproc.o
obj-$(CONFIG_TI_K3_DSP_REMOTEPROC) += ti_k3_dsp_remoteproc.o
obj-$(CONFIG_TI_K3_R5_REMOTEPROC) += ti_k3_r5_remoteproc.o
+obj-$(CONFIG_HOMO_REMOTEPROC) += homo_remoteproc.o
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -701,6 +701,16 @@ config RTC_DRV_S5M
This driver can also be built as a module. If so, the module
will be called rtc-s5m.
+config RTC_DRV_SD3068
+ tristate "ZXW Shenzhen whwave SD3068"
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for the ZXW Shenzhen whwave
+ SD3068 RTC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-sd3068
+
config RTC_DRV_SD3078
tristate "ZXW Shenzhen whwave SD3078"
select REGMAP_I2C
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -153,6 +153,7 @@ obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SC27XX) += rtc-sc27xx.o
+obj-$(CONFIG_RTC_DRV_SD3068) += rtc-sd3068.o
obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -585,6 +585,44 @@ config SPI_ORION
This enables using the SPI master controller on the Orion
and MVEBU chips.
+config SPI_PHYTIUM
+ tristate
+ depends on ARCH_PHYTIUM || COMPILE_TEST
+
+config SPI_PHYTIUM_PLAT
+ tristate "Phytium SPI controller platform support"
+ select SPI_PHYTIUM
+ help
+ This selects a platform driver for Phytium SPI controller.
+
+ If you say yes to this option, support will be included for
+ Pd1904 and pd2008 families of SPI controller.
+
+config SPI_PHYTIUM_PCI
+ tristate "Phytium SPI controller PCI support"
+ depends on PCI
+ select SPI_PHYTIUM
+ help
+ This selects a PCI driver for Phytium SPI controller.
+
+ If you say yes to this option, support will be included for
+ Phytium px210 chipset of SPI controller.
+
+ If unsure, say N.
+
+config SPI_PHYTIUM_QSPI
+ tristate "Phytium Quad SPI controller"
+ depends on ARCH_PHYTIUM || COMPILE_TEST
+ depends on OF
+ depends on SPI_MEM
+ help
+ This enables support for Phytium Quad SPI flash controller.
+
+ This driver does not support generic SPI. The implementation only
+ supports spi-mem interface.
+
+ If unsure, say N.
+
config SPI_PIC32
tristate "Microchip PIC32 series SPI"
depends on MACH_PIC32 || COMPILE_TEST
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -82,6 +82,11 @@ obj-$(CONFIG_SPI_OMAP_100K) += spi-omap
obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o
obj-$(CONFIG_SPI_ORION) += spi-orion.o
+obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium.o
+obj-$(CONFIG_SPI_PHYTIUM_PLAT) += spi-phytium-plat.o
+obj-$(CONFIG_SPI_PHYTIUM_PCI) += spi-phytium-pci.o
+obj-$(CONFIG_SPI_PHYTIUM_QSPI) += spi-phytium-qspi.o
+obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium-dma.o
obj-$(CONFIG_SPI_PIC32) += spi-pic32.o
obj-$(CONFIG_SPI_PIC32_SQI) += spi-pic32-sqi.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -5,6 +5,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/acpi.h>
#include <linux/arm-smccc.h>
#include <linux/crash_dump.h>
#include <linux/errno.h>
@@ -776,6 +777,14 @@ static const struct of_device_id optee_d
};
MODULE_DEVICE_TABLE(of, optee_dt_match);
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id optee_acpi_match[] = {
+ { "PHYT8003" },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, optee_acpi_match);
+#endif
+
static struct platform_driver optee_driver = {
.probe = optee_probe,
.remove = optee_remove,
@@ -783,6 +792,7 @@ static struct platform_driver optee_driv
.driver = {
.name = "optee",
.of_match_table = optee_dt_match,
+ .acpi_match_table = ACPI_PTR(optee_acpi_match),
},
};
module_platform_driver(optee_driver);
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -73,6 +73,17 @@ config SERIAL_AMBA_PL011_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
+config SERIAL_PHYTIUM_PCI
+ tristate "Phytium PCI serial port support"
+ depends on PCI
+ select SERIAL_CORE
+ help
+ This driver supports the Phytium UART controller on PCI/PCIe adapters.
+ If you want to compile this driver into the kernel, say Y here. To
+ compile this driver as a module, choose M here.
+
+ If unsure, say N.
+
config SERIAL_EARLYCON_ARM_SEMIHOST
bool "Early console using ARM semihosting"
depends on ARM64 || ARM
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -91,6 +91,8 @@ obj-$(CONFIG_SERIAL_RDA) += rda-uart.o
obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o
obj-$(CONFIG_SERIAL_SIFIVE) += sifive.o
+obj-$(CONFIG_SERIAL_PHYTIUM_PCI) += phytium-uart.o
+
# GPIOLIB helpers for modem control lines
obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -125,6 +125,8 @@ source "drivers/usb/chipidea/Kconfig"
source "drivers/usb/isp1760/Kconfig"
+source "drivers/usb/phytium/Kconfig"
+
comment "USB port drivers"
if USB
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -66,3 +66,5 @@ obj-$(CONFIG_USBIP_CORE) += usbip/
obj-$(CONFIG_TYPEC) += typec/
obj-$(CONFIG_USB_ROLE_SWITCH) += roles/
+
+obj-$(CONFIG_USB_PHYTIUM) += phytium/
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -72,6 +72,8 @@
#define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142
#define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242
+#define PCI_DEVICE_ID_PHYTIUM_XHCI 0xdc27
+
static const char hcd_name[] = "xhci_hcd";
static struct hc_driver __read_mostly xhci_pci_hc_driver;
@@ -283,6 +285,9 @@ static void xhci_pci_quirks(struct devic
if (pdev->vendor == PCI_VENDOR_ID_VIA)
xhci->quirks |= XHCI_RESET_ON_RESUME;
+ if (pdev->vendor == PCI_VENDOR_ID_PHYTIUM ||
+ pdev->device == PCI_DEVICE_ID_PHYTIUM_XHCI)
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
/* See https://bugzilla.kernel.org/show_bug.cgi?id=79511 */
if (pdev->vendor == PCI_VENDOR_ID_VIA &&
pdev->device == 0x3432)
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -137,6 +137,10 @@ static const struct xhci_plat_priv xhci_
.quirks = XHCI_RESET_ON_RESUME | XHCI_SUSPEND_RESUME_CLKS,
};
+static const struct xhci_plat_priv xhci_plat_phytium_pe220x = {
+ .quirks = XHCI_RESET_ON_RESUME,
+};
+
static const struct of_device_id usb_xhci_of_match[] = {
{
.compatible = "generic-xhci",
@@ -178,6 +182,9 @@ static const struct of_device_id usb_xhc
}, {
.compatible = "brcm,bcm7445-xhci",
.data = &xhci_plat_brcm,
+ }, {
+ .compatible = "phytium,pe220x-xhci",
+ .data = &xhci_plat_phytium_pe220x,
},
{},
};
@@ -289,6 +296,8 @@ static int xhci_plat_probe(struct platfo
if (pdev->dev.of_node)
priv_match = of_device_get_match_data(&pdev->dev);
+ else if (has_acpi_companion(&pdev->dev))
+ priv_match = acpi_device_get_match_data(&pdev->dev);
else
priv_match = dev_get_platdata(&pdev->dev);
@@ -536,6 +545,7 @@ static const struct dev_pm_ops xhci_plat
static const struct acpi_device_id usb_xhci_acpi_match[] = {
/* XHCI-compliant USB Controller */
{ "PNP0D10", },
+ { "PHYT0039", (kernel_ulong_t)&xhci_plat_phytium_pe220x },
{ }
};
MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -74,5 +74,15 @@ config W1_MASTER_SGI
This support is also available as a module. If so, the module
will be called sgi_w1.
+config W1_MASTER_PHYTIUM
+ tristate "Phytium 1-wire driver"
+ depends on ARCH_PHYTIUM || COMPILE_TEST
+ help
+ Say Y here if you want to get support for the 1-wire interface
+ on an Phytium SoC.
+
+ This driver can also be built as a module. If so, the module
+ will be called phytium-w1.
+
endmenu
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.
obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o
obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o
obj-$(CONFIG_W1_MASTER_SGI) += sgi_w1.o
+
+obj-$(CONFIG_W1_MASTER_PHYTIUM) += phytium_w1.o
\ No newline at end of file
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -68,7 +68,7 @@
int acpi_irq_penalty_init(void);
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
- int *polarity, char **name);
+ int *polarity, char **name, struct fwnode_handle **rs_fwnode);
int acpi_pci_link_free_irq(acpi_handle handle);
/* ACPI PCI Device Binding (pci_bind.c) */
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -24,7 +24,7 @@
enum arch_timer_reg {
ARCH_TIMER_REG_CTRL,
- ARCH_TIMER_REG_TVAL,
+ ARCH_TIMER_REG_CVAL,
};
enum arch_timer_ppi_nr {
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -340,6 +340,16 @@ struct irq_domain *acpi_irq_create_hiera
const struct irq_domain_ops *ops,
void *host_data);
+#ifdef CONFIG_ACPI_GENERIC_GSI
+struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
+#else
+static inline
+struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
+{
+ return NULL;
+}
+#endif
+
#ifdef CONFIG_X86_IO_APIC
extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
#else
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -196,6 +196,7 @@ enum cpuhp_state {
CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30,
CPUHP_AP_X86_HPET_ONLINE,
CPUHP_AP_X86_KVM_CLK_ONLINE,
+ CPUHP_AP_HOMO_RPROC_STARTING,
CPUHP_AP_ACTIVE,
CPUHP_ONLINE,
};
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -3142,4 +3142,6 @@
#define PCI_VENDOR_ID_NCUBE 0x10ff
+#define PCI_VENDOR_ID_PHYTIUM 0x1db7
+
#endif /* _LINUX_PCI_IDS_H */
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -107,6 +107,7 @@ extern const int phy_10gbit_features_arr
* @PHY_INTERFACE_MODE_100BASEX: 100 BaseX
* @PHY_INTERFACE_MODE_1000BASEX: 1000 BaseX
* @PHY_INTERFACE_MODE_2500BASEX: 2500 BaseX
+ * @PHY_INTERFACE_MODE_5GBASER: 5G BaseR
* @PHY_INTERFACE_MODE_RXAUI: Reduced XAUI
* @PHY_INTERFACE_MODE_XAUI: 10 Gigabit Attachment Unit Interface
* @PHY_INTERFACE_MODE_10GBASER: 10G BaseR
@@ -139,6 +140,7 @@ typedef enum {
PHY_INTERFACE_MODE_100BASEX,
PHY_INTERFACE_MODE_1000BASEX,
PHY_INTERFACE_MODE_2500BASEX,
+ PHY_INTERFACE_MODE_5GBASER,
PHY_INTERFACE_MODE_RXAUI,
PHY_INTERFACE_MODE_XAUI,
/* 10GBASE-R, XFI, SFI - single lane 10G Serdes */
@@ -209,6 +211,8 @@ static inline const char *phy_modes(phy_
return "1000base-x";
case PHY_INTERFACE_MODE_2500BASEX:
return "2500base-x";
+ case PHY_INTERFACE_MODE_5GBASER:
+ return "5gbase-r";
case PHY_INTERFACE_MODE_RXAUI:
return "rxaui";
case PHY_INTERFACE_MODE_XAUI:
@@ -549,7 +553,7 @@ struct phy_device {
struct phy_driver *drv;
u32 phy_id;
-
+ u32 force_mode;
struct phy_c45_device_ids c45_ids;
unsigned is_c45:1;
unsigned is_internal:1;
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -340,6 +340,7 @@ struct hdac_bus {
bool align_bdle_4k:1; /* BDLE align 4K boundary */
bool reverse_assign:1; /* assign devices in reverse order */
bool corbrp_self_clear:1; /* CORBRP clears itself after reset */
+ bool cmd_resend:1; /* command resend */
bool polling_mode:1;
bool needs_damn_long_delay:1;
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -279,4 +279,11 @@
/* Freescale LINFlexD UART */
#define PORT_LINFLEXUART 122
+
+/* Phytium PCI UART
+ * use bigger value to aviod code confilct
+ * when update in the future.
+ */
+#define PORT_PHYTIUM 200
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--- a/sound/hda/hdac_controller.c
+++ b/sound/hda/hdac_controller.c
@@ -143,6 +143,9 @@ int snd_hdac_bus_send_cmd(struct hdac_bu
{
unsigned int addr = azx_command_addr(val);
unsigned int wp, rp;
+ unsigned long timeout;
+ unsigned int rirb_wp;
+ int i = 0;
spin_lock_irq(&bus->reg_lock);
@@ -169,6 +172,42 @@ int snd_hdac_bus_send_cmd(struct hdac_bu
bus->corb.buf[wp] = cpu_to_le32(val);
snd_hdac_chip_writew(bus, CORBWP, wp);
+ if (bus->cmd_resend) {
+ timeout = jiffies + msecs_to_jiffies(1000);
+ udelay(80);
+ rirb_wp = snd_hdac_chip_readw(bus, RIRBWP);
+ while (rirb_wp == bus->rirb.wp) {
+ udelay(80);
+ rirb_wp = snd_hdac_chip_readw(bus, RIRBWP);
+ if (rirb_wp != bus->rirb.wp)
+ break;
+ if (i > 5)
+ break;
+ if (time_after(jiffies, timeout))
+ break;
+
+ /* add command to corb */
+ wp = snd_hdac_chip_readw(bus, CORBWP);
+ if (wp == 0xffff) {
+ /* something wrong, controller likely turned to D3 */
+ spin_unlock_irq(&bus->reg_lock);
+ return -EIO;
+ }
+ wp++;
+ wp %= AZX_MAX_CORB_ENTRIES;
+
+ rp = snd_hdac_chip_readw(bus, CORBRP);
+ if (wp == rp) {
+ /* oops, it's full */
+ spin_unlock_irq(&bus->reg_lock);
+ return -EAGAIN;
+ }
+ bus->corb.buf[wp] = cpu_to_le32(val);
+ snd_hdac_chip_writew(bus, CORBWP, wp);
+ i++;
+ }
+ }
+
spin_unlock_irq(&bus->reg_lock);
return 0;
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -87,7 +87,11 @@ void snd_hdac_stream_start(struct hdac_s
trace_snd_hdac_stream_start(bus, azx_dev);
+#ifdef CONFIG_SND_HDA_PHYTIUM
+ azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK) / 15;
+#else
azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK);
+#endif
if (!fresh_start)
azx_dev->start_wallclk -= azx_dev->period_wallclk;
@@ -550,7 +554,11 @@ static u64 azx_cc_read(const struct cycl
{
struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc);
+#ifdef CONFIG_SND_HDA_PHYTIUM
+ return snd_hdac_chip_readl(azx_dev->bus, WALLCLK) / 25;
+#else
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK);
+#endif
}
static void azx_timecounter_init(struct hdac_stream *azx_dev,
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -26,6 +26,22 @@ config SND_HDA_INTEL
To compile this driver as a module, choose M here: the module
will be called snd-hda-intel.
+config SND_HDA_PHYTIUM
+ tristate "PHYTIUM HD Audio"
+ depends on SOUND
+ select SND_HDA
+ select SND_HDA_ALIGNED_MMIO
+ help
+ Say Y here to support the HDA controller present in PHYTIUM
+ SoCs
+
+ This options enables support for the HD Audio controller
+ present in some PHYTIUM SoCs, used to communicate audio
+ to the "High Definition Audio" codec.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-hda-phytium.
+
config SND_HDA_TEGRA
tristate "NVIDIA Tegra HD Audio"
depends on ARCH_TEGRA
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
snd-hda-intel-objs := hda_intel.o
snd-hda-tegra-objs := hda_tegra.o
+snd-hda-phytium-objs := hda_phytium.o
snd-hda-codec-y := hda_bind.o hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o
snd-hda-codec-y += hda_controller.o
@@ -48,3 +49,4 @@ obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-
# when built in kernel
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
obj-$(CONFIG_SND_HDA_TEGRA) += snd-hda-tegra.o
+obj-$(CONFIG_SND_HDA_PHYTIUM) += snd-hda-phytium.o
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -17,6 +17,8 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include "hda_phytium.h"
+
#ifdef CONFIG_X86
/* for art-tsc conversion */
#include <asm/tsc.h>
@@ -157,6 +159,10 @@ static int azx_pcm_prepare(struct snd_pc
snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
unsigned short ctls = spdif ? spdif->ctls : 0;
+ struct hda_ft *hda;
+ hda = container_of(chip, struct hda_ft, chip);
+ hda->substream = substream;
+
trace_azx_pcm_prepare(chip, azx_dev);
dsp_lock(azx_dev);
if (dsp_is_locked(azx_dev)) {
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -77,6 +77,7 @@ source "sound/soc/ux500/Kconfig"
source "sound/soc/xilinx/Kconfig"
source "sound/soc/xtensa/Kconfig"
source "sound/soc/zte/Kconfig"
+source "sound/soc/phytium/Kconfig"
# Supported codecs
source "sound/soc/codecs/Kconfig"
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_SND_SOC) += ux500/
obj-$(CONFIG_SND_SOC) += xilinx/
obj-$(CONFIG_SND_SOC) += xtensa/
obj-$(CONFIG_SND_SOC) += zte/
+obj-$(CONFIG_SND_SOC) += phytium/
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -795,6 +795,15 @@ config SND_SOC_ES8328_SPI
depends on SPI_MASTER
select SND_SOC_ES8328
+config SND_SOC_ES8336
+ tristate "Everest Semi ES8336 CODEC"
+ depends on I2C
+ select GPIO_PHYTIUM_PCI
+
+config SND_SOC_ES8388
+ tristate "Everest Semi ES8388 CODEC"
+ depends on I2C
+
config SND_SOC_GTM601
tristate 'GTM601 UMTS modem audio codec'
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -90,6 +90,8 @@ snd-soc-es8316-objs := es8316.o
snd-soc-es8328-objs := es8328.o
snd-soc-es8328-i2c-objs := es8328-i2c.o
snd-soc-es8328-spi-objs := es8328-spi.o
+snd-soc-es8336-objs := es8336.o
+snd-soc-es8388-objs := es8388.o
snd-soc-gtm601-objs := gtm601.o
snd-soc-hdac-hdmi-objs := hdac_hdmi.o
snd-soc-hdac-hda-objs := hdac_hda.o
@@ -399,6 +401,8 @@ obj-$(CONFIG_SND_SOC_ES8316) += snd-s
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
+obj-$(CONFIG_SND_SOC_ES8336) += snd-soc-es8336.o
+obj-$(CONFIG_SND_SOC_ES8388) += snd-soc-es8388.o
obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o
obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o