1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Add mt7621 6.1 support

This commit is contained in:
Ycarus (Yannick Chabanois) 2023-08-02 19:37:46 +02:00
parent 0991134aed
commit 3cb104a04b
26 changed files with 3908 additions and 0 deletions

View file

@ -0,0 +1,306 @@
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
CONFIG_ARCH_MMAP_RND_BITS_MAX=15
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15
CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_AT803X_PHY=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BOARD_SCACHE=y
CONFIG_BOUNCE=y
CONFIG_CEVT_R4K=y
CONFIG_CLKSRC_MIPS_GIC=y
CONFIG_CLK_MT7621=y
CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US=100
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
CONFIG_CMDLINE_BOOL=y
# CONFIG_CMDLINE_OVERRIDE is not set
CONFIG_COMMON_CLK=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_DIEI=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_RIXI=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_TEO=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32=y
# CONFIG_CPU_MIPS32_R1 is not set
CONFIG_CPU_MIPS32_R2=y
CONFIG_CPU_MIPSR2=y
CONFIG_CPU_MIPSR2_IRQ_EI=y
CONFIG_CPU_MIPSR2_IRQ_VI=y
CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
CONFIG_CPU_PM=y
CONFIG_CPU_R4K_CACHE_TLB=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CPU_SUPPORTS_MSA=y
CONFIG_CRC16=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_CSRC_R4K=y
CONFIG_DEBUG_PINCTRL=y
CONFIG_DIMLIB=y
CONFIG_DMA_NONCOHERENT=y
# CONFIG_DTB_GNUBEE1 is not set
# CONFIG_DTB_GNUBEE2 is not set
CONFIG_DTB_RT_NONE=y
CONFIG_DTC=y
CONFIG_EARLY_PRINTK=y
CONFIG_FIXED_PHY=y
CONFIG_FWNODE_MDIO=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_LIB_ASHLDI3=y
CONFIG_GENERIC_LIB_ASHRDI3=y
CONFIG_GENERIC_LIB_CMPDI2=y
CONFIG_GENERIC_LIB_LSHRDI3=y
CONFIG_GENERIC_LIB_UCMPDI2=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GLOB=y
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_GPIO_CDEV=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_MT7621=y
# CONFIG_GPIO_RALINK is not set
CONFIG_GPIO_WATCHDOG=y
# CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set
CONFIG_GRO_CELLS=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HARDWARE_WATCHPOINTS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HIGHMEM=y
CONFIG_I2C=y
CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_GPIO=y
CONFIG_I2C_MT7621=y
CONFIG_ICPLUS_PHY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_MIPS_CPU=y
CONFIG_IRQ_WORK=y
CONFIG_KMAP_LOCAL=y
CONFIG_LED_TRIGGER_PHY=y
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEDIATEK_GE_PHY=y
CONFIG_MEMFD_CREATE=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MIKROTIK=y
CONFIG_MIKROTIK_RB_SYSFS=y
CONFIG_MIPS=y
CONFIG_MIPS_ASID_BITS=8
CONFIG_MIPS_ASID_SHIFT=0
CONFIG_MIPS_CLOCK_VSYSCALL=y
CONFIG_MIPS_CM=y
# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set
# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
CONFIG_MIPS_CMDLINE_FROM_DTB=y
CONFIG_MIPS_CPC=y
CONFIG_MIPS_CPS=y
CONFIG_MIPS_CPS_CPUIDLE=y
# CONFIG_MIPS_CPS_NS16550_BOOL is not set
CONFIG_MIPS_CPS_PM=y
CONFIG_MIPS_CPU_SCACHE=y
CONFIG_MIPS_EBPF_JIT=y
CONFIG_MIPS_GIC=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
CONFIG_MIPS_LD_CAN_LINK_VDSO=y
CONFIG_MIPS_MT=y
CONFIG_MIPS_MT_FPAFF=y
CONFIG_MIPS_MT_SMP=y
# CONFIG_MIPS_NO_APPENDED_DTB is not set
CONFIG_MIPS_NR_CPU_NR_MAP=4
CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y
CONFIG_MIPS_RAW_APPENDED_DTB=y
CONFIG_MIPS_SPRAM=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MT7621_WDT=y
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_NAND_CORE=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_NAND_MT7621=y
CONFIG_MTD_NAND_MTK_BMT=y
# CONFIG_MTD_PARSER_TPLINK_SAFELOADER is not set
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_ROUTERBOOT_PARTS=y
CONFIG_MTD_SERCOMM_PARTS=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
CONFIG_MTD_SPLIT_FIT_FW=y
CONFIG_MTD_SPLIT_MINOR_FW=y
CONFIG_MTD_SPLIT_SEAMA_FW=y
CONFIG_MTD_SPLIT_TPLINK_FW=y
CONFIG_MTD_SPLIT_TRX_FW=y
CONFIG_MTD_SPLIT_UIMAGE_FW=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_VIRT_CONCAT=y
# CONFIG_MTK_HSDMA is not set
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NET_DEVLINK=y
CONFIG_NET_DSA=y
CONFIG_NET_DSA_MT7530=y
CONFIG_NET_DSA_MT7530_MDIO=y
# CONFIG_NET_DSA_MT7530_MMIO is not set
CONFIG_NET_DSA_TAG_MTK=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_MEDIATEK_SOC=y
CONFIG_NET_SELFTESTS=y
CONFIG_NET_SWITCHDEV=y
CONFIG_NET_VENDOR_MEDIATEK=y
# CONFIG_NET_VENDOR_RALINK is not set
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NR_CPUS=4
CONFIG_NVMEM=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_PADATA=y
CONFIG_PCI=y
CONFIG_PCIE_MT7621=y
CONFIG_PCI_DISABLE_COMMON_QUIRKS=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_DRIVERS_GENERIC=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHY_MT7621_PCI=y
# CONFIG_PHY_RALINK_USB is not set
CONFIG_PINCTRL=y
CONFIG_PINCTRL_AW9523=y
CONFIG_PINCTRL_MT7621=y
CONFIG_PINCTRL_RALINK=y
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PINCTRL_SX150X=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_POWER_SUPPLY=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_QUEUED_RWLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_RALINK=y
# CONFIG_RALINK_WDT is not set
CONFIG_RATIONAL=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_BQ32K=y
CONFIG_RTC_DRV_PCF8563=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RTC_MC146818_LIB=y
# CONFIG_SCHED_CORE is not set
CONFIG_SCHED_SMT=y
CONFIG_SERIAL_8250_NR_UARTS=3
CONFIG_SERIAL_8250_RUNTIME_UARTS=3
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SGL_ALLOC=y
CONFIG_SMP=y
CONFIG_SMP_UP=y
CONFIG_SOCK_RX_QUEUE_MAPPING=y
CONFIG_SOC_BUS=y
# CONFIG_SOC_MT7620 is not set
CONFIG_SOC_MT7621=y
# CONFIG_SOC_RT288X is not set
# CONFIG_SOC_RT305X is not set
# CONFIG_SOC_RT3883 is not set
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SPI_MT7621=y
# CONFIG_SPI_RT2880 is not set
CONFIG_SRCU=y
CONFIG_SWPHY=y
CONFIG_SYNC_R4K=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_HIGHMEM=y
CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_MIPS16=y
CONFIG_SYS_SUPPORTS_MIPS_CPS=y
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
CONFIG_SYS_SUPPORTS_SCHED_SMT=y
CONFIG_SYS_SUPPORTS_SMP=y
CONFIG_SYS_SUPPORTS_ZBOOT=y
CONFIG_TARGET_ISA_REV=2
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_UBIFS_FS=y
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_WATCHDOG_CORE=y
CONFIG_WEAK_ORDERING=y
CONFIG_XPS=y
CONFIG_XXHASH=y
CONFIG_ZBOOT_LOAD_ADDRESS=0x0
CONFIG_ZLIB_DEFLATE=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y

View file

@ -0,0 +1,61 @@
--- a/arch/mips/ralink/reset.c
+++ b/arch/mips/ralink/reset.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/reset-controller.h>
+#include <linux/platform_device.h>
#include <asm/reboot.h>
@@ -65,21 +66,39 @@ static const struct reset_control_ops re
.deassert = ralink_deassert_device,
};
-static struct reset_controller_dev reset_dev = {
- .ops = &reset_ops,
- .owner = THIS_MODULE,
- .nr_resets = 32,
- .of_reset_n_cells = 1,
+static int ralink_reset_probe(struct platform_device *pdev)
+{
+ struct reset_controller_dev *rcdev;
+
+ rcdev = devm_kzalloc(&pdev->dev, sizeof(*rcdev), GFP_KERNEL);
+ if (!rcdev)
+ return -ENOMEM;
+
+ rcdev->ops = &reset_ops;
+ rcdev->owner = THIS_MODULE;
+ rcdev->nr_resets = 32;
+ rcdev->of_reset_n_cells = 1;
+ rcdev->of_node = pdev->dev.of_node;
+
+ return devm_reset_controller_register(&pdev->dev, rcdev);
+}
+
+static const struct of_device_id ralink_reset_dt_ids[] = {
+ { .compatible = "ralink,rt2880-reset" },
+ {}
+};
+
+static struct platform_driver ralink_reset_driver = {
+ .probe = ralink_reset_probe,
+ .driver = {
+ .name = "ralink-reset",
+ .of_match_table = ralink_reset_dt_ids,
+ }
};
void ralink_rst_init(void)
{
- reset_dev.of_node = of_find_compatible_node(NULL, NULL,
- "ralink,rt2880-reset");
- if (!reset_dev.of_node)
- pr_err("Failed to find reset controller node");
- else
- reset_controller_register(&reset_dev);
+ platform_driver_register(&ralink_reset_driver);
}
static void ralink_restart(char *command)

View file

@ -0,0 +1,20 @@
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -162,6 +162,7 @@ source "drivers/net/ethernet/pensando/Kc
source "drivers/net/ethernet/qlogic/Kconfig"
source "drivers/net/ethernet/brocade/Kconfig"
source "drivers/net/ethernet/qualcomm/Kconfig"
+source "drivers/net/ethernet/ralink/Kconfig"
source "drivers/net/ethernet/rdc/Kconfig"
source "drivers/net/ethernet/realtek/Kconfig"
source "drivers/net/ethernet/renesas/Kconfig"
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_NET_VENDOR_PACKET_ENGINES)
obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/
+obj-$(CONFIG_NET_VENDOR_RALINK) += ralink/
obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/
obj-$(CONFIG_NET_VENDOR_RDC) += rdc/

