lantiq: add support for kernel 4.9
The following patches were dropped because they are already applied upstream: 0012-pinctrl-lantiq-fix-up-pinmux.patch 0013-MTD-lantiq-xway-fix-invalid-operator.patch 0014-MTD-lantiq-xway-the-latched-command-should-be-persis.patch 0015-MTD-lantiq-xway-remove-endless-loop.patch 0016-MTD-lantiq-xway-add-missing-write_buf-and-read_buf-t.patch 0017-MTD-xway-fix-nand-locking.patch 0044-pinctrl-lantiq-introduce-new-dedicated-devicetree-bi.patch 0045-pinctrl-lantiq-Fix-GPIO-Setup-of-GPIO-Port3.patch 0046-pinctrl-lantiq-2-pins-have-the-wrong-mux-list.patch 0047-irq-fixes.patch 0047-mtd-plat-nand-pass-of-node.patch 0060-usb-dwc2-Add-support-for-Lantiq-ARX-and-XRX-SoCs.patch 0120-MIPS-lantiq-add-support-for-device-tree-file-from-bo.patch 0121-MIPS-lantiq-make-it-possible-to-build-in-no-device-t.patch 122-MIPS-store-the-appended-dtb-address-in-a-variable.patch The PHY driver was reduced to the code adding the LED configuration, the rest is already upstream: 0023-NET-PHY-adds-driver-for-lantiq-PHY11G.patch The SPI driver was replaced with the version pending for upstream inclusion: New driver: 0090-spi-add-transfer_status-callback.patch 0091-spi-lantiq-ssc-add-support-for-Lantiq-SSC-SPI-controller.patch Old driver: 0100-spi-add-support-for-Lantiq-SPI-controller.patch Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
		
							
								
								
									
										209
									
								
								target/linux/lantiq/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								target/linux/lantiq/config-4.9
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | |||||||
|  | CONFIG_ARCH_BINFMT_ELF_STATE=y | ||||||
|  | CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||||
|  | CONFIG_ARCH_DISCARD_MEMBLOCK=y | ||||||
|  | CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||||
|  | # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set | ||||||
|  | CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||||
|  | # CONFIG_ARCH_HAS_SG_CHAIN is not set | ||||||
|  | CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||||
|  | CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||||
|  | CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y | ||||||
|  | CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||||
|  | CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||||
|  | CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||||
|  | CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||||
|  | CONFIG_BLK_MQ_PCI=y | ||||||
|  | CONFIG_CEVT_R4K=y | ||||||
|  | CONFIG_CLKDEV_LOOKUP=y | ||||||
|  | CONFIG_CLONE_BACKWARDS=y | ||||||
|  | CONFIG_CPU_BIG_ENDIAN=y | ||||||
|  | CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||||
|  | CONFIG_CPU_HAS_PREFETCH=y | ||||||
|  | CONFIG_CPU_HAS_RIXI=y | ||||||
|  | CONFIG_CPU_HAS_SYNC=y | ||||||
|  | CONFIG_CPU_MIPS32=y | ||||||
|  | # CONFIG_CPU_MIPS32_R1 is not set | ||||||
|  | CONFIG_CPU_MIPS32_R2=y | ||||||
|  | CONFIG_CPU_MIPSR2=y | ||||||
|  | CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||||
|  | CONFIG_CPU_R4K_CACHE_TLB=y | ||||||
|  | CONFIG_CPU_R4K_FPU=y | ||||||
|  | CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||||
|  | CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||||
|  | CONFIG_CPU_SUPPORTS_MSA=y | ||||||
|  | CONFIG_CRYPTO_HASH=y | ||||||
|  | CONFIG_CRYPTO_HASH2=y | ||||||
|  | CONFIG_CRYPTO_RNG2=y | ||||||
|  | CONFIG_CRYPTO_WORKQUEUE=y | ||||||
|  | CONFIG_CSRC_R4K=y | ||||||
|  | CONFIG_DMA_NONCOHERENT=y | ||||||
|  | CONFIG_DTC=y | ||||||
|  | # CONFIG_DT_EASY50712 is not set | ||||||
|  | CONFIG_EARLY_PRINTK=y | ||||||
|  | CONFIG_ETHERNET_PACKET_MANGLE=y | ||||||
|  | CONFIG_FIXED_PHY=y | ||||||
|  | CONFIG_GENERIC_ATOMIC64=y | ||||||
|  | CONFIG_GENERIC_CLOCKEVENTS=y | ||||||
|  | CONFIG_GENERIC_CMOS_UPDATE=y | ||||||
|  | CONFIG_GENERIC_IO=y | ||||||
|  | CONFIG_GENERIC_IRQ_CHIP=y | ||||||
|  | CONFIG_GENERIC_IRQ_SHOW=y | ||||||
|  | CONFIG_GENERIC_PCI_IOMAP=y | ||||||
|  | CONFIG_GENERIC_SCHED_CLOCK=y | ||||||
|  | CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||||
|  | CONFIG_GENERIC_TIME_VSYSCALL=y | ||||||
|  | CONFIG_GPIOLIB=y | ||||||
|  | CONFIG_GPIO_MM_LANTIQ=y | ||||||
|  | CONFIG_GPIO_STP_XWAY=y | ||||||
|  | CONFIG_GPIO_SYSFS=y | ||||||
|  | CONFIG_HANDLE_DOMAIN_IRQ=y | ||||||
|  | CONFIG_HARDWARE_WATCHPOINTS=y | ||||||
|  | CONFIG_HAS_DMA=y | ||||||
|  | CONFIG_HAS_IOMEM=y | ||||||
|  | CONFIG_HAS_IOPORT_MAP=y | ||||||
|  | # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||||
|  | # CONFIG_HAVE_ARCH_BITREVERSE is not set | ||||||
|  | CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||||
|  | CONFIG_HAVE_ARCH_KGDB=y | ||||||
|  | CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||||
|  | CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||||
|  | # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||||
|  | CONFIG_HAVE_CBPF_JIT=y | ||||||
|  | CONFIG_HAVE_CC_STACKPROTECTOR=y | ||||||
|  | CONFIG_HAVE_CLK=y | ||||||
|  | CONFIG_HAVE_CONTEXT_TRACKING=y | ||||||
|  | CONFIG_HAVE_C_RECORDMCOUNT=y | ||||||
|  | CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||||
|  | CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||||
|  | CONFIG_HAVE_DMA_API_DEBUG=y | ||||||
|  | CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||||
|  | CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||||
|  | CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||||
|  | CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||||
|  | CONFIG_HAVE_FUNCTION_TRACER=y | ||||||
|  | CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||||
|  | CONFIG_HAVE_IDE=y | ||||||
|  | CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||||
|  | CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||||
|  | CONFIG_HAVE_KVM=y | ||||||
|  | CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||||
|  | CONFIG_HAVE_MEMBLOCK=y | ||||||
|  | CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||||
|  | CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||||
|  | CONFIG_HAVE_NET_DSA=y | ||||||
|  | CONFIG_HAVE_OPROFILE=y | ||||||
|  | CONFIG_HAVE_PERF_EVENTS=y | ||||||
|  | CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||||
|  | CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||||
|  | CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||||
|  | CONFIG_HW_HAS_PCI=y | ||||||
|  | CONFIG_HW_RANDOM=y | ||||||
|  | CONFIG_HZ=250 | ||||||
|  | # CONFIG_HZ_100 is not set | ||||||
|  | CONFIG_HZ_250=y | ||||||
|  | CONFIG_HZ_PERIODIC=y | ||||||
|  | CONFIG_INITRAMFS_SOURCE="" | ||||||
|  | CONFIG_IRQCHIP=y | ||||||
|  | CONFIG_IRQ_DOMAIN=y | ||||||
|  | CONFIG_IRQ_FORCED_THREADING=y | ||||||
|  | CONFIG_IRQ_MIPS_CPU=y | ||||||
|  | CONFIG_IRQ_WORK=y | ||||||
|  | CONFIG_LANTIQ=y | ||||||
|  | CONFIG_LANTIQ_DT_NONE=y | ||||||
|  | CONFIG_LANTIQ_ETOP=y | ||||||
|  | CONFIG_LANTIQ_WDT=y | ||||||
|  | # CONFIG_LANTIQ_XRX200 is not set | ||||||
|  | CONFIG_LEDS_GPIO=y | ||||||
|  | CONFIG_LIBFDT=y | ||||||
|  | CONFIG_MDIO_BOARDINFO=y | ||||||
|  | CONFIG_MIPS=y | ||||||
|  | CONFIG_MIPS_ASID_BITS=8 | ||||||
|  | CONFIG_MIPS_ASID_SHIFT=0 | ||||||
|  | CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||||
|  | # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||||
|  | # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||||
|  | CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||||
|  | # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||||
|  | # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set | ||||||
|  | CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||||
|  | # CONFIG_MIPS_MACHINE is not set | ||||||
|  | # CONFIG_MIPS_MT_SMP is not set | ||||||
|  | # CONFIG_MIPS_NO_APPENDED_DTB is not set | ||||||
|  | CONFIG_MIPS_RAW_APPENDED_DTB=y | ||||||
|  | CONFIG_MIPS_SPRAM=y | ||||||
|  | # CONFIG_MIPS_VPE_LOADER is not set | ||||||
|  | CONFIG_MODULES_USE_ELF_REL=y | ||||||
|  | CONFIG_MTD_CFI_ADV_OPTIONS=y | ||||||
|  | CONFIG_MTD_CFI_GEOMETRY=y | ||||||
|  | CONFIG_MTD_CMDLINE_PARTS=y | ||||||
|  | CONFIG_MTD_JEDECPROBE=y | ||||||
|  | CONFIG_MTD_LANTIQ=y | ||||||
|  | CONFIG_MTD_M25P80=y | ||||||
|  | CONFIG_MTD_SPI_NOR=y | ||||||
|  | CONFIG_MTD_SPLIT_BRNIMAGE_FW=y | ||||||
|  | CONFIG_MTD_SPLIT_EVA_FW=y | ||||||
|  | CONFIG_MTD_SPLIT_FIRMWARE=y | ||||||
|  | CONFIG_MTD_SPLIT_TPLINK_FW=y | ||||||
|  | CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||||
|  | CONFIG_NEED_DMA_MAP_STATE=y | ||||||
|  | CONFIG_NEED_PER_CPU_KM=y | ||||||
|  | CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||||
|  | # CONFIG_NO_IOPORT_MAP is not set | ||||||
|  | CONFIG_OF=y | ||||||
|  | CONFIG_OF_ADDRESS=y | ||||||
|  | CONFIG_OF_ADDRESS_PCI=y | ||||||
|  | CONFIG_OF_EARLY_FLATTREE=y | ||||||
|  | CONFIG_OF_FLATTREE=y | ||||||
|  | CONFIG_OF_GPIO=y | ||||||
|  | CONFIG_OF_IRQ=y | ||||||
|  | CONFIG_OF_MDIO=y | ||||||
|  | CONFIG_OF_NET=y | ||||||
|  | CONFIG_OF_PCI=y | ||||||
|  | CONFIG_OF_PCI_IRQ=y | ||||||
|  | CONFIG_PCI=y | ||||||
|  | # CONFIG_PCIE_LANTIQ is not set | ||||||
|  | CONFIG_PCI_DOMAINS=y | ||||||
|  | CONFIG_PCI_DRIVERS_LEGACY=y | ||||||
|  | CONFIG_PCI_LANTIQ=y | ||||||
|  | CONFIG_PERF_USE_VMALLOC=y | ||||||
|  | CONFIG_PGTABLE_LEVELS=2 | ||||||
|  | CONFIG_PHYLIB=y | ||||||
|  | CONFIG_PINCTRL=y | ||||||
|  | CONFIG_PINCTRL_LANTIQ=y | ||||||
|  | # CONFIG_PINCTRL_SINGLE is not set | ||||||
|  | CONFIG_PINCTRL_XWAY=y | ||||||
|  | CONFIG_PSB6970_PHY=y | ||||||
|  | # CONFIG_RCU_STALL_COMMON is not set | ||||||
|  | CONFIG_RESET_CONTROLLER=y | ||||||
|  | CONFIG_RTL8366RB_PHY=y | ||||||
|  | CONFIG_RTL8366_SMI=y | ||||||
|  | CONFIG_SCHED_HRTICK=y | ||||||
|  | # CONFIG_SCHED_INFO is not set | ||||||
|  | # CONFIG_SCSI_DMA is not set | ||||||
|  | # CONFIG_SENSORS_LTQ_CPUTEMP is not set | ||||||
|  | # CONFIG_SERIAL_8250 is not set | ||||||
|  | CONFIG_SERIAL_LANTIQ=y | ||||||
|  | # CONFIG_SG_POOL is not set | ||||||
|  | # CONFIG_SOC_AMAZON_SE is not set | ||||||
|  | # CONFIG_SOC_FALCON is not set | ||||||
|  | CONFIG_SOC_TYPE_XWAY=y | ||||||
|  | CONFIG_SOC_XWAY=y | ||||||
|  | CONFIG_SPI=y | ||||||
|  | CONFIG_SPI_LANTIQ_SSC=y | ||||||
|  | CONFIG_SPI_MASTER=y | ||||||
|  | CONFIG_SRCU=y | ||||||
|  | CONFIG_SWAP_IO_SPACE=y | ||||||
|  | CONFIG_SWCONFIG=y | ||||||
|  | CONFIG_SWPHY=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_BIG_ENDIAN=y | ||||||
|  | CONFIG_SYS_SUPPORTS_MIPS16=y | ||||||
|  | CONFIG_SYS_SUPPORTS_MULTITHREADING=y | ||||||
|  | CONFIG_TICK_CPU_ACCOUNTING=y | ||||||
|  | CONFIG_USE_OF=y | ||||||
|  | # CONFIG_XRX200_PHY_FW is not set | ||||||
| @@ -135,7 +135,7 @@ | |||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		spi: spi@E100800 { | 		spi: spi@E100800 { | ||||||
| 			compatible = "lantiq,xrx200-spi"; | 			compatible = "lantiq,xrx200-spi", "lantiq,xrx100-spi"; | ||||||
| 			reg = <0xE100800 0x100>; | 			reg = <0xE100800 0x100>; | ||||||
| 			interrupt-parent = <&icu0>; | 			interrupt-parent = <&icu0>; | ||||||
| 			interrupts = <22 23 24>; | 			interrupts = <22 23 24>; | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,500 @@ | |||||||
|  | From 9afadf01b1be371ee88491819aa67364684461f9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Fri, 3 Aug 2012 10:27:25 +0200 | ||||||
|  | Subject: [PATCH 04/36] MIPS: lantiq: add atm hack | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  arch/mips/include/asm/mach-lantiq/lantiq_atm.h |  196 +++++++++++++++++++++++ | ||||||
|  |  arch/mips/include/asm/mach-lantiq/lantiq_ptm.h |  203 ++++++++++++++++++++++++ | ||||||
|  |  arch/mips/lantiq/irq.c                         |    2 + | ||||||
|  |  arch/mips/mm/cache.c                           |    2 + | ||||||
|  |  include/uapi/linux/atm.h                       |    6 + | ||||||
|  |  net/atm/common.c                               |    6 + | ||||||
|  |  net/atm/proc.c                                 |    2 +- | ||||||
|  |  7 files changed, 416 insertions(+), 1 deletion(-) | ||||||
|  |  create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_atm.h | ||||||
|  |  create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_ptm.h | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/lantiq_atm.h | ||||||
|  | @@ -0,0 +1,196 @@ | ||||||
|  | +/****************************************************************************** | ||||||
|  | +** | ||||||
|  | +** FILE NAME    : ifx_atm.h | ||||||
|  | +** PROJECT      : UEIP | ||||||
|  | +** MODULES      : ATM | ||||||
|  | +** | ||||||
|  | +** DATE         : 17 Jun 2009 | ||||||
|  | +** AUTHOR       : Xu Liang | ||||||
|  | +** DESCRIPTION  : Global ATM driver header file | ||||||
|  | +** COPYRIGHT    :       Copyright (c) 2006 | ||||||
|  | +**                      Infineon Technologies AG | ||||||
|  | +**                      Am Campeon 1-12, 85579 Neubiberg, Germany | ||||||
|  | +** | ||||||
|  | +**    This program is free software; you can redistribute it and/or modify | ||||||
|  | +**    it under the terms of the GNU General Public License as published by | ||||||
|  | +**    the Free Software Foundation; either version 2 of the License, or | ||||||
|  | +**    (at your option) any later version. | ||||||
|  | +** | ||||||
|  | +** HISTORY | ||||||
|  | +** $Date        $Author         $Comment | ||||||
|  | +** 07 JUL 2009  Xu Liang        Init Version | ||||||
|  | +*******************************************************************************/ | ||||||
|  | + | ||||||
|  | +#ifndef IFX_ATM_H | ||||||
|  | +#define IFX_ATM_H | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_ATM UEIP Project - ATM driver module | ||||||
|  | +  \brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_ATM_IOCTL IOCTL Commands | ||||||
|  | +  \ingroup IFX_ATM | ||||||
|  | +  \brief IOCTL Commands used by user application. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_ATM_STRUCT Structures | ||||||
|  | +  \ingroup IFX_ATM | ||||||
|  | +  \brief Structures used by user application. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \file ifx_atm.h | ||||||
|  | +  \ingroup IFX_ATM | ||||||
|  | +  \brief ATM driver header file | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *              Definition | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \addtogroup IFX_ATM_STRUCT | ||||||
|  | + */ | ||||||
|  | +/*@{*/ | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + *  ATM MIB | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \struct atm_cell_ifEntry_t | ||||||
|  | +  \brief Structure used for Cell Level MIB Counters. | ||||||
|  | + | ||||||
|  | +  User application use this structure to call IOCTL command "PPE_ATM_MIB_CELL". | ||||||
|  | + */ | ||||||
|  | +typedef struct { | ||||||
|  | +	__u32	ifHCInOctets_h;     /*!< byte counter of ingress cells (upper 32 bits, total 64 bits)   */ | ||||||
|  | +	__u32	ifHCInOctets_l;     /*!< byte counter of ingress cells (lower 32 bits, total 64 bits)   */ | ||||||
|  | +	__u32	ifHCOutOctets_h;    /*!< byte counter of egress cells (upper 32 bits, total 64 bits)    */ | ||||||
|  | +	__u32	ifHCOutOctets_l;    /*!< byte counter of egress cells (lower 32 bits, total 64 bits)    */ | ||||||
|  | +	__u32	ifInErrors;         /*!< counter of error ingress cells     */ | ||||||
|  | +	__u32	ifInUnknownProtos;  /*!< counter of unknown ingress cells   */ | ||||||
|  | +	__u32	ifOutErrors;        /*!< counter of error egress cells      */ | ||||||
|  | +} atm_cell_ifEntry_t; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \struct atm_aal5_ifEntry_t | ||||||
|  | +  \brief Structure used for AAL5 Frame Level MIB Counters. | ||||||
|  | + | ||||||
|  | +  User application use this structure to call IOCTL command "PPE_ATM_MIB_AAL5". | ||||||
|  | + */ | ||||||
|  | +typedef struct { | ||||||
|  | +	__u32	ifHCInOctets_h;     /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */ | ||||||
|  | +	__u32	ifHCInOctets_l;     /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */ | ||||||
|  | +	__u32	ifHCOutOctets_h;    /*!< byte counter of egress packets (upper 32 bits, total 64 bits)  */ | ||||||
|  | +	__u32	ifHCOutOctets_l;    /*!< byte counter of egress packets (lower 32 bits, total 64 bits)  */ | ||||||
|  | +	__u32	ifInUcastPkts;      /*!< counter of ingress packets         */ | ||||||
|  | +	__u32	ifOutUcastPkts;     /*!< counter of egress packets          */ | ||||||
|  | +	__u32	ifInErrors;         /*!< counter of error ingress packets   */ | ||||||
|  | +	__u32	ifInDiscards;       /*!< counter of dropped ingress packets */ | ||||||
|  | +	__u32	ifOutErros;         /*!< counter of error egress packets    */ | ||||||
|  | +	__u32	ifOutDiscards;      /*!< counter of dropped egress packets  */ | ||||||
|  | +} atm_aal5_ifEntry_t; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \struct atm_aal5_vcc_t | ||||||
|  | +  \brief Structure used for per PVC AAL5 Frame Level MIB Counters. | ||||||
|  | + | ||||||
|  | +  This structure is a part of structure "atm_aal5_vcc_x_t". | ||||||
|  | + */ | ||||||
|  | +typedef struct { | ||||||
|  | +	__u32	aal5VccCrcErrors;       /*!< counter of ingress packets with CRC error  */ | ||||||
|  | +	__u32	aal5VccSarTimeOuts;     /*!< counter of ingress packets with Re-assemble timeout    */  //no timer support yet | ||||||
|  | +	__u32	aal5VccOverSizedSDUs;   /*!< counter of oversized ingress packets       */ | ||||||
|  | +} atm_aal5_vcc_t; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \struct atm_aal5_vcc_x_t | ||||||
|  | +  \brief Structure used for per PVC AAL5 Frame Level MIB Counters. | ||||||
|  | + | ||||||
|  | +  User application use this structure to call IOCTL command "PPE_ATM_MIB_VCC". | ||||||
|  | + */ | ||||||
|  | +typedef struct { | ||||||
|  | +	int             vpi;        /*!< VPI of the VCC to get MIB counters */ | ||||||
|  | +	int             vci;        /*!< VCI of the VCC to get MIB counters */ | ||||||
|  | +	atm_aal5_vcc_t  mib_vcc;    /*!< structure to get MIB counters      */ | ||||||
|  | +} atm_aal5_vcc_x_t; | ||||||
|  | + | ||||||
|  | +/*@}*/ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *                IOCTL | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \addtogroup IFX_ATM_IOCTL | ||||||
|  | + */ | ||||||
|  | +/*@{*/ | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + *  ioctl Command | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \brief ATM IOCTL Magic Number | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_IOC_MAGIC       'o' | ||||||
|  | +/*! | ||||||
|  | +  \brief ATM IOCTL Command - Get Cell Level MIB Counters | ||||||
|  | + | ||||||
|  | +   This command is obsolete. User can get cell level MIB from DSL API. | ||||||
|  | +   This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_MIB_CELL        _IOW(PPE_ATM_IOC_MAGIC,  0, atm_cell_ifEntry_t) | ||||||
|  | +/*! | ||||||
|  | +  \brief ATM IOCTL Command - Get AAL5 Level MIB Counters | ||||||
|  | + | ||||||
|  | +   Get AAL5 packet counters. | ||||||
|  | +   This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_MIB_AAL5        _IOW(PPE_ATM_IOC_MAGIC,  1, atm_aal5_ifEntry_t) | ||||||
|  | +/*! | ||||||
|  | +  \brief ATM IOCTL Command - Get Per PVC MIB Counters | ||||||
|  | + | ||||||
|  | +   Get AAL5 packet counters for each PVC. | ||||||
|  | +   This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_MIB_VCC         _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t) | ||||||
|  | +/*! | ||||||
|  | +  \brief Total Number of ATM IOCTL Commands | ||||||
|  | + */ | ||||||
|  | +#define PPE_ATM_IOC_MAXNR       3 | ||||||
|  | + | ||||||
|  | +/*@}*/ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *                 API | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#ifdef __KERNEL__ | ||||||
|  | +struct port_cell_info { | ||||||
|  | +    unsigned int    port_num; | ||||||
|  | +    unsigned int    tx_link_rate[2]; | ||||||
|  | +}; | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +#endif  //  IFX_ATM_H | ||||||
|  | + | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/lantiq_ptm.h | ||||||
|  | @@ -0,0 +1,203 @@ | ||||||
|  | +/****************************************************************************** | ||||||
|  | +** | ||||||
|  | +** FILE NAME    : ifx_ptm.h | ||||||
|  | +** PROJECT      : UEIP | ||||||
|  | +** MODULES      : PTM | ||||||
|  | +** | ||||||
|  | +** DATE         : 17 Jun 2009 | ||||||
|  | +** AUTHOR       : Xu Liang | ||||||
|  | +** DESCRIPTION  : Global PTM driver header file | ||||||
|  | +** COPYRIGHT    :       Copyright (c) 2006 | ||||||
|  | +**                      Infineon Technologies AG | ||||||
|  | +**                      Am Campeon 1-12, 85579 Neubiberg, Germany | ||||||
|  | +** | ||||||
|  | +**    This program is free software; you can redistribute it and/or modify | ||||||
|  | +**    it under the terms of the GNU General Public License as published by | ||||||
|  | +**    the Free Software Foundation; either version 2 of the License, or | ||||||
|  | +**    (at your option) any later version. | ||||||
|  | +** | ||||||
|  | +** HISTORY | ||||||
|  | +** $Date        $Author         $Comment | ||||||
|  | +** 07 JUL 2009  Xu Liang        Init Version | ||||||
|  | +*******************************************************************************/ | ||||||
|  | + | ||||||
|  | +#ifndef IFX_PTM_H | ||||||
|  | +#define IFX_PTM_H | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_PTM UEIP Project - PTM driver module | ||||||
|  | +  \brief UEIP Project - PTM driver module, support Danube, Amazon-SE, AR9, VR9. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_PTM_IOCTL IOCTL Commands | ||||||
|  | +  \ingroup IFX_PTM | ||||||
|  | +  \brief IOCTL Commands used by user application. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \defgroup IFX_PTM_STRUCT Structures | ||||||
|  | +  \ingroup IFX_PTM | ||||||
|  | +  \brief Structures used by user application. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \file ifx_ptm.h | ||||||
|  | +  \ingroup IFX_PTM | ||||||
|  | +  \brief PTM driver header file | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *              Definition | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *                IOCTL | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \addtogroup IFX_PTM_IOCTL | ||||||
|  | + */ | ||||||
|  | +/*@{*/ | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + *  ioctl Command | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Get codeword MIB counters. | ||||||
|  | + | ||||||
|  | +  This command uses structure "PTM_CW_IF_ENTRY_T" to get codeword level MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_MIB_CW_GET              SIOCDEVPRIVATE + 1 | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Get packet MIB counters. | ||||||
|  | + | ||||||
|  | +  This command uses structure "PTM_FRAME_MIB_T" to get packet level MIB counters. | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_MIB_FRAME_GET           SIOCDEVPRIVATE + 2 | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Get firmware configuration (CRC). | ||||||
|  | + | ||||||
|  | +  This command uses structure "IFX_PTM_CFG_T" to get firmware configuration (CRC). | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_CFG_GET                 SIOCDEVPRIVATE + 3 | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Set firmware configuration (CRC). | ||||||
|  | + | ||||||
|  | +  This command uses structure "IFX_PTM_CFG_T" to set firmware configuration (CRC). | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_CFG_SET                 SIOCDEVPRIVATE + 4 | ||||||
|  | +/*! | ||||||
|  | +  \brief PTM IOCTL Command - Program priority value to TX queue mapping. | ||||||
|  | + | ||||||
|  | +  This command uses structure "IFX_PTM_PRIO_Q_MAP_T" to program priority value to TX queue mapping. | ||||||
|  | + */ | ||||||
|  | +#define IFX_PTM_MAP_PKT_PRIO_TO_Q       SIOCDEVPRIVATE + 14 | ||||||
|  | + | ||||||
|  | +/*@}*/ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \addtogroup IFX_PTM_STRUCT | ||||||
|  | + */ | ||||||
|  | +/*@{*/ | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + *  ioctl Data Type | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \typedef PTM_CW_IF_ENTRY_T | ||||||
|  | +  \brief Wrapping of structure "ptm_cw_ifEntry_t". | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \struct ptm_cw_ifEntry_t | ||||||
|  | +  \brief Structure used for CodeWord level MIB counters. | ||||||
|  | + */ | ||||||
|  | +typedef struct ptm_cw_ifEntry_t { | ||||||
|  | +    uint32_t    ifRxNoIdleCodewords;    /*!< output, number of ingress user codeword */ | ||||||
|  | +    uint32_t    ifRxIdleCodewords;      /*!< output, number of ingress idle codeword */ | ||||||
|  | +    uint32_t    ifRxCodingViolation;    /*!< output, number of error ingress codeword */ | ||||||
|  | +    uint32_t    ifTxNoIdleCodewords;    /*!< output, number of egress user codeword */ | ||||||
|  | +    uint32_t    ifTxIdleCodewords;      /*!< output, number of egress idle codeword */ | ||||||
|  | +} PTM_CW_IF_ENTRY_T; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \typedef PTM_FRAME_MIB_T | ||||||
|  | +  \brief Wrapping of structure "ptm_frame_mib_t". | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \struct ptm_frame_mib_t | ||||||
|  | +  \brief Structure used for packet level MIB counters. | ||||||
|  | + */ | ||||||
|  | +typedef struct ptm_frame_mib_t { | ||||||
|  | +    uint32_t    RxCorrect;      /*!< output, number of ingress packet */ | ||||||
|  | +    uint32_t    TC_CrcError;    /*!< output, number of egress packet with CRC error */ | ||||||
|  | +    uint32_t    RxDropped;      /*!< output, number of dropped ingress packet */ | ||||||
|  | +    uint32_t    TxSend;         /*!< output, number of egress packet */ | ||||||
|  | +} PTM_FRAME_MIB_T; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \typedef IFX_PTM_CFG_T | ||||||
|  | +  \brief Wrapping of structure "ptm_cfg_t". | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \struct ptm_cfg_t | ||||||
|  | +  \brief Structure used for ETH/TC CRC configuration. | ||||||
|  | + */ | ||||||
|  | +typedef struct ptm_cfg_t { | ||||||
|  | +    uint32_t    RxEthCrcPresent;    /*!< input/output, ingress packet has ETH CRC */ | ||||||
|  | +    uint32_t    RxEthCrcCheck;      /*!< input/output, check ETH CRC of ingress packet */ | ||||||
|  | +    uint32_t    RxTcCrcCheck;       /*!< input/output, check TC CRC of ingress codeword */ | ||||||
|  | +    uint32_t    RxTcCrcLen;         /*!< input/output, length of TC CRC of ingress codeword */ | ||||||
|  | +    uint32_t    TxEthCrcGen;        /*!< input/output, generate ETH CRC for egress packet */ | ||||||
|  | +    uint32_t    TxTcCrcGen;         /*!< input/output, generate TC CRC for egress codeword */ | ||||||
|  | +    uint32_t    TxTcCrcLen;         /*!< input/output, length of TC CRC of egress codeword */ | ||||||
|  | +} IFX_PTM_CFG_T; | ||||||
|  | + | ||||||
|  | +/*! | ||||||
|  | +  \typedef IFX_PTM_PRIO_Q_MAP_T | ||||||
|  | +  \brief Wrapping of structure "ppe_prio_q_map". | ||||||
|  | + */ | ||||||
|  | +/*! | ||||||
|  | +  \struct ppe_prio_q_map | ||||||
|  | +  \brief Structure used for Priority Value to TX Queue mapping. | ||||||
|  | + */ | ||||||
|  | +typedef struct ppe_prio_q_map { | ||||||
|  | +    int             pkt_prio; | ||||||
|  | +    int             qid; | ||||||
|  | +    int             vpi;    //  ignored in eth interface | ||||||
|  | +    int             vci;    //  ignored in eth interface | ||||||
|  | +} IFX_PTM_PRIO_Q_MAP_T; | ||||||
|  | + | ||||||
|  | +/*@}*/ | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * #################################### | ||||||
|  | + *                 API | ||||||
|  | + * #################################### | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#ifdef __KERNEL__ | ||||||
|  | +struct port_cell_info { | ||||||
|  | +    unsigned int    port_num; | ||||||
|  | +    unsigned int    tx_link_rate[2]; | ||||||
|  | +}; | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +#endif  //  IFX_PTM_H | ||||||
|  | + | ||||||
|  | --- a/arch/mips/lantiq/irq.c | ||||||
|  | +++ b/arch/mips/lantiq/irq.c | ||||||
|  | @@ -14,6 +14,7 @@ | ||||||
|  |  #include <linux/of_platform.h> | ||||||
|  |  #include <linux/of_address.h> | ||||||
|  |  #include <linux/of_irq.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  |   | ||||||
|  |  #include <asm/bootinfo.h> | ||||||
|  |  #include <asm/irq_cpu.h> | ||||||
|  | @@ -100,6 +101,7 @@ void ltq_mask_and_ack_irq(struct irq_dat | ||||||
|  |  	ltq_icu_w32(im, ltq_icu_r32(im, ier) & ~BIT(offset), ier); | ||||||
|  |  	ltq_icu_w32(im, BIT(offset), isr); | ||||||
|  |  } | ||||||
|  | +EXPORT_SYMBOL(ltq_mask_and_ack_irq); | ||||||
|  |   | ||||||
|  |  static void ltq_ack_irq(struct irq_data *d) | ||||||
|  |  { | ||||||
|  | --- a/arch/mips/mm/cache.c | ||||||
|  | +++ b/arch/mips/mm/cache.c | ||||||
|  | @@ -63,6 +63,8 @@ void (*_dma_cache_wback)(unsigned long s | ||||||
|  |  void (*_dma_cache_inv)(unsigned long start, unsigned long size); | ||||||
|  |   | ||||||
|  |  EXPORT_SYMBOL(_dma_cache_wback_inv); | ||||||
|  | +EXPORT_SYMBOL(_dma_cache_wback); | ||||||
|  | +EXPORT_SYMBOL(_dma_cache_inv); | ||||||
|  |   | ||||||
|  |  #endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */ | ||||||
|  |   | ||||||
|  | --- a/include/uapi/linux/atm.h | ||||||
|  | +++ b/include/uapi/linux/atm.h | ||||||
|  | @@ -130,8 +130,14 @@ | ||||||
|  |  #define ATM_ABR		4 | ||||||
|  |  #define ATM_ANYCLASS	5		/* compatible with everything */ | ||||||
|  |   | ||||||
|  | +#define ATM_VBR_NRT     ATM_VBR | ||||||
|  | +#define ATM_VBR_RT      6 | ||||||
|  | +#define ATM_UBR_PLUS    7 | ||||||
|  | +#define ATM_GFR         8 | ||||||
|  | + | ||||||
|  |  #define ATM_MAX_PCR	-1		/* maximum available PCR */ | ||||||
|  |   | ||||||
|  | + | ||||||
|  |  struct atm_trafprm { | ||||||
|  |  	unsigned char	traffic_class;	/* traffic class (ATM_UBR, ...) */ | ||||||
|  |  	int		max_pcr;	/* maximum PCR in cells per second */ | ||||||
|  | --- a/net/atm/common.c | ||||||
|  | +++ b/net/atm/common.c | ||||||
|  | @@ -62,11 +62,17 @@ static void vcc_remove_socket(struct soc | ||||||
|  |  	write_unlock_irq(&vcc_sklist_lock); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int) = NULL; | ||||||
|  | +EXPORT_SYMBOL(ifx_atm_alloc_tx); | ||||||
|  | + | ||||||
|  |  static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size) | ||||||
|  |  { | ||||||
|  |  	struct sk_buff *skb; | ||||||
|  |  	struct sock *sk = sk_atm(vcc); | ||||||
|  |   | ||||||
|  | +	if (ifx_atm_alloc_tx != NULL) | ||||||
|  | +		return ifx_atm_alloc_tx(vcc, size); | ||||||
|  | + | ||||||
|  |  	if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) { | ||||||
|  |  		pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n", | ||||||
|  |  			 sk_wmem_alloc_get(sk), size, sk->sk_sndbuf); | ||||||
|  | --- a/net/atm/proc.c | ||||||
|  | +++ b/net/atm/proc.c | ||||||
|  | @@ -154,7 +154,7 @@ static void *vcc_seq_next(struct seq_fil | ||||||
|  |  static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc) | ||||||
|  |  { | ||||||
|  |  	static const char *const class_name[] = { | ||||||
|  | -		"off", "UBR", "CBR", "VBR", "ABR"}; | ||||||
|  | +		"off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR"}; | ||||||
|  |  	static const char *const aal_name[] = { | ||||||
|  |  		"---",	"1",	"2",	"3/4",	/*  0- 3 */ | ||||||
|  |  		"???",	"5",	"???",	"???",	/*  4- 7 */ | ||||||
| @@ -0,0 +1,111 @@ | |||||||
|  | From d27ec8bb97db0f60d81ab255d51ac4e967362067 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Thu, 7 Aug 2014 18:34:19 +0200 | ||||||
|  | Subject: [PATCH 07/36] MIPS: lantiq: add basic tffs driver | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  arch/mips/lantiq/xway/Makefile |    2 +- | ||||||
|  |  arch/mips/lantiq/xway/tffs.c   |   87 ++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  2 files changed, 88 insertions(+), 1 deletion(-) | ||||||
|  |  create mode 100644 arch/mips/lantiq/xway/tffs.c | ||||||
|  |  | ||||||
|  | --- a/arch/mips/lantiq/xway/Makefile | ||||||
|  | +++ b/arch/mips/lantiq/xway/Makefile | ||||||
|  | @@ -1,5 +1,5 @@ | ||||||
|  |  obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o | ||||||
|  |   | ||||||
|  | -obj-y += vmmc.o | ||||||
|  | +obj-y += vmmc.o tffs.o | ||||||
|  |   | ||||||
|  |  obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/lantiq/xway/tffs.c | ||||||
|  | @@ -0,0 +1,87 @@ | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/mtd/mtd.h> | ||||||
|  | +#include <linux/errno.h> | ||||||
|  | +#include <linux/slab.h> | ||||||
|  | + | ||||||
|  | +struct tffs_entry { | ||||||
|  | +    uint16_t id; | ||||||
|  | +    uint16_t len; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct tffs_id { | ||||||
|  | +	uint32_t id; | ||||||
|  | +	char *name; | ||||||
|  | +	unsigned char *val; | ||||||
|  | +	uint32_t offset; | ||||||
|  | +	uint32_t len; | ||||||
|  | +} ids[] = { | ||||||
|  | +	{ 0x01A9, "annex" }, | ||||||
|  | +	{ 0x0188, "maca" }, | ||||||
|  | +	{ 0x0189, "macb" }, | ||||||
|  | +	{ 0x018a, "macwlan" }, | ||||||
|  | +	{ 0x0195, "macwlan2" }, | ||||||
|  | +	{ 0x018b, "macdsl" }, | ||||||
|  | +	{ 0x01C2, "webgui_pass" }, | ||||||
|  | +	{ 0x01AB, "wlan_key" }, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct mtd_info *tffs1, *tffs2; | ||||||
|  | + | ||||||
|  | +static struct tffs_id* tffs_find_id(int id) | ||||||
|  | +{ | ||||||
|  | +	int i; | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < ARRAY_SIZE(ids); i++) | ||||||
|  | +		if (id == ids[i].id) | ||||||
|  | +			return &ids[i]; | ||||||
|  | + | ||||||
|  | +	return NULL; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void tffs_index(void) | ||||||
|  | +{ | ||||||
|  | +	struct tffs_entry *E = NULL; | ||||||
|  | +	struct tffs_entry entry; | ||||||
|  | +	int ret, retlen; | ||||||
|  | + | ||||||
|  | +	while ((unsigned int) E + sizeof(struct tffs_entry) < tffs2->size) { | ||||||
|  | +		struct tffs_id *id; | ||||||
|  | +		int len; | ||||||
|  | + | ||||||
|  | +		ret = mtd_read(tffs2, (unsigned int) E, sizeof(struct tffs_entry), &retlen, (unsigned char *)&entry); | ||||||
|  | +		if (ret) | ||||||
|  | +			return; | ||||||
|  | + | ||||||
|  | +		if (entry.id == 0xffff) | ||||||
|  | +			return; | ||||||
|  | + | ||||||
|  | +		id = tffs_find_id(entry.id); | ||||||
|  | +		if (id) { | ||||||
|  | +			id->offset = (uint32_t) E; | ||||||
|  | +			id->len = entry.len; | ||||||
|  | +			id->val = kzalloc(entry.len + 1, GFP_KERNEL); | ||||||
|  | +			mtd_read(tffs2, ((unsigned int) E) + sizeof(struct tffs_entry), entry.len, &retlen, id->val); | ||||||
|  | + | ||||||
|  | +		} | ||||||
|  | +		//printk(KERN_INFO "found entry at 0x%08X-> [<0x%x> %u bytes]\n", (uint32_t) E, entry.id, entry.len); | ||||||
|  | +		if (id && id->name) | ||||||
|  | +			printk(KERN_INFO "found entry name -> %s=%s\n", id->name, id->val); | ||||||
|  | + | ||||||
|  | +		len = (entry.len + 3) & ~0x03; | ||||||
|  | +		E = (struct tffs_entry *)(((unsigned int)E) + sizeof(struct tffs_entry) + len); | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __init tffs_init(void) | ||||||
|  | +{ | ||||||
|  | +	tffs1 = get_mtd_device_nm("tffs (1)"); | ||||||
|  | +	tffs2 = get_mtd_device_nm("tffs (2)"); | ||||||
|  | +	if (IS_ERR(tffs1) || IS_ERR(tffs2)) | ||||||
|  | +		return -1; | ||||||
|  | + | ||||||
|  | +	tffs_index(); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | +late_initcall(tffs_init); | ||||||
|  | + | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,122 @@ | |||||||
|  | From 997a8965db8417266bea3fbdcfa3e5655a1b52fa Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Tue, 9 Sep 2014 23:12:15 +0200 | ||||||
|  | Subject: [PATCH 18/36] MTD: nand: lots of xrx200 fixes | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/mtd/nand/xway_nand.c |   63 ++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 63 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/mtd/nand/xway_nand.c | ||||||
|  | +++ b/drivers/mtd/nand/xway_nand.c | ||||||
|  | @@ -63,6 +63,24 @@ | ||||||
|  |  #define NAND_CON_CSMUX		(1 << 1) | ||||||
|  |  #define NAND_CON_NANDM		1 | ||||||
|  |   | ||||||
|  | +#define DANUBE_PCI_REG32( addr )    (*(volatile u32 *)(addr)) | ||||||
|  | +#define PCI_CR_PR_OFFSET	    (KSEG1+0x1E105400) | ||||||
|  | +#define PCI_CR_PC_ARB		    (PCI_CR_PR_OFFSET + 0x0080) | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * req_mask provides a mechanism to prevent interference between | ||||||
|  | + * nand and pci (probably only relevant for the BT Home Hub 2B). | ||||||
|  | + * Setting it causes the corresponding pci req pins to be masked | ||||||
|  | + * during nand access, and also moves ebu locking from the read/write | ||||||
|  | + * functions to the chip select function to ensure that the whole | ||||||
|  | + * operation runs with interrupts disabled. | ||||||
|  | + * In addition it switches on some extra waiting in xway_cmd_ctrl(). | ||||||
|  | + * This seems to be necessary if the ebu_cs1 pin has open-drain disabled, | ||||||
|  | + * which in turn seems to be necessary for the nor chip to be recognised | ||||||
|  | + * reliably, on a board (Home Hub 2B again) which has both nor and nand. | ||||||
|  | + */ | ||||||
|  | +static __be32 req_mask = 0; | ||||||
|  | + | ||||||
|  |  struct xway_nand_data { | ||||||
|  |  	struct nand_chip	chip; | ||||||
|  |  	unsigned long		csflags; | ||||||
|  | @@ -94,10 +112,22 @@ static void xway_select_chip(struct mtd_ | ||||||
|  |  	case -1: | ||||||
|  |  		ltq_ebu_w32_mask(NAND_CON_CE, 0, EBU_NAND_CON); | ||||||
|  |  		ltq_ebu_w32_mask(NAND_CON_NANDM, 0, EBU_NAND_CON); | ||||||
|  | + | ||||||
|  | +		if (req_mask) { | ||||||
|  | +			/* Unmask all external PCI request */ | ||||||
|  | +			DANUBE_PCI_REG32(PCI_CR_PC_ARB) &= ~(req_mask << 16); | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  |  		spin_unlock_irqrestore(&ebu_lock, data->csflags); | ||||||
|  |  		break; | ||||||
|  |  	case 0: | ||||||
|  |  		spin_lock_irqsave(&ebu_lock, data->csflags); | ||||||
|  | + | ||||||
|  | +		if (req_mask) { | ||||||
|  | +			/* Mask all external PCI request */ | ||||||
|  | +			DANUBE_PCI_REG32(PCI_CR_PC_ARB) |= (req_mask << 16); | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  |  		ltq_ebu_w32_mask(0, NAND_CON_NANDM, EBU_NAND_CON); | ||||||
|  |  		ltq_ebu_w32_mask(0, NAND_CON_CE, EBU_NAND_CON); | ||||||
|  |  		break; | ||||||
|  | @@ -108,6 +138,12 @@ static void xway_select_chip(struct mtd_ | ||||||
|  |   | ||||||
|  |  static void xway_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | ||||||
|  |  { | ||||||
|  | + | ||||||
|  | +	if (req_mask) { | ||||||
|  | +		if (cmd != NAND_CMD_STATUS) | ||||||
|  | +			ltq_ebu_w32(0, EBU_NAND_WAIT); /* Clear nand ready */ | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	if (cmd == NAND_CMD_NONE) | ||||||
|  |  		return; | ||||||
|  |   | ||||||
|  | @@ -118,6 +154,24 @@ static void xway_cmd_ctrl(struct mtd_inf | ||||||
|  |   | ||||||
|  |  	while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0) | ||||||
|  |  		; | ||||||
|  | + | ||||||
|  | +	if (req_mask) { | ||||||
|  | +	       /* | ||||||
|  | +		* program and erase have their own busy handlers | ||||||
|  | +		* status and sequential in needs no delay | ||||||
|  | +		*/ | ||||||
|  | +		switch (cmd) { | ||||||
|  | +			case NAND_CMD_ERASE1: | ||||||
|  | +			case NAND_CMD_SEQIN: | ||||||
|  | +			case NAND_CMD_STATUS: | ||||||
|  | +			case NAND_CMD_READID: | ||||||
|  | +			return; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		/* wait until command is processed */ | ||||||
|  | +		while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD) == 0) | ||||||
|  | +			; | ||||||
|  | +	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int xway_dev_ready(struct mtd_info *mtd) | ||||||
|  | @@ -157,6 +211,7 @@ static int xway_nand_probe(struct platfo | ||||||
|  |  	int err; | ||||||
|  |  	u32 cs; | ||||||
|  |  	u32 cs_flag = 0; | ||||||
|  | +	const __be32 *req_mask_ptr; | ||||||
|  |   | ||||||
|  |  	/* Allocate memory for the device structure (and zero it) */ | ||||||
|  |  	data = devm_kzalloc(&pdev->dev, sizeof(struct xway_nand_data), | ||||||
|  | @@ -192,6 +247,15 @@ static int xway_nand_probe(struct platfo | ||||||
|  |  	if (!err && cs == 1) | ||||||
|  |  		cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1; | ||||||
|  |   | ||||||
|  | +	req_mask_ptr = of_get_property(pdev->dev.of_node, | ||||||
|  | +					"req-mask", NULL); | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Load the PCI req lines to mask from the device tree. If the | ||||||
|  | +	 * property is not present, setting req_mask to 0 disables masking. | ||||||
|  | +	 */ | ||||||
|  | +	req_mask = (req_mask_ptr ? *req_mask_ptr : 0); | ||||||
|  | + | ||||||
|  |  	/* setup the EBU to run in NAND mode on our base addr */ | ||||||
|  |  	ltq_ebu_w32(CPHYSADDR(data->nandaddr) | ||||||
|  |  		    | ADDSEL1_MASK(3) | ADDSEL1_REGEN, EBU_ADDSEL1); | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | From e3b20f04e9f9cae1babe091fdc1d08d7703ae344 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Thu, 7 Aug 2014 18:18:00 +0200 | ||||||
|  | Subject: [PATCH 20/36] MTD: lantiq: handle NO_XIP on cfi0001 flash | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/mtd/maps/lantiq-flash.c |    6 +++++- | ||||||
|  |  1 file changed, 5 insertions(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/mtd/maps/lantiq-flash.c | ||||||
|  | +++ b/drivers/mtd/maps/lantiq-flash.c | ||||||
|  | @@ -137,7 +137,11 @@ ltq_mtd_probe(struct platform_device *pd | ||||||
|  |  	if (!ltq_mtd->map) | ||||||
|  |  		return -ENOMEM; | ||||||
|  |   | ||||||
|  | -	ltq_mtd->map->phys = ltq_mtd->res->start; | ||||||
|  | +	if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL)) | ||||||
|  | +		ltq_mtd->map->phys = NO_XIP; | ||||||
|  | +	else | ||||||
|  | +		ltq_mtd->map->phys = ltq_mtd->res->start; | ||||||
|  | +	ltq_mtd->res->start; | ||||||
|  |  	ltq_mtd->map->size = resource_size(ltq_mtd->res); | ||||||
|  |  	ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res); | ||||||
|  |  	if (IS_ERR(ltq_mtd->map->virt)) | ||||||
| @@ -0,0 +1,44 @@ | |||||||
|  | From 4400e1f593ea40a51912128adb4f53d59e62cad8 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Wed, 10 Sep 2014 22:40:18 +0200 | ||||||
|  | Subject: [PATCH 22/36] MTD: m25p80: allow loading mtd name from OF | ||||||
|  |  | ||||||
|  | In accordance with the physmap flash we should honour the linux,mtd-name | ||||||
|  | property when deciding what name the mtd device has. | ||||||
|  |  | ||||||
|  | Signed-off-by: Thomas Langer <thomas.langer@lantiq.com> | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/mtd/devices/m25p80.c |    6 ++++++ | ||||||
|  |  1 file changed, 6 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/mtd/devices/m25p80.c | ||||||
|  | +++ b/drivers/mtd/devices/m25p80.c | ||||||
|  | @@ -19,6 +19,7 @@ | ||||||
|  |  #include <linux/errno.h> | ||||||
|  |  #include <linux/module.h> | ||||||
|  |  #include <linux/device.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  |   | ||||||
|  |  #include <linux/mtd/mtd.h> | ||||||
|  |  #include <linux/mtd/partitions.h> | ||||||
|  | @@ -198,6 +199,10 @@ static int m25p_probe(struct spi_device | ||||||
|  |  	enum read_mode mode = SPI_NOR_NORMAL; | ||||||
|  |  	char *flash_name; | ||||||
|  |  	int ret; | ||||||
|  | +	const char __maybe_unused	*of_mtd_name = NULL; | ||||||
|  | + | ||||||
|  | +	of_property_read_string(spi->dev.of_node, | ||||||
|  | +		"linux,mtd-name", &of_mtd_name); | ||||||
|  |   | ||||||
|  |  	data = dev_get_platdata(&spi->dev); | ||||||
|  |   | ||||||
|  | @@ -227,6 +232,8 @@ static int m25p_probe(struct spi_device | ||||||
|  |   | ||||||
|  |  	if (data && data->name) | ||||||
|  |  		nor->mtd.name = data->name; | ||||||
|  | +	else if (of_mtd_name) | ||||||
|  | +		nor->mtd.name = of_mtd_name; | ||||||
|  |   | ||||||
|  |  	/* For some (historical?) reason many platforms provide two different | ||||||
|  |  	 * names in flash_platform_data: "name" and "type". Quite often name is | ||||||
| @@ -0,0 +1,294 @@ | |||||||
|  | From 0a63ab263725c427051a8bbaa0732b749627da27 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Thu, 7 Aug 2014 18:15:36 +0200 | ||||||
|  | Subject: [PATCH 23/36] NET: PHY: adds driver for lantiq PHY11G | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/phy/Kconfig  |    5 + | ||||||
|  |  drivers/net/phy/Makefile |    1 + | ||||||
|  |  drivers/net/phy/lantiq.c |  231 ++++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  3 files changed, 237 insertions(+) | ||||||
|  |  create mode 100644 drivers/net/phy/lantiq.c | ||||||
|  |  | ||||||
|  | --- a/drivers/net/phy/intel-xway.c | ||||||
|  | +++ b/drivers/net/phy/intel-xway.c | ||||||
|  | @@ -152,6 +152,51 @@ | ||||||
|  |  #define PHY_ID_PHY11G_VR9		0xD565A409 | ||||||
|  |  #define PHY_ID_PHY22F_VR9		0xD565A419 | ||||||
|  |   | ||||||
|  | +#if IS_ENABLED(CONFIG_OF_MDIO) | ||||||
|  | +static int vr9_gphy_of_reg_init(struct phy_device *phydev) | ||||||
|  | +{ | ||||||
|  | +	u32 tmp; | ||||||
|  | + | ||||||
|  | +	/* store the led values if one was passed by the devicetree */ | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,ledch", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LEDCH, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,ledcl", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LEDCL, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led0h", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LED0H, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led0l", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LED0L, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led1h", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LED1H, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led1l", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LED1L, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led2h", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LED3H, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led2l", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LED3L, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led3h", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LED3H, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(phydev->mdio.dev.of_node, "lantiq,led3l", &tmp)) | ||||||
|  | +		phy_write_mmd_indirect(phydev, XWAY_MMD_LED3L, MDIO_MMD_VEND2, tmp); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | +#else | ||||||
|  | +static int vr9_gphy_of_reg_init(struct phy_device *phydev) | ||||||
|  | +{ | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | +#endif /* CONFIG_OF_MDIO */ | ||||||
|  | + | ||||||
|  |  static int xway_gphy_config_init(struct phy_device *phydev) | ||||||
|  |  { | ||||||
|  |  	int err; | ||||||
|  | @@ -190,6 +235,7 @@ static int xway_gphy_config_init(struct | ||||||
|  |  	phy_write_mmd_indirect(phydev, XWAY_MMD_LED2H, MDIO_MMD_VEND2, ledxh); | ||||||
|  |  	phy_write_mmd_indirect(phydev, XWAY_MMD_LED2L, MDIO_MMD_VEND2, ledxl); | ||||||
|  |   | ||||||
|  | +	vr9_gphy_of_reg_init(phydev); | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/Documentation/devicetree/bindings/phy/phy-lanitq.txt | ||||||
|  | @@ -0,0 +1,216 @@ | ||||||
|  | +Lanitq PHY binding | ||||||
|  | +============================================ | ||||||
|  | + | ||||||
|  | +This devicetree binding controls the lantiq ethernet phys led functionality. | ||||||
|  | + | ||||||
|  | +Example: | ||||||
|  | +	mdio@0 { | ||||||
|  | +		#address-cells = <1>; | ||||||
|  | +		#size-cells = <0>; | ||||||
|  | +		compatible = "lantiq,xrx200-mdio"; | ||||||
|  | +			phy5: ethernet-phy@5 { | ||||||
|  | +			reg = <0x1>; | ||||||
|  | +			compatible = "lantiq,phy11g", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +		}; | ||||||
|  | +		phy11: ethernet-phy@11 { | ||||||
|  | +			reg = <0x11>; | ||||||
|  | +			compatible = "lantiq,phy22f", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +			lantiq,led2h = <0x00>; | ||||||
|  | +			lantiq,led2l = <0x03>; | ||||||
|  | +		}; | ||||||
|  | +		phy12: ethernet-phy@12 { | ||||||
|  | +			reg = <0x12>; | ||||||
|  | +			compatible = "lantiq,phy22f", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +			lantiq,led1h = <0x00>; | ||||||
|  | +			lantiq,led1l = <0x03>; | ||||||
|  | +		}; | ||||||
|  | +		phy13: ethernet-phy@13 { | ||||||
|  | +			reg = <0x13>; | ||||||
|  | +			compatible = "lantiq,phy22f", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +			lantiq,led2h = <0x00>; | ||||||
|  | +			lantiq,led2l = <0x03>; | ||||||
|  | +		}; | ||||||
|  | +		phy14: ethernet-phy@14 { | ||||||
|  | +			reg = <0x14>; | ||||||
|  | +			compatible = "lantiq,phy22f", "ethernet-phy-ieee802.3-c22"; | ||||||
|  | +			lantiq,led1h = <0x00>; | ||||||
|  | +			lantiq,led1l = <0x03>; | ||||||
|  | +		}; | ||||||
|  | +	}; | ||||||
|  | + | ||||||
|  | +Register Description | ||||||
|  | +============================================ | ||||||
|  | + | ||||||
|  | +LEDCH: | ||||||
|  | + | ||||||
|  | +Name	Hardware Reset Value | ||||||
|  | +LEDCH	0x00C5 | ||||||
|  | + | ||||||
|  | +| 15 |    |    |    |    |    |    |  8 | | ||||||
|  | +========================================= | ||||||
|  | +|		RES			| | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +|  7 |    |    |    |    |    |    |  0 | | ||||||
|  | +========================================= | ||||||
|  | +|   FBF   |   SBF   |RES |     NACS     | | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +Field	Bits	Type	Description | ||||||
|  | +FBF	7:6	RW	Fast Blink Frequency | ||||||
|  | +			--- | ||||||
|  | +			0x0 (00b) F02HZ 2 Hz blinking frequency | ||||||
|  | +			0x1 (01b) F04HZ 4 Hz blinking frequency | ||||||
|  | +			0x2 (10b) F08HZ 8 Hz blinking frequency | ||||||
|  | +			0x3 (11b) F16HZ 16 Hz blinking frequency | ||||||
|  | + | ||||||
|  | +SBF	5:4	RW	Slow Blink Frequency | ||||||
|  | +			--- | ||||||
|  | +			0x0 (00b) F02HZ 2 Hz blinking frequency | ||||||
|  | +			0x1 (01b) F04HZ 4 Hz blinking frequency | ||||||
|  | +			0x2 (10b) F08HZ 8 Hz blinking frequency | ||||||
|  | +			0x3 (11b) F16HZ 16 Hz blinking frequency | ||||||
|  | + | ||||||
|  | +NACS	2:0	RW	Inverse of Scan Function | ||||||
|  | +			--- | ||||||
|  | +			0x0 (000b) NONE No Function | ||||||
|  | +			0x1 (001b) LINK Complex function enabled when link is up | ||||||
|  | +			0x2 (010b) PDOWN Complex function enabled when device is powered-down | ||||||
|  | +			0x3 (011b) EEE Complex function enabled when device is in EEE mode | ||||||
|  | +			0x4 (100b) ANEG Complex function enabled when auto-negotiation is running | ||||||
|  | +			0x5 (101b) ABIST Complex function enabled when analog self-test is running | ||||||
|  | +			0x6 (110b) CDIAG Complex function enabled when cable diagnostics are running | ||||||
|  | +			0x7 (111b) TEST Complex function enabled when test mode is running | ||||||
|  | + | ||||||
|  | +LEDCL: | ||||||
|  | + | ||||||
|  | +Name	Hardware Reset Value | ||||||
|  | +LEDCL	0x0067 | ||||||
|  | + | ||||||
|  | +| 15 |    |    |    |    |    |    |  8 | | ||||||
|  | +========================================= | ||||||
|  | +|		RES			| | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +|  7 |    |    |    |    |    |    |  0 | | ||||||
|  | +========================================= | ||||||
|  | +|RES |     SCAN     |RES |    CBLINK    | | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +Field	Bits	Type	Description | ||||||
|  | +SCAN	6:4	RW	Complex Scan Configuration | ||||||
|  | +			--- | ||||||
|  | +			000 B NONE No Function | ||||||
|  | +			001 B LINK Complex function enabled when link is up | ||||||
|  | +			010 B PDOWN Complex function enabled when device is powered-down | ||||||
|  | +			011 B EEE Complex function enabled when device is in EEE mode | ||||||
|  | +			100 B ANEG Complex function enabled when auto-negotiation is running | ||||||
|  | +			101 B ABIST Complex function enabled when analog self-test is running | ||||||
|  | +			110 B CDIAG Complex function enabled when cable diagnostics are running | ||||||
|  | +			111 B TEST Complex function enabled when test mode is running | ||||||
|  | + | ||||||
|  | +CBLINK	2:0	RW	Complex Blinking Configuration | ||||||
|  | +			--- | ||||||
|  | +			000 B NONE No Function | ||||||
|  | +			001 B LINK Complex function enabled when link is up | ||||||
|  | +			010 B PDOWN Complex function enabled when device is powered-down | ||||||
|  | +			011 B EEE Complex function enabled when device is in EEE mode | ||||||
|  | +			100 B ANEG Complex function enabled when auto-negotiation is running | ||||||
|  | +			101 B ABIST Complex function enabled when analog self-test is running | ||||||
|  | +			110 B CDIAG Complex function enabled when cable diagnostics are running | ||||||
|  | +			111 B TEST Complex function enabled when test mode is running | ||||||
|  | + | ||||||
|  | +LEDxH: | ||||||
|  | + | ||||||
|  | +Name	Hardware Reset Value | ||||||
|  | +LED0H	0x0070 | ||||||
|  | +LED1H	0x0020 | ||||||
|  | +LED2H	0x0040 | ||||||
|  | +LED3H	0x0040 | ||||||
|  | + | ||||||
|  | +| 15 |    |    |    |    |    |    |  8 | | ||||||
|  | +========================================= | ||||||
|  | +|		RES			| | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +|  7 |    |    |    |    |    |    |  0 | | ||||||
|  | +========================================= | ||||||
|  | +|        CON        |       BLINKF      | | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +Field	Bits	Type	Description | ||||||
|  | +CON	7:4	RW	Constant On Configuration | ||||||
|  | +			--- | ||||||
|  | +			0x0 (0000b) NONE LED does not light up constantly | ||||||
|  | +			0x1 (0001b) LINK10 LED is on when link is 10 Mbit/s | ||||||
|  | +			0x2 (0010b) LINK100 LED is on when link is 100 Mbit/s | ||||||
|  | +			0x3 (0011b) LINK10X LED is on when link is 10/100 Mbit/s | ||||||
|  | +			0x4 (0100b) LINK1000 LED is on when link is 1000 Mbit/s | ||||||
|  | +			0x5 (0101b) LINK10_0 LED is on when link is 10/1000 Mbit/s | ||||||
|  | +			0x6 (0110b) LINK100X LED is on when link is 100/1000 Mbit/s | ||||||
|  | +			0x7 (0111b) LINK10XX LED is on when link is 10/100/1000 Mbit/s | ||||||
|  | +			0x8 (1000b) PDOWN LED is on when device is powered-down | ||||||
|  | +			0x9 (1001b) EEE LED is on when device is in EEE mode | ||||||
|  | +			0xA (1010b) ANEG LED is on when auto-negotiation is running | ||||||
|  | +			0xB (1011b) ABIST LED is on when analog self-test is running | ||||||
|  | +			0xC (1100b) CDIAG LED is on when cable diagnostics are running | ||||||
|  | + | ||||||
|  | +BLINKF	3:0	RW	Fast Blinking Configuration | ||||||
|  | +			--- | ||||||
|  | +			0x0 (0000b) NONE No Blinking | ||||||
|  | +			0x1 (0001b) LINK10 Blink when link is 10 Mbit/s | ||||||
|  | +			0x2 (0010b) LINK100 Blink when link is 100 Mbit/s | ||||||
|  | +			0x3 (0011b) LINK10X Blink when link is 10/100 Mbit/s | ||||||
|  | +			0x4 (0100b) LINK1000 Blink when link is 1000 Mbit/s | ||||||
|  | +			0x5 (0101b) LINK10_0 Blink when link is 10/1000 Mbit/s | ||||||
|  | +			0x6 (0110b) LINK100X Blink when link is 100/1000 Mbit/s | ||||||
|  | +			0x7 (0111b) LINK10XX Blink when link is 10/100/1000 Mbit/s | ||||||
|  | +			0x8 (1000b) PDOWN Blink when device is powered-down | ||||||
|  | +			0x9 (1001b) EEE Blink when device is in EEE mode | ||||||
|  | +			0xA (1010b) ANEG Blink when auto-negotiation is running | ||||||
|  | +			0xB (1011b) ABIST Blink when analog self-test is running | ||||||
|  | +			0xC (1100b) CDIAG Blink when cable diagnostics are running | ||||||
|  | + | ||||||
|  | +LEDxL: | ||||||
|  | + | ||||||
|  | +Name	Hardware Reset Value | ||||||
|  | +LED0L	0x0003 | ||||||
|  | +LED1L	0x0000 | ||||||
|  | +LED2L	0x0000 | ||||||
|  | +LED3L	0x0020 | ||||||
|  | + | ||||||
|  | +| 15 |    |    |    |    |    |    |  8 | | ||||||
|  | +========================================= | ||||||
|  | +|		RES			| | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +|  7 |    |    |    |    |    |    |  0 | | ||||||
|  | +========================================= | ||||||
|  | +|      BLINKS       |       PULSE       | | ||||||
|  | +========================================= | ||||||
|  | + | ||||||
|  | +Field	Bits	Type	Description | ||||||
|  | +BLINKS	7:4	RW	Slow Blinkin Configuration | ||||||
|  | +			--- | ||||||
|  | +			0x0 (0000b) NONE No Blinking | ||||||
|  | +			0x1 (0001b) LINK10 Blink when link is 10 Mbit/s | ||||||
|  | +			0x2 (0010b) LINK100 Blink when link is 100 Mbit/s | ||||||
|  | +			0x3 (0011b) LINK10X Blink when link is 10/100 Mbit/s | ||||||
|  | +			0x4 (0100b) LINK1000 Blink when link is 1000 Mbit/s | ||||||
|  | +			0x5 (0101b) LINK10_0 Blink when link is 10/1000 Mbit/s | ||||||
|  | +			0x6 (0110b) LINK100X Blink when link is 100/1000 Mbit/s | ||||||
|  | +			0x7 (0111b) LINK10XX Blink when link is 10/100/1000 Mbit/s | ||||||
|  | +			0x8 (1000b) PDOWN Blink when device is powered-down | ||||||
|  | +			0x9 (1001b) EEE Blink when device is in EEE mode | ||||||
|  | +			0xA (1010b) ANEG Blink when auto-negotiation is running | ||||||
|  | +			0xB (1011b) ABIST Blink when analog self-test is running | ||||||
|  | +			0xC (1100b) CDIAG Blink when cable diagnostics are runningning | ||||||
|  | + | ||||||
|  | +PULSE	3:0	RW	Pulsing Configuration | ||||||
|  | +			The pulse field is a mask field by which certain events can be combined | ||||||
|  | +			--- | ||||||
|  | +			0x0 (0000b) NONE No pulsing | ||||||
|  | +			0x1 (0001b) TXACT Transmit activity | ||||||
|  | +			0x2 (0010b) RXACT Receive activity | ||||||
|  | +			0x4 (0100b) COL Collision | ||||||
|  | +			0x8 (1000b) RES Reserved | ||||||
| @@ -0,0 +1,364 @@ | |||||||
|  | From 77e89d5a28be35058041c79e9874ab26f222c603 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Mon, 22 Oct 2012 09:26:24 +0200 | ||||||
|  | Subject: [PATCH 24/36] NET: lantiq: adds PHY11G firmware blobs | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  firmware/Makefile       |    4 + | ||||||
|  |  firmware/lantiq/COPYING |  286 +++++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  firmware/lantiq/README  |   45 ++++++++ | ||||||
|  |  3 files changed, 335 insertions(+) | ||||||
|  |  create mode 100644 firmware/lantiq/COPYING | ||||||
|  |  create mode 100644 firmware/lantiq/README | ||||||
|  |  | ||||||
|  | --- a/firmware/Makefile | ||||||
|  | +++ b/firmware/Makefile | ||||||
|  | @@ -134,6 +134,10 @@ fw-shipped-$(CONFIG_USB_SERIAL_KEYSPAN_P | ||||||
|  |  fw-shipped-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda/xircom_pgs.fw | ||||||
|  |  fw-shipped-$(CONFIG_USB_VICAM) += vicam/firmware.fw | ||||||
|  |  fw-shipped-$(CONFIG_VIDEO_CPIA2) += cpia2/stv0672_vp4.bin | ||||||
|  | +fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy11g_a1x.bin | ||||||
|  | +fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy11g_a2x.bin | ||||||
|  | +fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy22f_a1x.bin | ||||||
|  | +fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy22f_a2x.bin | ||||||
|  |  fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin | ||||||
|  |   | ||||||
|  |  fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-) | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/firmware/lantiq/COPYING | ||||||
|  | @@ -0,0 +1,286 @@ | ||||||
|  | +All firmware files are copyrighted by Lantiq Deutschland GmbH. | ||||||
|  | +The files have been extracted from header files found in Lantiq BSPs. | ||||||
|  | +If not stated otherwise all files are licensed under GPL. | ||||||
|  | + | ||||||
|  | +======================================================================= | ||||||
|  | + | ||||||
|  | +		    GNU GENERAL PUBLIC LICENSE | ||||||
|  | +		       Version 2, June 1991 | ||||||
|  | + | ||||||
|  | + Copyright (C) 1989, 1991 Free Software Foundation, Inc. | ||||||
|  | +     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  | + Everyone is permitted to copy and distribute verbatim copies | ||||||
|  | + of this license document, but changing it is not allowed. | ||||||
|  | + | ||||||
|  | +			    Preamble | ||||||
|  | + | ||||||
|  | +  The licenses for most software are designed to take away your | ||||||
|  | +freedom to share and change it.  By contrast, the GNU General Public | ||||||
|  | +License is intended to guarantee your freedom to share and change free | ||||||
|  | +software--to make sure the software is free for all its users.  This | ||||||
|  | +General Public License applies to most of the Free Software | ||||||
|  | +Foundation's software and to any other program whose authors commit to | ||||||
|  | +using it.  (Some other Free Software Foundation software is covered by | ||||||
|  | +the GNU Library General Public License instead.)  You can apply it to | ||||||
|  | +your programs, too. | ||||||
|  | + | ||||||
|  | +  When we speak of free software, we are referring to freedom, not | ||||||
|  | +price.  Our General Public Licenses are designed to make sure that you | ||||||
|  | +have the freedom to distribute copies of free software (and charge for | ||||||
|  | +this service if you wish), that you receive source code or can get it | ||||||
|  | +if you want it, that you can change the software or use pieces of it | ||||||
|  | +in new free programs; and that you know you can do these things. | ||||||
|  | + | ||||||
|  | +  To protect your rights, we need to make restrictions that forbid | ||||||
|  | +anyone to deny you these rights or to ask you to surrender the rights. | ||||||
|  | +These restrictions translate to certain responsibilities for you if you | ||||||
|  | +distribute copies of the software, or if you modify it. | ||||||
|  | + | ||||||
|  | +  For example, if you distribute copies of such a program, whether | ||||||
|  | +gratis or for a fee, you must give the recipients all the rights that | ||||||
|  | +you have.  You must make sure that they, too, receive or can get the | ||||||
|  | +source code.  And you must show them these terms so they know their | ||||||
|  | +rights. | ||||||
|  | + | ||||||
|  | +  We protect your rights with two steps: (1) copyright the software, and | ||||||
|  | +(2) offer you this license which gives you legal permission to copy, | ||||||
|  | +distribute and/or modify the software. | ||||||
|  | + | ||||||
|  | +  Also, for each author's protection and ours, we want to make certain | ||||||
|  | +that everyone understands that there is no warranty for this free | ||||||
|  | +software.  If the software is modified by someone else and passed on, we | ||||||
|  | +want its recipients to know that what they have is not the original, so | ||||||
|  | +that any problems introduced by others will not reflect on the original | ||||||
|  | +authors' reputations. | ||||||
|  | + | ||||||
|  | +  Finally, any free program is threatened constantly by software | ||||||
|  | +patents.  We wish to avoid the danger that redistributors of a free | ||||||
|  | +program will individually obtain patent licenses, in effect making the | ||||||
|  | +program proprietary.  To prevent this, we have made it clear that any | ||||||
|  | +patent must be licensed for everyone's free use or not licensed at all. | ||||||
|  | + | ||||||
|  | +  The precise terms and conditions for copying, distribution and | ||||||
|  | +modification follow. | ||||||
|  | + | ||||||
|  | +		    GNU GENERAL PUBLIC LICENSE | ||||||
|  | +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||||||
|  | + | ||||||
|  | +  0. This License applies to any program or other work which contains | ||||||
|  | +a notice placed by the copyright holder saying it may be distributed | ||||||
|  | +under the terms of this General Public License.  The "Program", below, | ||||||
|  | +refers to any such program or work, and a "work based on the Program" | ||||||
|  | +means either the Program or any derivative work under copyright law: | ||||||
|  | +that is to say, a work containing the Program or a portion of it, | ||||||
|  | +either verbatim or with modifications and/or translated into another | ||||||
|  | +language.  (Hereinafter, translation is included without limitation in | ||||||
|  | +the term "modification".)  Each licensee is addressed as "you". | ||||||
|  | + | ||||||
|  | +Activities other than copying, distribution and modification are not | ||||||
|  | +covered by this License; they are outside its scope.  The act of | ||||||
|  | +running the Program is not restricted, and the output from the Program | ||||||
|  | +is covered only if its contents constitute a work based on the | ||||||
|  | +Program (independent of having been made by running the Program). | ||||||
|  | +Whether that is true depends on what the Program does. | ||||||
|  | + | ||||||
|  | +  1. You may copy and distribute verbatim copies of the Program's | ||||||
|  | +source code as you receive it, in any medium, provided that you | ||||||
|  | +conspicuously and appropriately publish on each copy an appropriate | ||||||
|  | +copyright notice and disclaimer of warranty; keep intact all the | ||||||
|  | +notices that refer to this License and to the absence of any warranty; | ||||||
|  | +and give any other recipients of the Program a copy of this License | ||||||
|  | +along with the Program. | ||||||
|  | + | ||||||
|  | +You may charge a fee for the physical act of transferring a copy, and | ||||||
|  | +you may at your option offer warranty protection in exchange for a fee. | ||||||
|  | + | ||||||
|  | +  2. You may modify your copy or copies of the Program or any portion | ||||||
|  | +of it, thus forming a work based on the Program, and copy and | ||||||
|  | +distribute such modifications or work under the terms of Section 1 | ||||||
|  | +above, provided that you also meet all of these conditions: | ||||||
|  | + | ||||||
|  | +    a) You must cause the modified files to carry prominent notices | ||||||
|  | +    stating that you changed the files and the date of any change. | ||||||
|  | + | ||||||
|  | +    b) You must cause any work that you distribute or publish, that in | ||||||
|  | +    whole or in part contains or is derived from the Program or any | ||||||
|  | +    part thereof, to be licensed as a whole at no charge to all third | ||||||
|  | +    parties under the terms of this License. | ||||||
|  | + | ||||||
|  | +    c) If the modified program normally reads commands interactively | ||||||
|  | +    when run, you must cause it, when started running for such | ||||||
|  | +    interactive use in the most ordinary way, to print or display an | ||||||
|  | +    announcement including an appropriate copyright notice and a | ||||||
|  | +    notice that there is no warranty (or else, saying that you provide | ||||||
|  | +    a warranty) and that users may redistribute the program under | ||||||
|  | +    these conditions, and telling the user how to view a copy of this | ||||||
|  | +    License.  (Exception: if the Program itself is interactive but | ||||||
|  | +    does not normally print such an announcement, your work based on | ||||||
|  | +    the Program is not required to print an announcement.) | ||||||
|  | + | ||||||
|  | +These requirements apply to the modified work as a whole.  If | ||||||
|  | +identifiable sections of that work are not derived from the Program, | ||||||
|  | +and can be reasonably considered independent and separate works in | ||||||
|  | +themselves, then this License, and its terms, do not apply to those | ||||||
|  | +sections when you distribute them as separate works.  But when you | ||||||
|  | +distribute the same sections as part of a whole which is a work based | ||||||
|  | +on the Program, the distribution of the whole must be on the terms of | ||||||
|  | +this License, whose permissions for other licensees extend to the | ||||||
|  | +entire whole, and thus to each and every part regardless of who wrote it. | ||||||
|  | + | ||||||
|  | +Thus, it is not the intent of this section to claim rights or contest | ||||||
|  | +your rights to work written entirely by you; rather, the intent is to | ||||||
|  | +exercise the right to control the distribution of derivative or | ||||||
|  | +collective works based on the Program. | ||||||
|  | + | ||||||
|  | +In addition, mere aggregation of another work not based on the Program | ||||||
|  | +with the Program (or with a work based on the Program) on a volume of | ||||||
|  | +a storage or distribution medium does not bring the other work under | ||||||
|  | +the scope of this License. | ||||||
|  | + | ||||||
|  | +  3. You may copy and distribute the Program (or a work based on it, | ||||||
|  | +under Section 2) in object code or executable form under the terms of | ||||||
|  | +Sections 1 and 2 above provided that you also do one of the following: | ||||||
|  | + | ||||||
|  | +    a) Accompany it with the complete corresponding machine-readable | ||||||
|  | +    source code, which must be distributed under the terms of Sections | ||||||
|  | +    1 and 2 above on a medium customarily used for software interchange; or, | ||||||
|  | + | ||||||
|  | +    b) Accompany it with a written offer, valid for at least three | ||||||
|  | +    years, to give any third party, for a charge no more than your | ||||||
|  | +    cost of physically performing source distribution, a complete | ||||||
|  | +    machine-readable copy of the corresponding source code, to be | ||||||
|  | +    distributed under the terms of Sections 1 and 2 above on a medium | ||||||
|  | +    customarily used for software interchange; or, | ||||||
|  | + | ||||||
|  | +    c) Accompany it with the information you received as to the offer | ||||||
|  | +    to distribute corresponding source code.  (This alternative is | ||||||
|  | +    allowed only for noncommercial distribution and only if you | ||||||
|  | +    received the program in object code or executable form with such | ||||||
|  | +    an offer, in accord with Subsection b above.) | ||||||
|  | + | ||||||
|  | +The source code for a work means the preferred form of the work for | ||||||
|  | +making modifications to it.  For an executable work, complete source | ||||||
|  | +code means all the source code for all modules it contains, plus any | ||||||
|  | +associated interface definition files, plus the scripts used to | ||||||
|  | +control compilation and installation of the executable.  However, as a | ||||||
|  | +special exception, the source code distributed need not include | ||||||
|  | +anything that is normally distributed (in either source or binary | ||||||
|  | +form) with the major components (compiler, kernel, and so on) of the | ||||||
|  | +operating system on which the executable runs, unless that component | ||||||
|  | +itself accompanies the executable. | ||||||
|  | + | ||||||
|  | +If distribution of executable or object code is made by offering | ||||||
|  | +access to copy from a designated place, then offering equivalent | ||||||
|  | +access to copy the source code from the same place counts as | ||||||
|  | +distribution of the source code, even though third parties are not | ||||||
|  | +compelled to copy the source along with the object code. | ||||||
|  | + | ||||||
|  | +  4. You may not copy, modify, sublicense, or distribute the Program | ||||||
|  | +except as expressly provided under this License.  Any attempt | ||||||
|  | +otherwise to copy, modify, sublicense or distribute the Program is | ||||||
|  | +void, and will automatically terminate your rights under this License. | ||||||
|  | +However, parties who have received copies, or rights, from you under | ||||||
|  | +this License will not have their licenses terminated so long as such | ||||||
|  | +parties remain in full compliance. | ||||||
|  | + | ||||||
|  | +  5. You are not required to accept this License, since you have not | ||||||
|  | +signed it.  However, nothing else grants you permission to modify or | ||||||
|  | +distribute the Program or its derivative works.  These actions are | ||||||
|  | +prohibited by law if you do not accept this License.  Therefore, by | ||||||
|  | +modifying or distributing the Program (or any work based on the | ||||||
|  | +Program), you indicate your acceptance of this License to do so, and | ||||||
|  | +all its terms and conditions for copying, distributing or modifying | ||||||
|  | +the Program or works based on it. | ||||||
|  | + | ||||||
|  | +  6. Each time you redistribute the Program (or any work based on the | ||||||
|  | +Program), the recipient automatically receives a license from the | ||||||
|  | +original licensor to copy, distribute or modify the Program subject to | ||||||
|  | +these terms and conditions.  You may not impose any further | ||||||
|  | +restrictions on the recipients' exercise of the rights granted herein. | ||||||
|  | +You are not responsible for enforcing compliance by third parties to | ||||||
|  | +this License. | ||||||
|  | + | ||||||
|  | +  7. If, as a consequence of a court judgment or allegation of patent | ||||||
|  | +infringement or for any other reason (not limited to patent issues), | ||||||
|  | +conditions are imposed on you (whether by court order, agreement or | ||||||
|  | +otherwise) that contradict the conditions of this License, they do not | ||||||
|  | +excuse you from the conditions of this License.  If you cannot | ||||||
|  | +distribute so as to satisfy simultaneously your obligations under this | ||||||
|  | +License and any other pertinent obligations, then as a consequence you | ||||||
|  | +may not distribute the Program at all.  For example, if a patent | ||||||
|  | +license would not permit royalty-free redistribution of the Program by | ||||||
|  | +all those who receive copies directly or indirectly through you, then | ||||||
|  | +the only way you could satisfy both it and this License would be to | ||||||
|  | +refrain entirely from distribution of the Program. | ||||||
|  | + | ||||||
|  | +If any portion of this section is held invalid or unenforceable under | ||||||
|  | +any particular circumstance, the balance of the section is intended to | ||||||
|  | +apply and the section as a whole is intended to apply in other | ||||||
|  | +circumstances. | ||||||
|  | + | ||||||
|  | +It is not the purpose of this section to induce you to infringe any | ||||||
|  | +patents or other property right claims or to contest validity of any | ||||||
|  | +such claims; this section has the sole purpose of protecting the | ||||||
|  | +integrity of the free software distribution system, which is | ||||||
|  | +implemented by public license practices.  Many people have made | ||||||
|  | +generous contributions to the wide range of software distributed | ||||||
|  | +through that system in reliance on consistent application of that | ||||||
|  | +system; it is up to the author/donor to decide if he or she is willing | ||||||
|  | +to distribute software through any other system and a licensee cannot | ||||||
|  | +impose that choice. | ||||||
|  | + | ||||||
|  | +This section is intended to make thoroughly clear what is believed to | ||||||
|  | +be a consequence of the rest of this License. | ||||||
|  | + | ||||||
|  | +  8. If the distribution and/or use of the Program is restricted in | ||||||
|  | +certain countries either by patents or by copyrighted interfaces, the | ||||||
|  | +original copyright holder who places the Program under this License | ||||||
|  | +may add an explicit geographical distribution limitation excluding | ||||||
|  | +those countries, so that distribution is permitted only in or among | ||||||
|  | +countries not thus excluded.  In such case, this License incorporates | ||||||
|  | +the limitation as if written in the body of this License. | ||||||
|  | + | ||||||
|  | +  9. The Free Software Foundation may publish revised and/or new versions | ||||||
|  | +of the General Public License from time to time.  Such new versions will | ||||||
|  | +be similar in spirit to the present version, but may differ in detail to | ||||||
|  | +address new problems or concerns. | ||||||
|  | + | ||||||
|  | +Each version is given a distinguishing version number.  If the Program | ||||||
|  | +specifies a version number of this License which applies to it and "any | ||||||
|  | +later version", you have the option of following the terms and conditions | ||||||
|  | +either of that version or of any later version published by the Free | ||||||
|  | +Software Foundation.  If the Program does not specify a version number of | ||||||
|  | +this License, you may choose any version ever published by the Free Software | ||||||
|  | +Foundation. | ||||||
|  | + | ||||||
|  | +  10. If you wish to incorporate parts of the Program into other free | ||||||
|  | +programs whose distribution conditions are different, write to the author | ||||||
|  | +to ask for permission.  For software which is copyrighted by the Free | ||||||
|  | +Software Foundation, write to the Free Software Foundation; we sometimes | ||||||
|  | +make exceptions for this.  Our decision will be guided by the two goals | ||||||
|  | +of preserving the free status of all derivatives of our free software and | ||||||
|  | +of promoting the sharing and reuse of software generally. | ||||||
|  | + | ||||||
|  | +			    NO WARRANTY | ||||||
|  | + | ||||||
|  | +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | ||||||
|  | +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN | ||||||
|  | +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | ||||||
|  | +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | ||||||
|  | +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||||
|  | +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS | ||||||
|  | +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE | ||||||
|  | +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | ||||||
|  | +REPAIR OR CORRECTION. | ||||||
|  | + | ||||||
|  | +  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | ||||||
|  | +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | ||||||
|  | +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | ||||||
|  | +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | ||||||
|  | +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | ||||||
|  | +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | ||||||
|  | +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | ||||||
|  | +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | ||||||
|  | +POSSIBILITY OF SUCH DAMAGES. | ||||||
|  | + | ||||||
|  | +		     END OF TERMS AND CONDITIONS | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/firmware/lantiq/README | ||||||
|  | @@ -0,0 +1,45 @@ | ||||||
|  | +# | ||||||
|  | +# This program is free software; you can redistribute it and/or | ||||||
|  | +# modify it under the terms of the GNU General Public License as | ||||||
|  | +# published by the Free Software Foundation; either version 2 of | ||||||
|  | +# the License, or (at your option) any later version. | ||||||
|  | +# | ||||||
|  | +# This program is distributed in the hope that it will be useful, | ||||||
|  | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | +# GNU General Public License for more details. | ||||||
|  | +# | ||||||
|  | +# You should have received a copy of the GNU General Public License | ||||||
|  | +# along with this program; if not, write to the Free Software | ||||||
|  | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||||||
|  | +# MA 02111-1307 USA | ||||||
|  | +# | ||||||
|  | +# (C) Copyright 2007 - 2012 | ||||||
|  | +# Lantiq Deutschland GmbH | ||||||
|  | +# | ||||||
|  | +# (C) Copyright 2012 | ||||||
|  | +# Daniel Schwierzeck <daniel.schwierzeck@googlemail.com> | ||||||
|  | +# | ||||||
|  | + | ||||||
|  | +# | ||||||
|  | +# How to use | ||||||
|  | +# | ||||||
|  | +Configure kernel with: | ||||||
|  | +CONFIG_FW_LOADER=y | ||||||
|  | +CONFIG_EXTRA_FIRMWARE_DIR="FIRMWARE_DIR" | ||||||
|  | +CONFIG_EXTRA_FIRMWARE="FIRMWARE_FILES" | ||||||
|  | + | ||||||
|  | +where FIRMWARE_DIR should point to this git tree and FIRMWARE_FILES is a list | ||||||
|  | +of space separated files from list below. | ||||||
|  | + | ||||||
|  | +# | ||||||
|  | +# Firmware files | ||||||
|  | +# | ||||||
|  | + | ||||||
|  | +# GPHY core on Lantiq XWAY VR9 v1.1 | ||||||
|  | +lantiq/vr9_phy11g_a1x.bin | ||||||
|  | +lantiq/vr9_phy22f_a1x.bin | ||||||
|  | + | ||||||
|  | +# GPHY core on Lantiq XWAY VR9 v1.2 | ||||||
|  | +lantiq/vr9_phy11g_a2x.bin | ||||||
|  | +lantiq/vr9_phy22f_a2x.bin | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | From c6feeeb407a3b8a6597ae377ba4dd138e185e3dd Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Sun, 27 Jul 2014 09:38:50 +0100 | ||||||
|  | Subject: [PATCH 26/36] 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 | ||||||
|  | @@ -996,7 +996,8 @@ void phy_state_machine(struct work_struc | ||||||
|  |  		/* If the link is down, give up on negotiation for now */ | ||||||
|  |  		if (!phydev->link) { | ||||||
|  |  			phydev->state = PHY_NOLINK; | ||||||
|  | -			netif_carrier_off(phydev->attached_dev); | ||||||
|  | +			if (!phydev->no_auto_carrier_off) | ||||||
|  | +				netif_carrier_off(phydev->attached_dev); | ||||||
|  |  			phydev->adjust_link(phydev->attached_dev); | ||||||
|  |  			break; | ||||||
|  |  		} | ||||||
|  | @@ -1079,7 +1080,8 @@ void phy_state_machine(struct work_struc | ||||||
|  |  			netif_carrier_on(phydev->attached_dev); | ||||||
|  |  		} else { | ||||||
|  |  			phydev->state = PHY_NOLINK; | ||||||
|  | -			netif_carrier_off(phydev->attached_dev); | ||||||
|  | +			if (!phydev->no_auto_carrier_off) | ||||||
|  | +				netif_carrier_off(phydev->attached_dev); | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  |  		phydev->adjust_link(phydev->attached_dev); | ||||||
|  | @@ -1091,7 +1093,8 @@ void phy_state_machine(struct work_struc | ||||||
|  |  	case PHY_HALTED: | ||||||
|  |  		if (phydev->link) { | ||||||
|  |  			phydev->link = 0; | ||||||
|  | -			netif_carrier_off(phydev->attached_dev); | ||||||
|  | +			if (!phydev->no_auto_carrier_off) | ||||||
|  | +				netif_carrier_off(phydev->attached_dev); | ||||||
|  |  			phydev->adjust_link(phydev->attached_dev); | ||||||
|  |  			do_suspend = true; | ||||||
|  |  		} | ||||||
|  | --- a/include/linux/phy.h | ||||||
|  | +++ b/include/linux/phy.h | ||||||
|  | @@ -373,6 +373,7 @@ struct phy_device { | ||||||
|  |  	bool is_pseudo_fixed_link; | ||||||
|  |  	bool has_fixups; | ||||||
|  |  	bool suspended; | ||||||
|  | +	bool no_auto_carrier_off; | ||||||
|  |   | ||||||
|  |  	enum phy_state state; | ||||||
|  |   | ||||||
| @@ -0,0 +1,881 @@ | |||||||
|  | From 870ed9cae083ff8a60a739ef7e74c5a1800533be Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Tue, 9 Sep 2014 22:45:34 +0200 | ||||||
|  | Subject: [PATCH 28/36] NET: lantiq: various etop fixes | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/net/ethernet/lantiq_etop.c |  555 +++++++++++++++++++++++++----------- | ||||||
|  |  1 file changed, 389 insertions(+), 166 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | @@ -11,7 +11,7 @@ | ||||||
|  |   *   You should have received a copy of the GNU General Public License | ||||||
|  |   *   along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||||
|  |   * | ||||||
|  | - *   Copyright (C) 2011 John Crispin <blogic@openwrt.org> | ||||||
|  | + *   Copyright (C) 2011-12 John Crispin <blogic@openwrt.org> | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #include <linux/kernel.h> | ||||||
|  | @@ -30,11 +30,16 @@ | ||||||
|  |  #include <linux/mm.h> | ||||||
|  |  #include <linux/platform_device.h> | ||||||
|  |  #include <linux/ethtool.h> | ||||||
|  | +#include <linux/if_vlan.h> | ||||||
|  |  #include <linux/init.h> | ||||||
|  |  #include <linux/delay.h> | ||||||
|  |  #include <linux/io.h> | ||||||
|  |  #include <linux/dma-mapping.h> | ||||||
|  |  #include <linux/module.h> | ||||||
|  | +#include <linux/clk.h> | ||||||
|  | +#include <linux/of_net.h> | ||||||
|  | +#include <linux/of_irq.h> | ||||||
|  | +#include <linux/of_platform.h> | ||||||
|  |   | ||||||
|  |  #include <asm/checksum.h> | ||||||
|  |   | ||||||
|  | @@ -42,7 +47,7 @@ | ||||||
|  |  #include <xway_dma.h> | ||||||
|  |  #include <lantiq_platform.h> | ||||||
|  |   | ||||||
|  | -#define LTQ_ETOP_MDIO		0x11804 | ||||||
|  | +#define LTQ_ETOP_MDIO_ACC	0x11804 | ||||||
|  |  #define MDIO_REQUEST		0x80000000 | ||||||
|  |  #define MDIO_READ		0x40000000 | ||||||
|  |  #define MDIO_ADDR_MASK		0x1f | ||||||
|  | @@ -51,44 +56,91 @@ | ||||||
|  |  #define MDIO_REG_OFFSET		0x10 | ||||||
|  |  #define MDIO_VAL_MASK		0xffff | ||||||
|  |   | ||||||
|  | -#define PPE32_CGEN		0x800 | ||||||
|  | -#define LQ_PPE32_ENET_MAC_CFG	0x1840 | ||||||
|  | +#define LTQ_ETOP_MDIO_CFG       0x11800 | ||||||
|  | +#define MDIO_CFG_MASK           0x6 | ||||||
|  | + | ||||||
|  | +#define LTQ_ETOP_CFG            0x11808 | ||||||
|  | +#define LTQ_ETOP_IGPLEN         0x11820 | ||||||
|  | +#define LTQ_ETOP_MAC_CFG	0x11840 | ||||||
|  |   | ||||||
|  |  #define LTQ_ETOP_ENETS0		0x11850 | ||||||
|  |  #define LTQ_ETOP_MAC_DA0	0x1186C | ||||||
|  |  #define LTQ_ETOP_MAC_DA1	0x11870 | ||||||
|  | -#define LTQ_ETOP_CFG		0x16020 | ||||||
|  | -#define LTQ_ETOP_IGPLEN		0x16080 | ||||||
|  | + | ||||||
|  | +#define MAC_CFG_MASK		0xfff | ||||||
|  | +#define MAC_CFG_CGEN		(1 << 11) | ||||||
|  | +#define MAC_CFG_DUPLEX		(1 << 2) | ||||||
|  | +#define MAC_CFG_SPEED		(1 << 1) | ||||||
|  | +#define MAC_CFG_LINK		(1 << 0) | ||||||
|  |   | ||||||
|  |  #define MAX_DMA_CHAN		0x8 | ||||||
|  |  #define MAX_DMA_CRC_LEN		0x4 | ||||||
|  |  #define MAX_DMA_DATA_LEN	0x600 | ||||||
|  |   | ||||||
|  |  #define ETOP_FTCU		BIT(28) | ||||||
|  | -#define ETOP_MII_MASK		0xf | ||||||
|  | -#define ETOP_MII_NORMAL		0xd | ||||||
|  | -#define ETOP_MII_REVERSE	0xe | ||||||
|  |  #define ETOP_PLEN_UNDER		0x40 | ||||||
|  | -#define ETOP_CGEN		0x800 | ||||||
|  | +#define ETOP_CFG_MII0		0x01 | ||||||
|  |   | ||||||
|  | -/* use 2 static channels for TX/RX */ | ||||||
|  | -#define LTQ_ETOP_TX_CHANNEL	1 | ||||||
|  | -#define LTQ_ETOP_RX_CHANNEL	6 | ||||||
|  | -#define IS_TX(x)		(x == LTQ_ETOP_TX_CHANNEL) | ||||||
|  | -#define IS_RX(x)		(x == LTQ_ETOP_RX_CHANNEL) | ||||||
|  | +#define ETOP_CFG_MASK           0xfff | ||||||
|  | +#define ETOP_CFG_FEN0		(1 << 8) | ||||||
|  | +#define ETOP_CFG_SEN0		(1 << 6) | ||||||
|  | +#define ETOP_CFG_OFF1		(1 << 3) | ||||||
|  | +#define ETOP_CFG_REMII0		(1 << 1) | ||||||
|  | +#define ETOP_CFG_OFF0		(1 << 0) | ||||||
|  | + | ||||||
|  | +#define LTQ_GBIT_MDIO_CTL	0xCC | ||||||
|  | +#define LTQ_GBIT_MDIO_DATA	0xd0 | ||||||
|  | +#define LTQ_GBIT_GCTL0		0x68 | ||||||
|  | +#define LTQ_GBIT_PMAC_HD_CTL	0x8c | ||||||
|  | +#define LTQ_GBIT_P0_CTL		0x4 | ||||||
|  | +#define LTQ_GBIT_PMAC_RX_IPG	0xa8 | ||||||
|  | +#define LTQ_GBIT_RGMII_CTL	0x78 | ||||||
|  | + | ||||||
|  | +#define PMAC_HD_CTL_AS		(1 << 19) | ||||||
|  | +#define PMAC_HD_CTL_RXSH	(1 << 22) | ||||||
|  | + | ||||||
|  | +/* Switch Enable (0=disable, 1=enable) */ | ||||||
|  | +#define GCTL0_SE		0x80000000 | ||||||
|  | +/* Disable MDIO auto polling (0=disable, 1=enable) */ | ||||||
|  | +#define PX_CTL_DMDIO		0x00400000 | ||||||
|  | + | ||||||
|  | +/* MDC clock divider, clock = 25MHz/((MDC_CLOCK + 1) * 2) */ | ||||||
|  | +#define MDC_CLOCK_MASK		0xff000000 | ||||||
|  | +#define MDC_CLOCK_OFFSET	24 | ||||||
|  | + | ||||||
|  | +/* register information for the gbit's MDIO bus */ | ||||||
|  | +#define MDIO_XR9_REQUEST	0x00008000 | ||||||
|  | +#define MDIO_XR9_READ		0x00000800 | ||||||
|  | +#define MDIO_XR9_WRITE		0x00000400 | ||||||
|  | +#define MDIO_XR9_REG_MASK	0x1f | ||||||
|  | +#define MDIO_XR9_ADDR_MASK	0x1f | ||||||
|  | +#define MDIO_XR9_RD_MASK	0xffff | ||||||
|  | +#define MDIO_XR9_REG_OFFSET	0 | ||||||
|  | +#define MDIO_XR9_ADDR_OFFSET	5 | ||||||
|  | +#define MDIO_XR9_WR_OFFSET	16 | ||||||
|  |   | ||||||
|  | +#define LTQ_DMA_ETOP	((of_machine_is_compatible("lantiq,ase")) ? \ | ||||||
|  | +			(INT_NUM_IM3_IRL0) : (INT_NUM_IM2_IRL0)) | ||||||
|  | + | ||||||
|  | +/* the newer xway socks have a embedded 3/7 port gbit multiplexer */ | ||||||
|  |  #define ltq_etop_r32(x)		ltq_r32(ltq_etop_membase + (x)) | ||||||
|  |  #define ltq_etop_w32(x, y)	ltq_w32(x, ltq_etop_membase + (y)) | ||||||
|  |  #define ltq_etop_w32_mask(x, y, z)	\ | ||||||
|  |  		ltq_w32_mask(x, y, ltq_etop_membase + (z)) | ||||||
|  |   | ||||||
|  | -#define DRV_VERSION	"1.0" | ||||||
|  | +#define ltq_gbit_r32(x)		ltq_r32(ltq_gbit_membase + (x)) | ||||||
|  | +#define ltq_gbit_w32(x, y)	ltq_w32(x, ltq_gbit_membase + (y)) | ||||||
|  | +#define ltq_gbit_w32_mask(x, y, z)	\ | ||||||
|  | +		ltq_w32_mask(x, y, ltq_gbit_membase + (z)) | ||||||
|  | + | ||||||
|  | +#define DRV_VERSION	"1.2" | ||||||
|  |   | ||||||
|  |  static void __iomem *ltq_etop_membase; | ||||||
|  | +static void __iomem *ltq_gbit_membase; | ||||||
|  |   | ||||||
|  |  struct ltq_etop_chan { | ||||||
|  | -	int idx; | ||||||
|  |  	int tx_free; | ||||||
|  | +	int irq; | ||||||
|  |  	struct net_device *netdev; | ||||||
|  |  	struct napi_struct napi; | ||||||
|  |  	struct ltq_dma_channel dma; | ||||||
|  | @@ -98,21 +150,34 @@ struct ltq_etop_chan { | ||||||
|  |  struct ltq_etop_priv { | ||||||
|  |  	struct net_device *netdev; | ||||||
|  |  	struct platform_device *pdev; | ||||||
|  | -	struct ltq_eth_data *pldata; | ||||||
|  |  	struct resource *res; | ||||||
|  |   | ||||||
|  |  	struct mii_bus *mii_bus; | ||||||
|  |   | ||||||
|  | -	struct ltq_etop_chan ch[MAX_DMA_CHAN]; | ||||||
|  | -	int tx_free[MAX_DMA_CHAN >> 1]; | ||||||
|  | +	struct ltq_etop_chan txch; | ||||||
|  | +	struct ltq_etop_chan rxch; | ||||||
|  | + | ||||||
|  | +	int tx_irq; | ||||||
|  | +	int rx_irq; | ||||||
|  | + | ||||||
|  | +	unsigned char mac[6]; | ||||||
|  | +	int mii_mode; | ||||||
|  |   | ||||||
|  |  	spinlock_t lock; | ||||||
|  | + | ||||||
|  | +	struct clk *clk_ppe; | ||||||
|  | +	struct clk *clk_switch; | ||||||
|  | +	struct clk *clk_ephy; | ||||||
|  | +	struct clk *clk_ephycgu; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static int ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, | ||||||
|  | +				int phy_reg, u16 phy_data); | ||||||
|  | + | ||||||
|  |  static int | ||||||
|  |  ltq_etop_alloc_skb(struct ltq_etop_chan *ch) | ||||||
|  |  { | ||||||
|  | -	ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN); | ||||||
|  | +	ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN); | ||||||
|  |  	if (!ch->skb[ch->dma.desc]) | ||||||
|  |  		return -ENOMEM; | ||||||
|  |  	ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL, | ||||||
|  | @@ -147,8 +212,11 @@ ltq_etop_hw_receive(struct ltq_etop_chan | ||||||
|  |  	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |   | ||||||
|  |  	skb_put(skb, len); | ||||||
|  | +	skb->dev = ch->netdev; | ||||||
|  |  	skb->protocol = eth_type_trans(skb, ch->netdev); | ||||||
|  |  	netif_receive_skb(skb); | ||||||
|  | +	ch->netdev->stats.rx_packets++; | ||||||
|  | +	ch->netdev->stats.rx_bytes += len; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | @@ -156,8 +224,10 @@ ltq_etop_poll_rx(struct napi_struct *nap | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_chan *ch = container_of(napi, | ||||||
|  |  				struct ltq_etop_chan, napi); | ||||||
|  | +	struct ltq_etop_priv *priv = netdev_priv(ch->netdev); | ||||||
|  |  	int rx = 0; | ||||||
|  |  	int complete = 0; | ||||||
|  | +	unsigned long flags; | ||||||
|  |   | ||||||
|  |  	while ((rx < budget) && !complete) { | ||||||
|  |  		struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc]; | ||||||
|  | @@ -171,7 +241,9 @@ ltq_etop_poll_rx(struct napi_struct *nap | ||||||
|  |  	} | ||||||
|  |  	if (complete || !rx) { | ||||||
|  |  		napi_complete(&ch->napi); | ||||||
|  | +		spin_lock_irqsave(&priv->lock, flags); | ||||||
|  |  		ltq_dma_ack_irq(&ch->dma); | ||||||
|  | +		spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |  	} | ||||||
|  |  	return rx; | ||||||
|  |  } | ||||||
|  | @@ -183,12 +255,14 @@ ltq_etop_poll_tx(struct napi_struct *nap | ||||||
|  |  		container_of(napi, struct ltq_etop_chan, napi); | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(ch->netdev); | ||||||
|  |  	struct netdev_queue *txq = | ||||||
|  | -		netdev_get_tx_queue(ch->netdev, ch->idx >> 1); | ||||||
|  | +		netdev_get_tx_queue(ch->netdev, ch->dma.nr >> 1); | ||||||
|  |  	unsigned long flags; | ||||||
|  |   | ||||||
|  |  	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  |  	while ((ch->dma.desc_base[ch->tx_free].ctl & | ||||||
|  |  			(LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) { | ||||||
|  | +		ch->netdev->stats.tx_packets++; | ||||||
|  | +		ch->netdev->stats.tx_bytes += ch->skb[ch->tx_free]->len; | ||||||
|  |  		dev_kfree_skb_any(ch->skb[ch->tx_free]); | ||||||
|  |  		ch->skb[ch->tx_free] = NULL; | ||||||
|  |  		memset(&ch->dma.desc_base[ch->tx_free], 0, | ||||||
|  | @@ -201,7 +275,9 @@ ltq_etop_poll_tx(struct napi_struct *nap | ||||||
|  |  	if (netif_tx_queue_stopped(txq)) | ||||||
|  |  		netif_tx_start_queue(txq); | ||||||
|  |  	napi_complete(&ch->napi); | ||||||
|  | +	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  |  	ltq_dma_ack_irq(&ch->dma); | ||||||
|  | +	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |  	return 1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -209,9 +285,10 @@ static irqreturn_t | ||||||
|  |  ltq_etop_dma_irq(int irq, void *_priv) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = _priv; | ||||||
|  | -	int ch = irq - LTQ_DMA_CH0_INT; | ||||||
|  | - | ||||||
|  | -	napi_schedule(&priv->ch[ch].napi); | ||||||
|  | +	if (irq == priv->txch.dma.irq) | ||||||
|  | +		napi_schedule(&priv->txch.napi); | ||||||
|  | +	else | ||||||
|  | +		napi_schedule(&priv->rxch.napi); | ||||||
|  |  	return IRQ_HANDLED; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -223,7 +300,7 @@ ltq_etop_free_channel(struct net_device | ||||||
|  |  	ltq_dma_free(&ch->dma); | ||||||
|  |  	if (ch->dma.irq) | ||||||
|  |  		free_irq(ch->dma.irq, priv); | ||||||
|  | -	if (IS_RX(ch->idx)) { | ||||||
|  | +	if (ch == &priv->txch) { | ||||||
|  |  		int desc; | ||||||
|  |  		for (desc = 0; desc < LTQ_DESC_NUM; desc++) | ||||||
|  |  			dev_kfree_skb_any(ch->skb[ch->dma.desc]); | ||||||
|  | @@ -234,65 +311,133 @@ static void | ||||||
|  |  ltq_etop_hw_exit(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int i; | ||||||
|  |   | ||||||
|  | -	ltq_pmu_disable(PMU_PPE); | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) | ||||||
|  | -		if (IS_TX(i) || IS_RX(i)) | ||||||
|  | -			ltq_etop_free_channel(dev, &priv->ch[i]); | ||||||
|  | +	clk_disable(priv->clk_ppe); | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) | ||||||
|  | +		clk_disable(priv->clk_switch); | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ase")) { | ||||||
|  | +		clk_disable(priv->clk_ephy); | ||||||
|  | +		clk_disable(priv->clk_ephycgu); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ltq_etop_free_channel(dev, &priv->txch); | ||||||
|  | +	ltq_etop_free_channel(dev, &priv->rxch); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +ltq_etop_gbit_init(struct net_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | + | ||||||
|  | +	clk_enable(priv->clk_switch); | ||||||
|  | + | ||||||
|  | +	/* enable gbit port0 on the SoC */ | ||||||
|  | +	ltq_gbit_w32_mask((1 << 17), (1 << 18), LTQ_GBIT_P0_CTL); | ||||||
|  | + | ||||||
|  | +	ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0); | ||||||
|  | +	/* disable MDIO auto polling mode */ | ||||||
|  | +	ltq_gbit_w32_mask(0, PX_CTL_DMDIO, LTQ_GBIT_P0_CTL); | ||||||
|  | +	/* set 1522 packet size */ | ||||||
|  | +	ltq_gbit_w32_mask(0x300, 0, LTQ_GBIT_GCTL0); | ||||||
|  | +	/* disable pmac & dmac headers */ | ||||||
|  | +	ltq_gbit_w32_mask(PMAC_HD_CTL_AS | PMAC_HD_CTL_RXSH, 0, | ||||||
|  | +		LTQ_GBIT_PMAC_HD_CTL); | ||||||
|  | +	/* Due to traffic halt when burst length 8, | ||||||
|  | +		replace default IPG value with 0x3B */ | ||||||
|  | +	ltq_gbit_w32(0x3B, LTQ_GBIT_PMAC_RX_IPG); | ||||||
|  | +	/* set mdc clock to 2.5 MHz */ | ||||||
|  | +	ltq_gbit_w32_mask(MDC_CLOCK_MASK, 4 << MDC_CLOCK_OFFSET, | ||||||
|  | +		LTQ_GBIT_RGMII_CTL); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  |  ltq_etop_hw_init(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int i; | ||||||
|  | +	int mii_mode = priv->mii_mode; | ||||||
|  |   | ||||||
|  | -	ltq_pmu_enable(PMU_PPE); | ||||||
|  | +	clk_enable(priv->clk_ppe); | ||||||
|  |   | ||||||
|  | -	switch (priv->pldata->mii_mode) { | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		ltq_etop_gbit_init(dev); | ||||||
|  | +		/* force the etops link to the gbit to MII */ | ||||||
|  | +		mii_mode = PHY_INTERFACE_MODE_MII; | ||||||
|  | +	} | ||||||
|  | +	ltq_etop_w32_mask(MDIO_CFG_MASK, 0, LTQ_ETOP_MDIO_CFG); | ||||||
|  | +	ltq_etop_w32_mask(MAC_CFG_MASK, MAC_CFG_CGEN | MAC_CFG_DUPLEX | | ||||||
|  | +			MAC_CFG_SPEED | MAC_CFG_LINK, LTQ_ETOP_MAC_CFG); | ||||||
|  | + | ||||||
|  | +	switch (mii_mode) { | ||||||
|  |  	case PHY_INTERFACE_MODE_RMII: | ||||||
|  | -		ltq_etop_w32_mask(ETOP_MII_MASK, | ||||||
|  | -			ETOP_MII_REVERSE, LTQ_ETOP_CFG); | ||||||
|  | +		ltq_etop_w32_mask(ETOP_CFG_MASK, ETOP_CFG_REMII0 | ETOP_CFG_OFF1 | | ||||||
|  | +			ETOP_CFG_SEN0 | ETOP_CFG_FEN0, LTQ_ETOP_CFG); | ||||||
|  |  		break; | ||||||
|  |   | ||||||
|  |  	case PHY_INTERFACE_MODE_MII: | ||||||
|  | -		ltq_etop_w32_mask(ETOP_MII_MASK, | ||||||
|  | -			ETOP_MII_NORMAL, LTQ_ETOP_CFG); | ||||||
|  | +		ltq_etop_w32_mask(ETOP_CFG_MASK, ETOP_CFG_OFF1 | | ||||||
|  | +			ETOP_CFG_SEN0 | ETOP_CFG_FEN0, LTQ_ETOP_CFG); | ||||||
|  |  		break; | ||||||
|  |   | ||||||
|  |  	default: | ||||||
|  | +		if (of_machine_is_compatible("lantiq,ase")) { | ||||||
|  | +			clk_enable(priv->clk_ephy); | ||||||
|  | +			/* disable external MII */ | ||||||
|  | +			ltq_etop_w32_mask(0, ETOP_CFG_MII0, LTQ_ETOP_CFG); | ||||||
|  | +			/* enable clock for internal PHY */ | ||||||
|  | +			clk_enable(priv->clk_ephycgu); | ||||||
|  | +			/* we need to write this magic to the internal phy to | ||||||
|  | +			   make it work */ | ||||||
|  | +			ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020); | ||||||
|  | +			pr_info("Selected EPHY mode\n"); | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  |  		netdev_err(dev, "unknown mii mode %d\n", | ||||||
|  | -			priv->pldata->mii_mode); | ||||||
|  | +			mii_mode); | ||||||
|  |  		return -ENOTSUPP; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	/* enable crc generation */ | ||||||
|  | -	ltq_etop_w32(PPE32_CGEN, LQ_PPE32_ENET_MAC_CFG); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +ltq_etop_dma_init(struct net_device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | +	int tx = priv->tx_irq - LTQ_DMA_ETOP; | ||||||
|  | +	int rx = priv->rx_irq - LTQ_DMA_ETOP; | ||||||
|  | +	int err; | ||||||
|  |   | ||||||
|  |  	ltq_dma_init_port(DMA_PORT_ETOP); | ||||||
|  |   | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) { | ||||||
|  | -		int irq = LTQ_DMA_CH0_INT + i; | ||||||
|  | -		struct ltq_etop_chan *ch = &priv->ch[i]; | ||||||
|  | - | ||||||
|  | -		ch->idx = ch->dma.nr = i; | ||||||
|  | - | ||||||
|  | -		if (IS_TX(i)) { | ||||||
|  | -			ltq_dma_alloc_tx(&ch->dma); | ||||||
|  | -			request_irq(irq, ltq_etop_dma_irq, 0, "etop_tx", priv); | ||||||
|  | -		} else if (IS_RX(i)) { | ||||||
|  | -			ltq_dma_alloc_rx(&ch->dma); | ||||||
|  | -			for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM; | ||||||
|  | -					ch->dma.desc++) | ||||||
|  | -				if (ltq_etop_alloc_skb(ch)) | ||||||
|  | -					return -ENOMEM; | ||||||
|  | -			ch->dma.desc = 0; | ||||||
|  | -			request_irq(irq, ltq_etop_dma_irq, 0, "etop_rx", priv); | ||||||
|  | +	priv->txch.dma.nr = tx; | ||||||
|  | +	ltq_dma_alloc_tx(&priv->txch.dma); | ||||||
|  | +	err = request_irq(priv->tx_irq, ltq_etop_dma_irq, 0, "eth_tx", priv); | ||||||
|  | +	if (err) { | ||||||
|  | +		netdev_err(dev, "failed to allocate tx irq\n"); | ||||||
|  | +		goto err_out; | ||||||
|  | +	} | ||||||
|  | +	priv->txch.dma.irq = priv->tx_irq; | ||||||
|  | + | ||||||
|  | +	priv->rxch.dma.nr = rx; | ||||||
|  | +	ltq_dma_alloc_rx(&priv->rxch.dma); | ||||||
|  | +	for (priv->rxch.dma.desc = 0; priv->rxch.dma.desc < LTQ_DESC_NUM; | ||||||
|  | +			priv->rxch.dma.desc++) { | ||||||
|  | +		if (ltq_etop_alloc_skb(&priv->rxch)) { | ||||||
|  | +			netdev_err(dev, "failed to allocate skbs\n"); | ||||||
|  | +			err = -ENOMEM; | ||||||
|  | +			goto err_out; | ||||||
|  |  		} | ||||||
|  | -		ch->dma.irq = irq; | ||||||
|  |  	} | ||||||
|  | -	return 0; | ||||||
|  | +	priv->rxch.dma.desc = 0; | ||||||
|  | +	err = request_irq(priv->rx_irq, ltq_etop_dma_irq, 0, "eth_rx", priv); | ||||||
|  | +	if (err) | ||||||
|  | +		netdev_err(dev, "failed to allocate rx irq\n"); | ||||||
|  | +	else | ||||||
|  | +		priv->rxch.dma.irq = priv->rx_irq; | ||||||
|  | +err_out: | ||||||
|  | +	return err; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void | ||||||
|  | @@ -306,7 +451,10 @@ ltq_etop_get_drvinfo(struct net_device * | ||||||
|  |  static int | ||||||
|  |  ltq_etop_nway_reset(struct net_device *dev) | ||||||
|  |  { | ||||||
|  | -	return phy_start_aneg(dev->phydev); | ||||||
|  | +	if (dev->phydev) | ||||||
|  | +		return phy_start_aneg(dev->phydev); | ||||||
|  | +	else | ||||||
|  | +		return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static const struct ethtool_ops ltq_etop_ethtool_ops = { | ||||||
|  | @@ -317,6 +465,39 @@ static const struct ethtool_ops ltq_etop | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | +ltq_etop_mdio_wr_xr9(struct mii_bus *bus, int phy_addr, | ||||||
|  | +		int phy_reg, u16 phy_data) | ||||||
|  | +{ | ||||||
|  | +	u32 val = MDIO_XR9_REQUEST | MDIO_XR9_WRITE | | ||||||
|  | +		(phy_data << MDIO_XR9_WR_OFFSET) | | ||||||
|  | +		((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) | | ||||||
|  | +		((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET); | ||||||
|  | + | ||||||
|  | +	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST) | ||||||
|  | +		; | ||||||
|  | +	ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL); | ||||||
|  | +	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST) | ||||||
|  | +		; | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +ltq_etop_mdio_rd_xr9(struct mii_bus *bus, int phy_addr, int phy_reg) | ||||||
|  | +{ | ||||||
|  | +	u32 val = MDIO_XR9_REQUEST | MDIO_XR9_READ | | ||||||
|  | +		((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) | | ||||||
|  | +		((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET); | ||||||
|  | + | ||||||
|  | +	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST) | ||||||
|  | +		; | ||||||
|  | +	ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL); | ||||||
|  | +	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST) | ||||||
|  | +		; | ||||||
|  | +	val = ltq_gbit_r32(LTQ_GBIT_MDIO_DATA) & MDIO_XR9_RD_MASK; | ||||||
|  | +	return val; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  |  ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data) | ||||||
|  |  { | ||||||
|  |  	u32 val = MDIO_REQUEST | | ||||||
|  | @@ -324,9 +505,9 @@ ltq_etop_mdio_wr(struct mii_bus *bus, in | ||||||
|  |  		((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET) | | ||||||
|  |  		phy_data; | ||||||
|  |   | ||||||
|  | -	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) | ||||||
|  | +	while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) | ||||||
|  |  		; | ||||||
|  | -	ltq_etop_w32(val, LTQ_ETOP_MDIO); | ||||||
|  | +	ltq_etop_w32(val, LTQ_ETOP_MDIO_ACC); | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -337,12 +518,12 @@ ltq_etop_mdio_rd(struct mii_bus *bus, in | ||||||
|  |  		((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) | | ||||||
|  |  		((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET); | ||||||
|  |   | ||||||
|  | -	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) | ||||||
|  | +	while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) | ||||||
|  |  		; | ||||||
|  | -	ltq_etop_w32(val, LTQ_ETOP_MDIO); | ||||||
|  | -	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) | ||||||
|  | +	ltq_etop_w32(val, LTQ_ETOP_MDIO_ACC); | ||||||
|  | +	while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) | ||||||
|  |  		; | ||||||
|  | -	val = ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_VAL_MASK; | ||||||
|  | +	val = ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_VAL_MASK; | ||||||
|  |  	return val; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -357,8 +538,18 @@ ltq_etop_mdio_probe(struct net_device *d | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  |  	struct phy_device *phydev; | ||||||
|  | +	u32 phy_supported =  (SUPPORTED_10baseT_Half | ||||||
|  | +			| SUPPORTED_10baseT_Full | ||||||
|  | +			| SUPPORTED_100baseT_Half | ||||||
|  | +			| SUPPORTED_100baseT_Full | ||||||
|  | +			| SUPPORTED_Autoneg | ||||||
|  | +			| SUPPORTED_MII | ||||||
|  | +			| SUPPORTED_TP); | ||||||
|  |   | ||||||
|  | -	phydev = phy_find_first(priv->mii_bus); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ase")) | ||||||
|  | +		phydev = mdiobus_get_phy(priv->mii_bus, 8); | ||||||
|  | +	else | ||||||
|  | +		phydev = mdiobus_get_phy(priv->mii_bus, 0); | ||||||
|  |   | ||||||
|  |  	if (!phydev) { | ||||||
|  |  		netdev_err(dev, "no PHY found\n"); | ||||||
|  | @@ -366,21 +557,18 @@ ltq_etop_mdio_probe(struct net_device *d | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	phydev = phy_connect(dev, phydev_name(phydev), | ||||||
|  | -			     <q_etop_mdio_link, priv->pldata->mii_mode); | ||||||
|  | +			     <q_etop_mdio_link, priv->mii_mode); | ||||||
|  |   | ||||||
|  |  	if (IS_ERR(phydev)) { | ||||||
|  |  		netdev_err(dev, "Could not attach to PHY\n"); | ||||||
|  |  		return PTR_ERR(phydev); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	phydev->supported &= (SUPPORTED_10baseT_Half | ||||||
|  | -			      | SUPPORTED_10baseT_Full | ||||||
|  | -			      | SUPPORTED_100baseT_Half | ||||||
|  | -			      | SUPPORTED_100baseT_Full | ||||||
|  | -			      | SUPPORTED_Autoneg | ||||||
|  | -			      | SUPPORTED_MII | ||||||
|  | -			      | SUPPORTED_TP); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) | ||||||
|  | +		phy_supported |= SUPPORTED_1000baseT_Half | ||||||
|  | +			| SUPPORTED_1000baseT_Full; | ||||||
|  |   | ||||||
|  | +	phydev->supported &= phy_supported; | ||||||
|  |  	phydev->advertising = phydev->supported; | ||||||
|  |  	phy_attached_info(phydev); | ||||||
|  |   | ||||||
|  | @@ -401,8 +589,13 @@ ltq_etop_mdio_init(struct net_device *de | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	priv->mii_bus->priv = dev; | ||||||
|  | -	priv->mii_bus->read = ltq_etop_mdio_rd; | ||||||
|  | -	priv->mii_bus->write = ltq_etop_mdio_wr; | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		priv->mii_bus->read = ltq_etop_mdio_rd_xr9; | ||||||
|  | +		priv->mii_bus->write = ltq_etop_mdio_wr_xr9; | ||||||
|  | +	} else { | ||||||
|  | +		priv->mii_bus->read = ltq_etop_mdio_rd; | ||||||
|  | +		priv->mii_bus->write = ltq_etop_mdio_wr; | ||||||
|  | +	} | ||||||
|  |  	priv->mii_bus->name = "ltq_mii"; | ||||||
|  |  	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", | ||||||
|  |  		priv->pdev->name, priv->pdev->id); | ||||||
|  | @@ -439,17 +632,19 @@ static int | ||||||
|  |  ltq_etop_open(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int i; | ||||||
|  | +	unsigned long flags; | ||||||
|  |   | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) { | ||||||
|  | -		struct ltq_etop_chan *ch = &priv->ch[i]; | ||||||
|  | +	napi_enable(&priv->txch.napi); | ||||||
|  | +	napi_enable(&priv->rxch.napi); | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  | +	ltq_dma_open(&priv->txch.dma); | ||||||
|  | +	ltq_dma_open(&priv->rxch.dma); | ||||||
|  | +	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  | + | ||||||
|  | +	if (dev->phydev) | ||||||
|  | +		phy_start(dev->phydev); | ||||||
|  |   | ||||||
|  | -		if (!IS_TX(i) && (!IS_RX(i))) | ||||||
|  | -			continue; | ||||||
|  | -		ltq_dma_open(&ch->dma); | ||||||
|  | -		napi_enable(&ch->napi); | ||||||
|  | -	} | ||||||
|  | -	phy_start(dev->phydev); | ||||||
|  |  	netif_tx_start_all_queues(dev); | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | @@ -458,18 +653,19 @@ static int | ||||||
|  |  ltq_etop_stop(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	int i; | ||||||
|  | +	unsigned long flags; | ||||||
|  |   | ||||||
|  |  	netif_tx_stop_all_queues(dev); | ||||||
|  | -	phy_stop(dev->phydev); | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) { | ||||||
|  | -		struct ltq_etop_chan *ch = &priv->ch[i]; | ||||||
|  | - | ||||||
|  | -		if (!IS_RX(i) && !IS_TX(i)) | ||||||
|  | -			continue; | ||||||
|  | -		napi_disable(&ch->napi); | ||||||
|  | -		ltq_dma_close(&ch->dma); | ||||||
|  | -	} | ||||||
|  | +	if (dev->phydev) | ||||||
|  | +		phy_stop(dev->phydev); | ||||||
|  | +	napi_disable(&priv->txch.napi); | ||||||
|  | +	napi_disable(&priv->rxch.napi); | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&priv->lock, flags); | ||||||
|  | +	ltq_dma_close(&priv->txch.dma); | ||||||
|  | +	ltq_dma_close(&priv->rxch.dma); | ||||||
|  | +	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  | + | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -479,16 +675,16 @@ ltq_etop_tx(struct sk_buff *skb, struct | ||||||
|  |  	int queue = skb_get_queue_mapping(skb); | ||||||
|  |  	struct netdev_queue *txq = netdev_get_tx_queue(dev, queue); | ||||||
|  |  	struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  | -	struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1]; | ||||||
|  | -	struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc]; | ||||||
|  | -	int len; | ||||||
|  | +	struct ltq_dma_desc *desc = | ||||||
|  | +		&priv->txch.dma.desc_base[priv->txch.dma.desc]; | ||||||
|  |  	unsigned long flags; | ||||||
|  |  	u32 byte_offset; | ||||||
|  | +	int len; | ||||||
|  |   | ||||||
|  |  	len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; | ||||||
|  |   | ||||||
|  | -	if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) { | ||||||
|  | -		dev_kfree_skb_any(skb); | ||||||
|  | +	if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || | ||||||
|  | +			priv->txch.skb[priv->txch.dma.desc]) { | ||||||
|  |  		netdev_err(dev, "tx ring full\n"); | ||||||
|  |  		netif_tx_stop_queue(txq); | ||||||
|  |  		return NETDEV_TX_BUSY; | ||||||
|  | @@ -496,7 +692,7 @@ ltq_etop_tx(struct sk_buff *skb, struct | ||||||
|  |   | ||||||
|  |  	/* dma needs to start on a 16 byte aligned address */ | ||||||
|  |  	byte_offset = CPHYSADDR(skb->data) % 16; | ||||||
|  | -	ch->skb[ch->dma.desc] = skb; | ||||||
|  | +	priv->txch.skb[priv->txch.dma.desc] = skb; | ||||||
|  |   | ||||||
|  |  	netif_trans_update(dev); | ||||||
|  |   | ||||||
|  | @@ -506,11 +702,11 @@ ltq_etop_tx(struct sk_buff *skb, struct | ||||||
|  |  	wmb(); | ||||||
|  |  	desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP | | ||||||
|  |  		LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK); | ||||||
|  | -	ch->dma.desc++; | ||||||
|  | -	ch->dma.desc %= LTQ_DESC_NUM; | ||||||
|  | +	priv->txch.dma.desc++; | ||||||
|  | +	priv->txch.dma.desc %= LTQ_DESC_NUM; | ||||||
|  |  	spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |   | ||||||
|  | -	if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN) | ||||||
|  | +	if (priv->txch.dma.desc_base[priv->txch.dma.desc].ctl & LTQ_DMA_OWN) | ||||||
|  |  		netif_tx_stop_queue(txq); | ||||||
|  |   | ||||||
|  |  	return NETDEV_TX_OK; | ||||||
|  | @@ -525,8 +721,10 @@ ltq_etop_change_mtu(struct net_device *d | ||||||
|  |  		struct ltq_etop_priv *priv = netdev_priv(dev); | ||||||
|  |  		unsigned long flags; | ||||||
|  |   | ||||||
|  | +		int max = ETH_HLEN + VLAN_HLEN + new_mtu + ETH_FCS_LEN; | ||||||
|  | + | ||||||
|  |  		spin_lock_irqsave(&priv->lock, flags); | ||||||
|  | -		ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu, | ||||||
|  | +		ltq_etop_w32((ETOP_PLEN_UNDER << 16) | max, | ||||||
|  |  			LTQ_ETOP_IGPLEN); | ||||||
|  |  		spin_unlock_irqrestore(&priv->lock, flags); | ||||||
|  |  	} | ||||||
|  | @@ -595,6 +793,9 @@ ltq_etop_init(struct net_device *dev) | ||||||
|  |  	if (err) | ||||||
|  |  		goto err_hw; | ||||||
|  |  	ltq_etop_change_mtu(dev, 1500); | ||||||
|  | +	err = ltq_etop_dma_init(dev); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_hw; | ||||||
|  |   | ||||||
|  |  	memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr)); | ||||||
|  |  	if (!is_valid_ether_addr(mac.sa_data)) { | ||||||
|  | @@ -612,9 +813,10 @@ ltq_etop_init(struct net_device *dev) | ||||||
|  |  		dev->addr_assign_type = NET_ADDR_RANDOM; | ||||||
|  |   | ||||||
|  |  	ltq_etop_set_multicast_list(dev); | ||||||
|  | -	err = ltq_etop_mdio_init(dev); | ||||||
|  | -	if (err) | ||||||
|  | -		goto err_netdev; | ||||||
|  | +	if (!ltq_etop_mdio_init(dev)) | ||||||
|  | +		dev->ethtool_ops = <q_etop_ethtool_ops; | ||||||
|  | +	else | ||||||
|  | +		pr_warn("etop: mdio probe failed\n");; | ||||||
|  |  	return 0; | ||||||
|  |   | ||||||
|  |  err_netdev: | ||||||
|  | @@ -634,6 +836,9 @@ ltq_etop_tx_timeout(struct net_device *d | ||||||
|  |  	err = ltq_etop_hw_init(dev); | ||||||
|  |  	if (err) | ||||||
|  |  		goto err_hw; | ||||||
|  | +	err = ltq_etop_dma_init(dev); | ||||||
|  | +	if (err) | ||||||
|  | +		goto err_hw; | ||||||
|  |  	netif_trans_update(dev); | ||||||
|  |  	netif_wake_queue(dev); | ||||||
|  |  	return; | ||||||
|  | @@ -657,14 +862,19 @@ static const struct net_device_ops ltq_e | ||||||
|  |  	.ndo_tx_timeout = ltq_etop_tx_timeout, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | -static int __init | ||||||
|  | -ltq_etop_probe(struct platform_device *pdev) | ||||||
|  | +static int ltq_etop_probe(struct platform_device *pdev) | ||||||
|  |  { | ||||||
|  |  	struct net_device *dev; | ||||||
|  |  	struct ltq_etop_priv *priv; | ||||||
|  | -	struct resource *res; | ||||||
|  | +	struct resource *res, *gbit_res, irqres[2]; | ||||||
|  | +	const u8 *mac; | ||||||
|  |  	int err; | ||||||
|  | -	int i; | ||||||
|  | + | ||||||
|  | +	err = of_irq_to_resource_table(pdev->dev.of_node, irqres, 2); | ||||||
|  | +	if (err != 2) { | ||||||
|  | +		dev_err(&pdev->dev, "failed to get etop irqs\n"); | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  |  	if (!res) { | ||||||
|  | @@ -690,31 +900,62 @@ ltq_etop_probe(struct platform_device *p | ||||||
|  |  		goto err_out; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4); | ||||||
|  | -	if (!dev) { | ||||||
|  | -		err = -ENOMEM; | ||||||
|  | -		goto err_out; | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		gbit_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||||||
|  | +		if (!gbit_res) { | ||||||
|  | +			dev_err(&pdev->dev, "failed to get gbit resource\n"); | ||||||
|  | +			err = -ENOENT; | ||||||
|  | +			goto err_out; | ||||||
|  | +		} | ||||||
|  | +		ltq_gbit_membase = devm_ioremap_nocache(&pdev->dev, | ||||||
|  | +			gbit_res->start, resource_size(gbit_res)); | ||||||
|  | +		if (!ltq_gbit_membase) { | ||||||
|  | +			dev_err(&pdev->dev, "failed to remap gigabit switch %d\n", | ||||||
|  | +				pdev->id); | ||||||
|  | +			err = -ENOMEM; | ||||||
|  | +			goto err_out; | ||||||
|  | +		} | ||||||
|  |  	} | ||||||
|  | + | ||||||
|  | +	dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4); | ||||||
|  |  	strcpy(dev->name, "eth%d"); | ||||||
|  |  	dev->netdev_ops = <q_eth_netdev_ops; | ||||||
|  | -	dev->ethtool_ops = <q_etop_ethtool_ops; | ||||||
|  |  	priv = netdev_priv(dev); | ||||||
|  |  	priv->res = res; | ||||||
|  |  	priv->pdev = pdev; | ||||||
|  | -	priv->pldata = dev_get_platdata(&pdev->dev); | ||||||
|  |  	priv->netdev = dev; | ||||||
|  | +	priv->tx_irq = irqres[0].start; | ||||||
|  | +	priv->rx_irq = irqres[1].start; | ||||||
|  | +	priv->mii_mode = of_get_phy_mode(pdev->dev.of_node); | ||||||
|  | + | ||||||
|  | +	mac = of_get_mac_address(pdev->dev.of_node); | ||||||
|  | +	if (mac) | ||||||
|  | +		memcpy(priv->mac, mac, ETH_ALEN); | ||||||
|  | + | ||||||
|  | +	priv->clk_ppe = clk_get(&pdev->dev, NULL); | ||||||
|  | +	if (IS_ERR(priv->clk_ppe)) | ||||||
|  | +		return PTR_ERR(priv->clk_ppe); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		priv->clk_switch = clk_get(&pdev->dev, "switch"); | ||||||
|  | +		if (IS_ERR(priv->clk_switch)) | ||||||
|  | +			return PTR_ERR(priv->clk_switch); | ||||||
|  | +	} | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ase")) { | ||||||
|  | +		priv->clk_ephy = clk_get(&pdev->dev, "ephy"); | ||||||
|  | +		if (IS_ERR(priv->clk_ephy)) | ||||||
|  | +			return PTR_ERR(priv->clk_ephy); | ||||||
|  | +		priv->clk_ephycgu = clk_get(&pdev->dev, "ephycgu"); | ||||||
|  | +		if (IS_ERR(priv->clk_ephycgu)) | ||||||
|  | +			return PTR_ERR(priv->clk_ephycgu); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	spin_lock_init(&priv->lock); | ||||||
|  |  	SET_NETDEV_DEV(dev, &pdev->dev); | ||||||
|  |   | ||||||
|  | -	for (i = 0; i < MAX_DMA_CHAN; i++) { | ||||||
|  | -		if (IS_TX(i)) | ||||||
|  | -			netif_napi_add(dev, &priv->ch[i].napi, | ||||||
|  | -				ltq_etop_poll_tx, 8); | ||||||
|  | -		else if (IS_RX(i)) | ||||||
|  | -			netif_napi_add(dev, &priv->ch[i].napi, | ||||||
|  | -				ltq_etop_poll_rx, 32); | ||||||
|  | -		priv->ch[i].netdev = dev; | ||||||
|  | -	} | ||||||
|  | +	netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8); | ||||||
|  | +	netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32); | ||||||
|  | +	priv->txch.netdev = dev; | ||||||
|  | +	priv->rxch.netdev = dev; | ||||||
|  |   | ||||||
|  |  	err = register_netdev(dev); | ||||||
|  |  	if (err) | ||||||
|  | @@ -743,31 +984,22 @@ ltq_etop_remove(struct platform_device * | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static const struct of_device_id ltq_etop_match[] = { | ||||||
|  | +	{ .compatible = "lantiq,etop-xway" }, | ||||||
|  | +	{}, | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, ltq_etop_match); | ||||||
|  | + | ||||||
|  |  static struct platform_driver ltq_mii_driver = { | ||||||
|  | +	.probe = ltq_etop_probe, | ||||||
|  |  	.remove = ltq_etop_remove, | ||||||
|  |  	.driver = { | ||||||
|  |  		.name = "ltq_etop", | ||||||
|  | +		.of_match_table = ltq_etop_match, | ||||||
|  |  	}, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | -int __init | ||||||
|  | -init_ltq_etop(void) | ||||||
|  | -{ | ||||||
|  | -	int ret = platform_driver_probe(<q_mii_driver, ltq_etop_probe); | ||||||
|  | - | ||||||
|  | -	if (ret) | ||||||
|  | -		pr_err("ltq_etop: Error registering platform driver!"); | ||||||
|  | -	return ret; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static void __exit | ||||||
|  | -exit_ltq_etop(void) | ||||||
|  | -{ | ||||||
|  | -	platform_driver_unregister(<q_mii_driver); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -module_init(init_ltq_etop); | ||||||
|  | -module_exit(exit_ltq_etop); | ||||||
|  | +module_platform_driver(ltq_mii_driver); | ||||||
|  |   | ||||||
|  |  MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | ||||||
|  |  MODULE_DESCRIPTION("Lantiq SoC ETOP"); | ||||||
| @@ -0,0 +1,170 @@ | |||||||
|  | From cc809a441d8f2924f785eb863dfa6aef47a25b0b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Tue, 12 Aug 2014 20:49:27 +0200 | ||||||
|  | Subject: [PATCH 30/36] GPIO: add named gpio exports | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  drivers/gpio/gpiolib-of.c     |   68 +++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  drivers/gpio/gpiolib.c        |   11 +++++-- | ||||||
|  |  include/asm-generic/gpio.h    |    5 +++ | ||||||
|  |  include/linux/gpio/consumer.h |    8 +++++ | ||||||
|  |  4 files changed, 90 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/gpio/gpiolib-of.c | ||||||
|  | +++ b/drivers/gpio/gpiolib-of.c | ||||||
|  | @@ -23,6 +23,8 @@ | ||||||
|  |  #include <linux/pinctrl/pinctrl.h> | ||||||
|  |  #include <linux/slab.h> | ||||||
|  |  #include <linux/gpio/machine.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  |   | ||||||
|  |  #include "gpiolib.h" | ||||||
|  |   | ||||||
|  | @@ -538,3 +540,73 @@ void of_gpiochip_remove(struct gpio_chip | ||||||
|  |  	gpiochip_remove_pin_ranges(chip); | ||||||
|  |  	of_node_put(chip->of_node); | ||||||
|  |  } | ||||||
|  | + | ||||||
|  | +#ifdef CONFIG_GPIO_SYSFS | ||||||
|  | + | ||||||
|  | +static struct of_device_id gpio_export_ids[] = { | ||||||
|  | +	{ .compatible = "gpio-export" }, | ||||||
|  | +	{ /* sentinel */ } | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int __init of_gpio_export_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct device_node *np = pdev->dev.of_node; | ||||||
|  | +	struct device_node *cnp; | ||||||
|  | +	u32 val; | ||||||
|  | +	int nb = 0; | ||||||
|  | + | ||||||
|  | +	for_each_child_of_node(np, cnp) { | ||||||
|  | +		const char *name = NULL; | ||||||
|  | +		int gpio; | ||||||
|  | +		bool dmc; | ||||||
|  | +		int max_gpio = 1; | ||||||
|  | +		int i; | ||||||
|  | + | ||||||
|  | +		of_property_read_string(cnp, "gpio-export,name", &name); | ||||||
|  | + | ||||||
|  | +		if (!name) | ||||||
|  | +			max_gpio = of_gpio_count(cnp); | ||||||
|  | + | ||||||
|  | +		for (i = 0; i < max_gpio; i++) { | ||||||
|  | +			unsigned flags = 0; | ||||||
|  | +			enum of_gpio_flags of_flags; | ||||||
|  | + | ||||||
|  | +			gpio = of_get_gpio_flags(cnp, i, &of_flags); | ||||||
|  | + | ||||||
|  | +			if (of_flags == OF_GPIO_ACTIVE_LOW) | ||||||
|  | +				flags |= GPIOF_ACTIVE_LOW; | ||||||
|  | + | ||||||
|  | +			if (!of_property_read_u32(cnp, "gpio-export,output", &val)) | ||||||
|  | +				flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; | ||||||
|  | +			else | ||||||
|  | +				flags |= GPIOF_IN; | ||||||
|  | + | ||||||
|  | +			if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) | ||||||
|  | +				continue; | ||||||
|  | + | ||||||
|  | +			dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); | ||||||
|  | +			gpio_export_with_name(gpio, dmc, name); | ||||||
|  | +			nb++; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver gpio_export_driver = { | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name		= "gpio-export", | ||||||
|  | +		.owner	= THIS_MODULE, | ||||||
|  | +		.of_match_table	= of_match_ptr(gpio_export_ids), | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int __init of_gpio_export_init(void) | ||||||
|  | +{ | ||||||
|  | +	return platform_driver_probe(&gpio_export_driver, of_gpio_export_probe); | ||||||
|  | +} | ||||||
|  | +device_initcall(of_gpio_export_init); | ||||||
|  | + | ||||||
|  | +#endif | ||||||
|  | --- a/include/asm-generic/gpio.h | ||||||
|  | +++ b/include/asm-generic/gpio.h | ||||||
|  | @@ -126,6 +126,12 @@ static inline int gpio_export(unsigned g | ||||||
|  |  	return gpiod_export(gpio_to_desc(gpio), direction_may_change); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); | ||||||
|  | +static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) | ||||||
|  | +{ | ||||||
|  | +	return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static inline int gpio_export_link(struct device *dev, const char *name, | ||||||
|  |  				   unsigned gpio) | ||||||
|  |  { | ||||||
|  | --- a/include/linux/gpio/consumer.h | ||||||
|  | +++ b/include/linux/gpio/consumer.h | ||||||
|  | @@ -427,6 +427,7 @@ static inline struct gpio_desc *devm_get | ||||||
|  |   | ||||||
|  |  #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) | ||||||
|  |   | ||||||
|  | +int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); | ||||||
|  |  int gpiod_export(struct gpio_desc *desc, bool direction_may_change); | ||||||
|  |  int gpiod_export_link(struct device *dev, const char *name, | ||||||
|  |  		      struct gpio_desc *desc); | ||||||
|  | @@ -434,6 +435,13 @@ void gpiod_unexport(struct gpio_desc *de | ||||||
|  |   | ||||||
|  |  #else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ | ||||||
|  |   | ||||||
|  | +static inline int _gpiod_export(struct gpio_desc *desc, | ||||||
|  | +			       bool direction_may_change, | ||||||
|  | +			       const char *name) | ||||||
|  | +{ | ||||||
|  | +	return -ENOSYS; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static inline int gpiod_export(struct gpio_desc *desc, | ||||||
|  |  			       bool direction_may_change) | ||||||
|  |  { | ||||||
|  | --- a/drivers/gpio/gpiolib-sysfs.c | ||||||
|  | +++ b/drivers/gpio/gpiolib-sysfs.c | ||||||
|  | @@ -544,7 +544,7 @@ static struct class gpio_class = { | ||||||
|  |   * | ||||||
|  |   * Returns zero on success, else an error. | ||||||
|  |   */ | ||||||
|  | -int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | ||||||
|  | +int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) | ||||||
|  |  { | ||||||
|  |  	struct gpio_chip	*chip; | ||||||
|  |  	struct gpio_device	*gdev; | ||||||
|  | @@ -606,6 +606,8 @@ int gpiod_export(struct gpio_desc *desc, | ||||||
|  |  	offset = gpio_chip_hwgpio(desc); | ||||||
|  |  	if (chip->names && chip->names[offset]) | ||||||
|  |  		ioname = chip->names[offset]; | ||||||
|  | +	if (name) | ||||||
|  | +		ioname = name; | ||||||
|  |   | ||||||
|  |  	dev = device_create_with_groups(&gpio_class, &gdev->dev, | ||||||
|  |  					MKDEV(0, 0), data, gpio_groups, | ||||||
|  | @@ -627,6 +629,12 @@ err_unlock: | ||||||
|  |  	gpiod_dbg(desc, "%s: status %d\n", __func__, status); | ||||||
|  |  	return status; | ||||||
|  |  } | ||||||
|  | +EXPORT_SYMBOL_GPL(__gpiod_export); | ||||||
|  | + | ||||||
|  | +int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | ||||||
|  | +{ | ||||||
|  | +	return __gpiod_export(desc, direction_may_change, NULL); | ||||||
|  | +} | ||||||
|  |  EXPORT_SYMBOL_GPL(gpiod_export); | ||||||
|  |   | ||||||
|  |  static int match_export(struct device *dev, const void *desc) | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,219 @@ | |||||||
|  | From f8c5db89e793a4bc6c1e87bd7b3a5cec16b75bc3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <blogic@openwrt.org> | ||||||
|  | Date: Wed, 10 Sep 2014 22:42:14 +0200 | ||||||
|  | Subject: [PATCH 35/36] owrt: lantiq: wifi and ethernet eeprom handling | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <blogic@openwrt.org> | ||||||
|  | --- | ||||||
|  |  .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |   3 + | ||||||
|  |  arch/mips/lantiq/xway/Makefile                     |   3 + | ||||||
|  |  arch/mips/lantiq/xway/ath5k_eep.c                  | 136 +++++++++++++++++++++ | ||||||
|  |  arch/mips/lantiq/xway/eth_mac.c                    |  25 ++++ | ||||||
|  |  drivers/net/ethernet/lantiq_etop.c                 |   6 +- | ||||||
|  |  5 files changed, 172 insertions(+), 1 deletion(-) | ||||||
|  |  create mode 100644 arch/mips/lantiq/xway/ath5k_eep.c | ||||||
|  |  create mode 100644 arch/mips/lantiq/xway/eth_mac.c | ||||||
|  |  | ||||||
|  | --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h | ||||||
|  | @@ -104,5 +104,8 @@ int xrx200_gphy_boot(struct device *dev, | ||||||
|  |  extern void ltq_pmu_enable(unsigned int module); | ||||||
|  |  extern void ltq_pmu_disable(unsigned int module); | ||||||
|  |   | ||||||
|  | +/* allow the ethernet driver to load a flash mapped mac addr */ | ||||||
|  | +const u8* ltq_get_eth_mac(void); | ||||||
|  | + | ||||||
|  |  #endif /* CONFIG_SOC_TYPE_XWAY */ | ||||||
|  |  #endif /* _LTQ_XWAY_H__ */ | ||||||
|  | --- a/arch/mips/lantiq/xway/Makefile | ||||||
|  | +++ b/arch/mips/lantiq/xway/Makefile | ||||||
|  | @@ -2,4 +2,7 @@ obj-y := prom.o sysctrl.o clk.o reset.o | ||||||
|  |   | ||||||
|  |  obj-y += vmmc.o tffs.o | ||||||
|  |   | ||||||
|  | +obj-y += eth_mac.o | ||||||
|  | +obj-$(CONFIG_PCI) += ath5k_eep.o | ||||||
|  | + | ||||||
|  |  obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/lantiq/xway/ath5k_eep.c | ||||||
|  | @@ -0,0 +1,136 @@ | ||||||
|  | +/* | ||||||
|  | + *  Copyright (C) 2011 Luca Olivetti <luca@ventoso.org> | ||||||
|  | + *  Copyright (C) 2011 John Crispin <blogic@openwrt.org> | ||||||
|  | + *  Copyright (C) 2011 Andrej Vlašić <andrej.vlasic0@gmail.com> | ||||||
|  | + *  Copyright (C) 2013 Álvaro Fernández Rojas <noltari@gmail.com> | ||||||
|  | + *  Copyright (C) 2013 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us> | ||||||
|  | + *  Copyright (C) 2015 Vittorio Gambaletta <openwrt@vittgam.net> | ||||||
|  | + * | ||||||
|  | + *  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/platform_device.h> | ||||||
|  | +#include <linux/etherdevice.h> | ||||||
|  | +#include <linux/ath5k_platform.h> | ||||||
|  | +#include <linux/pci.h> | ||||||
|  | +#include <linux/err.h> | ||||||
|  | +#include <linux/mtd/mtd.h> | ||||||
|  | +#include <lantiq_soc.h> | ||||||
|  | + | ||||||
|  | +extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev); | ||||||
|  | +struct ath5k_platform_data ath5k_pdata; | ||||||
|  | +static u8 athxk_eeprom_mac[6]; | ||||||
|  | + | ||||||
|  | +static int ath5k_pci_plat_dev_init(struct pci_dev *dev) | ||||||
|  | +{ | ||||||
|  | +	dev->dev.platform_data = &ath5k_pdata; | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int ath5k_eep_load; | ||||||
|  | +int __init of_ath5k_eeprom_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct device_node *np = pdev->dev.of_node, *mtd_np = NULL; | ||||||
|  | +	int mac_offset; | ||||||
|  | +	u32 mac_inc = 0; | ||||||
|  | +	int i; | ||||||
|  | +	struct mtd_info *the_mtd; | ||||||
|  | +	size_t flash_readlen; | ||||||
|  | +	const __be32 *list; | ||||||
|  | +	const char *part; | ||||||
|  | +	phandle phandle; | ||||||
|  | + | ||||||
|  | +	list = of_get_property(np, "ath,eep-flash", &i); | ||||||
|  | +	if (!list || (i != (2 * sizeof(*list)))) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	phandle = be32_to_cpup(list++); | ||||||
|  | +	if (phandle) | ||||||
|  | +		mtd_np = of_find_node_by_phandle(phandle); | ||||||
|  | + | ||||||
|  | +	if (!mtd_np) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	part = of_get_property(mtd_np, "label", NULL); | ||||||
|  | +	if (!part) | ||||||
|  | +		part = mtd_np->name; | ||||||
|  | + | ||||||
|  | +	the_mtd = get_mtd_device_nm(part); | ||||||
|  | +	if (IS_ERR(the_mtd)) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	ath5k_pdata.eeprom_data = kmalloc(ATH5K_PLAT_EEP_MAX_WORDS<<1, GFP_KERNEL); | ||||||
|  | + | ||||||
|  | +	i = mtd_read(the_mtd, be32_to_cpup(list), ATH5K_PLAT_EEP_MAX_WORDS << 1, | ||||||
|  | +		&flash_readlen, (void *) ath5k_pdata.eeprom_data); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) { | ||||||
|  | +		size_t mac_readlen; | ||||||
|  | +		mtd_read(the_mtd, mac_offset, 6, &mac_readlen, | ||||||
|  | +			(void *) athxk_eeprom_mac); | ||||||
|  | +	} | ||||||
|  | +	put_mtd_device(the_mtd); | ||||||
|  | + | ||||||
|  | +	if (((ATH5K_PLAT_EEP_MAX_WORDS<<1) != flash_readlen) || i) { | ||||||
|  | +		dev_err(&pdev->dev, "failed to load eeprom from mtd\n"); | ||||||
|  | +		return -ENODEV; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (of_find_property(np, "ath,eep-swap", NULL)) | ||||||
|  | +		for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS; i++) | ||||||
|  | +			ath5k_pdata.eeprom_data[i] = swab16(ath5k_pdata.eeprom_data[i]); | ||||||
|  | + | ||||||
|  | +	if (!is_valid_ether_addr(athxk_eeprom_mac) && ltq_get_eth_mac()) | ||||||
|  | +		ether_addr_copy(athxk_eeprom_mac, ltq_get_eth_mac()); | ||||||
|  | + | ||||||
|  | +	if (!is_valid_ether_addr(athxk_eeprom_mac)) { | ||||||
|  | +		dev_warn(&pdev->dev, "using random mac\n"); | ||||||
|  | +		random_ether_addr(athxk_eeprom_mac); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc)) | ||||||
|  | +		athxk_eeprom_mac[5] += mac_inc; | ||||||
|  | + | ||||||
|  | +	ath5k_pdata.macaddr = athxk_eeprom_mac; | ||||||
|  | +	ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init; | ||||||
|  | + | ||||||
|  | +	dev_info(&pdev->dev, "loaded ath5k eeprom\n"); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct of_device_id ath5k_eeprom_ids[] = { | ||||||
|  | +	{ .compatible = "ath5k,eeprom" }, | ||||||
|  | +	{ } | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct platform_driver ath5k_eeprom_driver = { | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name		= "ath5k,eeprom", | ||||||
|  | +		.owner	= THIS_MODULE, | ||||||
|  | +		.of_match_table	= of_match_ptr(ath5k_eeprom_ids), | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int __init of_ath5k_eeprom_init(void) | ||||||
|  | +{ | ||||||
|  | +	int ret = platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe); | ||||||
|  | + | ||||||
|  | +	if (ret) | ||||||
|  | +		ath5k_eep_load = 1; | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __init of_ath5k_eeprom_init_late(void) | ||||||
|  | +{ | ||||||
|  | +	if (!ath5k_eep_load) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe); | ||||||
|  | +} | ||||||
|  | +late_initcall(of_ath5k_eeprom_init_late); | ||||||
|  | +subsys_initcall(of_ath5k_eeprom_init); | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/lantiq/xway/eth_mac.c | ||||||
|  | @@ -0,0 +1,25 @@ | ||||||
|  | +/* | ||||||
|  | + *  Copyright (C) 2012 John Crispin <blogic@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. | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/if_ether.h> | ||||||
|  | + | ||||||
|  | +static u8 eth_mac[6]; | ||||||
|  | +static int eth_mac_set; | ||||||
|  | + | ||||||
|  | +const u8* ltq_get_eth_mac(void) | ||||||
|  | +{ | ||||||
|  | +	return eth_mac; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __init setup_ethaddr(char *str) | ||||||
|  | +{ | ||||||
|  | +	eth_mac_set = mac_pton(str, eth_mac); | ||||||
|  | +	return !eth_mac_set; | ||||||
|  | +} | ||||||
|  | +early_param("ethaddr", setup_ethaddr); | ||||||
|  | --- a/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | +++ b/drivers/net/ethernet/lantiq_etop.c | ||||||
|  | @@ -797,7 +797,11 @@ ltq_etop_init(struct net_device *dev) | ||||||
|  |  	if (err) | ||||||
|  |  		goto err_hw; | ||||||
|  |   | ||||||
|  | -	memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr)); | ||||||
|  | +	memcpy(&mac.sa_data, ltq_get_eth_mac(), ETH_ALEN); | ||||||
|  | + | ||||||
|  | +	if (priv->mac && !is_valid_ether_addr(mac.sa_data)) | ||||||
|  | +		memcpy(&mac.sa_data, priv->mac, ETH_ALEN); | ||||||
|  | + | ||||||
|  |  	if (!is_valid_ether_addr(mac.sa_data)) { | ||||||
|  |  		pr_warn("etop: invalid MAC, using random\n"); | ||||||
|  |  		eth_random_addr(mac.sa_data); | ||||||
| @@ -0,0 +1,35 @@ | |||||||
|  | --- a/drivers/usb/dwc2/platform.c | ||||||
|  | +++ b/drivers/usb/dwc2/platform.c | ||||||
|  | @@ -42,6 +42,7 @@ | ||||||
|  |  #include <linux/dma-mapping.h> | ||||||
|  |  #include <linux/of_device.h> | ||||||
|  |  #include <linux/mutex.h> | ||||||
|  | +#include <linux/of_gpio.h> | ||||||
|  |  #include <linux/platform_device.h> | ||||||
|  |  #include <linux/phy/phy.h> | ||||||
|  |  #include <linux/platform_data/s3c-hsotg.h> | ||||||
|  | @@ -544,6 +545,7 @@ static int dwc2_driver_probe(struct plat | ||||||
|  |  	struct dwc2_hsotg *hsotg; | ||||||
|  |  	struct resource *res; | ||||||
|  |  	int retval; | ||||||
|  | +	int gpio_count;	 | ||||||
|  |   | ||||||
|  |  	match = of_match_device(dwc2_of_match_table, &dev->dev); | ||||||
|  |  	if (match && match->data) { | ||||||
|  | @@ -562,6 +564,16 @@ static int dwc2_driver_probe(struct plat | ||||||
|  |  		defparams.dma_desc_fs_enable = 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	gpio_count = of_gpio_count(dev->dev.of_node); | ||||||
|  | +	while (gpio_count > 0) { | ||||||
|  | +		enum of_gpio_flags flags; | ||||||
|  | +		int gpio = of_get_gpio_flags(dev->dev.of_node, --gpio_count, &flags); | ||||||
|  | +		if (gpio_request(gpio, "usb")) | ||||||
|  | +			continue; | ||||||
|  | +		dev_info(&dev->dev, "requested GPIO %d\n", gpio); | ||||||
|  | +		gpio_direction_output(gpio, (flags & OF_GPIO_ACTIVE_LOW) ? (0) : (1)); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); | ||||||
|  |  	if (!hsotg) | ||||||
|  |  		return -ENOMEM; | ||||||
| @@ -0,0 +1,23 @@ | |||||||
|  | From 9807eb80a1b3bad7a4a89aa6566497bb1cadd6ef Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Fri, 3 Jun 2016 13:12:20 +0200 | ||||||
|  | Subject: [PATCH] arch: mips: increase io_space_limit | ||||||
|  |  | ||||||
|  | this value comes from x86 and breaks some pci devices | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | --- | ||||||
|  |  arch/mips/include/asm/io.h |    2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/arch/mips/include/asm/io.h | ||||||
|  | +++ b/arch/mips/include/asm/io.h | ||||||
|  | @@ -50,7 +50,7 @@ | ||||||
|  |   | ||||||
|  |  /* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */ | ||||||
|  |   | ||||||
|  | -#define IO_SPACE_LIMIT 0xffff | ||||||
|  | +#define IO_SPACE_LIMIT 0xffffffff | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  |   * On MIPS I/O ports are memory mapped, so we access them using normal | ||||||
							
								
								
									
										23
									
								
								target/linux/lantiq/patches-4.9/0047-poweroff.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								target/linux/lantiq/patches-4.9/0047-poweroff.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | --- a/arch/mips/lantiq/xway/reset.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/reset.c | ||||||
|  | @@ -301,12 +301,6 @@ static void ltq_machine_halt(void) | ||||||
|  |  	unreachable(); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static void ltq_machine_power_off(void) | ||||||
|  | -{ | ||||||
|  | -	local_irq_disable(); | ||||||
|  | -	unreachable(); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static void ltq_usb_init(void) | ||||||
|  |  { | ||||||
|  |  	/* Power for USB cores 1 & 2 */ | ||||||
|  | @@ -379,7 +373,6 @@ static int __init mips_reboot_setup(void | ||||||
|  |   | ||||||
|  |  	_machine_restart = ltq_machine_restart; | ||||||
|  |  	_machine_halt = ltq_machine_halt; | ||||||
|  | -	pm_power_off = ltq_machine_power_off; | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
| @@ -0,0 +1,87 @@ | |||||||
|  | From: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Date: Thu, 19 Jan 2017 12:14:44 +0100 | ||||||
|  | Subject: [PATCH] MIPS: Lantiq: Fix cascaded IRQ setup | ||||||
|  |  | ||||||
|  | With the IRQ stack changes integrated, the XRX200 devices started | ||||||
|  | emitting a constant stream of kernel messages like this: | ||||||
|  |  | ||||||
|  | [  565.415310] Spurious IRQ: CAUSE=0x1100c300 | ||||||
|  |  | ||||||
|  | This appears to be caused by IP0 firing for some reason without being | ||||||
|  | handled. Fix this by setting up IP2-6 as a proper chained IRQ handler and | ||||||
|  | calling do_IRQ for all MIPS CPU interrupts. | ||||||
|  |  | ||||||
|  | Cc: john@phrozen.org | ||||||
|  | Cc: stable@vger.kernel.org | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/arch/mips/lantiq/irq.c | ||||||
|  | +++ b/arch/mips/lantiq/irq.c | ||||||
|  | @@ -271,6 +271,11 @@ static void ltq_hw5_irqdispatch(void) | ||||||
|  |  DEFINE_HWx_IRQDISPATCH(5) | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | +static void ltq_hw_irq_handler(struct irq_desc *desc) | ||||||
|  | +{ | ||||||
|  | +	ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  #ifdef CONFIG_MIPS_MT_SMP | ||||||
|  |  void __init arch_init_ipiirq(int irq, struct irqaction *action) | ||||||
|  |  { | ||||||
|  | @@ -315,23 +320,19 @@ static struct irqaction irq_call = { | ||||||
|  |  asmlinkage void plat_irq_dispatch(void) | ||||||
|  |  { | ||||||
|  |  	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; | ||||||
|  | -	unsigned int i; | ||||||
|  | +	int irq; | ||||||
|  |   | ||||||
|  | -	if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) { | ||||||
|  | -		do_IRQ(MIPS_CPU_TIMER_IRQ); | ||||||
|  | -		goto out; | ||||||
|  | -	} else { | ||||||
|  | -		for (i = 0; i < MAX_IM; i++) { | ||||||
|  | -			if (pending & (CAUSEF_IP2 << i)) { | ||||||
|  | -				ltq_hw_irqdispatch(i); | ||||||
|  | -				goto out; | ||||||
|  | -			} | ||||||
|  | -		} | ||||||
|  | +	if (!pending) { | ||||||
|  | +		spurious_interrupt(); | ||||||
|  | +		return; | ||||||
|  |  	} | ||||||
|  | -	pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status()); | ||||||
|  |   | ||||||
|  | -out: | ||||||
|  | -	return; | ||||||
|  | +	pending >>= CAUSEB_IP; | ||||||
|  | +	while (pending) { | ||||||
|  | +		irq = fls(pending) - 1; | ||||||
|  | +		do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||||||
|  | +		pending &= ~BIT(irq); | ||||||
|  | +	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | ||||||
|  | @@ -356,11 +357,6 @@ static const struct irq_domain_ops irq_d | ||||||
|  |  	.map = icu_map, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | -static struct irqaction cascade = { | ||||||
|  | -	.handler = no_action, | ||||||
|  | -	.name = "cascade", | ||||||
|  | -}; | ||||||
|  | - | ||||||
|  |  int __init icu_of_init(struct device_node *node, struct device_node *parent) | ||||||
|  |  { | ||||||
|  |  	struct device_node *eiu_node; | ||||||
|  | @@ -392,7 +388,7 @@ int __init icu_of_init(struct device_nod | ||||||
|  |  	mips_cpu_irq_init(); | ||||||
|  |   | ||||||
|  |  	for (i = 0; i < MAX_IM; i++) | ||||||
|  | -		setup_irq(i + 2, &cascade); | ||||||
|  | +		irq_set_chained_handler(i + 2, ltq_hw_irq_handler); | ||||||
|  |   | ||||||
|  |  	if (cpu_has_vint) { | ||||||
|  |  		pr_info("Setting up vectored interrupts\n"); | ||||||
| @@ -0,0 +1,99 @@ | |||||||
|  | From de2cad82c4d0872066f83ce59462603852b47f03 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | Date: Fri, 6 Jan 2017 17:55:24 +0100 | ||||||
|  | Subject: [PATCH 2/2] usb: dwc2:  add support for other Lantiq SoCs | ||||||
|  |  | ||||||
|  | The size of the internal RAM of the DesignWare USB controller changed | ||||||
|  | between the different Lantiq SoCs. We have the following sizes: | ||||||
|  |  | ||||||
|  | Amazon + Danube: 8 KByte | ||||||
|  | Amazon SE + arx100: 2 KByte | ||||||
|  | xrx200 + xrx300: 2.5 KByte | ||||||
|  |  | ||||||
|  | For Danube SoC we do not provide the params and let the driver decide | ||||||
|  | to use sane defaults, for the Amazon SE and arx100 we use small fifos | ||||||
|  | and for the xrx200 and xrx300 SCs a little bit bigger periodic fifo. | ||||||
|  | The auto detection of max_transfer_size and max_packet_count should | ||||||
|  | work, so remove it. | ||||||
|  |  | ||||||
|  | Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | --- | ||||||
|  |  drivers/usb/dwc2/platform.c | 46 ++++++++++++++++++++++++++++++++++++++------- | ||||||
|  |  1 file changed, 39 insertions(+), 7 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/usb/dwc2/platform.c | ||||||
|  | +++ b/drivers/usb/dwc2/platform.c | ||||||
|  | @@ -151,7 +151,7 @@ static const struct dwc2_core_params par | ||||||
|  |  	.hibernation			= -1, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | -static const struct dwc2_core_params params_ltq = { | ||||||
|  | +static const struct dwc2_core_params params_ase = { | ||||||
|  |  	.otg_cap			= 2,	/* non-HNP/non-SRP */ | ||||||
|  |  	.otg_ver			= -1, | ||||||
|  |  	.dma_enable			= -1, | ||||||
|  | @@ -163,8 +163,8 @@ static const struct dwc2_core_params par | ||||||
|  |  	.host_rx_fifo_size		= 288,	/* 288 DWORDs */ | ||||||
|  |  	.host_nperio_tx_fifo_size	= 128,	/* 128 DWORDs */ | ||||||
|  |  	.host_perio_tx_fifo_size	= 96,	/* 96 DWORDs */ | ||||||
|  | -	.max_transfer_size		= 65535, | ||||||
|  | -	.max_packet_count		= 511, | ||||||
|  | +	.max_transfer_size		= -1, | ||||||
|  | +	.max_packet_count		= -1, | ||||||
|  |  	.host_channels			= -1, | ||||||
|  |  	.phy_type			= -1, | ||||||
|  |  	.phy_utmi_width			= -1, | ||||||
|  | @@ -176,8 +176,37 @@ static const struct dwc2_core_params par | ||||||
|  |  	.host_ls_low_power_phy_clk	= -1, | ||||||
|  |  	.ts_dline			= -1, | ||||||
|  |  	.reload_ctl			= -1, | ||||||
|  | -	.ahbcfg				= GAHBCFG_HBSTLEN_INCR16 << | ||||||
|  | -					  GAHBCFG_HBSTLEN_SHIFT, | ||||||
|  | +	.ahbcfg				= -1, | ||||||
|  | +	.uframe_sched			= -1, | ||||||
|  | +	.external_id_pin_ctl		= -1, | ||||||
|  | +	.hibernation			= -1, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const struct dwc2_core_params params_xrx200 = { | ||||||
|  | +	.otg_cap			= 2,	/* non-HNP/non-SRP */ | ||||||
|  | +	.otg_ver			= -1, | ||||||
|  | +	.dma_enable			= -1, | ||||||
|  | +	.dma_desc_enable		= -1, | ||||||
|  | +	.speed				= -1, | ||||||
|  | +	.enable_dynamic_fifo		= -1, | ||||||
|  | +	.en_multiple_tx_fifo		= -1, | ||||||
|  | +	.host_rx_fifo_size		= 288,	/* 288 DWORDs */ | ||||||
|  | +	.host_nperio_tx_fifo_size	= 128,	/* 128 DWORDs */ | ||||||
|  | +	.host_perio_tx_fifo_size	= 136,	/* 136 DWORDs */ | ||||||
|  | +	.max_transfer_size		= -1, | ||||||
|  | +	.max_packet_count		= -1, | ||||||
|  | +	.host_channels			= -1, | ||||||
|  | +	.phy_type			= -1, | ||||||
|  | +	.phy_utmi_width			= -1, | ||||||
|  | +	.phy_ulpi_ddr			= -1, | ||||||
|  | +	.phy_ulpi_ext_vbus		= -1, | ||||||
|  | +	.i2c_enable			= -1, | ||||||
|  | +	.ulpi_fs_ls			= -1, | ||||||
|  | +	.host_support_fs_ls_low_power	= -1, | ||||||
|  | +	.host_ls_low_power_phy_clk	= -1, | ||||||
|  | +	.ts_dline			= -1, | ||||||
|  | +	.reload_ctl			= -1, | ||||||
|  | +	.ahbcfg				= -1, | ||||||
|  |  	.uframe_sched			= -1, | ||||||
|  |  	.external_id_pin_ctl		= -1, | ||||||
|  |  	.hibernation			= -1, | ||||||
|  | @@ -515,8 +544,11 @@ static const struct of_device_id dwc2_of | ||||||
|  |  	{ .compatible = "brcm,bcm2835-usb", .data = ¶ms_bcm2835 }, | ||||||
|  |  	{ .compatible = "hisilicon,hi6220-usb", .data = ¶ms_hi6220 }, | ||||||
|  |  	{ .compatible = "rockchip,rk3066-usb", .data = ¶ms_rk3066 }, | ||||||
|  | -	{ .compatible = "lantiq,arx100-usb", .data = ¶ms_ltq }, | ||||||
|  | -	{ .compatible = "lantiq,xrx200-usb", .data = ¶ms_ltq }, | ||||||
|  | +	{ .compatible = "lantiq,danube-usb", .data = NULL }, | ||||||
|  | +	{ .compatible = "lantiq,ase-usb", .data = ¶ms_ase }, | ||||||
|  | +	{ .compatible = "lantiq,arx100-usb", .data = ¶ms_ase }, | ||||||
|  | +	{ .compatible = "lantiq,xrx200-usb", .data = ¶ms_xrx200 }, | ||||||
|  | +	{ .compatible = "lantiq,xrx300-usb", .data = ¶ms_xrx200 }, | ||||||
|  |  	{ .compatible = "snps,dwc2", .data = NULL }, | ||||||
|  |  	{ .compatible = "samsung,s3c6400-hsotg", .data = NULL}, | ||||||
|  |  	{ .compatible = "amlogic,meson8b-usb", .data = ¶ms_amlogic }, | ||||||
| @@ -0,0 +1,202 @@ | |||||||
|  | From 14909c4e4e836925668e74fc6e0e85ba0283cbf9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | Date: Fri, 6 Jan 2017 17:40:12 +0100 | ||||||
|  | Subject: [PATCH 2/2] MIPS: lantiq: improve USB initialization | ||||||
|  |  | ||||||
|  | This adds code to initialize the USB controller and PHY also on Danube, | ||||||
|  | Amazon SE and AR10. This code is based on the Vendor driver from | ||||||
|  | different UGW versions and compared to the hardware documentation. | ||||||
|  |  | ||||||
|  | Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | --- | ||||||
|  |  arch/mips/lantiq/xway/reset.c   | 120 ++++++++++++++++++++++++++++++---------- | ||||||
|  |  arch/mips/lantiq/xway/sysctrl.c |  20 +++++++ | ||||||
|  |  2 files changed, 110 insertions(+), 30 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/arch/mips/lantiq/xway/reset.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/reset.c | ||||||
|  | @@ -72,6 +72,8 @@ | ||||||
|  |  #define RCU_USBCFG_HDSEL_BIT	BIT(11) | ||||||
|  |  #define RCU_USBCFG_HOST_END_BIT	BIT(10) | ||||||
|  |  #define RCU_USBCFG_SLV_END_BIT	BIT(9) | ||||||
|  | +#define RCU_USBCFG_SLV_END_BIT_AR9	BIT(17) | ||||||
|  | + | ||||||
|  |   | ||||||
|  |  /* USB reset bits */ | ||||||
|  |  #define RCU_USBRESET		0x0010 | ||||||
|  | @@ -85,6 +87,8 @@ | ||||||
|  |   | ||||||
|  |  #define RCU_CFG1A		0x0038 | ||||||
|  |  #define RCU_CFG1B		0x003C | ||||||
|  | +#define  RCU_CFG1_TX_PEE	BIT(0) | ||||||
|  | +#define  RCU_CFG1_DIS_THR_SHIFT	15 /* Disconnect Threshold */	 | ||||||
|  |   | ||||||
|  |  /* USB PMU devices */ | ||||||
|  |  #define PMU_AHBM		BIT(15) | ||||||
|  | @@ -306,38 +310,91 @@ static void ltq_usb_init(void) | ||||||
|  |  	/* Power for USB cores 1 & 2 */ | ||||||
|  |  	ltq_pmu_enable(PMU_AHBM); | ||||||
|  |  	ltq_pmu_enable(PMU_USB0); | ||||||
|  | -	ltq_pmu_enable(PMU_USB1); | ||||||
|  |   | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1A) | BIT(0), RCU_CFG1A); | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1B) | BIT(0), RCU_CFG1B); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar10") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,grx390") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,ar9") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,vr9")) | ||||||
|  | +		ltq_pmu_enable(PMU_USB1); | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,vr9") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,ar10")) { | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1A) | RCU_CFG1_TX_PEE | | ||||||
|  | +			    7 << RCU_CFG1_DIS_THR_SHIFT, RCU_CFG1A); | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1B) | RCU_CFG1_TX_PEE | | ||||||
|  | +			    7 << RCU_CFG1_DIS_THR_SHIFT, RCU_CFG1B); | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	/* Enable USB PHY power for cores 1 & 2 */ | ||||||
|  |  	ltq_pmu_enable(PMU_USB0_P); | ||||||
|  | -	ltq_pmu_enable(PMU_USB1_P); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar10") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,grx390") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,ar9") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,vr9")) | ||||||
|  | +		ltq_pmu_enable(PMU_USB1_P); | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ase") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,danube")) { | ||||||
|  | +		/* Configure cores to host mode */ | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT, | ||||||
|  | +			RCU_USB1CFG); | ||||||
|  | + | ||||||
|  | +		/* Select DMA endianness (Host-endian: big-endian) */ | ||||||
|  | +		ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT) | ||||||
|  | +			| RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		/* Configure cores to host mode */ | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT, | ||||||
|  | +			RCU_USB1CFG); | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USB2CFG) & ~RCU_USBCFG_HDSEL_BIT, | ||||||
|  | +			RCU_USB2CFG); | ||||||
|  | + | ||||||
|  | +		/* Select DMA endianness (Host-endian: big-endian) */ | ||||||
|  | +		ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT_AR9) | ||||||
|  | +			| RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG); | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32((RCU_USB2CFG) & ~RCU_USBCFG_SLV_END_BIT_AR9) | ||||||
|  | +			| RCU_USBCFG_HOST_END_BIT, RCU_USB2CFG); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,vr9") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,ar10")) { | ||||||
|  | +		/* Configure cores to host mode */ | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT, | ||||||
|  | +			RCU_USB1CFG); | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USB2CFG) & ~RCU_USBCFG_HDSEL_BIT, | ||||||
|  | +			RCU_USB2CFG); | ||||||
|  | + | ||||||
|  | +		/* Select DMA endianness (Host-endian: big-endian) */ | ||||||
|  | +		ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT) | ||||||
|  | +			| RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG); | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32((RCU_USB2CFG) & ~RCU_USBCFG_SLV_END_BIT) | ||||||
|  | +			| RCU_USBCFG_HOST_END_BIT, RCU_USB2CFG); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar9")) { | ||||||
|  | +		/* Hard reset USB state machines */ | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | ||||||
|  | +			   | USBRESET_BIT | BIT(28), RCU_USBRESET); | ||||||
|  | +		udelay(50 * 1000); | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | ||||||
|  | +			    & ~(USBRESET_BIT | BIT(28)), RCU_USBRESET); | ||||||
|  | +	} else { | ||||||
|  | +		/* Hard reset USB state machines */ | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | USBRESET_BIT, RCU_USBRESET); | ||||||
|  | +		udelay(50 * 1000); | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) & ~USBRESET_BIT, RCU_USBRESET); | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  | -	/* Configure cores to host mode */ | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT, | ||||||
|  | -		RCU_USB1CFG); | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32(RCU_USB2CFG) & ~RCU_USBCFG_HDSEL_BIT, | ||||||
|  | -		RCU_USB2CFG); | ||||||
|  | - | ||||||
|  | -	/* Select DMA endianness (Host-endian: big-endian) */ | ||||||
|  | -	ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT) | ||||||
|  | -		| RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG); | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32((RCU_USB2CFG) & ~RCU_USBCFG_SLV_END_BIT) | ||||||
|  | -		| RCU_USBCFG_HOST_END_BIT, RCU_USB2CFG); | ||||||
|  | - | ||||||
|  | -	/* Hard reset USB state machines */ | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | USBRESET_BIT, RCU_USBRESET); | ||||||
|  | -	udelay(50 * 1000); | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) & ~USBRESET_BIT, RCU_USBRESET); | ||||||
|  | - | ||||||
|  | -	/* Soft reset USB state machines */ | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2) | ||||||
|  | -		| USB1RESET_BIT | USB2RESET_BIT, RCU_USBRESET2); | ||||||
|  | -	udelay(50 * 1000); | ||||||
|  | -	ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2) | ||||||
|  | -		& ~(USB1RESET_BIT | USB2RESET_BIT), RCU_USBRESET2); | ||||||
|  | +	if (of_machine_is_compatible("lantiq,vr9")) { | ||||||
|  | +		/* Soft reset USB state machines */ | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2) | ||||||
|  | +			| USB1RESET_BIT | USB2RESET_BIT, RCU_USBRESET2); | ||||||
|  | +		udelay(50 * 1000); | ||||||
|  | +		ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2) | ||||||
|  | +			& ~(USB1RESET_BIT | USB2RESET_BIT), RCU_USBRESET2); | ||||||
|  | +	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int __init mips_reboot_setup(void) | ||||||
|  | @@ -363,8 +420,11 @@ static int __init mips_reboot_setup(void | ||||||
|  |  	if (!ltq_rcu_membase) | ||||||
|  |  		panic("Failed to remap core memory"); | ||||||
|  |   | ||||||
|  | -	if (of_machine_is_compatible("lantiq,ar9") || | ||||||
|  | -	    of_machine_is_compatible("lantiq,vr9")) | ||||||
|  | +	if (of_machine_is_compatible("lantiq,danube") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,ase") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,ar9") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,vr9") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,ar10")) | ||||||
|  |  		ltq_usb_init(); | ||||||
|  |   | ||||||
|  |  	if (of_machine_is_compatible("lantiq,vr9")) | ||||||
|  | --- a/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | @@ -254,6 +254,25 @@ static void pmu_disable(struct clk *clk) | ||||||
|  |  		pr_warn("deactivating PMU module failed!"); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void usb_set_clock(void) | ||||||
|  | +{ | ||||||
|  | +	unsigned int val = ltq_cgu_r32(ifccr); | ||||||
|  | + | ||||||
|  | +	if (of_machine_is_compatible("lantiq,ar10") || | ||||||
|  | +	    of_machine_is_compatible("lantiq,grx390")) { | ||||||
|  | +		val &= ~0x03; /* XTAL divided by 3 */ | ||||||
|  | +	} else if (of_machine_is_compatible("lantiq,ar9") || | ||||||
|  | +		   of_machine_is_compatible("lantiq,vr9")) { | ||||||
|  | +		/* TODO: this depends on the XTAL frequency */ | ||||||
|  | +		val |= 0x03; /* XTAL divided by 3 */ | ||||||
|  | +	} else if (of_machine_is_compatible("lantiq,ase")) { | ||||||
|  | +		val |= 0x20; /* from XTAL */ | ||||||
|  | +	} else if (of_machine_is_compatible("lantiq,danube")) { | ||||||
|  | +		val |= 0x30; /* 12 MHz, generated from 36 MHz */ | ||||||
|  | +	} | ||||||
|  | +	ltq_cgu_w32(val, ifccr); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  /* the pci enable helper */ | ||||||
|  |  static int pci_enable(struct clk *clk) | ||||||
|  |  { | ||||||
|  | @@ -608,4 +627,5 @@ void __init ltq_soc_init(void) | ||||||
|  |   | ||||||
|  |  	if (of_machine_is_compatible("lantiq,vr9")) | ||||||
|  |  		xbar_fpi_burst_disable(); | ||||||
|  | +	usb_set_clock(); | ||||||
|  |  } | ||||||
| @@ -0,0 +1,53 @@ | |||||||
|  | From: Felix Fietkau <nbd@nbd.name> | ||||||
|  | Date: Thu, 19 Jan 2017 14:14:36 +0100 | ||||||
|  | Subject: [PATCH] MIPS: Lantiq: Keep ethernet enabled during boot | ||||||
|  |  | ||||||
|  | Disabling ethernet during reboot (only to enable it again when the | ||||||
|  | ethernet driver attaches) can put the chip into a faulty state where it | ||||||
|  | corrupts the header of all incoming packets. | ||||||
|  |  | ||||||
|  | This happens if packets arrive during the time window where the core is | ||||||
|  | disabled, and it can be easily reproduced by rebooting while sending a | ||||||
|  | flood ping to the broadcast address. | ||||||
|  |  | ||||||
|  | Cc: john@phrozen.org | ||||||
|  | Cc: hauke.mehrtens@lantiq.com | ||||||
|  | Cc: stable@vger.kernel.org | ||||||
|  | Fixes: 95135bfa7ead ("MIPS: Lantiq: Deactivate most of the devices by default") | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | @@ -564,7 +564,7 @@ void __init ltq_soc_init(void) | ||||||
|  |  		clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI); | ||||||
|  |  		clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI); | ||||||
|  |  		clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL); | ||||||
|  | -		clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP); | ||||||
|  | +		clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH | PMU_PPE_DP); | ||||||
|  |  		clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); | ||||||
|  |  		clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); | ||||||
|  |  	} else if (of_machine_is_compatible("lantiq,ar10")) { | ||||||
|  | @@ -572,7 +572,7 @@ void __init ltq_soc_init(void) | ||||||
|  |  				  ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz()); | ||||||
|  |  		clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); | ||||||
|  |  		clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1); | ||||||
|  | -		clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | | ||||||
|  | +		clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH | | ||||||
|  |  			       PMU_PPE_DP | PMU_PPE_TC); | ||||||
|  |  		clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); | ||||||
|  |  		clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); | ||||||
|  | @@ -594,11 +594,11 @@ void __init ltq_soc_init(void) | ||||||
|  |  		clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS); | ||||||
|  |   | ||||||
|  |  		clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); | ||||||
|  | -		clkdev_add_pmu("1e108000.eth", NULL, 1, 0, | ||||||
|  | +		clkdev_add_pmu("1e108000.eth", NULL, 0, 0, | ||||||
|  |  				PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM | | ||||||
|  |  				PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 | | ||||||
|  |  				PMU_PPE_QSB | PMU_PPE_TOP); | ||||||
|  | -		clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); | ||||||
|  | +		clkdev_add_pmu("1f203000.rcu", "gphy", 0, 0, PMU_GPHY); | ||||||
|  |  		clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); | ||||||
|  |  		clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); | ||||||
|  |  		clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); | ||||||
| @@ -0,0 +1,42 @@ | |||||||
|  | --- a/drivers/spi/spi.c | ||||||
|  | +++ b/drivers/spi/spi.c | ||||||
|  | @@ -1013,6 +1013,20 @@ static int spi_transfer_one_message(stru | ||||||
|  |  								 msecs_to_jiffies(ms)); | ||||||
|  |  			} | ||||||
|  |   | ||||||
|  | +			if (master->transfer_status) { | ||||||
|  | +				ret = master->transfer_status(master, ms); | ||||||
|  | +				if (ret) { | ||||||
|  | +					SPI_STATISTICS_INCREMENT_FIELD(statm, | ||||||
|  | +								       errors); | ||||||
|  | +					SPI_STATISTICS_INCREMENT_FIELD(stats, | ||||||
|  | +								       errors); | ||||||
|  | +					dev_err(&msg->spi->dev, | ||||||
|  | +						"SPI transfer status: %d\n", | ||||||
|  | +						ret); | ||||||
|  | +					goto out; | ||||||
|  | +				} | ||||||
|  | +			} | ||||||
|  | + | ||||||
|  |  			if (ms == 0) { | ||||||
|  |  				SPI_STATISTICS_INCREMENT_FIELD(statm, | ||||||
|  |  							       timedout); | ||||||
|  | --- a/include/linux/spi/spi.h | ||||||
|  | +++ b/include/linux/spi/spi.h | ||||||
|  | @@ -370,6 +370,8 @@ static inline void spi_unregister_driver | ||||||
|  |   *                    transfer_one_message are mutually exclusive; when both | ||||||
|  |   *                    are set, the generic subsystem does not call your | ||||||
|  |   *                    transfer_one callback. | ||||||
|  | + * @transfer_status: This callback allows the driver to return an error code | ||||||
|  | + *		     in case the scheduled single spi transfer failed. | ||||||
|  |   * @handle_err: the subsystem calls the driver to handle an error that occurs | ||||||
|  |   *		in the generic implementation of transfer_one_message(). | ||||||
|  |   * @unprepare_message: undo any work done by prepare_message(). | ||||||
|  | @@ -546,6 +548,7 @@ struct spi_master { | ||||||
|  |  	void (*set_cs)(struct spi_device *spi, bool enable); | ||||||
|  |  	int (*transfer_one)(struct spi_master *master, struct spi_device *spi, | ||||||
|  |  			    struct spi_transfer *transfer); | ||||||
|  | +	int (*transfer_status)(struct spi_master *master, unsigned long timeout); | ||||||
|  |  	void (*handle_err)(struct spi_master *master, | ||||||
|  |  			   struct spi_message *message); | ||||||
|  |   | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										93
									
								
								target/linux/lantiq/patches-4.9/0101-find_active_root.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								target/linux/lantiq/patches-4.9/0101-find_active_root.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | |||||||
|  | --- a/drivers/mtd/ofpart.c | ||||||
|  | +++ b/drivers/mtd/ofpart.c | ||||||
|  | @@ -25,6 +25,38 @@ static bool node_has_compatible(struct d | ||||||
|  |  	return of_get_property(pp, "compatible", NULL); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static uint8_t * brnboot_get_selected_root_part(struct mtd_info *master, | ||||||
|  | +						loff_t offset) | ||||||
|  | +{ | ||||||
|  | +	static uint8_t root_id; | ||||||
|  | +	int err, len; | ||||||
|  | + | ||||||
|  | +	err = mtd_read(master, offset, 0x01, &len, &root_id); | ||||||
|  | + | ||||||
|  | +	if (mtd_is_bitflip(err) || !err) | ||||||
|  | +		return &root_id; | ||||||
|  | + | ||||||
|  | +	return NULL; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void brnboot_set_active_root_part(struct mtd_partition *pparts, | ||||||
|  | +					 struct device_node **part_nodes, | ||||||
|  | +					 int nr_parts, | ||||||
|  | +					 uint8_t *root_id) | ||||||
|  | +{ | ||||||
|  | +	int i; | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < nr_parts; i++) { | ||||||
|  | +		int part_root_id; | ||||||
|  | + | ||||||
|  | +		if (!of_property_read_u32(part_nodes[i], "brnboot,root-id", &part_root_id) | ||||||
|  | +		    && part_root_id == *root_id) { | ||||||
|  | +			pparts[i].name = "firmware"; | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int parse_ofpart_partitions(struct mtd_info *master, | ||||||
|  |  				   const struct mtd_partition **pparts, | ||||||
|  |  				   struct mtd_part_parser_data *data) | ||||||
|  | @@ -36,7 +68,8 @@ static int parse_ofpart_partitions(struc | ||||||
|  |  	struct device_node *pp; | ||||||
|  |  	int nr_parts, i, ret = 0; | ||||||
|  |  	bool dedicated = true; | ||||||
|  | - | ||||||
|  | +	uint8_t *proot_id = NULL; | ||||||
|  | +	struct device_node **part_nodes; | ||||||
|  |   | ||||||
|  |  	/* Pull of_node from the master device node */ | ||||||
|  |  	mtd_node = mtd_get_of_node(master); | ||||||
|  | @@ -72,7 +105,9 @@ static int parse_ofpart_partitions(struc | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  |  	parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); | ||||||
|  | -	if (!parts) | ||||||
|  | +	part_nodes = kzalloc(nr_parts * sizeof(*part_nodes), GFP_KERNEL); | ||||||
|  | + | ||||||
|  | +	if (!parts || !part_nodes) | ||||||
|  |  		return -ENOMEM; | ||||||
|  |   | ||||||
|  |  	i = 0; | ||||||
|  | @@ -120,12 +155,22 @@ static int parse_ofpart_partitions(struc | ||||||
|  |  		if (of_get_property(pp, "lock", &len)) | ||||||
|  |  			parts[i].mask_flags |= MTD_POWERUP_LOCK; | ||||||
|  |   | ||||||
|  | +		if (!proot_id && of_device_is_compatible(pp, "brnboot,root-selector")) | ||||||
|  | +			proot_id = brnboot_get_selected_root_part(master, parts[i].offset); | ||||||
|  | + | ||||||
|  | +		part_nodes[i] = pp; | ||||||
|  | + | ||||||
|  |  		i++; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (!nr_parts) | ||||||
|  |  		goto ofpart_none; | ||||||
|  |   | ||||||
|  | +	if (proot_id) | ||||||
|  | +		brnboot_set_active_root_part(parts, part_nodes, nr_parts, proot_id); | ||||||
|  | + | ||||||
|  | +	kfree(part_nodes); | ||||||
|  | + | ||||||
|  |  	*pparts = parts; | ||||||
|  |  	return nr_parts; | ||||||
|  |   | ||||||
|  | @@ -136,6 +181,7 @@ ofpart_fail: | ||||||
|  |  ofpart_none: | ||||||
|  |  	of_node_put(pp); | ||||||
|  |  	kfree(parts); | ||||||
|  | +	kfree(part_nodes); | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
| @@ -0,0 +1,166 @@ | |||||||
|  | --- a/arch/mips/pci/ifxmips_pcie.c | ||||||
|  | +++ b/arch/mips/pci/ifxmips_pcie.c | ||||||
|  | @@ -18,6 +18,9 @@ | ||||||
|  |  #include <linux/pci_regs.h> | ||||||
|  |  #include <linux/module.h> | ||||||
|  |   | ||||||
|  | +#include <linux/of_gpio.h> | ||||||
|  | +#include <linux/of_platform.h> | ||||||
|  | + | ||||||
|  |  #include "ifxmips_pcie.h" | ||||||
|  |  #include "ifxmips_pcie_reg.h" | ||||||
|  |   | ||||||
|  | @@ -40,6 +43,7 @@ | ||||||
|  |  static DEFINE_SPINLOCK(ifx_pcie_lock); | ||||||
|  |   | ||||||
|  |  u32 g_pcie_debug_flag = PCIE_MSG_ANY & (~PCIE_MSG_CFG); | ||||||
|  | +static int pcie_reset_gpio; | ||||||
|  |   | ||||||
|  |  static ifx_pcie_irq_t pcie_irqs[IFX_PCIE_CORE_NR] = { | ||||||
|  |      { | ||||||
|  | @@ -82,6 +86,22 @@ void ifx_pcie_debug(const char *fmt, ... | ||||||
|  |  	printk("%s", buf); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static inline void pcie_ep_gpio_rst_init(int pcie_port) | ||||||
|  | +{ | ||||||
|  | +	gpio_direction_output(pcie_reset_gpio, 1); | ||||||
|  | +	gpio_set_value(pcie_reset_gpio, 1); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void pcie_device_rst_assert(int pcie_port) | ||||||
|  | +{ | ||||||
|  | +	gpio_set_value(pcie_reset_gpio, 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline void pcie_device_rst_deassert(int pcie_port) | ||||||
|  | +{ | ||||||
|  | +	mdelay(100); | ||||||
|  | +	gpio_direction_output(pcie_reset_gpio, 1); | ||||||
|  | +} | ||||||
|  |   | ||||||
|  |  static inline int pcie_ltssm_enable(int pcie_port) | ||||||
|  |  { | ||||||
|  | @@ -1045,8 +1065,9 @@ pcie_rc_initialize(int pcie_port) | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int __init ifx_pcie_bios_init(void) | ||||||
|  | +static int __init ifx_pcie_bios_probe(struct platform_device *pdev) | ||||||
|  |  { | ||||||
|  | +    struct device_node *node = pdev->dev.of_node; | ||||||
|  |      void __iomem *io_map_base; | ||||||
|  |      int pcie_port; | ||||||
|  |      int startup_port; | ||||||
|  | @@ -1055,7 +1076,17 @@ static int __init ifx_pcie_bios_init(voi | ||||||
|  |      pcie_ahb_pmu_setup(); | ||||||
|  |   | ||||||
|  |      startup_port = IFX_PCIE_PORT0; | ||||||
|  | -     | ||||||
|  | + | ||||||
|  | +    pcie_reset_gpio = of_get_named_gpio(node, "gpio-reset", 0); | ||||||
|  | +    if (gpio_is_valid(pcie_reset_gpio)) { | ||||||
|  | +        int ret = devm_gpio_request(&pdev->dev, pcie_reset_gpio, "pcie-reset"); | ||||||
|  | +        if (ret) { | ||||||
|  | +            dev_err(&pdev->dev, "failed to request gpio %d\n", pcie_reset_gpio); | ||||||
|  | +            return ret; | ||||||
|  | +        } | ||||||
|  | +        gpio_direction_output(pcie_reset_gpio, 1); | ||||||
|  | +    } | ||||||
|  | + | ||||||
|  |      for (pcie_port = startup_port; pcie_port < IFX_PCIE_CORE_NR; pcie_port++){ | ||||||
|  |  	if (pcie_rc_initialize(pcie_port) == 0) { | ||||||
|  |  	    IFX_PCIE_PRINT(PCIE_MSG_INIT, "%s: ifx_pcie_cfg_base 0x%p\n",  | ||||||
|  | @@ -1067,6 +1098,7 @@ static int __init ifx_pcie_bios_init(voi | ||||||
|  |                  return -ENOMEM; | ||||||
|  |              } | ||||||
|  |              ifx_pcie_controller[pcie_port].pcic.io_map_base = (unsigned long)io_map_base; | ||||||
|  | +            pci_load_of_ranges(&ifx_pcie_controller[pcie_port].pcic, node); | ||||||
|  |   | ||||||
|  |              register_pci_controller(&ifx_pcie_controller[pcie_port].pcic); | ||||||
|  |              /* XXX, clear error status */ | ||||||
|  | @@ -1083,6 +1115,30 @@ static int __init ifx_pcie_bios_init(voi | ||||||
|  |   | ||||||
|  |      return 0; | ||||||
|  |  } | ||||||
|  | + | ||||||
|  | +static const struct of_device_id ifxmips_pcie_match[] = { | ||||||
|  | +        { .compatible = "lantiq,pcie-xrx200" }, | ||||||
|  | +        {}, | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, ifxmips_pcie_match); | ||||||
|  | + | ||||||
|  | +static struct platform_driver ltq_pci_driver = { | ||||||
|  | +        .probe = ifx_pcie_bios_probe, | ||||||
|  | +        .driver = { | ||||||
|  | +                .name = "pcie-xrx200", | ||||||
|  | +                .owner = THIS_MODULE, | ||||||
|  | +                .of_match_table = ifxmips_pcie_match, | ||||||
|  | +        }, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +int __init ifx_pcie_bios_init(void) | ||||||
|  | +{ | ||||||
|  | +        int ret = platform_driver_register(<q_pci_driver); | ||||||
|  | +        if (ret) | ||||||
|  | +                pr_info("pcie-xrx200: Error registering platform driver!"); | ||||||
|  | +        return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  arch_initcall(ifx_pcie_bios_init); | ||||||
|  |   | ||||||
|  |  MODULE_LICENSE("GPL"); | ||||||
|  | --- a/arch/mips/pci/ifxmips_pcie_vr9.h | ||||||
|  | +++ b/arch/mips/pci/ifxmips_pcie_vr9.h | ||||||
|  | @@ -22,8 +22,6 @@ | ||||||
|  |  #include <linux/gpio.h> | ||||||
|  |  #include <lantiq_soc.h> | ||||||
|  |   | ||||||
|  | -#define IFX_PCIE_GPIO_RESET  494 | ||||||
|  | - | ||||||
|  |  #define IFX_REG_R32    ltq_r32 | ||||||
|  |  #define IFX_REG_W32    ltq_w32 | ||||||
|  |  #define CONFIG_IFX_PCIE_HW_SWAP | ||||||
|  | @@ -53,21 +51,6 @@ | ||||||
|  |  #define OUT			((volatile u32*)(IFX_GPIO + 0x0070)) | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -static inline void pcie_ep_gpio_rst_init(int pcie_port) | ||||||
|  | -{ | ||||||
|  | - | ||||||
|  | -	gpio_request(IFX_PCIE_GPIO_RESET, "pcie-reset"); | ||||||
|  | -	gpio_direction_output(IFX_PCIE_GPIO_RESET, 1); | ||||||
|  | -	gpio_set_value(IFX_PCIE_GPIO_RESET, 1); | ||||||
|  | - | ||||||
|  | -/*    ifx_gpio_pin_reserve(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_output_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_dir_out_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_altsel0_clear(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_altsel1_clear(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -    ifx_gpio_open_drain_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id);*/ | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static inline void pcie_ahb_pmu_setup(void)  | ||||||
|  |  { | ||||||
|  |  	/* Enable AHB bus master/slave */ | ||||||
|  | @@ -180,20 +163,6 @@ static inline void pcie_phy_rst_deassert | ||||||
|  |      IFX_REG_W32(reg, IFX_RCU_RST_REQ); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static inline void pcie_device_rst_assert(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -	gpio_set_value(IFX_PCIE_GPIO_RESET, 0); | ||||||
|  | -//    ifx_gpio_output_clear(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static inline void pcie_device_rst_deassert(int pcie_port) | ||||||
|  | -{ | ||||||
|  | -    mdelay(100); | ||||||
|  | -	gpio_direction_output(IFX_PCIE_GPIO_RESET, 1); | ||||||
|  | -//    gpio_set_value(IFX_PCIE_GPIO_RESET, 1); | ||||||
|  | -    //ifx_gpio_output_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static inline void pcie_core_pmu_setup(int pcie_port) | ||||||
|  |  { | ||||||
|  |  	struct clk *clk; | ||||||
							
								
								
									
										208
									
								
								target/linux/lantiq/patches-4.9/0152-lantiq-VPE.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								target/linux/lantiq/patches-4.9/0152-lantiq-VPE.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | |||||||
|  | --- a/arch/mips/Kconfig | ||||||
|  | +++ b/arch/mips/Kconfig | ||||||
|  | @@ -2310,6 +2310,12 @@ config MIPS_VPE_LOADER | ||||||
|  |  	  Includes a loader for loading an elf relocatable object | ||||||
|  |  	  onto another VPE and running it. | ||||||
|  |   | ||||||
|  | +config IFX_VPE_EXT | ||||||
|  | +	bool "IFX APRP Extensions" | ||||||
|  | +	depends on MIPS_VPE_LOADER | ||||||
|  | +	help | ||||||
|  | +	  IFX included extensions in APRP | ||||||
|  | + | ||||||
|  |  config MIPS_VPE_LOADER_CMP | ||||||
|  |  	bool | ||||||
|  |  	default "y" | ||||||
|  | --- a/arch/mips/include/asm/vpe.h | ||||||
|  | +++ b/arch/mips/include/asm/vpe.h | ||||||
|  | @@ -127,4 +127,23 @@ void cleanup_tc(struct tc *tc); | ||||||
|  |   | ||||||
|  |  int __init vpe_module_init(void); | ||||||
|  |  void __exit vpe_module_exit(void); | ||||||
|  | + | ||||||
|  | +/* For the explanation of the APIs please refer the section "MT APRP Kernel | ||||||
|  | + * Programming" in AR9 SW Architecture Specification | ||||||
|  | + */ | ||||||
|  | +int32_t vpe1_sw_start(void *sw_start_addr, uint32_t tcmask, uint32_t flags); | ||||||
|  | +int32_t vpe1_sw_stop(uint32_t flags); | ||||||
|  | +uint32_t vpe1_get_load_addr(uint32_t flags); | ||||||
|  | +uint32_t vpe1_get_max_mem(uint32_t flags); | ||||||
|  | + | ||||||
|  | +/* Watchdog APIs */ | ||||||
|  | +extern uint32_t vpe1_wdog_ctr; | ||||||
|  | +extern uint32_t vpe1_wdog_timeout; | ||||||
|  | + | ||||||
|  | +unsigned long vpe1_sw_wdog_start(unsigned long); | ||||||
|  | +unsigned long vpe1_sw_wdog_stop(unsigned long); | ||||||
|  | + | ||||||
|  | +typedef int (*VPE_SW_WDOG_RESET)(unsigned long wdog_cleared_ok_count); | ||||||
|  | +int32_t vpe1_sw_wdog_register_reset_handler(VPE_SW_WDOG_RESET reset_fn); | ||||||
|  | + | ||||||
|  |  #endif /* _ASM_VPE_H */ | ||||||
|  | --- a/arch/mips/kernel/vpe-mt.c | ||||||
|  | +++ b/arch/mips/kernel/vpe-mt.c | ||||||
|  | @@ -29,6 +29,7 @@ int vpe_run(struct vpe *v) | ||||||
|  |  	struct vpe_notifications *notifier; | ||||||
|  |  	unsigned int vpeflags; | ||||||
|  |  	struct tc *t; | ||||||
|  | +	unsigned long physical_memsize = 0L; | ||||||
|  |   | ||||||
|  |  	/* check we are the Master VPE */ | ||||||
|  |  	local_irq_save(flags); | ||||||
|  | @@ -417,6 +418,8 @@ int __init vpe_module_init(void) | ||||||
|  |  			} | ||||||
|  |   | ||||||
|  |  			v->ntcs = hw_tcs - aprp_cpu_index(); | ||||||
|  | +			write_tc_c0_tcbind((read_tc_c0_tcbind() & | ||||||
|  | +						~TCBIND_CURVPE) | 1); | ||||||
|  |   | ||||||
|  |  			/* add the tc to the list of this vpe's tc's. */ | ||||||
|  |  			list_add(&t->tc, &v->tc); | ||||||
|  | @@ -519,3 +522,47 @@ void __exit vpe_module_exit(void) | ||||||
|  |  			release_vpe(v); | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  | + | ||||||
|  | +#ifdef CONFIG_IFX_VPE_EXT | ||||||
|  | +int32_t vpe1_sw_start(void *sw_start_addr, uint32_t tcmask, uint32_t flags) | ||||||
|  | +{ | ||||||
|  | +	enum vpe_state state; | ||||||
|  | +	struct vpe *v = get_vpe(tclimit); | ||||||
|  | +	struct vpe_notifications *not; | ||||||
|  | + | ||||||
|  | +	if (tcmask || flags) { | ||||||
|  | +		pr_warn("Currently tcmask and flags should be 0. Other values are not supported\n"); | ||||||
|  | +		return -1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	state = xchg(&v->state, VPE_STATE_INUSE); | ||||||
|  | +	if (state != VPE_STATE_UNUSED) { | ||||||
|  | +		vpe_stop(v); | ||||||
|  | + | ||||||
|  | +		list_for_each_entry(not, &v->notify, list) { | ||||||
|  | +			not->stop(tclimit); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	v->__start = (unsigned long)sw_start_addr; | ||||||
|  | + | ||||||
|  | +	if (!vpe_run(v)) { | ||||||
|  | +		pr_debug("VPE loader: VPE1 running successfully\n"); | ||||||
|  | +		return 0; | ||||||
|  | +	} | ||||||
|  | +	return -1; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_sw_start); | ||||||
|  | + | ||||||
|  | +int32_t vpe1_sw_stop(uint32_t flags) | ||||||
|  | +{ | ||||||
|  | +	struct vpe *v = get_vpe(tclimit); | ||||||
|  | + | ||||||
|  | +	if (!vpe_free(v)) { | ||||||
|  | +		pr_debug("RP Stopped\n"); | ||||||
|  | +		return 0; | ||||||
|  | +	} else | ||||||
|  | +		return -1; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_sw_stop); | ||||||
|  | +#endif | ||||||
|  | --- a/arch/mips/kernel/vpe.c | ||||||
|  | +++ b/arch/mips/kernel/vpe.c | ||||||
|  | @@ -49,6 +49,59 @@ struct vpe_control vpecontrol = { | ||||||
|  |  	.tc_list	= LIST_HEAD_INIT(vpecontrol.tc_list) | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +#ifdef CONFIG_IFX_VPE_EXT | ||||||
|  | +unsigned int vpe1_load_addr; | ||||||
|  | + | ||||||
|  | +static int __init load_address(char *str) | ||||||
|  | +{ | ||||||
|  | +	get_option(&str, &vpe1_load_addr); | ||||||
|  | +	return 1; | ||||||
|  | +} | ||||||
|  | +__setup("vpe1_load_addr=", load_address); | ||||||
|  | + | ||||||
|  | +static unsigned int vpe1_mem; | ||||||
|  | +static int __init vpe1mem(char *str) | ||||||
|  | +{ | ||||||
|  | +	vpe1_mem = memparse(str, &str); | ||||||
|  | +	return 1; | ||||||
|  | +} | ||||||
|  | +__setup("vpe1_mem=", vpe1mem); | ||||||
|  | + | ||||||
|  | +uint32_t vpe1_wdog_ctr; | ||||||
|  | +static int __init wdog_ctr(char *str) | ||||||
|  | +{ | ||||||
|  | +	get_option(&str, &vpe1_wdog_ctr); | ||||||
|  | +	return 1; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_wdog_ctr); | ||||||
|  | +__setup("vpe1_wdog_ctr_addr=", wdog_ctr); | ||||||
|  | + | ||||||
|  | +uint32_t vpe1_wdog_timeout; | ||||||
|  | +static int __init wdog_timeout(char *str) | ||||||
|  | +{ | ||||||
|  | +	get_option(&str, &vpe1_wdog_timeout); | ||||||
|  | +	return 1; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_wdog_timeout); | ||||||
|  | +__setup("vpe1_wdog_timeout=", wdog_timeout); | ||||||
|  | + | ||||||
|  | +uint32_t vpe1_get_load_addr(uint32_t flags) | ||||||
|  | +{ | ||||||
|  | +	return vpe1_load_addr; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_get_load_addr); | ||||||
|  | + | ||||||
|  | +uint32_t vpe1_get_max_mem(uint32_t flags) | ||||||
|  | +{ | ||||||
|  | +	if (!vpe1_mem) | ||||||
|  | +		return P_SIZE; | ||||||
|  | +	else | ||||||
|  | +		return vpe1_mem; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(vpe1_get_max_mem); | ||||||
|  | + | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  /* get the vpe associated with this minor */ | ||||||
|  |  struct vpe *get_vpe(int minor) | ||||||
|  |  { | ||||||
|  | --- a/arch/mips/lantiq/prom.c | ||||||
|  | +++ b/arch/mips/lantiq/prom.c | ||||||
|  | @@ -31,10 +31,14 @@ EXPORT_SYMBOL_GPL(ebu_lock); | ||||||
|  |   */ | ||||||
|  |  static struct ltq_soc_info soc_info; | ||||||
|  |   | ||||||
|  | +/* for Multithreading (APRP), vpe.c will use it */ | ||||||
|  | +unsigned long cp0_memsize; | ||||||
|  | + | ||||||
|  |  const char *get_system_type(void) | ||||||
|  |  { | ||||||
|  |  	return soc_info.sys_type; | ||||||
|  |  } | ||||||
|  | +EXPORT_SYMBOL(ltq_soc_type); | ||||||
|  |   | ||||||
|  |  int ltq_soc_type(void) | ||||||
|  |  { | ||||||
|  | --- a/arch/mips/include/asm/mipsmtregs.h | ||||||
|  | +++ b/arch/mips/include/asm/mipsmtregs.h | ||||||
|  | @@ -31,6 +31,9 @@ | ||||||
|  |  #define read_c0_vpeconf1()		__read_32bit_c0_register($1, 3) | ||||||
|  |  #define write_c0_vpeconf1(val)		__write_32bit_c0_register($1, 3, val) | ||||||
|  |   | ||||||
|  | +#define read_c0_vpeopt()		__read_32bit_c0_register($1, 7) | ||||||
|  | +#define write_c0_vpeopt(val)		__write_32bit_c0_register($1, 7, val) | ||||||
|  | + | ||||||
|  |  #define read_c0_tcstatus()		__read_32bit_c0_register($2, 1) | ||||||
|  |  #define write_c0_tcstatus(val)		__write_32bit_c0_register($2, 1, val) | ||||||
|  |   | ||||||
|  | @@ -376,6 +379,8 @@ do {									\ | ||||||
|  |  #define write_vpe_c0_vpeconf0(val)	mttc0(1, 2, val) | ||||||
|  |  #define read_vpe_c0_vpeconf1()		mftc0(1, 3) | ||||||
|  |  #define write_vpe_c0_vpeconf1(val)	mttc0(1, 3, val) | ||||||
|  | +#define read_vpe_c0_vpeopt()		mftc0(1, 7) | ||||||
|  | +#define write_vpe_c0_vpeopt(val)	mttc0(1, 7, val) | ||||||
|  |  #define read_vpe_c0_count()		mftc0(9, 0) | ||||||
|  |  #define write_vpe_c0_count(val)		mttc0(9, 0, val) | ||||||
|  |  #define read_vpe_c0_status()		mftc0(12, 0) | ||||||
							
								
								
									
										170
									
								
								target/linux/lantiq/patches-4.9/0153-lantiq-VPE-softdog.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								target/linux/lantiq/patches-4.9/0153-lantiq-VPE-softdog.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | |||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/include/asm/mach-lantiq/vpe.h | ||||||
|  | @@ -0,0 +1,44 @@ | ||||||
|  | +/* | ||||||
|  | + *   This program is free software; you can redistribute it and/or modify | ||||||
|  | + *   it under the terms of the GNU General Public License as published by | ||||||
|  | + *   the Free Software Foundation; either version 2 of the License, or | ||||||
|  | + *   (at your option) any later version. | ||||||
|  | + * | ||||||
|  | + *   This program is distributed in the hope that it will be useful, | ||||||
|  | + *   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | + *   GNU General Public License for more details. | ||||||
|  | + * | ||||||
|  | + *   You should have received a copy of the GNU General Public License | ||||||
|  | + *   along with this program; if not, write to the Free Software | ||||||
|  | + *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | ||||||
|  | + * | ||||||
|  | + *   Copyright (C) 2005 infineon | ||||||
|  | + *   Copyright (C) 2007 John Crispin <blogic@openwrt.org> | ||||||
|  | + * | ||||||
|  | + */ | ||||||
|  | +#ifndef _IFXMIPS_VPE_H__ | ||||||
|  | +#define _IFXMIPS_VPE_H__ | ||||||
|  | + | ||||||
|  | +/* For the explanation of the APIs please refer the section "MT APRP Kernel | ||||||
|  | + * Programming" in AR9 SW Architecture Specification | ||||||
|  | + */ | ||||||
|  | +int32_t vpe1_sw_start(void* sw_start_addr, uint32_t tcmask, uint32_t flags); | ||||||
|  | +int32_t vpe1_sw_stop(uint32_t flags); | ||||||
|  | +uint32_t vpe1_get_load_addr (uint32_t flags); | ||||||
|  | +uint32_t vpe1_get_max_mem (uint32_t flags); | ||||||
|  | + | ||||||
|  | +int32_t vpe1_set_boot_param(char *field, char *value, char flags); | ||||||
|  | +int32_t vpe1_get_boot_param(char *field, char **value, char flags); | ||||||
|  | + | ||||||
|  | +/* Watchdog APIs */ | ||||||
|  | +extern unsigned long vpe1_wdog_ctr; | ||||||
|  | +extern unsigned long vpe1_wdog_timeout; | ||||||
|  | + | ||||||
|  | +unsigned long vpe1_sw_wdog_start(unsigned long); | ||||||
|  | +unsigned long vpe1_sw_wdog_stop(unsigned long); | ||||||
|  | + | ||||||
|  | +typedef int (*VPE_SW_WDOG_RESET)(unsigned long wdog_cleared_ok_count); | ||||||
|  | +int32_t vpe1_sw_wdog_register_reset_handler(VPE_SW_WDOG_RESET reset_fn); | ||||||
|  | + | ||||||
|  | +#endif | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/mips/lantiq/softdog_vpe.c | ||||||
|  | @@ -0,0 +1,109 @@ | ||||||
|  | +/* | ||||||
|  | +** ============================================================================= | ||||||
|  | +** FILE NAME     : softdog_vpe.c | ||||||
|  | +** MODULES       : LXDB | ||||||
|  | +** DATE          : 24-03-2008 | ||||||
|  | +** AUTHOR        : LXDB Team | ||||||
|  | +** DESCRIPTION   : This header file contains the code for the watchdog | ||||||
|  | +**                 implentation on vpe1 side. | ||||||
|  | +** REFERENCES    : | ||||||
|  | +** COPYRIGHT     : Copyright (c) 2008 | ||||||
|  | +**                 Am Campeon 1-12, 85579 Neubiberg, Germany | ||||||
|  | +** Any use of this software is subject to the conclusion of a respective | ||||||
|  | +** License agreement. Without such a License agreement no rights to the | ||||||
|  | +** software are granted | ||||||
|  | +** | ||||||
|  | +** HISTORY       : | ||||||
|  | +** $Date   $Author    $Comment | ||||||
|  | +** 24-03-2008   LXDB    Initial version | ||||||
|  | +** ============================================================================ | ||||||
|  | +*/ | ||||||
|  | + | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/moduleparam.h> | ||||||
|  | +#include <linux/types.h> | ||||||
|  | +#include <linux/timer.h> | ||||||
|  | +#include <linux/reboot.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/jiffies.h> | ||||||
|  | + | ||||||
|  | +#include <vpe.h> | ||||||
|  | + | ||||||
|  | +static unsigned long last_wdog_value; | ||||||
|  | +static unsigned long vpe1_wdog_cleared; | ||||||
|  | + | ||||||
|  | +static unsigned long vpe1_wdog_dead; | ||||||
|  | +static void watchdog_vpe0_fire(unsigned long); /* Called when vpe0 timer expires */ | ||||||
|  | +static void keep_alive_vpe0(unsigned long); | ||||||
|  | +VPE_SW_WDOG_RESET reset_local_fn; | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +static struct timer_list watchdog_vpe0_ticktock = | ||||||
|  | +                TIMER_INITIALIZER(watchdog_vpe0_fire, 0, 0); | ||||||
|  | + | ||||||
|  | +static void watchdog_vpe0_fire (unsigned long flags) | ||||||
|  | +{ | ||||||
|  | +	volatile unsigned long *wdog_ctr_value; | ||||||
|  | +	wdog_ctr_value = (void*)vpe1_wdog_ctr; | ||||||
|  | +	if (*wdog_ctr_value == last_wdog_value) { /* VPE1 watchdog expiry handling */ | ||||||
|  | +		vpe1_sw_wdog_stop(flags); | ||||||
|  | +		vpe1_wdog_dead++; | ||||||
|  | +		printk(KERN_DEBUG "VPE1 watchdog reset handler called\n"); | ||||||
|  | +	/* Call the reset handler function */ | ||||||
|  | +		reset_local_fn(flags); | ||||||
|  | +	} else { /* Everything is OK on vpe1 side. Continue. */ | ||||||
|  | +		last_wdog_value = *wdog_ctr_value; | ||||||
|  | +		vpe1_wdog_cleared++; | ||||||
|  | +		keep_alive_vpe0(flags); | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +int32_t vpe1_sw_wdog_register_reset_handler (VPE_SW_WDOG_RESET reset_fn) | ||||||
|  | +{ | ||||||
|  | +	reset_local_fn = (VPE_SW_WDOG_RESET)reset_fn; | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void keep_alive_vpe0(unsigned long flags) | ||||||
|  | +{ | ||||||
|  | +	mod_timer(&watchdog_vpe0_ticktock, jiffies+ vpe1_wdog_timeout ); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +unsigned long vpe1_sw_wdog_start(unsigned long flags) | ||||||
|  | +{ | ||||||
|  | +	volatile unsigned long *wdog_ctr_value; | ||||||
|  | +	wdog_ctr_value = (void*)vpe1_wdog_ctr; | ||||||
|  | +	*wdog_ctr_value = 0; | ||||||
|  | +	last_wdog_value = 0; | ||||||
|  | +	keep_alive_vpe0(flags); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +unsigned long vpe1_sw_wdog_stop(unsigned long flags) | ||||||
|  | +{ | ||||||
|  | +	del_timer(&watchdog_vpe0_ticktock); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __init watchdog_vpe1_init(void) | ||||||
|  | +{ | ||||||
|  | +	/* Nothing to be done here */ | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void __exit watchdog_vpe1_exit(void) | ||||||
|  | +{ | ||||||
|  | +	unsigned long flags=0; | ||||||
|  | +	vpe1_sw_wdog_stop(flags); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +module_init(watchdog_vpe1_init); | ||||||
|  | +module_exit(watchdog_vpe1_exit); | ||||||
|  | + | ||||||
|  | +EXPORT_SYMBOL(vpe1_sw_wdog_register_reset_handler); | ||||||
|  | +EXPORT_SYMBOL(vpe1_sw_wdog_start); | ||||||
|  | +EXPORT_SYMBOL(vpe1_sw_wdog_stop); | ||||||
|  | + | ||||||
|  | +MODULE_AUTHOR("LXDB"); | ||||||
|  | +MODULE_DESCRIPTION("Software Watchdog For VPE1"); | ||||||
|  | +MODULE_LICENSE("GPL"); | ||||||
|  | --- a/arch/mips/lantiq/Makefile | ||||||
|  | +++ b/arch/mips/lantiq/Makefile | ||||||
|  | @@ -6,6 +6,8 @@ | ||||||
|  |   | ||||||
|  |  obj-y := irq.o clk.o prom.o | ||||||
|  |   | ||||||
|  | +obj-$(CONFIG_MIPS_VPE_LOADER) += softdog_vpe.o | ||||||
|  | + | ||||||
|  |  obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | ||||||
|  |   | ||||||
|  |  obj-$(CONFIG_SOC_TYPE_XWAY) += xway/ | ||||||
| @@ -0,0 +1,22 @@ | |||||||
|  | --- a/arch/mips/pci/pci-lantiq.c | ||||||
|  | +++ b/arch/mips/pci/pci-lantiq.c | ||||||
|  | @@ -61,6 +61,8 @@ | ||||||
|  |  #define ltq_pci_cfg_w32(x, y)	ltq_w32((x), ltq_pci_mapped_cfg + (y)) | ||||||
|  |  #define ltq_pci_cfg_r32(x)	ltq_r32(ltq_pci_mapped_cfg + (x)) | ||||||
|  |   | ||||||
|  | +extern u32 max_low_pfn; | ||||||
|  | + | ||||||
|  |  __iomem void *ltq_pci_mapped_cfg; | ||||||
|  |  static __iomem void *ltq_pci_membase; | ||||||
|  |   | ||||||
|  | @@ -86,8 +88,8 @@ static inline u32 ltq_calc_bar11mask(voi | ||||||
|  |  	u32 mem, bar11mask; | ||||||
|  |   | ||||||
|  |  	/* BAR11MASK value depends on available memory on system. */ | ||||||
|  | -	mem = get_num_physpages() * PAGE_SIZE; | ||||||
|  | -	bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) - 1)) - 1)) | 8; | ||||||
|  | +	mem = max_low_pfn << PAGE_SHIFT; | ||||||
|  | +	bar11mask = ((-roundup_pow_of_two(mem)) & 0x0F000000) | 8; | ||||||
|  |   | ||||||
|  |  	return bar11mask; | ||||||
|  |  } | ||||||
| @@ -0,0 +1,221 @@ | |||||||
|  | --- a/drivers/mtd/maps/lantiq-flash.c | ||||||
|  | +++ b/drivers/mtd/maps/lantiq-flash.c | ||||||
|  | @@ -19,6 +19,7 @@ | ||||||
|  |  #include <linux/mtd/cfi.h> | ||||||
|  |  #include <linux/platform_device.h> | ||||||
|  |  #include <linux/mtd/physmap.h> | ||||||
|  | +#include <linux/mtd/concat.h> | ||||||
|  |  #include <linux/of.h> | ||||||
|  |   | ||||||
|  |  #include <lantiq_soc.h> | ||||||
|  | @@ -38,13 +39,16 @@ enum { | ||||||
|  |  	LTQ_NOR_NORMAL | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +#define MAX_RESOURCES		4 | ||||||
|  | + | ||||||
|  |  struct ltq_mtd { | ||||||
|  | -	struct resource *res; | ||||||
|  | -	struct mtd_info *mtd; | ||||||
|  | -	struct map_info *map; | ||||||
|  | +	struct mtd_info *mtd[MAX_RESOURCES]; | ||||||
|  | +	struct mtd_info	*cmtd; | ||||||
|  | +	struct map_info map[MAX_RESOURCES]; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const char ltq_map_name[] = "ltq_nor"; | ||||||
|  | +static const char * const ltq_probe_types[] = { "cmdlinepart", "ofpart", NULL }; | ||||||
|  |   | ||||||
|  |  static map_word | ||||||
|  |  ltq_read16(struct map_info *map, unsigned long adr) | ||||||
|  | @@ -108,11 +112,43 @@ ltq_copy_to(struct map_info *map, unsign | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | +ltq_mtd_remove(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); | ||||||
|  | +	int i; | ||||||
|  | + | ||||||
|  | +	if (ltq_mtd == NULL) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	if (ltq_mtd->cmtd) { | ||||||
|  | +		mtd_device_unregister(ltq_mtd->cmtd); | ||||||
|  | +		if (ltq_mtd->cmtd != ltq_mtd->mtd[0]) | ||||||
|  | +			mtd_concat_destroy(ltq_mtd->cmtd); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < MAX_RESOURCES; i++) { | ||||||
|  | +		if (ltq_mtd->mtd[i] != NULL) | ||||||
|  | +			map_destroy(ltq_mtd->mtd[i]); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	kfree(ltq_mtd); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  |  ltq_mtd_probe(struct platform_device *pdev) | ||||||
|  |  { | ||||||
|  |  	struct ltq_mtd *ltq_mtd; | ||||||
|  |  	struct cfi_private *cfi; | ||||||
|  | -	int err; | ||||||
|  | +	int err = 0; | ||||||
|  | +	int i; | ||||||
|  | +	int devices_found = 0; | ||||||
|  | + | ||||||
|  | +	static const char *rom_probe_types[] = { | ||||||
|  | +		"cfi_probe", "jedec_probe", NULL | ||||||
|  | +	}; | ||||||
|  | +	const char **type; | ||||||
|  |   | ||||||
|  |  	if (of_machine_is_compatible("lantiq,falcon") && | ||||||
|  |  			(ltq_boot_select() != BS_FLASH)) { | ||||||
|  | @@ -126,75 +162,89 @@ ltq_mtd_probe(struct platform_device *pd | ||||||
|  |   | ||||||
|  |  	platform_set_drvdata(pdev, ltq_mtd); | ||||||
|  |   | ||||||
|  | -	ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | -	if (!ltq_mtd->res) { | ||||||
|  | -		dev_err(&pdev->dev, "failed to get memory resource\n"); | ||||||
|  | -		return -ENOENT; | ||||||
|  | +	for (i = 0; i < pdev->num_resources; i++) { | ||||||
|  | +		printk(KERN_NOTICE "lantiq nor flash device: %.8llx at %.8llx\n", | ||||||
|  | +		       (unsigned long long)resource_size(&pdev->resource[i]), | ||||||
|  | +		       (unsigned long long)pdev->resource[i].start); | ||||||
|  | +	 | ||||||
|  | +		if (!devm_request_mem_region(&pdev->dev, | ||||||
|  | +			pdev->resource[i].start, | ||||||
|  | +			resource_size(&pdev->resource[i]), | ||||||
|  | +			dev_name(&pdev->dev))) { | ||||||
|  | +			dev_err(&pdev->dev, "Could not reserve memory region\n"); | ||||||
|  | +			return -ENOMEM; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		ltq_mtd->map[i].name = ltq_map_name; | ||||||
|  | +		ltq_mtd->map[i].bankwidth = 2; | ||||||
|  | +		ltq_mtd->map[i].read = ltq_read16; | ||||||
|  | +		ltq_mtd->map[i].write = ltq_write16; | ||||||
|  | +		ltq_mtd->map[i].copy_from = ltq_copy_from; | ||||||
|  | +		ltq_mtd->map[i].copy_to = ltq_copy_to; | ||||||
|  | + | ||||||
|  | +		if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL)) | ||||||
|  | +			ltq_mtd->map[i].phys = NO_XIP; | ||||||
|  | +		else | ||||||
|  | +			ltq_mtd->map[i].phys = pdev->resource[i].start; | ||||||
|  | +		ltq_mtd->map[i].size = resource_size(&pdev->resource[i]); | ||||||
|  | +		ltq_mtd->map[i].virt = devm_ioremap(&pdev->dev, pdev->resource[i].start, | ||||||
|  | +						 ltq_mtd->map[i].size); | ||||||
|  | +		if (IS_ERR(ltq_mtd->map[i].virt)) | ||||||
|  | +			return PTR_ERR(ltq_mtd->map[i].virt); | ||||||
|  | + | ||||||
|  | +		if (ltq_mtd->map[i].virt == NULL) { | ||||||
|  | +			dev_err(&pdev->dev, "Failed to ioremap flash region\n"); | ||||||
|  | +			err = PTR_ERR(ltq_mtd->map[i].virt); | ||||||
|  | +			goto err_out; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		ltq_mtd->map[i].map_priv_1 = LTQ_NOR_PROBING; | ||||||
|  | +		for (type = rom_probe_types; !ltq_mtd->mtd[i] && *type; type++) | ||||||
|  | +			ltq_mtd->mtd[i] = do_map_probe(*type, <q_mtd->map[i]); | ||||||
|  | +		ltq_mtd->map[i].map_priv_1 = LTQ_NOR_NORMAL; | ||||||
|  | + | ||||||
|  | +		if (!ltq_mtd->mtd[i]) { | ||||||
|  | +			dev_err(&pdev->dev, "probing failed\n"); | ||||||
|  | +			return -ENXIO; | ||||||
|  | +		} else { | ||||||
|  | +			devices_found++; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		ltq_mtd->mtd[i]->owner = THIS_MODULE; | ||||||
|  | +		ltq_mtd->mtd[i]->dev.parent = &pdev->dev; | ||||||
|  | + | ||||||
|  | +		cfi = ltq_mtd->map[i].fldrv_priv; | ||||||
|  | +		cfi->addr_unlock1 ^= 1; | ||||||
|  | +		cfi->addr_unlock2 ^= 1; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	ltq_mtd->map = devm_kzalloc(&pdev->dev, sizeof(struct map_info), | ||||||
|  | -				    GFP_KERNEL); | ||||||
|  | -	if (!ltq_mtd->map) | ||||||
|  | -		return -ENOMEM; | ||||||
|  | +	if (devices_found == 1) { | ||||||
|  | +		ltq_mtd->cmtd = ltq_mtd->mtd[0]; | ||||||
|  | +	} else if (devices_found > 1) { | ||||||
|  | +		/* | ||||||
|  | +		 * We detected multiple devices. Concatenate them together. | ||||||
|  | +		 */ | ||||||
|  | +		ltq_mtd->cmtd = mtd_concat_create(ltq_mtd->mtd, devices_found, dev_name(&pdev->dev)); | ||||||
|  | +		if (ltq_mtd->cmtd == NULL) | ||||||
|  | +			err = -ENXIO; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  | -	if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL)) | ||||||
|  | -		ltq_mtd->map->phys = NO_XIP; | ||||||
|  | -	else | ||||||
|  | -		ltq_mtd->map->phys = ltq_mtd->res->start; | ||||||
|  | -	ltq_mtd->res->start; | ||||||
|  | -	ltq_mtd->map->size = resource_size(ltq_mtd->res); | ||||||
|  | -	ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res); | ||||||
|  | -	if (IS_ERR(ltq_mtd->map->virt)) | ||||||
|  | -		return PTR_ERR(ltq_mtd->map->virt); | ||||||
|  | - | ||||||
|  | -	ltq_mtd->map->name = ltq_map_name; | ||||||
|  | -	ltq_mtd->map->bankwidth = 2; | ||||||
|  | -	ltq_mtd->map->read = ltq_read16; | ||||||
|  | -	ltq_mtd->map->write = ltq_write16; | ||||||
|  | -	ltq_mtd->map->copy_from = ltq_copy_from; | ||||||
|  | -	ltq_mtd->map->copy_to = ltq_copy_to; | ||||||
|  | - | ||||||
|  | -	ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING; | ||||||
|  | -	ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map); | ||||||
|  | -	ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL; | ||||||
|  | - | ||||||
|  | -	if (!ltq_mtd->mtd) { | ||||||
|  | -		dev_err(&pdev->dev, "probing failed\n"); | ||||||
|  | -		return -ENXIO; | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  | -	ltq_mtd->mtd->dev.parent = &pdev->dev; | ||||||
|  | -	mtd_set_of_node(ltq_mtd->mtd, pdev->dev.of_node); | ||||||
|  | - | ||||||
|  | -	cfi = ltq_mtd->map->fldrv_priv; | ||||||
|  | -	cfi->addr_unlock1 ^= 1; | ||||||
|  | -	cfi->addr_unlock2 ^= 1; | ||||||
|  | +	ltq_mtd->cmtd->dev.parent = &pdev->dev; | ||||||
|  | +	mtd_set_of_node(ltq_mtd->cmtd, pdev->dev.of_node); | ||||||
|  |   | ||||||
|  | -	err = mtd_device_register(ltq_mtd->mtd, NULL, 0); | ||||||
|  | +	err = mtd_device_register(ltq_mtd->cmtd, NULL, 0); | ||||||
|  |  	if (err) { | ||||||
|  |  		dev_err(&pdev->dev, "failed to add partitions\n"); | ||||||
|  | -		goto err_destroy; | ||||||
|  | +		goto err_out; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |   | ||||||
|  | -err_destroy: | ||||||
|  | -	map_destroy(ltq_mtd->mtd); | ||||||
|  | +err_out: | ||||||
|  | +	ltq_mtd_remove(pdev); | ||||||
|  |  	return err; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int | ||||||
|  | -ltq_mtd_remove(struct platform_device *pdev) | ||||||
|  | -{ | ||||||
|  | -	struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); | ||||||
|  | - | ||||||
|  | -	if (ltq_mtd && ltq_mtd->mtd) { | ||||||
|  | -		mtd_device_unregister(ltq_mtd->mtd); | ||||||
|  | -		map_destroy(ltq_mtd->mtd); | ||||||
|  | -	} | ||||||
|  | -	return 0; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static const struct of_device_id ltq_mtd_match[] = { | ||||||
|  |  	{ .compatible = "lantiq,nor" }, | ||||||
|  |  	{}, | ||||||
| @@ -0,0 +1,152 @@ | |||||||
|  | From 58078a30038b578c26c532545448fe3746648390 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | Date: Thu, 29 Dec 2016 21:02:57 +0100 | ||||||
|  | Subject: [PATCH] MIPS: lantiq: lock DMA register accesses for SMP | ||||||
|  |  | ||||||
|  | The DMA controller channel and port configuration is changed by | ||||||
|  | selecting the port or channel in one register and then update the | ||||||
|  | configuration in other registers. This has to be done in an atomic | ||||||
|  | operation. Previously only the local interrupts were deactivated which | ||||||
|  | works for single CPU systems. If the system supports SMP a better | ||||||
|  | locking is needed, use spinlocks instead. | ||||||
|  | On more recent SoCs (at least xrx200 and later) there are two memory | ||||||
|  | regions to change the configuration, there we could use one area for | ||||||
|  | each CPU and do not have to synchronize between the CPUs and more. | ||||||
|  |  | ||||||
|  | Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> | ||||||
|  | --- | ||||||
|  |  arch/mips/lantiq/xway/dma.c | 38 ++++++++++++++++++++------------------ | ||||||
|  |  1 file changed, 20 insertions(+), 18 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/arch/mips/lantiq/xway/dma.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/dma.c | ||||||
|  | @@ -20,6 +20,7 @@ | ||||||
|  |  #include <linux/io.h> | ||||||
|  |  #include <linux/dma-mapping.h> | ||||||
|  |  #include <linux/module.h> | ||||||
|  | +#include <linux/spinlock.h> | ||||||
|  |  #include <linux/clk.h> | ||||||
|  |  #include <linux/err.h> | ||||||
|  |   | ||||||
|  | @@ -59,16 +60,17 @@ | ||||||
|  |  						ltq_dma_membase + (z)) | ||||||
|  |   | ||||||
|  |  static void __iomem *ltq_dma_membase; | ||||||
|  | +static DEFINE_SPINLOCK(ltq_dma_lock); | ||||||
|  |   | ||||||
|  |  void | ||||||
|  |  ltq_dma_enable_irq(struct ltq_dma_channel *ch) | ||||||
|  |  { | ||||||
|  |  	unsigned long flags; | ||||||
|  |   | ||||||
|  | -	local_irq_save(flags); | ||||||
|  | +	spin_lock_irqsave(<q_dma_lock, flags); | ||||||
|  |  	ltq_dma_w32(ch->nr, LTQ_DMA_CS); | ||||||
|  |  	ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN); | ||||||
|  | -	local_irq_restore(flags); | ||||||
|  | +	spin_unlock_irqrestore(<q_dma_lock, flags); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(ltq_dma_enable_irq); | ||||||
|  |   | ||||||
|  | @@ -77,10 +79,10 @@ ltq_dma_disable_irq(struct ltq_dma_chann | ||||||
|  |  { | ||||||
|  |  	unsigned long flags; | ||||||
|  |   | ||||||
|  | -	local_irq_save(flags); | ||||||
|  | +	spin_lock_irqsave(<q_dma_lock, flags); | ||||||
|  |  	ltq_dma_w32(ch->nr, LTQ_DMA_CS); | ||||||
|  |  	ltq_dma_w32_mask(1 << ch->nr, 0, LTQ_DMA_IRNEN); | ||||||
|  | -	local_irq_restore(flags); | ||||||
|  | +	spin_unlock_irqrestore(<q_dma_lock, flags); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(ltq_dma_disable_irq); | ||||||
|  |   | ||||||
|  | @@ -89,10 +91,10 @@ ltq_dma_ack_irq(struct ltq_dma_channel * | ||||||
|  |  { | ||||||
|  |  	unsigned long flags; | ||||||
|  |   | ||||||
|  | -	local_irq_save(flags); | ||||||
|  | +	spin_lock_irqsave(<q_dma_lock, flags); | ||||||
|  |  	ltq_dma_w32(ch->nr, LTQ_DMA_CS); | ||||||
|  |  	ltq_dma_w32(DMA_IRQ_ACK, LTQ_DMA_CIS); | ||||||
|  | -	local_irq_restore(flags); | ||||||
|  | +	spin_unlock_irqrestore(<q_dma_lock, flags); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(ltq_dma_ack_irq); | ||||||
|  |   | ||||||
|  | @@ -101,11 +103,11 @@ ltq_dma_open(struct ltq_dma_channel *ch) | ||||||
|  |  { | ||||||
|  |  	unsigned long flag; | ||||||
|  |   | ||||||
|  | -	local_irq_save(flag); | ||||||
|  | +	spin_lock_irqsave(<q_dma_lock, flag); | ||||||
|  |  	ltq_dma_w32(ch->nr, LTQ_DMA_CS); | ||||||
|  |  	ltq_dma_w32_mask(0, DMA_CHAN_ON, LTQ_DMA_CCTRL); | ||||||
|  | -	ltq_dma_enable_irq(ch); | ||||||
|  | -	local_irq_restore(flag); | ||||||
|  | +	ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN); | ||||||
|  | +	spin_unlock_irqrestore(<q_dma_lock, flag); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(ltq_dma_open); | ||||||
|  |   | ||||||
|  | @@ -114,11 +116,11 @@ ltq_dma_close(struct ltq_dma_channel *ch | ||||||
|  |  { | ||||||
|  |  	unsigned long flag; | ||||||
|  |   | ||||||
|  | -	local_irq_save(flag); | ||||||
|  | +	spin_lock_irqsave(<q_dma_lock, flag); | ||||||
|  |  	ltq_dma_w32(ch->nr, LTQ_DMA_CS); | ||||||
|  |  	ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); | ||||||
|  | -	ltq_dma_disable_irq(ch); | ||||||
|  | -	local_irq_restore(flag); | ||||||
|  | +	ltq_dma_w32_mask(1 << ch->nr, 0, LTQ_DMA_IRNEN); | ||||||
|  | +	spin_unlock_irqrestore(<q_dma_lock, flag); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(ltq_dma_close); | ||||||
|  |   | ||||||
|  | @@ -133,7 +135,7 @@ ltq_dma_alloc(struct ltq_dma_channel *ch | ||||||
|  |  				&ch->phys, GFP_ATOMIC); | ||||||
|  |  	memset(ch->desc_base, 0, LTQ_DESC_NUM * LTQ_DESC_SIZE); | ||||||
|  |   | ||||||
|  | -	local_irq_save(flags); | ||||||
|  | +	spin_lock_irqsave(<q_dma_lock, flags); | ||||||
|  |  	ltq_dma_w32(ch->nr, LTQ_DMA_CS); | ||||||
|  |  	ltq_dma_w32(ch->phys, LTQ_DMA_CDBA); | ||||||
|  |  	ltq_dma_w32(LTQ_DESC_NUM, LTQ_DMA_CDLEN); | ||||||
|  | @@ -142,7 +144,7 @@ ltq_dma_alloc(struct ltq_dma_channel *ch | ||||||
|  |  	ltq_dma_w32_mask(0, DMA_CHAN_RST, LTQ_DMA_CCTRL); | ||||||
|  |  	while (ltq_dma_r32(LTQ_DMA_CCTRL) & DMA_CHAN_RST) | ||||||
|  |  		; | ||||||
|  | -	local_irq_restore(flags); | ||||||
|  | +	spin_unlock_irqrestore(<q_dma_lock, flags); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  void | ||||||
|  | @@ -152,11 +154,11 @@ ltq_dma_alloc_tx(struct ltq_dma_channel | ||||||
|  |   | ||||||
|  |  	ltq_dma_alloc(ch); | ||||||
|  |   | ||||||
|  | -	local_irq_save(flags); | ||||||
|  | +	spin_lock_irqsave(<q_dma_lock, flags); | ||||||
|  |  	ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE); | ||||||
|  |  	ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN); | ||||||
|  |  	ltq_dma_w32(DMA_WEIGHT | DMA_TX, LTQ_DMA_CCTRL); | ||||||
|  | -	local_irq_restore(flags); | ||||||
|  | +	spin_unlock_irqrestore(<q_dma_lock, flags); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(ltq_dma_alloc_tx); | ||||||
|  |   | ||||||
|  | @@ -167,11 +169,11 @@ ltq_dma_alloc_rx(struct ltq_dma_channel | ||||||
|  |   | ||||||
|  |  	ltq_dma_alloc(ch); | ||||||
|  |   | ||||||
|  | -	local_irq_save(flags); | ||||||
|  | +	spin_lock_irqsave(<q_dma_lock, flags); | ||||||
|  |  	ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE); | ||||||
|  |  	ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN); | ||||||
|  |  	ltq_dma_w32(DMA_WEIGHT, LTQ_DMA_CCTRL); | ||||||
|  | -	local_irq_restore(flags); | ||||||
|  | +	spin_unlock_irqrestore(<q_dma_lock, flags); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(ltq_dma_alloc_rx); | ||||||
|  |   | ||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | --- a/drivers/mtd/chips/cfi_cmdset_0001.c | ||||||
|  | +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | ||||||
|  | @@ -39,7 +39,7 @@ | ||||||
|  |  /* #define CMDSET0001_DISABLE_WRITE_SUSPEND */ | ||||||
|  |   | ||||||
|  |  // debugging, turns off buffer write mode if set to 1 | ||||||
|  | -#define FORCE_WORD_WRITE 0 | ||||||
|  | +#define FORCE_WORD_WRITE 1 | ||||||
|  |   | ||||||
|  |  /* Intel chips */ | ||||||
|  |  #define I82802AB	0x00ad | ||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | --- a/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | +++ b/arch/mips/lantiq/xway/sysctrl.c | ||||||
|  | @@ -442,6 +442,20 @@ static void clkdev_add_clkout(void) | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void set_phy_clock_source(struct device_node *np_cgu) | ||||||
|  | +{ | ||||||
|  | +	u32 phy_clk_src, ifcc; | ||||||
|  | + | ||||||
|  | +	if (!np_cgu) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	if (of_property_read_u32(np_cgu, "lantiq,phy-clk-src", &phy_clk_src)) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	ifcc = ltq_cgu_r32(ifccr) & ~(0x1c); | ||||||
|  | +	ltq_cgu_w32(ifcc | (phy_clk_src << 2), ifccr); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  /* bring up all register ranges that we need for basic system control */ | ||||||
|  |  void __init ltq_soc_init(void) | ||||||
|  |  { | ||||||
|  | @@ -628,4 +642,6 @@ void __init ltq_soc_init(void) | ||||||
|  |  	if (of_machine_is_compatible("lantiq,vr9")) | ||||||
|  |  		xbar_fpi_burst_disable(); | ||||||
|  |  	usb_set_clock(); | ||||||
|  | + | ||||||
|  | +	set_phy_clock_source(np_cgu); | ||||||
|  |  } | ||||||
| @@ -0,0 +1,184 @@ | |||||||
|  | --- a/drivers/hwmon/Makefile | ||||||
|  | +++ b/drivers/hwmon/Makefile | ||||||
|  | @@ -109,6 +109,7 @@ obj-$(CONFIG_SENSORS_LTC4222)	+= ltc4222 | ||||||
|  |  obj-$(CONFIG_SENSORS_LTC4245)	+= ltc4245.o | ||||||
|  |  obj-$(CONFIG_SENSORS_LTC4260)	+= ltc4260.o | ||||||
|  |  obj-$(CONFIG_SENSORS_LTC4261)	+= ltc4261.o | ||||||
|  | +obj-$(CONFIG_SENSORS_LTQ_CPUTEMP) += ltq-cputemp.o | ||||||
|  |  obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o | ||||||
|  |  obj-$(CONFIG_SENSORS_MAX16065)	+= max16065.o | ||||||
|  |  obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o | ||||||
|  | --- a/drivers/hwmon/Kconfig | ||||||
|  | +++ b/drivers/hwmon/Kconfig | ||||||
|  | @@ -780,6 +780,14 @@ config SENSORS_LTC4261 | ||||||
|  |  	  This driver can also be built as a module. If so, the module will | ||||||
|  |  	  be called ltc4261. | ||||||
|  |   | ||||||
|  | +config SENSORS_LTQ_CPUTEMP | ||||||
|  | +	bool "Lantiq CPU temperature sensor" | ||||||
|  | +	depends on LANTIQ | ||||||
|  | +	default n | ||||||
|  | +	help | ||||||
|  | +	  If you say yes here you get support for the temperature | ||||||
|  | +	  sensor inside your CPU. | ||||||
|  | + | ||||||
|  |  config SENSORS_MAX1111 | ||||||
|  |  	tristate "Maxim MAX1111 Serial 8-bit ADC chip and compatibles" | ||||||
|  |  	depends on SPI_MASTER | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/hwmon/ltq-cputemp.c | ||||||
|  | @@ -0,0 +1,154 @@ | ||||||
|  | +/* Lantiq CPU Temperatur sensor driver for xrx200 | ||||||
|  | + * | ||||||
|  | + * Copyright (C) 2016 Florian Eckert <feckert@tdt.de> | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License as published by | ||||||
|  | + * the Free Software Foundation; either version 2 of the License, or | ||||||
|  | + * (at your option) any later version | ||||||
|  | + * | ||||||
|  | + * This program is distributed in the hope that it will be useful | ||||||
|  | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | + * GNU General Public License for more details | ||||||
|  | + * | ||||||
|  | + * You should have received a copy of the GNU General Public License | ||||||
|  | + * along with this program; if not, see <http://www.gnu.org/licenses/> | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/delay.h> | ||||||
|  | +#include <linux/of_device.h> | ||||||
|  | +#include <linux/hwmon.h> | ||||||
|  | +#include <linux/hwmon-sysfs.h> | ||||||
|  | + | ||||||
|  | +#include <lantiq_soc.h> | ||||||
|  | + | ||||||
|  | +/* gphy1 configuration register contains cpu temperature */ | ||||||
|  | +#define CGU_GPHY1_CR   0x0040 | ||||||
|  | +#define CGU_TEMP_PD    BIT(19) | ||||||
|  | + | ||||||
|  | +static void ltq_cputemp_enable(void) | ||||||
|  | +{ | ||||||
|  | +	ltq_cgu_w32(ltq_cgu_r32(CGU_GPHY1_CR) | CGU_TEMP_PD, CGU_GPHY1_CR); | ||||||
|  | + | ||||||
|  | +	/* wait a short moment to let the SoC get the first temperatur value */ | ||||||
|  | +	mdelay(100); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void ltq_cputemp_disable(void) | ||||||
|  | +{ | ||||||
|  | +	ltq_cgu_w32(ltq_cgu_r32(CGU_GPHY1_CR) & ~CGU_TEMP_PD, CGU_GPHY1_CR); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int ltq_cputemp_read(void) | ||||||
|  | +{ | ||||||
|  | +	int value; | ||||||
|  | + | ||||||
|  | +	/* get the temperature including one decimal place */ | ||||||
|  | +	value = (ltq_cgu_r32(CGU_GPHY1_CR) >> 9) & 0x01FF; | ||||||
|  | +	value = (value << 2 ) + value; | ||||||
|  | + | ||||||
|  | +	/* range -38 to +154 °C, register value zero is -38.0 °C */ | ||||||
|  | +	value -= 380; | ||||||
|  | + | ||||||
|  | +	return value; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static ssize_t show_cputemp(struct device *dev, | ||||||
|  | +			struct device_attribute *attr, char *buf) | ||||||
|  | +{ | ||||||
|  | +	int value; | ||||||
|  | + | ||||||
|  | +	value = ltq_cputemp_read(); | ||||||
|  | +	/* scale temp to millidegree */ | ||||||
|  | +	value = value * 100; | ||||||
|  | + | ||||||
|  | +	return sprintf(buf, "%d\n", value); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static DEVICE_ATTR(temp1_input, S_IRUGO, show_cputemp, NULL); | ||||||
|  | + | ||||||
|  | +static struct attribute *ltq_cputemp_attrs[] = { | ||||||
|  | +	&dev_attr_temp1_input.attr, | ||||||
|  | +	NULL | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +ATTRIBUTE_GROUPS(ltq_cputemp); | ||||||
|  | + | ||||||
|  | +static int ltq_cputemp_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	int value = 0; | ||||||
|  | +	int ret; | ||||||
|  | +	struct device *hwmon_dev; | ||||||
|  | + | ||||||
|  | +	/* available on vr9 v1.2 SoCs only */ | ||||||
|  | +	if (ltq_soc_type() != SOC_TYPE_VR9_2) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, | ||||||
|  | +							"CPU0", | ||||||
|  | +							NULL, | ||||||
|  | +							ltq_cputemp_groups); | ||||||
|  | + | ||||||
|  | +	if (IS_ERR(hwmon_dev)) { | ||||||
|  | +		dev_err(&pdev->dev, "Failed to register as hwmon device"); | ||||||
|  | +		ret = PTR_ERR(hwmon_dev); | ||||||
|  | +		goto error_hwmon; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ltq_cputemp_enable(); | ||||||
|  | +	value = ltq_cputemp_read(); | ||||||
|  | +	dev_info(&pdev->dev, "Current CPU die temperature: %d.%d °C", value / 10, value % 10); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | + | ||||||
|  | +error_hwmon: | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int ltq_cputemp_release(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	hwmon_device_unregister(&pdev->dev); | ||||||
|  | +	ltq_cputemp_disable(); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +const struct of_device_id ltq_cputemp_match[] = { | ||||||
|  | +	{ .compatible = "lantiq,cputemp" }, | ||||||
|  | +	{}, | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, ltq_cputemp_match); | ||||||
|  | + | ||||||
|  | +static struct platform_driver ltq_cputemp_driver = { | ||||||
|  | +	.probe = ltq_cputemp_probe, | ||||||
|  | +	.remove = ltq_cputemp_release, | ||||||
|  | +	.driver = { | ||||||
|  | +		.name = "ltq-cputemp", | ||||||
|  | +		.owner = THIS_MODULE, | ||||||
|  | +		.of_match_table = ltq_cputemp_match, | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +int __init init_ltq_cputemp(void) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	ret = platform_driver_register(<q_cputemp_driver); | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +void clean_ltq_cputemp(void) | ||||||
|  | +{ | ||||||
|  | +	platform_driver_unregister(<q_cputemp_driver); | ||||||
|  | +	return; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +module_init(init_ltq_cputemp); | ||||||
|  | +module_exit(clean_ltq_cputemp); | ||||||
|  | + | ||||||
|  | +MODULE_AUTHOR("Florian Eckert <feckert@tdt.de>"); | ||||||
|  | + | ||||||
|  | +MODULE_DESCRIPTION("Lantiq Temperature Sensor"); | ||||||
|  | +MODULE_LICENSE("GPL"); | ||||||
| @@ -13,6 +13,7 @@ CONFIG_ICPLUS_PHY=y | |||||||
| CONFIG_INPUT=y | CONFIG_INPUT=y | ||||||
| CONFIG_INPUT_EVDEV=y | CONFIG_INPUT_EVDEV=y | ||||||
| CONFIG_INPUT_POLLDEV=y | CONFIG_INPUT_POLLDEV=y | ||||||
|  | CONFIG_INTEL_XWAY_PHY=y | ||||||
| # CONFIG_ISDN is not set | # CONFIG_ISDN is not set | ||||||
| CONFIG_LANTIQ_PHY=y | CONFIG_LANTIQ_PHY=y | ||||||
| CONFIG_LANTIQ_XRX200=y | CONFIG_LANTIQ_XRX200=y | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Hauke Mehrtens
					Hauke Mehrtens