View file

@ -0,0 +1,19 @@
--- a/arch/mips/include/asm/mach-ralink/mt7620.h
+++ b/arch/mips/include/asm/mach-ralink/mt7620.h
@@ -96,4 +96,16 @@ static inline int mt7620_get_eco(void)
return rt_sysc_r32(SYSC_REG_CHIP_REV) & CHIP_REV_ECO_MASK;
}
+static inline int mt7620_get_chipver(void)
+{
+ return (rt_sysc_r32(SYSC_REG_CHIP_REV) >> CHIP_REV_VER_SHIFT) &
+ CHIP_REV_VER_MASK;
+}
+
+static inline int mt7620_get_pkg(void)
+{
+ return (rt_sysc_r32(SYSC_REG_CHIP_REV) >> CHIP_REV_PKG_SHIFT) &
+ CHIP_REV_PKG_MASK;
+}
+
#endif

View file

@ -0,0 +1,100 @@
From ce3d4a4111a5f7e6b4e74bceae5faa6ce388e8ec Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 14 Jul 2013 23:08:11 +0200
Subject: [PATCH 05/53] MIPS: use set_mode() to enable/disable the cevt-r4k
irq
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/ralink/Kconfig | 5 +++++
1 file changed, 5 insertions(+)
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -1,12 +1,17 @@
# SPDX-License-Identifier: GPL-2.0
if RALINK
+config CEVT_SYSTICK_QUIRK
+ bool
+ default n
+
config CLKEVT_RT3352
bool
depends on SOC_RT305X || SOC_MT7620
default y
select TIMER_OF
select CLKSRC_MMIO
+ select CEVT_SYSTICK_QUIRK
config RALINK_ILL_ACC
bool
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -16,6 +16,31 @@
#include <asm/time.h>
#include <asm/cevt-r4k.h>
+#ifdef CONFIG_CEVT_SYSTICK_QUIRK
+static int mips_state_oneshot(struct clock_event_device *evt)
+{
+ unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
+ if (!cp0_timer_irq_installed) {
+ cp0_timer_irq_installed = 1;
+ if (request_irq(evt->irq, c0_compare_interrupt, flags, "timer",
+ c0_compare_interrupt))
+ pr_err("Failed to request irq %d (timer)\n", evt->irq);
+ }
+
+ return 0;
+}
+
+static int mips_state_shutdown(struct clock_event_device *evt)
+{
+ if (cp0_timer_irq_installed) {
+ cp0_timer_irq_installed = 0;
+ free_irq(evt->irq, NULL);
+ }
+
+ return 0;
+}
+#endif
+
static int mips_next_event(unsigned long delta,
struct clock_event_device *evt)
{
@@ -292,7 +317,9 @@ core_initcall(r4k_register_cpufreq_notif
int r4k_clockevent_init(void)
{
+#ifndef CONFIG_CEVT_SYSTICK_QUIRK
unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
+#endif
unsigned int cpu = smp_processor_id();
struct clock_event_device *cd;
unsigned int irq, min_delta;
@@ -322,11 +349,16 @@ int r4k_clockevent_init(void)
cd->rating = 300;
cd->irq = irq;
cd->cpumask = cpumask_of(cpu);
+#ifdef CONFIG_CEVT_SYSTICK_QUIRK
+ cd->set_state_shutdown = mips_state_shutdown;
+ cd->set_state_oneshot = mips_state_oneshot;
+#endif
cd->set_next_event = mips_next_event;
cd->event_handler = mips_event_handler;
clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff);
+#ifndef CONFIG_CEVT_SYSTICK_QUIRK
if (cp0_timer_irq_installed)
return 0;
@@ -335,6 +367,7 @@ int r4k_clockevent_init(void)
if (request_irq(irq, c0_compare_interrupt, flags, "timer",
c0_compare_interrupt))
pr_err("Failed to request irq %d (timer)\n", irq);
+#endif
return 0;
}

View file

@ -0,0 +1,195 @@
From bd30f19a006fb52bac80c6463c49dd2f4159f4ac Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 28 Jul 2013 16:26:41 +0200
Subject: [PATCH 06/53] MIPS: ralink: add cpu frequency scaling
This feature will break udelay() and cause the delay loop to have longer delays
when the frequency is scaled causing a performance hit.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/ralink/cevt-rt3352.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
--- a/arch/mips/ralink/cevt-rt3352.c
+++ b/arch/mips/ralink/cevt-rt3352.c
@@ -29,6 +29,10 @@
/* enable the counter */
#define CFG_CNT_EN 0x1
+/* mt7620 frequency scaling defines */
+#define CLK_LUT_CFG 0x40
+#define SLEEP_EN BIT(31)
+
struct systick_device {
void __iomem *membase;
struct clock_event_device dev;
@@ -36,21 +40,53 @@ struct systick_device {
int freq_scale;
};
+static void (*systick_freq_scaling)(struct systick_device *sdev, int status);
+
static int systick_set_oneshot(struct clock_event_device *evt);
static int systick_shutdown(struct clock_event_device *evt);
+static inline void mt7620_freq_scaling(struct systick_device *sdev, int status)
+{
+ if (sdev->freq_scale == status)
+ return;
+
+ sdev->freq_scale = status;
+
+ pr_info("%s: %s autosleep mode\n", sdev->dev.name,
+ (status) ? ("enable") : ("disable"));
+ if (status)
+ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) | SLEEP_EN, CLK_LUT_CFG);
+ else
+ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) & ~SLEEP_EN, CLK_LUT_CFG);
+}
+
+static inline unsigned int read_count(struct systick_device *sdev)
+{
+ return ioread32(sdev->membase + SYSTICK_COUNT);
+}
+
+static inline unsigned int read_compare(struct systick_device *sdev)
+{
+ return ioread32(sdev->membase + SYSTICK_COMPARE);
+}
+
+static inline void write_compare(struct systick_device *sdev, unsigned int val)
+{
+ iowrite32(val, sdev->membase + SYSTICK_COMPARE);
+}
+
static int systick_next_event(unsigned long delta,
struct clock_event_device *evt)
{
struct systick_device *sdev;
- u32 count;
+ int res;
sdev = container_of(evt, struct systick_device, dev);
- count = ioread32(sdev->membase + SYSTICK_COUNT);
- count = (count + delta) % SYSTICK_FREQ;
- iowrite32(count, sdev->membase + SYSTICK_COMPARE);
+ delta += read_count(sdev);
+ write_compare(sdev, delta);
+ res = ((int)(read_count(sdev) - delta) >= 0) ? -ETIME : 0;
- return 0;
+ return res;
}
static void systick_event_handler(struct clock_event_device *dev)
@@ -60,20 +96,25 @@ static void systick_event_handler(struct
static irqreturn_t systick_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *dev = (struct clock_event_device *) dev_id;
+ int ret = 0;
+ struct clock_event_device *cdev;
+ struct systick_device *sdev;
- dev->event_handler(dev);
+ if (read_c0_cause() & STATUSF_IP7) {
+ cdev = (struct clock_event_device *) dev_id;
+ sdev = container_of(cdev, struct systick_device, dev);
+
+ /* Clear Count/Compare Interrupt */
+ write_compare(sdev, read_compare(sdev));
+ cdev->event_handler(cdev);
+ ret = 1;
+ }
- return IRQ_HANDLED;
+ return IRQ_RETVAL(ret);
}
static struct systick_device systick = {
.dev = {
- /*
- * cevt-r4k uses 300, make sure systick
- * gets used if available
- */
- .rating = 310,
.features = CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = systick_next_event,
.set_state_shutdown = systick_shutdown,
@@ -91,7 +132,13 @@ static int systick_shutdown(struct clock
if (sdev->irq_requested)
free_irq(systick.dev.irq, &systick.dev);
sdev->irq_requested = 0;
- iowrite32(0, systick.membase + SYSTICK_CONFIG);
+ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG);
+
+ if (systick_freq_scaling)
+ systick_freq_scaling(sdev, 0);
+
+ if (systick_freq_scaling)
+ systick_freq_scaling(sdev, 1);
return 0;
}
@@ -116,33 +163,46 @@ static int systick_set_oneshot(struct cl
return 0;
}
+static const struct of_device_id systick_match[] = {
+ { .compatible = "ralink,mt7620a-systick", .data = mt7620_freq_scaling},
+ {},
+};
+
static int __init ralink_systick_init(struct device_node *np)
{
- int ret;
+ const struct of_device_id *match;
+ int rating = 200;
systick.membase = of_iomap(np, 0);
if (!systick.membase)
return -ENXIO;
- systick.dev.name = np->name;
- clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
- systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
- systick.dev.max_delta_ticks = 0x7fff;
- systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
- systick.dev.min_delta_ticks = 0x3;
+ match = of_match_node(systick_match, np);
+ if (match) {
+ systick_freq_scaling = match->data;
+ /*
+ * cevt-r4k uses 300, make sure systick
+ * gets used if available
+ */
+ rating = 310;
+ }
+
+ /* enable counter than register clock source */
+ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG);
+ clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
+ SYSTICK_FREQ, rating, 16, clocksource_mmio_readl_up);
+
+ /* register clock event */
systick.dev.irq = irq_of_parse_and_map(np, 0);
if (!systick.dev.irq) {
pr_err("%pOFn: request_irq failed", np);
return -EINVAL;
}
- ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
- SYSTICK_FREQ, 301, 16,
- clocksource_mmio_readl_up);
- if (ret)
- return ret;
-
- clockevents_register_device(&systick.dev);
+ systick.dev.name = np->name;
+ systick.dev.rating = rating;
+ systick.dev.cpumask = cpumask_of(0);
+ clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 0x7fff);
pr_info("%pOFn: running - mult: %d, shift: %d\n",
np, systick.dev.mult, systick.dev.shift);

View file

@ -0,0 +1,63 @@
From f15d27f9c90ede4b16eb37f9ae573ef81c2b6996 Mon Sep 17 00:00:00 2001
From: David Bauer <mail@david-bauer.net>
Date: Thu, 31 Dec 2020 18:49:12 +0100
Subject: [PATCH] MIPS: add bootargs-override property
Add support for the bootargs-override property to the chosen node
similar to the one used on ipq806x or mpc85xx.
This is necessary, as the U-Boot used on some boards, notably the
Ubiquiti UniFi 6 Lite, overwrite the bootargs property of the chosen
node leading to a kernel panic when loading OpenWrt.
Signed-off-by: David Bauer <mail@david-bauer.net>
---
arch/mips/kernel/setup.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -544,8 +544,28 @@ static int __init bootcmdline_scan_chose
#endif /* CONFIG_OF_EARLY_FLATTREE */
+static int __init bootcmdline_scan_chosen_override(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ bool *dt_bootargs = data;
+ const char *p;
+ int l;
+
+ if (depth != 1 || !data || strcmp(uname, "chosen") != 0)
+ return 0;
+
+ p = of_get_flat_dt_prop(node, "bootargs-override", &l);
+ if (p != NULL && l > 0) {
+ strlcpy(boot_command_line, p, COMMAND_LINE_SIZE);
+ *dt_bootargs = true;
+ }
+
+ return 1;
+}
+
static void __init bootcmdline_init(void)
{
+ bool dt_bootargs_override = false;
bool dt_bootargs = false;
/*
@@ -559,6 +579,14 @@ static void __init bootcmdline_init(void
}
/*
+ * If bootargs-override in the chosen node is set, use this as the
+ * command line
+ */
+ of_scan_flat_dt(bootcmdline_scan_chosen_override, &dt_bootargs_override);
+ if (dt_bootargs_override)
+ return;
+
+ /*
* If the user specified a built-in command line &
* MIPS_CMDLINE_BUILTIN_EXTEND, then the built-in command line is
* prepended to arguments from the bootloader or DT so we'll copy them

View file

@ -0,0 +1,28 @@
From 5ede027f6c4a57ed25da872420508b7f1168b36b Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 7 Dec 2015 17:15:32 +0100
Subject: [PATCH 13/53] owrt: hack: fix mt7688 cache issue
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/kernel/setup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -686,7 +686,6 @@ static void __init arch_mem_init(char **
mips_reserve_vmcore();
mips_parse_crashkernel();
- device_tree_init();
/*
* In order to reduce the possibility of kernel panic when failed to
@@ -803,6 +802,7 @@ void __init setup_arch(char **cmdline_p)
cpu_cache_init();
paging_init();
+ device_tree_init();
memblock_dump_all();
}

View file

@ -0,0 +1,25 @@
From 9e6ce539092a1dd605a20bf73c655a9de58d8641 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 7 Dec 2015 17:18:05 +0100
Subject: [PATCH 15/53] arch: mips: do not select illegal access driver by
default
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/ralink/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -14,9 +14,9 @@ config CLKEVT_RT3352
select CEVT_SYSTICK_QUIRK
config RALINK_ILL_ACC
- bool
+ bool "illegal access irq"
depends on SOC_RT305X
- default y
+ default n
config IRQ_INTC
bool

View file

@ -0,0 +1,15 @@
--- a/arch/mips/ralink/irq-gic.c
+++ b/arch/mips/ralink/irq-gic.c
@@ -13,6 +13,12 @@
int get_c0_perfcount_int(void)
{
+ /*
+ * Performance counter events are routed through GIC.
+ * Prevent them from firing on CPU IRQ7 as well
+ */
+ clear_c0_status(IE_SW0 << 7);
+
return gic_get_c0_perfcount_int();
}
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);

View file

@ -0,0 +1,20 @@
From ee9081b2726a5ca8cde5497afdc5425e21ff8f8b Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 15 Jul 2013 00:39:21 +0200
Subject: [PATCH 37/53] mtd: cfi cmdset 0002 force word write
---
drivers/mtd/chips/cfi_cmdset_0002.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -40,7 +40,7 @@
#include <linux/mtd/xip.h>
#define AMD_BOOTLOC_BUG
-#define FORCE_WORD_WRITE 0
+#define FORCE_WORD_WRITE 1
#define MAX_RETRIES 3

View file

@ -0,0 +1,85 @@
From 3d5f4da8296b23eb3abf8b13122b0d06a215e79c Mon Sep 17 00:00:00 2001
From: Weijie Gao <weijie.gao@mediatek.com>
Date: Wed, 1 Apr 2020 02:07:59 +0800
Subject: [PATCH 2/2] dt-bindings: add documentation for mt7621-nand driver
This patch adds documentation for MediaTek MT7621 NAND flash controller
driver.
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
.../bindings/mtd/mediatek,mt7621-nfc.yaml | 68 ++++++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/mediatek,mt7621-nfc.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/mediatek,mt7621-nfc.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/mediatek,mt7621-nfc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT7621 SoC NAND Flash Controller (NFC) DT binding
+
+maintainers:
+ - Weijie Gao <weijie.gao@mediatek.com>
+
+description: |
+ This driver uses a single node to describe both NAND Flash controller
+ interface (NFI) and ECC engine for MT7621 SoC.
+ MT7621 supports only one chip select.
+
+properties:
+ "#address-cells": false
+ "#size-cells": false
+
+ compatible:
+ enum:
+ - mediatek,mt7621-nfc
+
+ reg:
+ items:
+ - description: Register base of NFI core
+ - description: Register base of ECC engine
+
+ reg-names:
+ items:
+ - const: nfi
+ - const: ecc
+
+ clocks:
+ items:
+ - description: Source clock for NFI core, fixed 125MHz
+
+ clock-names:
+ items:
+ - const: nfi_clk
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+
+examples:
+ - |
+ nficlock: nficlock {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+
+ clock-frequency = <125000000>;
+ };
+
+ nand@1e003000 {
+ compatible = "mediatek,mt7621-nfc";
+
+ reg = <0x1e003000 0x800
+ 0x1e003800 0x800>;
+ reg-names = "nfi", "ecc";
+
+ clocks = <&nficlock>;
+ clock-names = "nfi_clk";
+ };

View file

@ -0,0 +1,34 @@
From bd0f89de5476ca25e73fae829ba3e1dafae1d90d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= <opensource@vdorst.com>
Date: Fri, 21 Jun 2019 10:04:05 +0200
Subject: [PATCH] net: ethernet: mediatek: support net-labels
With this patch, device name can be set within dts file in the same way as dsa
port can.
Add: label = "wan"; to GMAC node.
Signed-off-by: René van Dorst <opensource@vdorst.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4633,6 +4633,7 @@ static const struct net_device_ops mtk_n
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
{
+ const char *name = of_get_property(np, "label", NULL);
const __be32 *_id = of_get_property(np, "reg", NULL);
phy_interface_t phy_mode;
struct phylink *phylink;
@@ -4791,6 +4792,9 @@ static int mtk_add_mac(struct mtk_eth *e
register_netdevice_notifier(&mac->device_notifier);
}
+ if (name)
+ strlcpy(eth->netdev[id]->name, name, IFNAMSIZ);
+
return 0;
free_netdev:

View file

@ -0,0 +1,118 @@
From ffbb1b37a3e1ce1a5c574a6bd4f5aede8bc468ac Mon Sep 17 00:00:00 2001
From: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
Date: Sat, 27 Feb 2021 20:20:07 -0800
Subject: [PATCH] Revert "net: phy: simplify phy_link_change arguments"
This reverts commit a307593a644443db12888f45eed0dafb5869e2cc.
This brings back the do_carrier flags used by the (hacky) next patch,
still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
---
drivers/net/phy/phy.c | 12 ++++++------
drivers/net/phy/phy_device.c | 12 +++++++-----
drivers/net/phy/phylink.c | 3 ++-
include/linux/phy.h | 2 +-
4 files changed, 16 insertions(+), 13 deletions(-)
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -71,13 +71,13 @@ static void phy_process_state_change(str
static void phy_link_up(struct phy_device *phydev)
{
- phydev->phy_link_change(phydev, true);
+ phydev->phy_link_change(phydev, true, true);
phy_led_trigger_change_speed(phydev);
}
-static void phy_link_down(struct phy_device *phydev)
+static void phy_link_down(struct phy_device *phydev, bool do_carrier)
{
- phydev->phy_link_change(phydev, false);
+ phydev->phy_link_change(phydev, false, do_carrier);
phy_led_trigger_change_speed(phydev);
}
@@ -563,7 +563,7 @@ int phy_start_cable_test(struct phy_devi
goto out;
/* Mark the carrier down until the test is complete */
- phy_link_down(phydev);
+ phy_link_down(phydev, true);
netif_testing_on(dev);
err = phydev->drv->cable_test_start(phydev);
@@ -634,7 +634,7 @@ int phy_start_cable_test_tdr(struct phy_
goto out;
/* Mark the carrier down until the test is complete */
- phy_link_down(phydev);
+ phy_link_down(phydev, true);
netif_testing_on(dev);
err = phydev->drv->cable_test_tdr_start(phydev, config);
@@ -706,7 +706,7 @@ static int phy_check_link_status(struct
phy_link_up(phydev);
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
phydev->state = PHY_NOLINK;
- phy_link_down(phydev);
+ phy_link_down(phydev, true);
}
return 0;
@@ -1192,7 +1192,7 @@ void phy_state_machine(struct work_struc
case PHY_HALTED:
if (phydev->link) {
phydev->link = 0;
- phy_link_down(phydev);
+ phy_link_down(phydev, true);
}
do_suspend = true;
break;
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1035,14 +1035,16 @@ struct phy_device *phy_find_first(struct
}
EXPORT_SYMBOL(phy_find_first);
-static void phy_link_change(struct phy_device *phydev, bool up)
+static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier)
{
struct net_device *netdev = phydev->attached_dev;
- if (up)
- netif_carrier_on(netdev);
- else
- netif_carrier_off(netdev);
+ if (do_carrier) {
+ if (up)
+ netif_carrier_on(netdev);
+ else
+ netif_carrier_off(netdev);
+ }
phydev->adjust_link(netdev);
if (phydev->mii_ts && phydev->mii_ts->link_state)
phydev->mii_ts->link_state(phydev->mii_ts, phydev);
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1322,7 +1322,8 @@ void phylink_destroy(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_destroy);
-static void phylink_phy_change(struct phy_device *phydev, bool up)
+static void phylink_phy_change(struct phy_device *phydev, bool up,
+ bool do_carrier)
{
struct phylink *pl = phydev->phylink;
bool tx_pause, rx_pause;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -706,7 +706,7 @@ struct phy_device {
u8 mdix;
u8 mdix_ctrl;
- void (*phy_link_change)(struct phy_device *phydev, bool up);
+ void (*phy_link_change)(struct phy_device *, bool up, bool do_carrier);
void (*adjust_link)(struct net_device *dev);
#if IS_ENABLED(CONFIG_MACSEC)

View file

@ -0,0 +1,47 @@
From 0b6eb1e68290243d439ee330ea8d0b239a5aec69 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 27 Jul 2014 09:38:50 +0100
Subject: [PATCH 34/53] NET: multi phy support
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/net/phy/phy.c | 9 ++++++---
include/linux/phy.h | 1 +
2 files changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -706,7 +706,10 @@ static int phy_check_link_status(struct
phy_link_up(phydev);
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
phydev->state = PHY_NOLINK;
- phy_link_down(phydev, true);
+ if (!phydev->no_auto_carrier_off)
+ phy_link_down(phydev, true);
+ else
+ phy_link_down(phydev, false);
}
return 0;
@@ -1192,7 +1195,10 @@ void phy_state_machine(struct work_struc
case PHY_HALTED:
if (phydev->link) {
phydev->link = 0;
- phy_link_down(phydev, true);
+ if (!phydev->no_auto_carrier_off)
+ phy_link_down(phydev, true);
+ else
+ phy_link_down(phydev, false);
}
do_suspend = true;
break;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -622,6 +622,7 @@ struct phy_device {
unsigned downshifted_rate:1;
unsigned is_on_sfp_module:1;
unsigned mac_managed_pm:1;
+ unsigned no_auto_carrier_off:1;
unsigned autoneg:1;
/* The most recently read link state */

View file

@ -0,0 +1,59 @@
From d410e5478c622c01fcf31427533df5f433df9146 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 28 Jul 2013 19:45:30 +0200
Subject: [PATCH 26/53] DT: Add documentation for gpio-ralink
Describe gpio-ralink binding.
Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: devicetree@vger.kernel.org
Cc: linux-gpio@vger.kernel.org
---
.../devicetree/bindings/gpio/gpio-ralink.txt | 40 ++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-ralink.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt
@@ -0,0 +1,40 @@
+Ralink SoC GPIO controller bindings
+
+Required properties:
+- compatible:
+ - "ralink,rt2880-gpio" for Ralink controllers
+- #gpio-cells : Should be two.
+ - first cell is the pin number
+ - second cell is used to specify optional parameters (unused)
+- gpio-controller : Marks the device node as a GPIO controller
+- reg : Physical base address and length of the controller's registers
+- interrupt-parent: phandle to the INTC device node
+- interrupts : Specify the INTC interrupt number
+- ngpios : Specify the number of GPIOs
+- ralink,register-map : The register layout depends on the GPIO bank and actual
+ SoC type. Register offsets need to be in this order.
+ [ INT, EDGE, RENA, FENA, DATA, DIR, POL, SET, RESET, TOGGLE ]
+
+Optional properties:
+- ralink,gpio-base : Specify the GPIO chips base number
+
+Example:
+
+ gpio0: gpio@600 {
+ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio";
+
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ reg = <0x600 0x34>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <6>;
+
+ ngpios = <24>;
+ ralink,gpio-base = <0>;
+ ralink,register-map = [ 00 04 08 0c
+ 20 24 28 2c
+ 30 34 ];
+
+ };

View file

@ -0,0 +1,416 @@
From 69fdd2c4f937796b934e89c33acde9d082e27bfd Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 4 Aug 2014 20:36:29 +0200
Subject: [PATCH 27/53] GPIO: MIPS: ralink: add gpio driver for ralink SoC
Add gpio driver for Ralink SoC. This driver makes the gpio core on
RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work.
Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: linux-gpio@vger.kernel.org
---
arch/mips/include/asm/mach-ralink/gpio.h | 24 ++
drivers/gpio/Kconfig | 6 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-ralink.c | 355 ++++++++++++++++++++++++++++++
4 files changed, 386 insertions(+)
create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h
create mode 100644 drivers/gpio/gpio-ralink.c
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/gpio.h
@@ -0,0 +1,24 @@
+/*
+ * Ralink SoC GPIO API support
+ *
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_MACH_RALINK_GPIO_H
+#define __ASM_MACH_RALINK_GPIO_H
+
+#define ARCH_NR_GPIOS 128
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
+
+#endif /* __ASM_MACH_RALINK_GPIO_H */
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -569,6 +569,12 @@ config GPIO_SNPS_CREG
where only several fields in register belong to GPIO lines and
each GPIO line owns a field with different length and on/off value.
+config GPIO_RALINK
+ bool "Ralink GPIO Support"
+ depends on RALINK
+ help
+ Say yes here to support the Ralink SoC GPIO device
+
config GPIO_SPEAR_SPICS
bool "ST SPEAr13xx SPI Chip Select as GPIO support"
depends on PLAT_SPEAR
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -121,6 +121,7 @@ obj-$(CONFIG_GPIO_PISOSR) += gpio-pisos
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
+obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o
--- /dev/null
+++ b/drivers/gpio/gpio-ralink.c
@@ -0,0 +1,341 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+
+enum ralink_gpio_reg {
+ GPIO_REG_INT = 0,
+ GPIO_REG_EDGE,
+ GPIO_REG_RENA,
+ GPIO_REG_FENA,
+ GPIO_REG_DATA,
+ GPIO_REG_DIR,
+ GPIO_REG_POL,
+ GPIO_REG_SET,
+ GPIO_REG_RESET,
+ GPIO_REG_TOGGLE,
+ GPIO_REG_MAX
+};
+
+struct ralink_gpio_chip {
+ struct gpio_chip chip;
+ u8 regs[GPIO_REG_MAX];
+
+ spinlock_t lock;
+ void __iomem *membase;
+ struct irq_domain *domain;
+ int irq;
+
+ u32 rising;
+ u32 falling;
+};
+
+#define MAP_MAX 4
+static struct irq_domain *irq_map[MAP_MAX];
+static int irq_map_count;
+static atomic_t irq_refcount = ATOMIC_INIT(0);
+
+static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip)
+{
+ struct ralink_gpio_chip *rg;
+
+ rg = container_of(chip, struct ralink_gpio_chip, chip);
+
+ return rg;
+}
+
+static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val)
+{
+ iowrite32(val, rg->membase + rg->regs[reg]);
+}
+
+static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg)
+{
+ return ioread32(rg->membase + rg->regs[reg]);
+}
+
+static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
+
+ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset));
+}
+
+static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
+
+ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset));
+}
+
+static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
+ unsigned long flags;
+ u32 t;
+
+ spin_lock_irqsave(&rg->lock, flags);
+ t = rt_gpio_r32(rg, GPIO_REG_DIR);
+ t &= ~BIT(offset);
+ rt_gpio_w32(rg, GPIO_REG_DIR, t);
+ spin_unlock_irqrestore(&rg->lock, flags);
+
+ return 0;
+}
+
+static int ralink_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
+ unsigned long flags;
+ u32 t;
+
+ spin_lock_irqsave(&rg->lock, flags);
+ ralink_gpio_set(chip, offset, value);
+ t = rt_gpio_r32(rg, GPIO_REG_DIR);
+ t |= BIT(offset);
+ rt_gpio_w32(rg, GPIO_REG_DIR, t);
+ spin_unlock_irqrestore(&rg->lock, flags);
+
+ return 0;
+}
+
+static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
+
+ if (rg->irq < 1)
+ return -1;
+
+ return irq_create_mapping(rg->domain, pin);
+}
+
+static void ralink_gpio_irq_handler(struct irq_desc *desc)
+{
+ int i;
+
+ for (i = 0; i < irq_map_count; i++) {
+ struct irq_domain *domain = irq_map[i];
+ struct ralink_gpio_chip *rg;
+ unsigned long pending;
+ int bit;
+
+ rg = (struct ralink_gpio_chip *) domain->host_data;
+ pending = rt_gpio_r32(rg, GPIO_REG_INT);
+
+ for_each_set_bit(bit, &pending, rg->chip.ngpio) {
+ u32 map = irq_find_mapping(domain, bit);
+ generic_handle_irq(map);
+ rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit));
+ }
+ }
+}
+
+static void ralink_gpio_irq_unmask(struct irq_data *d)
+{
+ struct ralink_gpio_chip *rg;
+ unsigned long flags;
+ u32 rise, fall;
+
+ rg = (struct ralink_gpio_chip *) d->domain->host_data;
+ rise = rt_gpio_r32(rg, GPIO_REG_RENA);
+ fall = rt_gpio_r32(rg, GPIO_REG_FENA);
+
+ spin_lock_irqsave(&rg->lock, flags);
+ rt_gpio_w32(rg, GPIO_REG_RENA, rise | (BIT(d->hwirq) & rg->rising));
+ rt_gpio_w32(rg, GPIO_REG_FENA, fall | (BIT(d->hwirq) & rg->falling));
+ spin_unlock_irqrestore(&rg->lock, flags);
+}
+
+static void ralink_gpio_irq_mask(struct irq_data *d)
+{
+ struct ralink_gpio_chip *rg;
+ unsigned long flags;
+ u32 rise, fall;
+
+ rg = (struct ralink_gpio_chip *) d->domain->host_data;
+ rise = rt_gpio_r32(rg, GPIO_REG_RENA);
+ fall = rt_gpio_r32(rg, GPIO_REG_FENA);
+
+ spin_lock_irqsave(&rg->lock, flags);
+ rt_gpio_w32(rg, GPIO_REG_FENA, fall & ~BIT(d->hwirq));
+ rt_gpio_w32(rg, GPIO_REG_RENA, rise & ~BIT(d->hwirq));
+ spin_unlock_irqrestore(&rg->lock, flags);
+}
+
+static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+ struct ralink_gpio_chip *rg;
+ u32 mask = BIT(d->hwirq);
+
+ rg = (struct ralink_gpio_chip *) d->domain->host_data;
+
+ if (type == IRQ_TYPE_PROBE) {
+ if ((rg->rising | rg->falling) & mask)
+ return 0;
+
+ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+ }
+
+ if (type & IRQ_TYPE_EDGE_RISING)
+ rg->rising |= mask;
+ else
+ rg->rising &= ~mask;
+
+ if (type & IRQ_TYPE_EDGE_FALLING)
+ rg->falling |= mask;
+ else
+ rg->falling &= ~mask;
+
+ return 0;
+}
+
+static struct irq_chip ralink_gpio_irq_chip = {
+ .name = "GPIO",
+ .irq_unmask = ralink_gpio_irq_unmask,
+ .irq_mask = ralink_gpio_irq_mask,
+ .irq_mask_ack = ralink_gpio_irq_mask,
+ .irq_set_type = ralink_gpio_irq_type,
+};
+
+static int gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &ralink_gpio_irq_chip, handle_level_irq);
+ irq_set_handler_data(irq, d);
+
+ return 0;
+}
+
+static const struct irq_domain_ops irq_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = gpio_map,
+};
+
+static void ralink_gpio_irq_init(struct device_node *np,
+ struct ralink_gpio_chip *rg)
+{
+ if (irq_map_count >= MAP_MAX)
+ return;
+
+ rg->irq = irq_of_parse_and_map(np, 0);
+ if (!rg->irq)
+ return;
+
+ rg->domain = irq_domain_add_linear(np, rg->chip.ngpio,
+ &irq_domain_ops, rg);
+ if (!rg->domain) {
+ dev_err(rg->chip.parent, "irq_domain_add_linear failed\n");
+ return;
+ }
+
+ irq_map[irq_map_count++] = rg->domain;
+
+ rt_gpio_w32(rg, GPIO_REG_RENA, 0x0);
+ rt_gpio_w32(rg, GPIO_REG_FENA, 0x0);
+
+ if (!atomic_read(&irq_refcount))
+ irq_set_chained_handler(rg->irq, ralink_gpio_irq_handler);
+ atomic_inc(&irq_refcount);
+
+ dev_info(rg->chip.parent, "registering %d irq handlers\n", rg->chip.ngpio);
+}
+
+static int ralink_gpio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct ralink_gpio_chip *rg;
+ const __be32 *ngpio, *gpiobase;
+
+ if (!res) {
+ dev_err(&pdev->dev, "failed to find resource\n");
+ return -ENOMEM;
+ }
+
+ rg = devm_kzalloc(&pdev->dev,
+ sizeof(struct ralink_gpio_chip), GFP_KERNEL);
+ if (!rg)
+ return -ENOMEM;
+
+ rg->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (!rg->membase) {
+ dev_err(&pdev->dev, "cannot remap I/O memory region\n");
+ return -ENOMEM;
+ }
+
+ if (of_property_read_u8_array(np, "ralink,register-map",
+ rg->regs, GPIO_REG_MAX)) {
+ dev_err(&pdev->dev, "failed to read register definition\n");
+ return -EINVAL;
+ }
+
+ ngpio = of_get_property(np, "ngpios", NULL);
+ if (!ngpio) {
+ dev_err(&pdev->dev, "failed to read number of pins\n");
+ return -EINVAL;
+ }
+
+ gpiobase = of_get_property(np, "ralink,gpio-base", NULL);
+ if (gpiobase)
+ rg->chip.base = be32_to_cpu(*gpiobase);
+ else
+ rg->chip.base = -1;
+
+ spin_lock_init(&rg->lock);
+
+ rg->chip.parent = &pdev->dev;
+ rg->chip.label = dev_name(&pdev->dev);
+ rg->chip.of_node = np;
+ rg->chip.ngpio = be32_to_cpu(*ngpio);
+ rg->chip.direction_input = ralink_gpio_direction_input;
+ rg->chip.direction_output = ralink_gpio_direction_output;
+ rg->chip.get = ralink_gpio_get;
+ rg->chip.set = ralink_gpio_set;
+ rg->chip.request = gpiochip_generic_request;
+ rg->chip.to_irq = ralink_gpio_to_irq;
+ rg->chip.free = gpiochip_generic_free;
+
+ /* set polarity to low for all lines */
+ rt_gpio_w32(rg, GPIO_REG_POL, 0);
+
+ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio);
+
+ ralink_gpio_irq_init(np, rg);
+
+ return gpiochip_add(&rg->chip);
+}
+
+static const struct of_device_id ralink_gpio_match[] = {
+ { .compatible = "ralink,rt2880-gpio" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ralink_gpio_match);
+
+static struct platform_driver ralink_gpio_driver = {
+ .probe = ralink_gpio_probe,
+ .driver = {
+ .name = "rt2880_gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = ralink_gpio_match,
+ },
+};
+
+static int __init ralink_gpio_init(void)
+{
+ return platform_driver_register(&ralink_gpio_driver);
+}
+
+subsys_initcall(ralink_gpio_init);

View file

@ -0,0 +1,44 @@
From 57fa7f2f4ef6f78ce1d30509c0d111aa3791b524 Mon Sep 17 00:00:00 2001
From: Daniel Santos <daniel.santos@pobox.com>
Date: Sun, 4 Nov 2018 20:24:32 -0600
Subject: gpio-ralink: Add support for GPIO as interrupt-controller
Signed-off-by: Daniel Santos <daniel.santos@pobox.com>
---
Documentation/devicetree/bindings/gpio/gpio-ralink.txt | 6 ++++++
drivers/gpio/gpio-ralink.c | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/gpio/gpio-ralink.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt
@@ -17,6 +17,9 @@ Required properties:
Optional properties:
- ralink,gpio-base : Specify the GPIO chips base number
+- interrupt-controller : marks this as an interrupt controller
+- #interrupt-cells : a standard two-cell interrupt flag, see
+ interrupt-controller/interrupts.txt
Example:
@@ -28,6 +31,9 @@ Example:
reg = <0x600 0x34>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
interrupt-parent = <&intc>;
interrupts = <6>;
--- a/drivers/gpio/gpio-ralink.c
+++ b/drivers/gpio/gpio-ralink.c
@@ -220,7 +220,7 @@ static int gpio_map(struct irq_domain *d
}
static const struct irq_domain_ops irq_domain_ops = {
- .xlate = irq_domain_xlate_onecell,
+ .xlate = irq_domain_xlate_twocell,
.map = gpio_map,
};

View file

@ -0,0 +1,244 @@
From 975e76214cd2516eb6cfff4c3eec581872645e88 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 19 Sep 2013 01:50:59 +0200
Subject: [PATCH 31/53] uvc: add iPassion iP2970 support
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/media/usb/uvc/uvc_driver.c | 12 +++
drivers/media/usb/uvc/uvc_status.c | 2 +
drivers/media/usb/uvc/uvc_video.c | 147 ++++++++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvcvideo.h | 5 +-
4 files changed, 165 insertions(+), 1 deletion(-)
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -3158,6 +3158,18 @@ static const struct usb_device_id uvc_id
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* iPassion iP2970 */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x1B3B,
+ .idProduct = 0x2970,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX
+ | UVC_QUIRK_STREAM_NO_FID
+ | UVC_QUIRK_MOTION
+ | UVC_QUIRK_SINGLE_ISO },
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
--- a/drivers/media/usb/uvc/uvc_status.c
+++ b/drivers/media/usb/uvc/uvc_status.c
@@ -224,6 +224,7 @@ static void uvc_status_complete(struct u
if (uvc_event_control(urb, status, len))
/* The URB will be resubmitted in work context. */
return;
+ dev->motion = 1;
break;
}
@@ -272,6 +273,7 @@ int uvc_status_init(struct uvc_device *d
}
pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
+ dev->motion = 0;
/* For high-speed interrupt endpoints, the bInterval value is used as
* an exponent of two. Some developers forgot about it.
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -19,6 +19,11 @@
#include <linux/wait.h>
#include <linux/atomic.h>
#include <asm/unaligned.h>
+#include <linux/skbuff.h>
+#include <linux/kobject.h>
+#include <linux/netlink.h>
+#include <linux/kobject.h>
+#include <linux/workqueue.h>
#include <media/v4l2-common.h>
@@ -1214,9 +1219,149 @@ static void uvc_video_decode_data(struct
uvc_urb->async_operations++;
}
+struct bh_priv {
+ unsigned long seen;
+};
+
+struct bh_event {
+ const char *name;
+ struct sk_buff *skb;
+ struct work_struct work;
+};
+
+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, "webcam", ##args )
+#define BH_DBG(fmt, args...) do {} while (0)
+#define BH_SKB_SIZE 2048
+
+extern u64 uevent_next_seqnum(void);
+static int seen = 0;
+
+static int bh_event_add_var(struct bh_event *event, int argv,
+ const char *format, ...)
+{
+ static char buf[128];
+ char *s;
+ va_list args;
+ int len;
+
+ if (argv)
+ return 0;
+
+ va_start(args, format);
+ len = vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ if (len >= sizeof(buf)) {
+ BH_ERR("buffer size too small\n");
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ s = skb_put(event->skb, len + 1);
+ strcpy(s, buf);
+
+ BH_DBG("added variable '%s'\n", s);
+
+ return 0;
+}
+
+static int motion_hotplug_fill_event(struct bh_event *event)
+{
+ int s = jiffies;
+ int ret;
+
+ if (!seen)
+ seen = jiffies;
+
+ ret = bh_event_add_var(event, 0, "HOME=%s", "/");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "PATH=%s",
+ "/sbin:/bin:/usr/sbin:/usr/bin");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=usb");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "ACTION=motion");
+ if (ret)
+ return ret;
+
+ ret = bh_event_add_var(event, 0, "SEEN=%d", s - seen);
+ if (ret)
+ return ret;
+ seen = s;
+
+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());
+
+ return ret;
+}
+
+static void motion_hotplug_work(struct work_struct *work)
+{
+ struct bh_event *event = container_of(work, struct bh_event, work);
+ int ret = 0;
+
+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
+ if (!event->skb)
+ goto out_free_event;
+
+ ret = bh_event_add_var(event, 0, "%s@", "add");
+ if (ret)
+ goto out_free_skb;
+
+ ret = motion_hotplug_fill_event(event);
+ if (ret)
+ goto out_free_skb;
+
+ NETLINK_CB(event->skb).dst_group = 1;
+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
+
+out_free_skb:
+ if (ret) {
+ BH_ERR("work error %d\n", ret);
+ kfree_skb(event->skb);
+ }
+out_free_event:
+ kfree(event);
+}
+
+static int motion_hotplug_create_event(void)
+{
+ struct bh_event *event;
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ return -ENOMEM;
+
+ event->name = "motion";
+
+ INIT_WORK(&event->work, (void *)(void *)motion_hotplug_work);
+ schedule_work(&event->work);
+
+ return 0;
+}
+
+#define MOTION_FLAG_OFFSET 4
static void uvc_video_decode_end(struct uvc_streaming *stream,
struct uvc_buffer *buf, const u8 *data, int len)
{
+ if ((stream->dev->quirks & UVC_QUIRK_MOTION) &&
+ (data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) {
+ u8 *mem;
+ buf->state = UVC_BUF_STATE_READY;
+ mem = (u8 *) (buf->mem + MOTION_FLAG_OFFSET);
+ if ( stream->dev->motion ) {
+ stream->dev->motion = 0;
+ motion_hotplug_create_event();
+ } else {
+ *mem &= 0x7f;
+ }
+ }
+
/* Mark the buffer as done if the EOF marker is set. */
if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) {
uvc_dbg(stream->dev, FRAME, "Frame complete (EOF found)\n");
@@ -1801,6 +1946,8 @@ static int uvc_init_video_isoc(struct uv
if (npackets == 0)
return -ENOMEM;
+ if (stream->dev->quirks & UVC_QUIRK_SINGLE_ISO)
+ npackets = 1;
size = npackets * psize;
for_each_uvc_urb(uvc_urb, stream) {
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -210,6 +210,8 @@
#define UVC_QUIRK_FORCE_Y8 0x00000800
#define UVC_QUIRK_FORCE_BPP 0x00001000
#define UVC_QUIRK_WAKE_AUTOSUSPEND 0x00002000
+#define UVC_QUIRK_MOTION 0x00004000
+#define UVC_QUIRK_SINGLE_ISO 0x00008000
/* Format flags */
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
@@ -701,6 +703,7 @@ struct uvc_device {
u8 *status;
struct input_dev *input;
char input_phys[64];
+ int motion;
struct uvc_ctrl_work {
struct work_struct work;

View file

@ -0,0 +1,44 @@
From da6015e7f19d749f135f7ac55c4ec47b06faa868 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 9 Aug 2013 20:12:59 +0200
Subject: [PATCH 41/53] DT: Add documentation for spi-rt2880
Describe the SPI master found on the MIPS based Ralink RT2880 SoC.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
.../devicetree/bindings/spi/spi-rt2880.txt | 28 ++++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spi/spi-rt2880.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-rt2880.txt
@@ -0,0 +1,28 @@
+Ralink SoC RT2880 SPI master controller.
+
+This SPI controller is found on most wireless SoCs made by ralink.
+
+Required properties:
+- compatible : "ralink,rt2880-spi"
+- reg : The register base for the controller.
+- #address-cells : <1>, as required by generic SPI binding.
+- #size-cells : <0>, also as required by generic SPI binding.
+
+Child nodes as per the generic SPI binding.
+
+Example:
+
+ spi@b00 {
+ compatible = "ralink,rt2880-spi";
+ reg = <0xb00 0x100>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ m25p80@0 {
+ compatible = "m25p80";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ };
+ };
+

View file

@ -0,0 +1,579 @@
From 683af4ebb91a1600df1946ac4769d916b8a1be65 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 27 Jul 2014 11:15:12 +0100
Subject: [PATCH 42/53] SPI: ralink: add Ralink SoC spi driver
Add the driver needed to make SPI work on Ralink SoC.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Acked-by: John Crispin <blogic@openwrt.org>
---
drivers/spi/Kconfig | 6 +
drivers/spi/Makefile | 1 +
drivers/spi/spi-rt2880.c | 530 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 537 insertions(+)
create mode 100644 drivers/spi/spi-rt2880.c
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -718,6 +718,12 @@ config SPI_QCOM_GENI
This driver can also be built as a module. If so, the module
will be called spi-geni-qcom.
+config SPI_RT2880
+ tristate "Ralink RT288x SPI Controller"
+ depends on RALINK
+ help
+ This selects a driver for the Ralink RT288x/RT305x SPI Controller.
+
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
depends on ARCH_S3C24XX
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o
obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
+obj-$(CONFIG_SPI_RT2880) += spi-rt2880.o
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
spi-s3c24xx-hw-y := spi-s3c24xx.o
obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o
--- /dev/null
+++ b/drivers/spi/spi-rt2880.c
@@ -0,0 +1,535 @@
+/*
+ * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver
+ *
+ * Copyright (C) 2011 Sergiy <piratfm@gmail.com>
+ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Some parts are based on spi-orion.c:
+ * Author: Shadi Ammouri <shadi@marvell.com>
+ * Copyright (C) 2007-2008 Marvell Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/reset.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#define DRIVER_NAME "spi-rt2880"
+
+#define RAMIPS_SPI_STAT 0x00
+#define RAMIPS_SPI_CFG 0x10
+#define RAMIPS_SPI_CTL 0x14
+#define RAMIPS_SPI_DATA 0x20
+#define RAMIPS_SPI_ADDR 0x24
+#define RAMIPS_SPI_BS 0x28
+#define RAMIPS_SPI_USER 0x2C
+#define RAMIPS_SPI_TXFIFO 0x30
+#define RAMIPS_SPI_RXFIFO 0x34
+#define RAMIPS_SPI_FIFO_STAT 0x38
+#define RAMIPS_SPI_MODE 0x3C
+#define RAMIPS_SPI_DEV_OFFSET 0x40
+#define RAMIPS_SPI_DMA 0x80
+#define RAMIPS_SPI_DMASTAT 0x84
+#define RAMIPS_SPI_ARBITER 0xF0
+
+/* SPISTAT register bit field */
+#define SPISTAT_BUSY BIT(0)
+
+/* SPICFG register bit field */
+#define SPICFG_ADDRMODE BIT(12)
+#define SPICFG_RXENVDIS BIT(11)
+#define SPICFG_RXCAP BIT(10)
+#define SPICFG_SPIENMODE BIT(9)
+#define SPICFG_MSBFIRST BIT(8)
+#define SPICFG_SPICLKPOL BIT(6)
+#define SPICFG_RXCLKEDGE_FALLING BIT(5)
+#define SPICFG_TXCLKEDGE_FALLING BIT(4)
+#define SPICFG_HIZSPI BIT(3)
+#define SPICFG_SPICLK_PRESCALE_MASK 0x7
+#define SPICFG_SPICLK_DIV2 0
+#define SPICFG_SPICLK_DIV4 1
+#define SPICFG_SPICLK_DIV8 2
+#define SPICFG_SPICLK_DIV16 3
+#define SPICFG_SPICLK_DIV32 4
+#define SPICFG_SPICLK_DIV64 5
+#define SPICFG_SPICLK_DIV128 6
+#define SPICFG_SPICLK_DISABLE 7
+
+/* SPICTL register bit field */
+#define SPICTL_START BIT(4)
+#define SPICTL_HIZSDO BIT(3)
+#define SPICTL_STARTWR BIT(2)
+#define SPICTL_STARTRD BIT(1)
+#define SPICTL_SPIENA BIT(0)
+
+/* SPIUSER register bit field */
+#define SPIUSER_USERMODE BIT(21)
+#define SPIUSER_INSTR_PHASE BIT(20)
+#define SPIUSER_ADDR_PHASE_MASK 0x7
+#define SPIUSER_ADDR_PHASE_OFFSET 17
+#define SPIUSER_MODE_PHASE BIT(16)
+#define SPIUSER_DUMMY_PHASE_MASK 0x3
+#define SPIUSER_DUMMY_PHASE_OFFSET 14
+#define SPIUSER_DATA_PHASE_MASK 0x3
+#define SPIUSER_DATA_PHASE_OFFSET 12
+#define SPIUSER_DATA_READ (BIT(0) << SPIUSER_DATA_PHASE_OFFSET)
+#define SPIUSER_DATA_WRITE (BIT(1) << SPIUSER_DATA_PHASE_OFFSET)
+#define SPIUSER_ADDR_TYPE_OFFSET 9
+#define SPIUSER_MODE_TYPE_OFFSET 6
+#define SPIUSER_DUMMY_TYPE_OFFSET 3
+#define SPIUSER_DATA_TYPE_OFFSET 0
+#define SPIUSER_TRANSFER_MASK 0x7
+#define SPIUSER_TRANSFER_SINGLE BIT(0)
+#define SPIUSER_TRANSFER_DUAL BIT(1)
+#define SPIUSER_TRANSFER_QUAD BIT(2)
+
+#define SPIUSER_TRANSFER_TYPE(type) ( \
+ (type << SPIUSER_ADDR_TYPE_OFFSET) | \
+ (type << SPIUSER_MODE_TYPE_OFFSET) | \
+ (type << SPIUSER_DUMMY_TYPE_OFFSET) | \
+ (type << SPIUSER_DATA_TYPE_OFFSET) \
+)
+
+/* SPIFIFOSTAT register bit field */
+#define SPIFIFOSTAT_TXEMPTY BIT(19)
+#define SPIFIFOSTAT_RXEMPTY BIT(18)
+#define SPIFIFOSTAT_TXFULL BIT(17)
+#define SPIFIFOSTAT_RXFULL BIT(16)
+#define SPIFIFOSTAT_FIFO_MASK 0xff
+#define SPIFIFOSTAT_TX_OFFSET 8
+#define SPIFIFOSTAT_RX_OFFSET 0
+
+#define SPI_FIFO_DEPTH 16
+
+/* SPIMODE register bit field */
+#define SPIMODE_MODE_OFFSET 24
+#define SPIMODE_DUMMY_OFFSET 0
+
+/* SPIARB register bit field */
+#define SPICTL_ARB_EN BIT(31)
+#define SPICTL_CSCTL1 BIT(16)
+#define SPI1_POR BIT(1)
+#define SPI0_POR BIT(0)
+
+#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | \
+ SPI_CS_HIGH)
+
+static atomic_t hw_reset_count = ATOMIC_INIT(0);
+
+struct rt2880_spi {
+ struct spi_master *master;
+ void __iomem *base;
+ u32 speed;
+ u16 wait_loops;
+ u16 mode;
+ struct clk *clk;
+};
+
+static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi)
+{
+ return spi_master_get_devdata(spi->master);
+}
+
+static inline u32 rt2880_spi_read(struct rt2880_spi *rs, u32 reg)
+{
+ return ioread32(rs->base + reg);
+}
+
+static inline void rt2880_spi_write(struct rt2880_spi *rs, u32 reg,
+ const u32 val)
+{
+ iowrite32(val, rs->base + reg);
+}
+
+static inline void rt2880_spi_setbits(struct rt2880_spi *rs, u32 reg, u32 mask)
+{
+ void __iomem *addr = rs->base + reg;
+
+ iowrite32((ioread32(addr) | mask), addr);
+}
+
+static inline void rt2880_spi_clrbits(struct rt2880_spi *rs, u32 reg, u32 mask)
+{
+ void __iomem *addr = rs->base + reg;
+
+ iowrite32((ioread32(addr) & ~mask), addr);
+}
+
+static u32 rt2880_spi_baudrate_get(struct spi_device *spi, unsigned int speed)
+{
+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
+ u32 rate;
+ u32 prescale;
+
+ /*
+ * the supported rates are: 2, 4, 8, ... 128
+ * round up as we look for equal or less speed
+ */
+ rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed);
+ rate = roundup_pow_of_two(rate);
+
+ /* Convert the rate to SPI clock divisor value. */
+ prescale = ilog2(rate / 2);
+
+ /* some tolerance. double and add 100 */
+ rs->wait_loops = (8 * HZ * loops_per_jiffy) /
+ (clk_get_rate(rs->clk) / rate);
+ rs->wait_loops = (rs->wait_loops << 1) + 100;
+ rs->speed = speed;
+
+ dev_dbg(&spi->dev, "speed: %lu/%u, rate: %u, prescal: %u, loops: %hu\n",
+ clk_get_rate(rs->clk) / rate, speed, rate, prescale,
+ rs->wait_loops);
+
+ return prescale;
+}
+
+static u32 get_arbiter_offset(struct spi_master *master)
+{
+ u32 offset;
+
+ offset = RAMIPS_SPI_ARBITER;
+ if (master->bus_num == 1)
+ offset -= RAMIPS_SPI_DEV_OFFSET;
+
+ return offset;
+}
+
+static void rt2880_spi_set_cs(struct spi_device *spi, bool enable)
+{
+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
+
+ if (enable)
+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
+ else
+ rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
+}
+
+static int rt2880_spi_wait_ready(struct rt2880_spi *rs, int len)
+{
+ int loop = rs->wait_loops * len;
+
+ while ((rt2880_spi_read(rs, RAMIPS_SPI_STAT) & SPISTAT_BUSY) && --loop)
+ cpu_relax();
+
+ if (loop)
+ return 0;
+
+ return -ETIMEDOUT;
+}
+
+static void rt2880_dump_reg(struct spi_master *master)
+{
+ struct rt2880_spi *rs = spi_master_get_devdata(master);
+
+ dev_dbg(&master->dev, "stat: %08x, cfg: %08x, ctl: %08x, " \
+ "data: %08x, arb: %08x\n",
+ rt2880_spi_read(rs, RAMIPS_SPI_STAT),
+ rt2880_spi_read(rs, RAMIPS_SPI_CFG),
+ rt2880_spi_read(rs, RAMIPS_SPI_CTL),
+ rt2880_spi_read(rs, RAMIPS_SPI_DATA),
+ rt2880_spi_read(rs, get_arbiter_offset(master)));
+}
+
+static int rt2880_spi_transfer_one(struct spi_master *master,
+ struct spi_device *spi, struct spi_transfer *xfer)
+{
+ struct rt2880_spi *rs = spi_master_get_devdata(master);
+ unsigned len;
+ const u8 *tx = xfer->tx_buf;
+ u8 *rx = xfer->rx_buf;
+ int err = 0;
+
+ /* change clock speed */
+ if (unlikely(rs->speed != xfer->speed_hz)) {
+ u32 reg;
+ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
+ reg &= ~SPICFG_SPICLK_PRESCALE_MASK;
+ reg |= rt2880_spi_baudrate_get(spi, xfer->speed_hz);
+ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
+ }
+
+ if (tx) {
+ len = xfer->len;
+ while (len-- > 0) {
+ rt2880_spi_write(rs, RAMIPS_SPI_DATA, *tx++);
+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR);
+ err = rt2880_spi_wait_ready(rs, 1);
+ if (err) {
+ dev_err(&spi->dev, "TX failed, err=%d\n", err);
+ goto out;
+ }
+ }
+ }
+
+ if (rx) {
+ len = xfer->len;
+ while (len-- > 0) {
+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD);
+ err = rt2880_spi_wait_ready(rs, 1);
+ if (err) {
+ dev_err(&spi->dev, "RX failed, err=%d\n", err);
+ goto out;
+ }
+ *rx++ = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA);
+ }
+ }
+
+out:
+ return err;
+}
+
+/* copy from spi.c */
+static void spi_set_cs(struct spi_device *spi, bool enable)
+{
+ if (spi->mode & SPI_CS_HIGH)
+ enable = !enable;
+
+ if (spi->cs_gpio >= 0)
+ gpio_set_value(spi->cs_gpio, !enable);
+ else if (spi->master->set_cs)
+ spi->master->set_cs(spi, !enable);
+}
+
+static int rt2880_spi_setup(struct spi_device *spi)
+{
+ struct spi_master *master = spi->master;
+ struct rt2880_spi *rs = spi_master_get_devdata(master);
+ u32 reg, old_reg, arbit_off;
+
+ if ((spi->max_speed_hz > master->max_speed_hz) ||
+ (spi->max_speed_hz < master->min_speed_hz)) {
+ dev_err(&spi->dev, "invalide requested speed %d Hz\n",
+ spi->max_speed_hz);
+ return -EINVAL;
+ }
+
+ if (!(master->bits_per_word_mask &
+ BIT(spi->bits_per_word - 1))) {
+ dev_err(&spi->dev, "invalide bits_per_word %d\n",
+ spi->bits_per_word);
+ return -EINVAL;
+ }
+
+ /* the hardware seems can't work on mode0 force it to mode3 */
+ if ((spi->mode & (SPI_CPOL | SPI_CPHA)) == SPI_MODE_0) {
+ dev_warn(&spi->dev, "force spi mode3\n");
+ spi->mode |= SPI_MODE_3;
+ }
+
+ /* chip polarity */
+ arbit_off = get_arbiter_offset(master);
+ reg = old_reg = rt2880_spi_read(rs, arbit_off);
+ if (spi->mode & SPI_CS_HIGH) {
+ switch (master->bus_num) {
+ case 1:
+ reg |= SPI1_POR;
+ break;
+ default:
+ reg |= SPI0_POR;
+ break;
+ }
+ } else {
+ switch (master->bus_num) {
+ case 1:
+ reg &= ~SPI1_POR;
+ break;
+ default:
+ reg &= ~SPI0_POR;
+ break;
+ }
+ }
+
+ /* enable spi1 */
+ if (master->bus_num == 1)
+ reg |= SPICTL_ARB_EN;
+
+ if (reg != old_reg)
+ rt2880_spi_write(rs, arbit_off, reg);
+
+ /* deselected the spi device */
+ spi_set_cs(spi, false);
+
+ rt2880_dump_reg(master);
+
+ return 0;
+}
+
+static int rt2880_spi_prepare_message(struct spi_master *master,
+ struct spi_message *msg)
+{
+ struct rt2880_spi *rs = spi_master_get_devdata(master);
+ struct spi_device *spi = msg->spi;
+ u32 reg;
+
+ if ((rs->mode == spi->mode) && (rs->speed == spi->max_speed_hz))
+ return 0;
+
+#if 0
+ /* set spido to tri-state */
+ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO);
+#endif
+
+ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG);
+
+ reg &= ~(SPICFG_MSBFIRST | SPICFG_SPICLKPOL |
+ SPICFG_RXCLKEDGE_FALLING |
+ SPICFG_TXCLKEDGE_FALLING |
+ SPICFG_SPICLK_PRESCALE_MASK);
+
+ /* MSB */
+ if (!(spi->mode & SPI_LSB_FIRST))
+ reg |= SPICFG_MSBFIRST;
+
+ /* spi mode */
+ switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
+ case SPI_MODE_0:
+ reg |= SPICFG_TXCLKEDGE_FALLING;
+ break;
+ case SPI_MODE_1:
+ reg |= SPICFG_RXCLKEDGE_FALLING;
+ break;
+ case SPI_MODE_2:
+ reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING;
+ break;
+ case SPI_MODE_3:
+ reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING;
+ break;
+ }
+ rs->mode = spi->mode;
+
+#if 0
+ /* set spiclk and spiena to tri-state */
+ reg |= SPICFG_HIZSPI;
+#endif
+
+ /* clock divide */
+ reg |= rt2880_spi_baudrate_get(spi, spi->max_speed_hz);
+
+ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg);
+
+ return 0;
+}
+
+static int rt2880_spi_probe(struct platform_device *pdev)
+{
+ struct spi_master *master;
+ struct rt2880_spi *rs;
+ void __iomem *base;
+ struct resource *r;
+ struct clk *clk;
+ int ret;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "unable to get SYS clock\n");
+ return PTR_ERR(clk);
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ goto err_clk;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(*rs));
+ if (master == NULL) {
+ dev_dbg(&pdev->dev, "master allocation failed\n");
+ ret = -ENOMEM;
+ goto err_clk;
+ }
+
+ master->dev.of_node = pdev->dev.of_node;
+ master->mode_bits = RT2880_SPI_MODE_BITS;
+ master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->min_speed_hz = clk_get_rate(clk) / 128;
+ master->max_speed_hz = clk_get_rate(clk) / 2;
+ master->flags = SPI_MASTER_HALF_DUPLEX;
+ master->setup = rt2880_spi_setup;
+ master->prepare_message = rt2880_spi_prepare_message;
+ master->set_cs = rt2880_spi_set_cs;
+ master->transfer_one = rt2880_spi_transfer_one,
+
+ dev_set_drvdata(&pdev->dev, master);
+
+ rs = spi_master_get_devdata(master);
+ rs->master = master;
+ rs->base = base;
+ rs->clk = clk;
+
+ if (atomic_inc_return(&hw_reset_count) == 1) {
+ ret = device_reset(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "device_reset error.\n");
+ goto err_master;
+ }
+ }
+
+ ret = devm_spi_register_master(&pdev->dev, master);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "devm_spi_register_master error.\n");
+ goto err_master;
+ }
+
+ return ret;
+
+err_master:
+ spi_master_put(master);
+ kfree(master);
+err_clk:
+ clk_disable_unprepare(clk);
+
+ return ret;
+}
+
+static int rt2880_spi_remove(struct platform_device *pdev)
+{
+ struct spi_master *master;
+ struct rt2880_spi *rs;
+
+ master = dev_get_drvdata(&pdev->dev);
+ rs = spi_master_get_devdata(master);
+
+ clk_disable_unprepare(rs->clk);
+ atomic_dec(&hw_reset_count);
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+
+static const struct of_device_id rt2880_spi_match[] = {
+ { .compatible = "ralink,rt2880-spi" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt2880_spi_match);
+
+static struct platform_driver rt2880_spi_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = rt2880_spi_match,
+ },
+ .probe = rt2880_spi_probe,
+ .remove = rt2880_spi_remove,
+};
+
+module_platform_driver(rt2880_spi_driver);
+
+MODULE_DESCRIPTION("Ralink SPI driver");
+MODULE_AUTHOR("Sergiy <piratfm@gmail.com>");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
From a7eb46e0ea4a11e4dfb56ab129bf816d1059a6c5 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 7 Dec 2015 17:31:08 +0100
Subject: [PATCH 51/53] serial: add ugly custom baud rate hack
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/tty/serial/serial_core.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -393,6 +393,9 @@ uart_get_baud_rate(struct uart_port *por
break;
}
+ if (tty_termios_baud_rate(termios) == 2500000)
+ return 250000;
+
for (try = 0; try < 2; try++) {
baud = tty_termios_baud_rate(termios);

View file

@ -0,0 +1,219 @@
From fc8f96309c21c1bc3276427309cd7d361347d66e Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 7 Dec 2015 17:16:50 +0100
Subject: [PATCH 52/53] pwm: add mediatek support
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/pwm/Kconfig | 9 +++
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-mediatek.c | 173 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 183 insertions(+)
create mode 100644 drivers/pwm/pwm-mediatek.c
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -383,6 +383,15 @@ config PWM_MEDIATEK
To compile this driver as a module, choose M here: the module
will be called pwm-mediatek.
+config PWM_MEDIATEK_RAMIPS
+ tristate "Mediatek PWM support"
+ depends on RALINK && OF
+ help
+ Generic PWM framework driver for Mediatek ARM SoC.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-mxs.
+
config PWM_MXS
tristate "Freescale MXS PWM support"
depends on ARCH_MXS || COMPILE_TEST
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-p
obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o
obj-$(CONFIG_PWM_MESON) += pwm-meson.o
obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o
+obj-$(CONFIG_PWM_MEDIATEK_RAMIPS) += pwm-mediatek-ramips.o
obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o
--- /dev/null
+++ b/drivers/pwm/pwm-mediatek-ramips.c
@@ -0,0 +1,175 @@
+/*
+ * Mediatek Pulse Width Modulator driver
+ *
+ * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define NUM_PWM 4
+
+/* PWM registers and bits definitions */
+#define PWMCON 0x00
+#define PWMHDUR 0x04
+#define PWMLDUR 0x08
+#define PWMGDUR 0x0c
+#define PWMWAVENUM 0x28
+#define PWMDWIDTH 0x2c
+#define PWMTHRES 0x30
+
+/**
+ * struct mtk_pwm_chip - struct representing pwm chip
+ *
+ * @mmio_base: base address of pwm chip
+ * @chip: linux pwm chip representation
+ */
+struct mtk_pwm_chip {
+ void __iomem *mmio_base;
+ struct pwm_chip chip;
+};
+
+static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct mtk_pwm_chip, chip);
+}
+
+static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num,
+ unsigned long offset)
+{
+ return ioread32(chip->mmio_base + 0x10 + (num * 0x40) + offset);
+}
+
+static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip,
+ unsigned int num, unsigned long offset,
+ unsigned long val)
+{
+ iowrite32(val, chip->mmio_base + 0x10 + (num * 0x40) + offset);
+}
+
+static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
+ u32 resolution = 100 / 4;
+ u32 clkdiv = 0;
+
+ while (period_ns / resolution > 8191) {
+ clkdiv++;
+ resolution *= 2;
+ }
+
+ if (clkdiv > 7)
+ return -1;
+
+ mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv);
+ mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution);
+ mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution);
+ return 0;
+}
+
+static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
+ u32 val;
+
+ val = ioread32(pc->mmio_base);
+ val |= BIT(pwm->hwpwm);
+ iowrite32(val, pc->mmio_base);
+
+ return 0;
+}
+
+static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
+ u32 val;
+
+ val = ioread32(pc->mmio_base);
+ val &= ~BIT(pwm->hwpwm);
+ iowrite32(val, pc->mmio_base);
+}
+
+static const struct pwm_ops mtk_pwm_ops = {
+ .config = mtk_pwm_config,
+ .enable = mtk_pwm_enable,
+ .disable = mtk_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static int mtk_pwm_probe(struct platform_device *pdev)
+{
+ struct mtk_pwm_chip *pc;
+ struct resource *r;
+ int ret;
+
+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc)
+ return -ENOMEM;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pc->mmio_base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(pc->mmio_base))
+ return PTR_ERR(pc->mmio_base);
+
+ platform_set_drvdata(pdev, pc);
+
+ pc->chip.dev = &pdev->dev;
+ pc->chip.ops = &mtk_pwm_ops;
+ pc->chip.base = -1;
+ pc->chip.npwm = NUM_PWM;
+
+ ret = pwmchip_add(&pc->chip);
+ if (ret < 0)
+ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+
+ return ret;
+}
+
+static int mtk_pwm_remove(struct platform_device *pdev)
+{
+ struct mtk_pwm_chip *pc = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < NUM_PWM; i++)
+ pwm_disable(&pc->chip.pwms[i]);
+
+ pwmchip_remove(&pc->chip);
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pwm_of_match[] = {
+ { .compatible = "mediatek,mt7628-pwm" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, mtk_pwm_of_match);
+
+static struct platform_driver mtk_pwm_driver = {
+ .driver = {
+ .name = "mtk-pwm",
+ .owner = THIS_MODULE,
+ .of_match_table = mtk_pwm_of_match,
+ },
+ .probe = mtk_pwm_probe,
+ .remove = mtk_pwm_remove,
+};
+
+module_platform_driver(mtk_pwm_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_ALIAS("platform:mtk-pwm");

View file

@ -0,0 +1,15 @@
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -498,6 +498,12 @@ static int dwc2_driver_probe(struct plat
if (retval)
return retval;
+ /* Enable USB port before any regs access */
+ if (readl(hsotg->regs + PCGCTL) & 0x0f) {
+ writel(0x00, hsotg->regs + PCGCTL);
+ /* TODO: mdelay(25) here? vendor driver don't use it */
+ }
+
hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg);
retval = dwc2_get_dr_mode(hsotg);

View file

@ -0,0 +1,97 @@
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_DW_XDATA_PCIE) += dw-xdata-pcie.o
obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
+obj-$(CONFIG_SOC_MT7620) += linkit.o
obj-$(CONFIG_OCXL) += ocxl/
obj-$(CONFIG_BCM_VK) += bcm-vk/
obj-y += cardreader/
--- /dev/null
+++ b/drivers/misc/linkit.c
@@ -0,0 +1,84 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ *
+ * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/mtd/mtd.h>
+#include <linux/gpio.h>
+
+#define LINKIT_LATCH_GPIO 11
+
+struct linkit_hw_data {
+ char board[16];
+ char rev[16];
+};
+
+static void sanify_string(char *s)
+{
+ int i;
+
+ for (i = 0; i < 15; i++)
+ if (s[i] <= 0x20)
+ s[i] = '\0';
+ s[15] = '\0';
+}
+
+static int linkit_probe(struct platform_device *pdev)
+{
+ struct linkit_hw_data hw;
+ struct mtd_info *mtd;
+ size_t retlen;
+ int ret;
+
+ mtd = get_mtd_device_nm("factory");
+ if (IS_ERR(mtd))
+ return PTR_ERR(mtd);
+
+ ret = mtd_read(mtd, 0x400, sizeof(hw), &retlen, (u_char *) &hw);
+ put_mtd_device(mtd);
+
+ sanify_string(hw.board);
+ sanify_string(hw.rev);
+
+ dev_info(&pdev->dev, "Version : %s\n", hw.board);
+ dev_info(&pdev->dev, "Revision : %s\n", hw.rev);
+
+ if (!strcmp(hw.board, "LINKITS7688")) {
+ dev_info(&pdev->dev, "setting up bootstrap latch\n");
+
+ if (devm_gpio_request(&pdev->dev, LINKIT_LATCH_GPIO, "bootstrap")) {
+ dev_err(&pdev->dev, "failed to setup bootstrap gpio\n");
+ return -1;
+ }
+ gpio_direction_output(LINKIT_LATCH_GPIO, 0);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id linkit_match[] = {
+ { .compatible = "mediatek,linkit" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, linkit_match);
+
+static struct platform_driver linkit_driver = {
+ .probe = linkit_probe,
+ .driver = {
+ .name = "mtk-linkit",
+ .owner = THIS_MODULE,
+ .of_match_table = linkit_match,
+ },
+};
+
+int __init linkit_init(void)
+{
+ return platform_driver_register(&linkit_driver);
+}
+late_initcall_sync(linkit_init);