diff options
49 files changed, 1412 insertions, 204 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 53363e3..5c30ae9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -33,6 +33,9 @@ config TARGET_MALTA select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 select SUPPORTS_CPU_MIPS32_R6 + select SUPPORTS_CPU_MIPS64_R1 + select SUPPORTS_CPU_MIPS64_R2 + select SUPPORTS_CPU_MIPS64_R6 select SWAP_IO_SPACE select MIPS_L1_CACHE_SHIFT_6 @@ -225,6 +228,9 @@ config MIPS_TUNE_14KC config MIPS_TUNE_24KC bool +config MIPS_TUNE_34KC + bool + config MIPS_TUNE_74KC bool @@ -240,6 +246,40 @@ config SWAP_IO_SPACE config SYS_MIPS_CACHE_INIT_RAM_LOAD bool +config SYS_DCACHE_SIZE + int + default 0 + help + The total size of the L1 Dcache, if known at compile time. + +config SYS_DCACHE_LINE_SIZE + hex + default 0 + help + The size of L1 Dcache lines, if known at compile time. + +config SYS_ICACHE_SIZE + int + default 0 + help + The total size of the L1 ICache, if known at compile time. + +config SYS_ICACHE_LINE_SIZE + int + default 0 + help + The size of L1 Icache lines, if known at compile time. + +config SYS_CACHE_SIZE_AUTO + def_bool y if SYS_DCACHE_SIZE = 0 && SYS_ICACHE_SIZE = 0 && \ + SYS_DCACHE_LINE_SIZE = 0 && SYS_ICACHE_LINE_SIZE = 0 + help + Select this (or let it be auto-selected by not defining any cache + sizes) in order to allow U-Boot to automatically detect the sizes + of caches at runtime. This has a small cost in code size & runtime + so if you know the cache configuration for your system at compile + time it would be beneficial to configure it. + config MIPS_L1_CACHE_SHIFT_4 bool diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 0b5dbb6..efe7e44 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -34,6 +34,7 @@ arch-$(CONFIG_CPU_MIPS64_R6) += -march=mips64r6 -Wa,-mips64r6 tune-$(CONFIG_MIPS_TUNE_4KC) += -mtune=4kc tune-$(CONFIG_MIPS_TUNE_14KC) += -mtune=14kc tune-$(CONFIG_MIPS_TUNE_24KC) += -mtune=24kc +tune-$(CONFIG_MIPS_TUNE_34KC) += -mtune=34kc tune-$(CONFIG_MIPS_TUNE_74KC) += -mtune=74kc # Include default header files diff --git a/arch/mips/config.mk b/arch/mips/config.mk index 609a998..dcd3460 100644 --- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -65,7 +65,7 @@ else PF_ABICALLS := -mabicalls PF_PIC := -fpic PF_PIE := -pie -PF_OBJCOPY := -j .got -j .u_boot_list -j .rel.dyn -j .padding +PF_OBJCOPY := -j .got -j .rel.dyn -j .padding PF_OBJCOPY += -j .dtb.init.rodata endif @@ -74,4 +74,5 @@ PLATFORM_CPPFLAGS += -msoft-float PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections LDFLAGS_FINAL += --gc-sections $(PF_PIE) -OBJCOPYFLAGS += -j .text -j .rodata -j .data $(PF_OBJCOPY) +OBJCOPYFLAGS += -j .text -j .rodata -j .data -j .u_boot_list +OBJCOPYFLAGS += $(PF_OBJCOPY) diff --git a/arch/mips/cpu/u-boot-spl.lds b/arch/mips/cpu/u-boot-spl.lds new file mode 100644 index 0000000..07004ea --- /dev/null +++ b/arch/mips/cpu/u-boot-spl.lds @@ -0,0 +1,90 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .spl_mem : ORIGIN = CONFIG_SPL_TEXT_BASE, \ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .bss_mem : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_ARCH(mips) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : { + *(.text*) + } > .spl_mem + + . = ALIGN(4); + .rodata : { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } > .spl_mem + + . = ALIGN(4); + .data : { + *(SORT_BY_ALIGNMENT(.data*)) + *(SORT_BY_ALIGNMENT(.sdata*)) + } > .spl_mem + +#ifdef CONFIG_SPL_DM + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } > .spl_mem +#endif + + . = ALIGN(4); + __image_copy_end = .; + + .bss (NOLOAD) : { + __bss_start = .; + *(.bss*) + *(.sbss*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > .bss_mem + + .rel.dyn (NOLOAD) : { + *(.rel.dyn) + } + + .dynsym : { + *(.dynsym) + } + + .dynbss : { + *(.dynbss) + } + + .dynstr : { + *(.dynstr) + } + + .dynamic : { + *(.dynamic) + } + + .plt : { + *(.plt) + } + + .interp : { + *(.interp) + } + + .gnu : { + *(.gnu*) + } + + .MIPS.stubs : { + *(.MIPS.stubs) + } + + .hash : { + *(.hash) + } +} diff --git a/arch/mips/dts/ap121.dts b/arch/mips/dts/ap121.dts index e31f601..a934a58 100644 --- a/arch/mips/dts/ap121.dts +++ b/arch/mips/dts/ap121.dts @@ -41,3 +41,8 @@ reg = <0>; }; }; + +&gmac0 { + phy-mode = "rmii"; + status = "okay"; +}; diff --git a/arch/mips/dts/ar933x.dtsi b/arch/mips/dts/ar933x.dtsi index 00896b2..971f13e 100644 --- a/arch/mips/dts/ar933x.dtsi +++ b/arch/mips/dts/ar933x.dtsi @@ -75,7 +75,7 @@ }; gmac0: eth@0x19000000 { - compatible = "qca,ag7240-mac"; + compatible = "qca,ag933x-mac"; reg = <0x19000000 0x200>; phy = <&phy0>; phy-mode = "rmii"; @@ -92,7 +92,7 @@ }; gmac1: eth@0x1a000000 { - compatible = "qca,ag7240-mac"; + compatible = "qca,ag933x-mac"; reg = <0x1a000000 0x200>; phy = <&phy0>; phy-mode = "rgmii"; diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h index 806bd26..0cea581 100644 --- a/arch/mips/include/asm/cache.h +++ b/arch/mips/include/asm/cache.h @@ -12,4 +12,11 @@ #define ARCH_DMA_MINALIGN (L1_CACHE_BYTES) +/* + * CONFIG_SYS_CACHELINE_SIZE is still used in various drivers primarily for + * DMA buffer alignment. Satisfy those drivers by providing it as a synonym + * of ARCH_DMA_MINALIGN for now. + */ +#define CONFIG_SYS_CACHELINE_SIZE ARCH_DMA_MINALIGN + #endif /* __MIPS_CACHE_H__ */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 723a60a..5b86386 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -92,11 +92,8 @@ static inline unsigned long virt_to_phys(volatile const void *address) #ifdef CONFIG_64BIT if (addr < CKSEG0) return XPHYSADDR(addr); - - return CPHYSADDR(addr); -#else - return addr - PAGE_OFFSET + PHYS_OFFSET; #endif + return CPHYSADDR(addr); } /* diff --git a/arch/mips/include/asm/u-boot-mips.h b/arch/mips/include/asm/u-boot-mips.h index a5b2fc0..1f527bb 100644 --- a/arch/mips/include/asm/u-boot-mips.h +++ b/arch/mips/include/asm/u-boot-mips.h @@ -1,23 +1,8 @@ /* * SPDX-License-Identifier: GPL-2.0+ - * - * Copyright (C) 2003 Wolfgang Denk, DENX Software Engineering, wd@denx.de */ -static inline unsigned long bss_start(void) -{ - extern char __bss_start[]; - return (unsigned long) &__bss_start; -} +#ifndef _U_BOOT_MIPS_H_ +#define _U_BOOT_MIPS_H_ -static inline unsigned long bss_end(void) -{ - extern ulong __bss_end; - return (unsigned long) &__bss_end; -} - -static inline unsigned long image_copy_end(void) -{ - extern char __image_copy_end[]; - return (unsigned long) &__image_copy_end; -} +#endif /* _U_BOOT_MIPS_H_ */ diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c index 7482005..5f520c0 100644 --- a/arch/mips/lib/cache.c +++ b/arch/mips/lib/cache.c @@ -9,23 +9,13 @@ #include <asm/cacheops.h> #include <asm/mipsregs.h> -#ifdef CONFIG_SYS_CACHELINE_SIZE - static inline unsigned long icache_line_size(void) { - return CONFIG_SYS_CACHELINE_SIZE; -} - -static inline unsigned long dcache_line_size(void) -{ - return CONFIG_SYS_CACHELINE_SIZE; -} + unsigned long conf1, il; -#else /* !CONFIG_SYS_CACHELINE_SIZE */ + if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO)) + return CONFIG_SYS_ICACHE_LINE_SIZE; -static inline unsigned long icache_line_size(void) -{ - unsigned long conf1, il; conf1 = read_c0_config1(); il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF; if (!il) @@ -36,6 +26,10 @@ static inline unsigned long icache_line_size(void) static inline unsigned long dcache_line_size(void) { unsigned long conf1, dl; + + if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO)) + return CONFIG_SYS_DCACHE_LINE_SIZE; + conf1 = read_c0_config1(); dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF; if (!dl) @@ -43,84 +37,59 @@ static inline unsigned long dcache_line_size(void) return 2 << dl; } -#endif /* !CONFIG_SYS_CACHELINE_SIZE */ +#define cache_loop(start, end, lsize, ops...) do { \ + const void *addr = (const void *)(start & ~(lsize - 1)); \ + const void *aend = (const void *)((end - 1) & ~(lsize - 1)); \ + const unsigned int cache_ops[] = { ops }; \ + unsigned int i; \ + \ + for (; addr <= aend; addr += lsize) { \ + for (i = 0; i < ARRAY_SIZE(cache_ops); i++) \ + mips_cache(cache_ops[i], addr); \ + } \ +} while (0) void flush_cache(ulong start_addr, ulong size) { unsigned long ilsize = icache_line_size(); unsigned long dlsize = dcache_line_size(); - const void *addr, *aend; /* aend will be miscalculated when size is zero, so we return here */ if (size == 0) return; - addr = (const void *)(start_addr & ~(dlsize - 1)); - aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1)); - if (ilsize == dlsize) { /* flush I-cache & D-cache simultaneously */ - while (1) { - mips_cache(HIT_WRITEBACK_INV_D, addr); - mips_cache(HIT_INVALIDATE_I, addr); - if (addr == aend) - break; - addr += dlsize; - } + cache_loop(start_addr, start_addr + size, ilsize, + HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I); return; } /* flush D-cache */ - while (1) { - mips_cache(HIT_WRITEBACK_INV_D, addr); - if (addr == aend) - break; - addr += dlsize; - } + cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D); /* flush I-cache */ - addr = (const void *)(start_addr & ~(ilsize - 1)); - aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1)); - while (1) { - mips_cache(HIT_INVALIDATE_I, addr); - if (addr == aend) - break; - addr += ilsize; - } + cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I); } void flush_dcache_range(ulong start_addr, ulong stop) { unsigned long lsize = dcache_line_size(); - const void *addr = (const void *)(start_addr & ~(lsize - 1)); - const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); /* aend will be miscalculated when size is zero, so we return here */ if (start_addr == stop) return; - while (1) { - mips_cache(HIT_WRITEBACK_INV_D, addr); - if (addr == aend) - break; - addr += lsize; - } + cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D); } void invalidate_dcache_range(ulong start_addr, ulong stop) { unsigned long lsize = dcache_line_size(); - const void *addr = (const void *)(start_addr & ~(lsize - 1)); - const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); /* aend will be miscalculated when size is zero, so we return here */ if (start_addr == stop) return; - while (1) { - mips_cache(HIT_INVALIDATE_D, addr); - if (addr == aend) - break; - addr += lsize; - } + cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_I); } diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S index 08b7c3a..bc8ab27 100644 --- a/arch/mips/lib/cache_init.S +++ b/arch/mips/lib/cache_init.S @@ -99,16 +99,16 @@ * */ LEAF(mips_cache_reset) -#ifdef CONFIG_SYS_ICACHE_SIZE +#ifndef CONFIG_SYS_CACHE_SIZE_AUTO li t2, CONFIG_SYS_ICACHE_SIZE - li t8, CONFIG_SYS_CACHELINE_SIZE + li t8, CONFIG_SYS_ICACHE_LINE_SIZE #else l1_info t2, t8, MIPS_CONF1_IA_SHF #endif -#ifdef CONFIG_SYS_DCACHE_SIZE +#ifndef CONFIG_SYS_CACHE_SIZE_AUTO li t3, CONFIG_SYS_DCACHE_SIZE - li t9, CONFIG_SYS_CACHELINE_SIZE + li t9, CONFIG_SYS_DCACHE_LINE_SIZE #else l1_info t3, t9, MIPS_CONF1_DA_SHF #endif @@ -116,7 +116,7 @@ LEAF(mips_cache_reset) #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD /* Determine the largest L1 cache size */ -#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE) +#ifndef CONFIG_SYS_CACHE_SIZE_AUTO #if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE li v0, CONFIG_SYS_ICACHE_SIZE #else diff --git a/arch/mips/mach-ath79/ar933x/clk.c b/arch/mips/mach-ath79/ar933x/clk.c index 9fcd496..6d98efc 100644 --- a/arch/mips/mach-ath79/ar933x/clk.c +++ b/arch/mips/mach-ath79/ar933x/clk.c @@ -9,7 +9,7 @@ #include <asm/addrspace.h> #include <asm/types.h> #include <mach/ar71xx_regs.h> -#include <mach/reset.h> +#include <mach/ath79.h> DECLARE_GLOBAL_DATA_PTR; @@ -17,7 +17,7 @@ static u32 ar933x_get_xtal(void) { u32 val; - val = get_bootstrap(); + val = ath79_get_bootstrap(); if (val & AR933X_BOOTSTRAP_REF_CLK_40) return 40000000; else diff --git a/arch/mips/mach-ath79/ar933x/ddr.c b/arch/mips/mach-ath79/ar933x/ddr.c index 7f20d34..2a25e23 100644 --- a/arch/mips/mach-ath79/ar933x/ddr.c +++ b/arch/mips/mach-ath79/ar933x/ddr.c @@ -10,7 +10,7 @@ #include <asm/addrspace.h> #include <asm/types.h> #include <mach/ar71xx_regs.h> -#include <mach/reset.h> +#include <mach/ath79.h> DECLARE_GLOBAL_DATA_PTR; @@ -114,7 +114,7 @@ void ddr_init(void) writel(DDR_CONF_REG_VAL, regs + AR71XX_DDR_REG_CONFIG); writel(DDR_CONF2_REG_VAL, regs + AR71XX_DDR_REG_CONFIG2); - val = get_bootstrap(); + val = ath79_get_bootstrap(); if (val & AR933X_BOOTSTRAP_DDR2) { /* AHB maximum timeout */ writel(0xfffff, regs + AR933X_DDR_REG_TIMEOUT_MAX); diff --git a/arch/mips/mach-ath79/ar934x/clk.c b/arch/mips/mach-ath79/ar934x/clk.c index 9c65184..9b41d3d 100644 --- a/arch/mips/mach-ath79/ar934x/clk.c +++ b/arch/mips/mach-ath79/ar934x/clk.c @@ -9,7 +9,7 @@ #include <asm/addrspace.h> #include <asm/types.h> #include <mach/ar71xx_regs.h> -#include <mach/reset.h> +#include <mach/ath79.h> #include <wait_bit.h> DECLARE_GLOBAL_DATA_PTR; @@ -119,7 +119,7 @@ void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz) writel(0x03000000, srif_regs + 0x188); /* Undocumented reg :-) */ /* Test for 40MHz XTAL */ - reg = get_bootstrap(); + reg = ath79_get_bootstrap(); if (reg & AR934X_BOOTSTRAP_REF_CLK_40) { xtal_40 = 1; cpu_srif = 0x41c00000; @@ -214,7 +214,7 @@ static u32 ar934x_get_xtal(void) { u32 val; - val = get_bootstrap(); + val = ath79_get_bootstrap(); if (val & AR934X_BOOTSTRAP_REF_CLK_40) return 40000000; else diff --git a/arch/mips/mach-ath79/ar934x/ddr.c b/arch/mips/mach-ath79/ar934x/ddr.c index 4621d58..2ba1efa 100644 --- a/arch/mips/mach-ath79/ar934x/ddr.c +++ b/arch/mips/mach-ath79/ar934x/ddr.c @@ -11,7 +11,7 @@ #include <asm/addrspace.h> #include <asm/types.h> #include <mach/ar71xx_regs.h> -#include <mach/reset.h> +#include <mach/ath79.h> DECLARE_GLOBAL_DATA_PTR; @@ -45,7 +45,7 @@ void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz) ddr_regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE, MAP_NOCACHE); - reg = get_bootstrap(); + reg = ath79_get_bootstrap(); if (reg & AR934X_BOOTSTRAP_SDRAM_DISABLED) { /* DDR */ if (reg & AR934X_BOOTSTRAP_DDR1) { /* DDR 1 */ memtype = AR934X_DDR1; diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h index dabcad0..7b48524 100644 --- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h +++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h @@ -331,6 +331,7 @@ #define AR933X_PLL_CPU_CONFIG_REG 0x00 #define AR933X_PLL_CLK_CTRL_REG 0x08 #define AR933X_PLL_DITHER_FRAC_REG 0x10 +#define AR933X_PLL_SWITCH_CLOCK_CONTROL_REG 0x24 #define AR933X_PLL_CPU_CONFIG_NINT_SHIFT 10 #define AR933X_PLL_CPU_CONFIG_NINT_MASK 0x3f diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h index 17af082..582c028 100644 --- a/arch/mips/mach-ath79/include/mach/ath79.h +++ b/arch/mips/mach-ath79/include/mach/ath79.h @@ -140,6 +140,7 @@ static inline int soc_is_qca956x(void) return soc_is_tp9343() || soc_is_qca9561(); } +u32 ath79_get_bootstrap(void); int ath79_eth_reset(void); int ath79_usb_reset(void); diff --git a/arch/mips/mach-ath79/include/mach/reset.h b/arch/mips/mach-ath79/include/mach/reset.h deleted file mode 100644 index c383bfe..0000000 --- a/arch/mips/mach-ath79/include/mach/reset.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __ASM_MACH_RESET_H -#define __ASM_MACH_RESET_H - -#include <linux/types.h> - -u32 get_bootstrap(void); - -#endif /* __ASM_MACH_RESET_H */ diff --git a/arch/mips/mach-ath79/qca953x/clk.c b/arch/mips/mach-ath79/qca953x/clk.c index ef0a28e..533356c 100644 --- a/arch/mips/mach-ath79/qca953x/clk.c +++ b/arch/mips/mach-ath79/qca953x/clk.c @@ -9,7 +9,7 @@ #include <asm/addrspace.h> #include <asm/types.h> #include <mach/ar71xx_regs.h> -#include <mach/reset.h> +#include <mach/ath79.h> DECLARE_GLOBAL_DATA_PTR; @@ -17,7 +17,7 @@ static u32 qca953x_get_xtal(void) { u32 val; - val = get_bootstrap(); + val = ath79_get_bootstrap(); if (val & QCA953X_BOOTSTRAP_REF_CLK_40) return 40000000; else diff --git a/arch/mips/mach-ath79/qca953x/ddr.c b/arch/mips/mach-ath79/qca953x/ddr.c index ac0130c..c6049d8 100644 --- a/arch/mips/mach-ath79/qca953x/ddr.c +++ b/arch/mips/mach-ath79/qca953x/ddr.c @@ -10,7 +10,7 @@ #include <asm/addrspace.h> #include <asm/types.h> #include <mach/ar71xx_regs.h> -#include <mach/reset.h> +#include <mach/ath79.h> DECLARE_GLOBAL_DATA_PTR; @@ -226,7 +226,7 @@ void ddr_init(void) regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE, MAP_NOCACHE); - val = get_bootstrap(); + val = ath79_get_bootstrap(); if (val & QCA953X_BOOTSTRAP_DDR1) { writel(DDR_CTL_CONFIG_VAL, regs + QCA953X_DDR_REG_CTL_CONF); udelay(10); diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c index a88bcbc..073a179 100644 --- a/arch/mips/mach-ath79/reset.c +++ b/arch/mips/mach-ath79/reset.c @@ -45,7 +45,7 @@ void _machine_restart(void) /* NOP */; } -u32 get_bootstrap(void) +u32 ath79_get_bootstrap(void) { void __iomem *base; u32 reg = 0; @@ -89,7 +89,7 @@ static int eth_init_ar933x(void) mdelay(10); /* Get Atheros S26 PHY out of reset. */ - clrsetbits_be32(pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG, + clrsetbits_be32(pregs + AR933X_PLL_SWITCH_CLOCK_CONTROL_REG, 0x1f, 0x10); mdelay(10); @@ -136,6 +136,23 @@ static int eth_init_ar934x(void) return 0; } +static int eth_init_qca953x(void) +{ + void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + const u32 mask = QCA953X_RESET_GE0_MAC | QCA953X_RESET_GE0_MDIO | + QCA953X_RESET_GE1_MAC | QCA953X_RESET_GE1_MDIO | + QCA953X_RESET_ETH_SWITCH_ANALOG | + QCA953X_RESET_ETH_SWITCH; + + setbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + clrbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + + return 0; +} + int ath79_eth_reset(void) { /* @@ -146,6 +163,8 @@ int ath79_eth_reset(void) return eth_init_ar933x(); if (soc_is_ar934x()) return eth_init_ar934x(); + if (soc_is_qca953x()) + return eth_init_qca953x(); return -EINVAL; } @@ -185,6 +204,35 @@ static int usb_reset_ar934x(void __iomem *reset_regs) return 0; } +static int usb_reset_qca953x(void __iomem *reset_regs) +{ + void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + + clrsetbits_be32(pregs + QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG, + 0xf00, 0x200); + mdelay(10); + + /* Ungate the USB block */ + setbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE, + QCA953X_RESET_USBSUS_OVERRIDE); + mdelay(1); + clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE, + QCA953X_RESET_USB_PHY); + mdelay(1); + clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE, + QCA953X_RESET_USB_PHY_ANALOG); + mdelay(1); + clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE, + QCA953X_RESET_USB_HOST); + mdelay(1); + clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE, + QCA953X_RESET_USB_PHY_PLL_PWD_EXT); + mdelay(1); + + return 0; +} + int ath79_usb_reset(void) { void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE, @@ -204,6 +252,8 @@ int ath79_usb_reset(void) return usb_reset_ar933x(reset_regs); if (soc_is_ar934x()) return usb_reset_ar934x(reset_regs); + if (soc_is_qca953x()) + return usb_reset_qca953x(reset_regs); return -EINVAL; } diff --git a/board/dbau1x00/Kconfig b/board/dbau1x00/Kconfig index 342ec59..448176d 100644 --- a/board/dbau1x00/Kconfig +++ b/board/dbau1x00/Kconfig @@ -12,6 +12,18 @@ config SYS_CONFIG_NAME config SYS_TEXT_BASE default 0xbfc00000 +config SYS_DCACHE_SIZE + default 16384 + +config SYS_DCACHE_LINE_SIZE + default 32 + +config SYS_ICACHE_SIZE + default 16384 + +config SYS_ICACHE_LINE_SIZE + default 32 + menu "dbau1x00 board options" choice diff --git a/board/imgtec/malta/Kconfig b/board/imgtec/malta/Kconfig index 2bb8e8b..98eb4d1 100644 --- a/board/imgtec/malta/Kconfig +++ b/board/imgtec/malta/Kconfig @@ -10,6 +10,7 @@ config SYS_CONFIG_NAME default "malta" config SYS_TEXT_BASE - default 0xbe000000 + default 0xbe000000 if 32BIT + default 0xffffffffbe000000 if 64BIT endif diff --git a/board/imgtec/malta/lowlevel_init.S b/board/imgtec/malta/lowlevel_init.S index 534db1d..3d48cdc 100644 --- a/board/imgtec/malta/lowlevel_init.S +++ b/board/imgtec/malta/lowlevel_init.S @@ -10,6 +10,7 @@ #include <pci.h> #include <asm/addrspace.h> +#include <asm/asm.h> #include <asm/regdef.h> #include <asm/malta.h> #include <asm/mipsregs.h> @@ -34,7 +35,7 @@ lowlevel_init: mtc0 t0, CP0_CONFIG, 2 /* detect the core card */ - li t0, KSEG1ADDR(MALTA_REVISION) + PTR_LI t0, CKSEG1ADDR(MALTA_REVISION) lw t0, 0(t0) srl t0, t0, MALTA_REVISION_CORID_SHF andi t0, t0, (MALTA_REVISION_CORID_MSK >> \ @@ -68,12 +69,12 @@ lowlevel_init: */ _gt64120: /* move GT64120 registers from 0x14000000 to 0x1be00000 */ - li t1, KSEG1ADDR(GT_DEF_BASE) + PTR_LI t1, CKSEG1ADDR(GT_DEF_BASE) li t0, CPU_TO_GT32(0xdf000000) sw t0, GT_ISD_OFS(t1) /* setup MEM-to-PCI0 mapping */ - li t1, KSEG1ADDR(MALTA_GT_BASE) + PTR_LI t1, CKSEG1ADDR(MALTA_GT_BASE) /* setup PCI0 io window to 0x18000000-0x181fffff */ li t0, CPU_TO_GT32(0xc0000000) @@ -100,7 +101,7 @@ _gt64120: */ _msc01: /* setup peripheral bus controller clock divide */ - li t0, KSEG1ADDR(MALTA_MSC01_PBC_BASE) + PTR_LI t0, CKSEG1ADDR(MALTA_MSC01_PBC_BASE) li t1, 0x1 << MSC01_PBC_CLKCFG_SHF sw t1, MSC01_PBC_CLKCFG_OFS(t0) @@ -122,7 +123,7 @@ _msc01: sw t1, MSC01_PBC_CS0CFG_OFS(t0) /* setup basic address decode */ - li t0, KSEG1ADDR(MALTA_MSC01_BIU_BASE) + PTR_LI t0, CKSEG1ADDR(MALTA_MSC01_BIU_BASE) li t1, 0x0 li t2, -CONFIG_SYS_MEM_SIZE sw t1, MSC01_BIU_MCBAS1L_OFS(t0) @@ -157,7 +158,7 @@ _msc01: sw t2, MSC01_BIU_IP3MSK2L_OFS(t0) /* setup PCI memory */ - li t0, KSEG1ADDR(MALTA_MSC01_PCI_BASE) + PTR_LI t0, CKSEG1ADDR(MALTA_MSC01_PCI_BASE) li t1, MALTA_MSC01_PCIMEM_BASE li t2, (-MALTA_MSC01_PCIMEM_SIZE) & MSC01_PCI_SC2PMMSKL_MSK_MSK li t3, MALTA_MSC01_PCIMEM_MAP diff --git a/board/micronas/vct/Kconfig b/board/micronas/vct/Kconfig index 535a77b..df7c029 100644 --- a/board/micronas/vct/Kconfig +++ b/board/micronas/vct/Kconfig @@ -12,6 +12,18 @@ config SYS_CONFIG_NAME config SYS_TEXT_BASE default 0x87000000 +config SYS_DCACHE_SIZE + default 16384 + +config SYS_DCACHE_LINE_SIZE + default 32 + +config SYS_ICACHE_SIZE + default 16384 + +config SYS_ICACHE_LINE_SIZE + default 32 + menu "vct board options" choice diff --git a/board/pb1x00/Kconfig b/board/pb1x00/Kconfig index 236a410..ef8905d 100644 --- a/board/pb1x00/Kconfig +++ b/board/pb1x00/Kconfig @@ -12,4 +12,16 @@ config SYS_CONFIG_NAME config SYS_TEXT_BASE default 0x83800000 +config SYS_DCACHE_SIZE + default 16384 + +config SYS_DCACHE_LINE_SIZE + default 32 + +config SYS_ICACHE_SIZE + default 16384 + +config SYS_ICACHE_LINE_SIZE + default 32 + endif diff --git a/board/qca/ap121/Kconfig b/board/qca/ap121/Kconfig index c3ecc8f..4fd6a71 100644 --- a/board/qca/ap121/Kconfig +++ b/board/qca/ap121/Kconfig @@ -12,4 +12,16 @@ config SYS_CONFIG_NAME config SYS_TEXT_BASE default 0x9f000000 +config SYS_DCACHE_SIZE + default 32768 + +config SYS_DCACHE_LINE_SIZE + default 32 + +config SYS_ICACHE_SIZE + default 65536 + +config SYS_ICACHE_LINE_SIZE + default 32 + endif diff --git a/board/qca/ap121/ap121.c b/board/qca/ap121/ap121.c index d6c60fe..e245faa 100644 --- a/board/qca/ap121/ap121.c +++ b/board/qca/ap121/ap121.c @@ -10,6 +10,7 @@ #include <asm/types.h> #include <mach/ar71xx_regs.h> #include <mach/ddr.h> +#include <mach/ath79.h> #include <debug_uart.h> DECLARE_GLOBAL_DATA_PTR; @@ -46,5 +47,6 @@ int board_early_init_f(void) debug_uart_init(); #endif ddr_init(); + ath79_eth_reset(); return 0; } diff --git a/board/qca/ap143/Kconfig b/board/qca/ap143/Kconfig index 5ea5d6f..74c632a 100644 --- a/board/qca/ap143/Kconfig +++ b/board/qca/ap143/Kconfig @@ -12,4 +12,16 @@ config SYS_CONFIG_NAME config SYS_TEXT_BASE default 0x9f000000 +config SYS_DCACHE_SIZE + default 32768 + +config SYS_DCACHE_LINE_SIZE + default 32 + +config SYS_ICACHE_SIZE + default 65536 + +config SYS_ICACHE_LINE_SIZE + default 32 + endif diff --git a/board/qca/ap143/ap143.c b/board/qca/ap143/ap143.c index 1572472..e921ea5 100644 --- a/board/qca/ap143/ap143.c +++ b/board/qca/ap143/ap143.c @@ -10,6 +10,7 @@ #include <asm/types.h> #include <mach/ar71xx_regs.h> #include <mach/ddr.h> +#include <mach/ath79.h> #include <debug_uart.h> DECLARE_GLOBAL_DATA_PTR; @@ -62,5 +63,6 @@ int board_early_init_f(void) debug_uart_init(); #endif ddr_init(); + ath79_eth_reset(); return 0; } diff --git a/board/qemu-mips/Kconfig b/board/qemu-mips/Kconfig index 3de1f44..e696a12 100644 --- a/board/qemu-mips/Kconfig +++ b/board/qemu-mips/Kconfig @@ -11,4 +11,16 @@ config SYS_TEXT_BASE default 0xbfc00000 if 32BIT default 0xffffffffbfc00000 if 64BIT +config SYS_DCACHE_SIZE + default 16384 + +config SYS_DCACHE_LINE_SIZE + default 32 + +config SYS_ICACHE_SIZE + default 16384 + +config SYS_ICACHE_LINE_SIZE + default 32 + endif diff --git a/board/tplink/wdr4300/Kconfig b/board/tplink/wdr4300/Kconfig index 65785bd..67a0228 100644 --- a/board/tplink/wdr4300/Kconfig +++ b/board/tplink/wdr4300/Kconfig @@ -15,4 +15,16 @@ config SYS_CONFIG_NAME config SYS_TEXT_BASE default 0xa1000000 +config SYS_DCACHE_SIZE + default 32768 + +config SYS_DCACHE_LINE_SIZE + default 32 + +config SYS_ICACHE_SIZE + default 65536 + +config SYS_ICACHE_LINE_SIZE + default 32 + endif diff --git a/configs/ap121_defconfig b/configs/ap121_defconfig index 7604e2e..91fa734 100644 --- a/configs/ap121_defconfig +++ b/configs/ap121_defconfig @@ -19,8 +19,13 @@ CONFIG_SYS_PROMPT="ap121 # " CONFIG_CMD_SF=y CONFIG_CMD_SPI=y # CONFIG_CMD_FPGA is not set -# CONFIG_CMD_NET is not set -# CONFIG_CMD_NFS is not set +CONFIG_CMD_NET=y +CONFIG_CMD_NFS=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_DM_ETH=y +CONFIG_AG7XXX=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_ATMEL=y diff --git a/configs/malta64_defconfig b/configs/malta64_defconfig new file mode 100644 index 0000000..7bef84c --- /dev/null +++ b/configs/malta64_defconfig @@ -0,0 +1,16 @@ +CONFIG_MIPS=y +CONFIG_TARGET_MALTA=y +CONFIG_CPU_MIPS64_R2=y +CONFIG_DEFAULT_DEVICE_TREE="mti,malta" +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="malta # " +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +# CONFIG_CMD_NFS is not set +CONFIG_CMD_PING=y +CONFIG_OF_EMBED=y +CONFIG_SYS_NS16550=y +CONFIG_USE_PRIVATE_LIBGCC=y diff --git a/configs/malta64el_defconfig b/configs/malta64el_defconfig new file mode 100644 index 0000000..47ded9e --- /dev/null +++ b/configs/malta64el_defconfig @@ -0,0 +1,17 @@ +CONFIG_MIPS=y +CONFIG_TARGET_MALTA=y +CONFIG_SYS_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS64_R2=y +CONFIG_DEFAULT_DEVICE_TREE="mti,malta" +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="maltael # " +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +# CONFIG_CMD_NFS is not set +CONFIG_CMD_PING=y +CONFIG_OF_EMBED=y +CONFIG_SYS_NS16550=y +CONFIG_USE_PRIVATE_LIBGCC=y diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 91b7690..c1cb689 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -46,6 +46,15 @@ menuconfig NETDEVICES if NETDEVICES +config AG7XXX + bool "Atheros AG7xxx Ethernet MAC support" + depends on DM_ETH && ARCH_ATH79 + select PHYLIB + help + This driver supports the Atheros AG7xxx Ethernet MAC. This MAC is + present in the Atheros AR7xxx, AR9xxx and QCA9xxx MIPS chips. + + config ALTERA_TSE bool "Altera Triple-Speed Ethernet MAC support" depends on DM_ETH diff --git a/drivers/net/Makefile b/drivers/net/Makefile index d5e4a97..5702592 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o obj-$(CONFIG_ALTERA_TSE) += altera_tse.o +obj-$(CONFIG_AG7XXX) += ag7xxx.o obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o obj-$(CONFIG_DRIVER_AX88180) += ax88180.o diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c new file mode 100644 index 0000000..346f138 --- /dev/null +++ b/drivers/net/ag7xxx.c @@ -0,0 +1,980 @@ +/* + * Atheros AR71xx / AR9xxx GMAC driver + * + * Copyright (C) 2016 Marek Vasut <marex@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <miiphy.h> +#include <malloc.h> +#include <linux/compiler.h> +#include <linux/err.h> +#include <linux/mii.h> +#include <wait_bit.h> +#include <asm/io.h> + +#include <mach/ath79.h> + +DECLARE_GLOBAL_DATA_PTR; + +enum ag7xxx_model { + AG7XXX_MODEL_AG933X, + AG7XXX_MODEL_AG934X, +}; + +#define AG7XXX_ETH_CFG1 0x00 +#define AG7XXX_ETH_CFG1_SOFT_RST BIT(31) +#define AG7XXX_ETH_CFG1_RX_RST BIT(19) +#define AG7XXX_ETH_CFG1_TX_RST BIT(18) +#define AG7XXX_ETH_CFG1_LOOPBACK BIT(8) +#define AG7XXX_ETH_CFG1_RX_EN BIT(2) +#define AG7XXX_ETH_CFG1_TX_EN BIT(0) + +#define AG7XXX_ETH_CFG2 0x04 +#define AG7XXX_ETH_CFG2_IF_1000 BIT(9) +#define AG7XXX_ETH_CFG2_IF_10_100 BIT(8) +#define AG7XXX_ETH_CFG2_IF_SPEED_MASK (3 << 8) +#define AG7XXX_ETH_CFG2_HUGE_FRAME_EN BIT(5) +#define AG7XXX_ETH_CFG2_LEN_CHECK BIT(4) +#define AG7XXX_ETH_CFG2_PAD_CRC_EN BIT(2) +#define AG7XXX_ETH_CFG2_FDX BIT(0) + +#define AG7XXX_ETH_MII_MGMT_CFG 0x20 +#define AG7XXX_ETH_MII_MGMT_CFG_RESET BIT(31) + +#define AG7XXX_ETH_MII_MGMT_CMD 0x24 +#define AG7XXX_ETH_MII_MGMT_CMD_READ 0x1 + +#define AG7XXX_ETH_MII_MGMT_ADDRESS 0x28 +#define AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT 8 + +#define AG7XXX_ETH_MII_MGMT_CTRL 0x2c + +#define AG7XXX_ETH_MII_MGMT_STATUS 0x30 + +#define AG7XXX_ETH_MII_MGMT_IND 0x34 +#define AG7XXX_ETH_MII_MGMT_IND_INVALID BIT(2) +#define AG7XXX_ETH_MII_MGMT_IND_BUSY BIT(0) + +#define AG7XXX_ETH_ADDR1 0x40 +#define AG7XXX_ETH_ADDR2 0x44 + +#define AG7XXX_ETH_FIFO_CFG_0 0x48 +#define AG7XXX_ETH_FIFO_CFG_1 0x4c +#define AG7XXX_ETH_FIFO_CFG_2 0x50 +#define AG7XXX_ETH_FIFO_CFG_3 0x54 +#define AG7XXX_ETH_FIFO_CFG_4 0x58 +#define AG7XXX_ETH_FIFO_CFG_5 0x5c + +#define AG7XXX_ETH_DMA_TX_CTRL 0x180 +#define AG7XXX_ETH_DMA_TX_CTRL_TXE BIT(0) + +#define AG7XXX_ETH_DMA_TX_DESC 0x184 + +#define AG7XXX_ETH_DMA_TX_STATUS 0x188 + +#define AG7XXX_ETH_DMA_RX_CTRL 0x18c +#define AG7XXX_ETH_DMA_RX_CTRL_RXE BIT(0) + +#define AG7XXX_ETH_DMA_RX_DESC 0x190 + +#define AG7XXX_ETH_DMA_RX_STATUS 0x194 + +/* Custom register at 0x18070000 */ +#define AG7XXX_GMAC_ETH_CFG 0x00 +#define AG7XXX_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8) +#define AG7XXX_ETH_CFG_SW_PHY_SWAP BIT(7) +#define AG7XXX_ETH_CFG_SW_ONLY_MODE BIT(6) +#define AG7XXX_ETH_CFG_GE0_ERR_EN BIT(5) +#define AG7XXX_ETH_CFG_MII_GE0_SLAVE BIT(4) +#define AG7XXX_ETH_CFG_MII_GE0_MASTER BIT(3) +#define AG7XXX_ETH_CFG_GMII_GE0 BIT(2) +#define AG7XXX_ETH_CFG_MII_GE0 BIT(1) +#define AG7XXX_ETH_CFG_RGMII_GE0 BIT(0) + +#define CONFIG_TX_DESCR_NUM 8 +#define CONFIG_RX_DESCR_NUM 8 +#define CONFIG_ETH_BUFSIZE 2048 +#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM) +#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM) + +/* DMA descriptor. */ +struct ag7xxx_dma_desc { + u32 data_addr; +#define AG7XXX_DMADESC_IS_EMPTY BIT(31) +#define AG7XXX_DMADESC_FTPP_OVERRIDE_OFFSET 16 +#define AG7XXX_DMADESC_PKT_SIZE_OFFSET 0 +#define AG7XXX_DMADESC_PKT_SIZE_MASK 0xfff + u32 config; + u32 next_desc; + u32 _pad[5]; +}; + +struct ar7xxx_eth_priv { + struct ag7xxx_dma_desc tx_mac_descrtable[CONFIG_TX_DESCR_NUM]; + struct ag7xxx_dma_desc rx_mac_descrtable[CONFIG_RX_DESCR_NUM]; + char txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN); + char rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN); + + void __iomem *regs; + void __iomem *phyregs; + + struct eth_device *dev; + struct phy_device *phydev; + struct mii_dev *bus; + + u32 interface; + u32 tx_currdescnum; + u32 rx_currdescnum; + enum ag7xxx_model model; +}; + +/* + * Switch and MDIO access + */ +static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val) +{ + struct ar7xxx_eth_priv *priv = bus->priv; + void __iomem *regs = priv->phyregs; + int ret; + + writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD); + writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg, + regs + AG7XXX_ETH_MII_MGMT_ADDRESS); + writel(AG7XXX_ETH_MII_MGMT_CMD_READ, + regs + AG7XXX_ETH_MII_MGMT_CMD); + + ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND, + AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0); + if (ret) + return ret; + + *val = readl(regs + AG7XXX_ETH_MII_MGMT_STATUS) & 0xffff; + writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD); + + return 0; +} + +static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val) +{ + struct ar7xxx_eth_priv *priv = bus->priv; + void __iomem *regs = priv->phyregs; + int ret; + + writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg, + regs + AG7XXX_ETH_MII_MGMT_ADDRESS); + writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL); + + ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND, + AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0); + + return ret; +} + +static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val) +{ + struct ar7xxx_eth_priv *priv = bus->priv; + u32 phy_addr; + u32 reg_addr; + u32 phy_temp; + u32 reg_temp; + u16 rv = 0; + int ret; + + if (priv->model == AG7XXX_MODEL_AG933X) { + phy_addr = 0x1f; + reg_addr = 0x10; + } else if (priv->model == AG7XXX_MODEL_AG934X) { + phy_addr = 0x18; + reg_addr = 0x00; + } else + return -EINVAL; + + ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9); + if (ret) + return ret; + + phy_temp = ((reg >> 6) & 0x7) | 0x10; + reg_temp = (reg >> 1) & 0x1e; + *val = 0; + + ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 0, &rv); + if (ret < 0) + return ret; + *val |= rv; + + ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv); + if (ret < 0) + return ret; + *val |= (rv << 16); + + return 0; +} + +static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val) +{ + struct ar7xxx_eth_priv *priv = bus->priv; + u32 phy_addr; + u32 reg_addr; + u32 phy_temp; + u32 reg_temp; + int ret; + + if (priv->model == AG7XXX_MODEL_AG933X) { + phy_addr = 0x1f; + reg_addr = 0x10; + } else if (priv->model == AG7XXX_MODEL_AG934X) { + phy_addr = 0x18; + reg_addr = 0x00; + } else + return -EINVAL; + + ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9); + if (ret) + return ret; + + phy_temp = ((reg >> 6) & 0x7) | 0x10; + reg_temp = (reg >> 1) & 0x1e; + + /* + * The switch on AR933x has some special register behavior, which + * expects particular write order of their nibbles: + * 0x40 ..... MSB first, LSB second + * 0x50 ..... MSB first, LSB second + * 0x98 ..... LSB first, MSB second + * others ... don't care + */ + if ((priv->model == AG7XXX_MODEL_AG933X) && (reg == 0x98)) { + ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff); + if (ret < 0) + return ret; + + ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16); + if (ret < 0) + return ret; + } else { + ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16); + if (ret < 0) + return ret; + + ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff); + if (ret < 0) + return ret; + } + + return 0; +} + +static u16 ag7xxx_mdio_rw(struct mii_dev *bus, int addr, int reg, u32 val) +{ + u32 data; + + /* Dummy read followed by PHY read/write command. */ + ag7xxx_switch_reg_read(bus, 0x98, &data); + data = val | (reg << 16) | (addr << 21) | BIT(30) | BIT(31); + ag7xxx_switch_reg_write(bus, 0x98, data); + + /* Wait for operation to finish */ + do { + ag7xxx_switch_reg_read(bus, 0x98, &data); + } while (data & BIT(31)); + + return data & 0xffff; +} + +static int ag7xxx_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + return ag7xxx_mdio_rw(bus, addr, reg, BIT(27)); +} + +static int ag7xxx_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + ag7xxx_mdio_rw(bus, addr, reg, val); + return 0; +} + +/* + * DMA ring handlers + */ +static void ag7xxx_dma_clean_tx(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + struct ag7xxx_dma_desc *curr, *next; + u32 start, end; + int i; + + for (i = 0; i < CONFIG_TX_DESCR_NUM; i++) { + curr = &priv->tx_mac_descrtable[i]; + next = &priv->tx_mac_descrtable[(i + 1) % CONFIG_TX_DESCR_NUM]; + + curr->data_addr = virt_to_phys(&priv->txbuffs[i * CONFIG_ETH_BUFSIZE]); + curr->config = AG7XXX_DMADESC_IS_EMPTY; + curr->next_desc = virt_to_phys(next); + } + + priv->tx_currdescnum = 0; + + /* Cache: Flush descriptors, don't care about buffers. */ + start = (u32)(&priv->tx_mac_descrtable[0]); + end = start + sizeof(priv->tx_mac_descrtable); + flush_dcache_range(start, end); +} + +static void ag7xxx_dma_clean_rx(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + struct ag7xxx_dma_desc *curr, *next; + u32 start, end; + int i; + + for (i = 0; i < CONFIG_RX_DESCR_NUM; i++) { + curr = &priv->rx_mac_descrtable[i]; + next = &priv->rx_mac_descrtable[(i + 1) % CONFIG_RX_DESCR_NUM]; + + curr->data_addr = virt_to_phys(&priv->rxbuffs[i * CONFIG_ETH_BUFSIZE]); + curr->config = AG7XXX_DMADESC_IS_EMPTY; + curr->next_desc = virt_to_phys(next); + } + + priv->rx_currdescnum = 0; + + /* Cache: Flush+Invalidate descriptors, Invalidate buffers. */ + start = (u32)(&priv->rx_mac_descrtable[0]); + end = start + sizeof(priv->rx_mac_descrtable); + flush_dcache_range(start, end); + invalidate_dcache_range(start, end); + + start = (u32)&priv->rxbuffs; + end = start + sizeof(priv->rxbuffs); + invalidate_dcache_range(start, end); +} + +/* + * Ethernet I/O + */ +static int ag7xxx_eth_send(struct udevice *dev, void *packet, int length) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + struct ag7xxx_dma_desc *curr; + u32 start, end; + + curr = &priv->tx_mac_descrtable[priv->tx_currdescnum]; + + /* Cache: Invalidate descriptor. */ + start = (u32)curr; + end = start + sizeof(*curr); + invalidate_dcache_range(start, end); + + if (!(curr->config & AG7XXX_DMADESC_IS_EMPTY)) { + printf("ag7xxx: Out of TX DMA descriptors!\n"); + return -EPERM; + } + + /* Copy the packet into the data buffer. */ + memcpy(phys_to_virt(curr->data_addr), packet, length); + curr->config = length & AG7XXX_DMADESC_PKT_SIZE_MASK; + + /* Cache: Flush descriptor, Flush buffer. */ + start = (u32)curr; + end = start + sizeof(*curr); + flush_dcache_range(start, end); + start = (u32)phys_to_virt(curr->data_addr); + end = start + length; + flush_dcache_range(start, end); + + /* Load the DMA descriptor and start TX DMA. */ + writel(AG7XXX_ETH_DMA_TX_CTRL_TXE, + priv->regs + AG7XXX_ETH_DMA_TX_CTRL); + + /* Switch to next TX descriptor. */ + priv->tx_currdescnum = (priv->tx_currdescnum + 1) % CONFIG_TX_DESCR_NUM; + + return 0; +} + +static int ag7xxx_eth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + struct ag7xxx_dma_desc *curr; + u32 start, end, length; + + curr = &priv->rx_mac_descrtable[priv->rx_currdescnum]; + + /* Cache: Invalidate descriptor. */ + start = (u32)curr; + end = start + sizeof(*curr); + invalidate_dcache_range(start, end); + + /* No packets received. */ + if (curr->config & AG7XXX_DMADESC_IS_EMPTY) + return -EAGAIN; + + length = curr->config & AG7XXX_DMADESC_PKT_SIZE_MASK; + + /* Cache: Invalidate buffer. */ + start = (u32)phys_to_virt(curr->data_addr); + end = start + length; + invalidate_dcache_range(start, end); + + /* Receive one packet and return length. */ + *packetp = phys_to_virt(curr->data_addr); + return length; +} + +static int ag7xxx_eth_free_pkt(struct udevice *dev, uchar *packet, + int length) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + struct ag7xxx_dma_desc *curr; + u32 start, end; + + curr = &priv->rx_mac_descrtable[priv->rx_currdescnum]; + + curr->config = AG7XXX_DMADESC_IS_EMPTY; + + /* Cache: Flush descriptor. */ + start = (u32)curr; + end = start + sizeof(*curr); + flush_dcache_range(start, end); + + /* Switch to next RX descriptor. */ + priv->rx_currdescnum = (priv->rx_currdescnum + 1) % CONFIG_RX_DESCR_NUM; + + return 0; +} + +static int ag7xxx_eth_start(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + + /* FIXME: Check if link up */ + + /* Clear the DMA rings. */ + ag7xxx_dma_clean_tx(dev); + ag7xxx_dma_clean_rx(dev); + + /* Load DMA descriptors and start the RX DMA. */ + writel(virt_to_phys(&priv->tx_mac_descrtable[priv->tx_currdescnum]), + priv->regs + AG7XXX_ETH_DMA_TX_DESC); + writel(virt_to_phys(&priv->rx_mac_descrtable[priv->rx_currdescnum]), + priv->regs + AG7XXX_ETH_DMA_RX_DESC); + writel(AG7XXX_ETH_DMA_RX_CTRL_RXE, + priv->regs + AG7XXX_ETH_DMA_RX_CTRL); + + return 0; +} + +static void ag7xxx_eth_stop(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + + /* Stop the TX DMA. */ + writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL); + wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0, + 1000, 0); + + /* Stop the RX DMA. */ + writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL); + wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0, + 1000, 0); +} + +/* + * Hardware setup + */ +static int ag7xxx_eth_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + unsigned char *mac = pdata->enetaddr; + u32 macid_lo, macid_hi; + + macid_hi = mac[3] | (mac[2] << 8) | (mac[1] << 16) | (mac[0] << 24); + macid_lo = (mac[5] << 16) | (mac[4] << 24); + + writel(macid_lo, priv->regs + AG7XXX_ETH_ADDR1); + writel(macid_hi, priv->regs + AG7XXX_ETH_ADDR2); + + return 0; +} + +static void ag7xxx_hw_setup(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + u32 speed; + + setbits_be32(priv->regs + AG7XXX_ETH_CFG1, + AG7XXX_ETH_CFG1_RX_RST | AG7XXX_ETH_CFG1_TX_RST | + AG7XXX_ETH_CFG1_SOFT_RST); + + mdelay(10); + + writel(AG7XXX_ETH_CFG1_RX_EN | AG7XXX_ETH_CFG1_TX_EN, + priv->regs + AG7XXX_ETH_CFG1); + + if (priv->interface == PHY_INTERFACE_MODE_RMII) + speed = AG7XXX_ETH_CFG2_IF_10_100; + else + speed = AG7XXX_ETH_CFG2_IF_1000; + + clrsetbits_be32(priv->regs + AG7XXX_ETH_CFG2, + AG7XXX_ETH_CFG2_IF_SPEED_MASK, + speed | AG7XXX_ETH_CFG2_PAD_CRC_EN | + AG7XXX_ETH_CFG2_LEN_CHECK); + + writel(0xfff0000, priv->regs + AG7XXX_ETH_FIFO_CFG_1); + writel(0x1fff, priv->regs + AG7XXX_ETH_FIFO_CFG_2); + + writel(0x1f00, priv->regs + AG7XXX_ETH_FIFO_CFG_0); + setbits_be32(priv->regs + AG7XXX_ETH_FIFO_CFG_4, 0x3ffff); + writel(0x10ffff, priv->regs + AG7XXX_ETH_FIFO_CFG_1); + writel(0xaaa0555, priv->regs + AG7XXX_ETH_FIFO_CFG_2); + writel(0x7eccf, priv->regs + AG7XXX_ETH_FIFO_CFG_5); + writel(0x1f00140, priv->regs + AG7XXX_ETH_FIFO_CFG_3); +} + +static int ag7xxx_mii_get_div(void) +{ + ulong freq = get_bus_freq(0); + + switch (freq / 1000000) { + case 150: return 0x7; + case 175: return 0x5; + case 200: return 0x4; + case 210: return 0x9; + case 220: return 0x9; + default: return 0x7; + } +} + +static int ag7xxx_mii_setup(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int i, ret, div = ag7xxx_mii_get_div(); + u32 reg; + + if (priv->model == AG7XXX_MODEL_AG933X) { + /* Unit 0 is PHY-less on AR9331, see datasheet Figure 2-3 */ + if (priv->interface == PHY_INTERFACE_MODE_RMII) + return 0; + } + + if (priv->model == AG7XXX_MODEL_AG934X) { + writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | 0x4, + priv->regs + AG7XXX_ETH_MII_MGMT_CFG); + writel(0x4, priv->regs + AG7XXX_ETH_MII_MGMT_CFG); + return 0; + } + + for (i = 0; i < 10; i++) { + writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | div, + priv->regs + AG7XXX_ETH_MII_MGMT_CFG); + writel(div, priv->regs + AG7XXX_ETH_MII_MGMT_CFG); + + /* Check the switch */ + ret = ag7xxx_switch_reg_read(priv->bus, 0x10c, ®); + if (ret) + continue; + + if (reg != 0x18007fff) + continue; + + return 0; + } + + return -EINVAL; +} + +static int ag933x_phy_setup_wan(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + + /* Configure switch port 4 (GMAC0) */ + return ag7xxx_mdio_write(priv->bus, 4, 0, MII_BMCR, 0x9000); +} + +static int ag933x_phy_setup_lan(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int i, ret; + u32 reg; + + /* Reset the switch */ + ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); + if (ret) + return ret; + reg |= BIT(31); + ret = ag7xxx_switch_reg_write(priv->bus, 0, reg); + if (ret) + return ret; + + do { + ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); + if (ret) + return ret; + } while (reg & BIT(31)); + + /* Configure switch ports 0...3 (GMAC1) */ + for (i = 0; i < 4; i++) { + ret = ag7xxx_mdio_write(priv->bus, 0x4, 0, MII_BMCR, 0x9000); + if (ret) + return ret; + } + + /* Enable CPU port */ + ret = ag7xxx_switch_reg_write(priv->bus, 0x78, BIT(8)); + if (ret) + return ret; + + for (i = 0; i < 4; i++) { + ret = ag7xxx_switch_reg_write(priv->bus, i * 0x100, BIT(9)); + if (ret) + return ret; + } + + /* QM Control */ + ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e); + if (ret) + return ret; + + /* Disable Atheros header */ + ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004); + if (ret) + return ret; + + /* Tag priority mapping */ + ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50); + if (ret) + return ret; + + /* Enable ARP packets to the CPU */ + ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, ®); + if (ret) + return ret; + reg |= 0x100000; + ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg); + if (ret) + return ret; + + return 0; +} + +static int ag933x_phy_setup_reset_set(struct udevice *dev, int port) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int ret; + + ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + if (ret) + return ret; + + if (priv->model == AG7XXX_MODEL_AG934X) { + ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_CTRL1000, + ADVERTISE_1000FULL); + if (ret) + return ret; + } + + return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR, + BMCR_ANENABLE | BMCR_RESET); +} + +static int ag933x_phy_setup_reset_fin(struct udevice *dev, int port) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int ret; + + do { + ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR); + if (ret < 0) + return ret; + mdelay(10); + } while (ret & BMCR_RESET); + + return 0; +} + +static int ag933x_phy_setup_common(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int i, ret, phymax; + + if (priv->model == AG7XXX_MODEL_AG933X) + phymax = 4; + else if (priv->model == AG7XXX_MODEL_AG934X) + phymax = 5; + else + return -EINVAL; + + if (priv->interface == PHY_INTERFACE_MODE_RMII) { + ret = ag933x_phy_setup_reset_set(dev, phymax); + if (ret) + return ret; + + ret = ag933x_phy_setup_reset_fin(dev, phymax); + if (ret) + return ret; + + /* Read out link status */ + ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR); + if (ret < 0) + return ret; + + return 0; + } + + /* Switch ports */ + for (i = 0; i < phymax; i++) { + ret = ag933x_phy_setup_reset_set(dev, i); + if (ret) + return ret; + } + + for (i = 0; i < phymax; i++) { + ret = ag933x_phy_setup_reset_fin(dev, i); + if (ret) + return ret; + } + + for (i = 0; i < phymax; i++) { + /* Read out link status */ + ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR); + if (ret < 0) + return ret; + } + + return 0; +} + +static int ag934x_phy_setup(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int i, ret; + u32 reg; + + ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f); + if (ret) + return ret; + ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x40000000); + if (ret) + return ret; + ret = ag7xxx_switch_reg_write(priv->bus, 0x4, 0x07600000); + if (ret) + return ret; + ret = ag7xxx_switch_reg_write(priv->bus, 0xc, 0x01000000); + if (ret) + return ret; + ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e); + if (ret) + return ret; + + /* AR8327/AR8328 v1.0 fixup */ + ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); + if (ret) + return ret; + if ((reg & 0xffff) == 0x1201) { + for (i = 0; i < 5; i++) { + ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x0); + if (ret) + return ret; + ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x02ea); + if (ret) + return ret; + ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x3d); + if (ret) + return ret; + ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x68a0); + if (ret) + return ret; + } + } + + ret = ag7xxx_switch_reg_read(priv->bus, 0x66c, ®); + if (ret) + return ret; + reg &= ~0x70000; + ret = ag7xxx_switch_reg_write(priv->bus, 0x66c, reg); + if (ret) + return ret; + + return 0; +} + +static int ag7xxx_mac_probe(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int ret; + + ag7xxx_hw_setup(dev); + ret = ag7xxx_mii_setup(dev); + if (ret) + return ret; + + ag7xxx_eth_write_hwaddr(dev); + + if (priv->model == AG7XXX_MODEL_AG933X) { + if (priv->interface == PHY_INTERFACE_MODE_RMII) + ret = ag933x_phy_setup_wan(dev); + else + ret = ag933x_phy_setup_lan(dev); + } else if (priv->model == AG7XXX_MODEL_AG934X) { + ret = ag934x_phy_setup(dev); + } else { + return -EINVAL; + } + + if (ret) + return ret; + + return ag933x_phy_setup_common(dev); +} + +static int ag7xxx_mdio_probe(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + struct mii_dev *bus = mdio_alloc(); + + if (!bus) + return -ENOMEM; + + bus->read = ag7xxx_mdio_read; + bus->write = ag7xxx_mdio_write; + snprintf(bus->name, sizeof(bus->name), dev->name); + + bus->priv = (void *)priv; + + return mdio_register(bus); +} + +static int ag7xxx_get_phy_iface_offset(struct udevice *dev) +{ + int offset; + + offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, "phy"); + if (offset <= 0) { + debug("%s: PHY OF node not found (ret=%i)\n", __func__, offset); + return -EINVAL; + } + + offset = fdt_parent_offset(gd->fdt_blob, offset); + if (offset <= 0) { + debug("%s: PHY OF node parent MDIO bus not found (ret=%i)\n", + __func__, offset); + return -EINVAL; + } + + offset = fdt_parent_offset(gd->fdt_blob, offset); + if (offset <= 0) { + debug("%s: PHY MDIO OF node parent MAC not found (ret=%i)\n", + __func__, offset); + return -EINVAL; + } + + return offset; +} + +static int ag7xxx_eth_probe(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + void __iomem *iobase, *phyiobase; + int ret, phyreg; + + /* Decoding of convoluted PHY wiring on Atheros MIPS. */ + ret = ag7xxx_get_phy_iface_offset(dev); + if (ret <= 0) + return ret; + phyreg = fdtdec_get_int(gd->fdt_blob, ret, "reg", -1); + + iobase = map_physmem(pdata->iobase, 0x200, MAP_NOCACHE); + phyiobase = map_physmem(phyreg, 0x200, MAP_NOCACHE); + + debug("%s, iobase=%p, phyiobase=%p, priv=%p\n", + __func__, iobase, phyiobase, priv); + priv->regs = iobase; + priv->phyregs = phyiobase; + priv->interface = pdata->phy_interface; + priv->model = dev_get_driver_data(dev); + + ret = ag7xxx_mdio_probe(dev); + if (ret) + return ret; + + priv->bus = miiphy_get_dev_by_name(dev->name); + + ret = ag7xxx_mac_probe(dev); + debug("%s, ret=%d\n", __func__, ret); + + return ret; +} + +static int ag7xxx_eth_remove(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + + free(priv->phydev); + mdio_unregister(priv->bus); + mdio_free(priv->bus); + + return 0; +} + +static const struct eth_ops ag7xxx_eth_ops = { + .start = ag7xxx_eth_start, + .send = ag7xxx_eth_send, + .recv = ag7xxx_eth_recv, + .free_pkt = ag7xxx_eth_free_pkt, + .stop = ag7xxx_eth_stop, + .write_hwaddr = ag7xxx_eth_write_hwaddr, +}; + +static int ag7xxx_eth_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + const char *phy_mode; + int ret; + + pdata->iobase = dev_get_addr(dev); + pdata->phy_interface = -1; + + /* Decoding of convoluted PHY wiring on Atheros MIPS. */ + ret = ag7xxx_get_phy_iface_offset(dev); + if (ret <= 0) + return ret; + + phy_mode = fdt_getprop(gd->fdt_blob, ret, "phy-mode", NULL); + if (phy_mode) + pdata->phy_interface = phy_get_interface_by_name(phy_mode); + if (pdata->phy_interface == -1) { + debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); + return -EINVAL; + } + + return 0; +} + +static const struct udevice_id ag7xxx_eth_ids[] = { + { .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X }, + { .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X }, + { } +}; + +U_BOOT_DRIVER(eth_ag7xxx) = { + .name = "eth_ag7xxx", + .id = UCLASS_ETH, + .of_match = ag7xxx_eth_ids, + .ofdata_to_platdata = ag7xxx_eth_ofdata_to_platdata, + .probe = ag7xxx_eth_probe, + .remove = ag7xxx_eth_remove, + .ops = &ag7xxx_eth_ops, + .priv_auto_alloc_size = sizeof(struct ar7xxx_eth_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c index 16a7512..1da9996 100644 --- a/drivers/net/pcnet.c +++ b/drivers/net/pcnet.c @@ -135,14 +135,11 @@ static void pcnet_halt (struct eth_device *dev); static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_num); static inline pci_addr_t pcnet_virt_to_mem(const struct eth_device *dev, - void *addr, bool uncached) + void *addr) { - pci_dev_t devbusfn = (pci_dev_t)dev->priv; + pci_dev_t devbusfn = (pci_dev_t)(unsigned long)dev->priv; void *virt_addr = addr; - if (uncached) - virt_addr = (void *)CKSEG0ADDR(addr); - return pci_virt_to_mem(devbusfn, virt_addr); } @@ -158,6 +155,7 @@ int pcnet_initialize(bd_t *bis) struct eth_device *dev; u16 command, status; int dev_nr = 0; + u32 bar; PCNET_DEBUG1("\npcnet_initialize...\n"); @@ -179,19 +177,18 @@ int pcnet_initialize(bd_t *bis) break; } memset(dev, 0, sizeof(*dev)); - dev->priv = (void *)devbusfn; + dev->priv = (void *)(unsigned long)devbusfn; sprintf(dev->name, "pcnet#%d", dev_nr); /* * Setup the PCI device. */ - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, - (unsigned int *)&dev->iobase); - dev->iobase = pci_io_to_phys(devbusfn, dev->iobase); + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &bar); + dev->iobase = pci_io_to_phys(devbusfn, bar); dev->iobase &= ~0xf; - PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ", - dev->name, devbusfn, dev->iobase); + PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%lx: ", + dev->name, devbusfn, (unsigned long)dev->iobase); command = PCI_COMMAND_IO | PCI_COMMAND_MASTER; pci_write_config_word(devbusfn, PCI_COMMAND, command); @@ -298,7 +295,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) { struct pcnet_uncached_priv *uc; int i, val; - u32 addr; + unsigned long addr; PCNET_DEBUG1("%s: pcnet_init...\n", dev->name); @@ -336,16 +333,18 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * must be aligned on 16-byte boundaries. */ if (lp == NULL) { - addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10); + addr = (unsigned long)malloc(sizeof(pcnet_priv_t) + 0x10); addr = (addr + 0xf) & ~0xf; lp = (pcnet_priv_t *)addr; - addr = (u32)memalign(ARCH_DMA_MINALIGN, sizeof(*lp->uc)); + addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, + sizeof(*lp->uc)); flush_dcache_range(addr, addr + sizeof(*lp->uc)); addr = UNCACHED_SDRAM(addr); lp->uc = (struct pcnet_uncached_priv *)addr; - addr = (u32)memalign(ARCH_DMA_MINALIGN, sizeof(*lp->rx_buf)); + addr = (unsigned long)memalign(ARCH_DMA_MINALIGN, + sizeof(*lp->rx_buf)); flush_dcache_range(addr, addr + sizeof(*lp->rx_buf)); lp->rx_buf = (void *)addr; } @@ -361,7 +360,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) */ lp->cur_rx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - addr = pcnet_virt_to_mem(dev, (*lp->rx_buf)[i], false); + addr = pcnet_virt_to_mem(dev, (*lp->rx_buf)[i]); uc->rx_ring[i].base = cpu_to_le32(addr); uc->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); uc->rx_ring[i].status = cpu_to_le16(0x8000); @@ -393,9 +392,9 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) uc->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS | RX_RING_LEN_BITS); - addr = pcnet_virt_to_mem(dev, uc->rx_ring, true); + addr = pcnet_virt_to_mem(dev, uc->rx_ring); uc->init_block.rx_ring = cpu_to_le32(addr); - addr = pcnet_virt_to_mem(dev, uc->tx_ring, true); + addr = pcnet_virt_to_mem(dev, uc->tx_ring); uc->init_block.tx_ring = cpu_to_le32(addr); PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n", @@ -406,7 +405,7 @@ static int pcnet_init(struct eth_device *dev, bd_t *bis) * Tell the controller where the Init Block is located. */ barrier(); - addr = pcnet_virt_to_mem(dev, &lp->uc->init_block, true); + addr = pcnet_virt_to_mem(dev, &lp->uc->init_block); pcnet_write_csr(dev, 1, addr & 0xffff); pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); @@ -464,7 +463,7 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len) * Setup Tx ring. Caution: the write order is important here, * set the status with the "ownership" bits last. */ - addr = pcnet_virt_to_mem(dev, packet, false); + addr = pcnet_virt_to_mem(dev, packet); writew(-pkt_len, &entry->length); writel(0, &entry->misc); writel(addr, &entry->base); diff --git a/include/configs/ap121.h b/include/configs/ap121.h index 6f69f31..b01031c 100644 --- a/include/configs/ap121.h +++ b/include/configs/ap121.h @@ -15,11 +15,6 @@ #define CONFIG_SYS_MHZ 200 #define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000) -/* Cache Configuration */ -#define CONFIG_SYS_DCACHE_SIZE 0x8000 -#define CONFIG_SYS_ICACHE_SIZE 0x10000 -#define CONFIG_SYS_CACHELINE_SIZE 32 - #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_MALLOC_LEN 0x40000 @@ -45,13 +40,13 @@ "rootfstype=squashfs" #define CONFIG_BOOTCOMMAND "sf probe;" \ "mtdparts default;" \ - "bootm 0x9f300000" + "bootm 0x9f650000" #define CONFIG_LZMA #define MTDIDS_DEFAULT "nor0=spi-flash.0" #define MTDPARTS_DEFAULT "mtdparts=spi-flash.0:" \ "256k(u-boot),64k(u-boot-env)," \ - "2752k(rootfs),896k(uImage)," \ + "6144k(rootfs),1600k(uImage)," \ "64k(NVRAM),64k(ART)" #define CONFIG_ENV_SPI_MAX_HZ 25000000 diff --git a/include/configs/ap143.h b/include/configs/ap143.h index f907c02..0fa73a7 100644 --- a/include/configs/ap143.h +++ b/include/configs/ap143.h @@ -15,11 +15,6 @@ #define CONFIG_SYS_MHZ 325 #define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000) -/* Cache Configuration */ -#define CONFIG_SYS_DCACHE_SIZE 0x8000 -#define CONFIG_SYS_ICACHE_SIZE 0x10000 -#define CONFIG_SYS_CACHELINE_SIZE 32 - #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_MALLOC_LEN 0x40000 @@ -49,14 +44,14 @@ "rootfstype=squashfs" #define CONFIG_BOOTCOMMAND "sf probe;" \ "mtdparts default;" \ - "bootm 0x9f300000" + "bootm 0x9f680000" #define CONFIG_LZMA #define MTDIDS_DEFAULT "nor0=spi-flash.0" #define MTDPARTS_DEFAULT "mtdparts=spi-flash.0:" \ "256k(u-boot),64k(u-boot-env)," \ - "2752k(rootfs),896k(uImage)," \ - "64k(NVRAM),64k(ART)" + "6336k(rootfs),1472k(uImage)," \ + "64k(ART)" #define CONFIG_ENV_SPI_MAX_HZ 25000000 #define CONFIG_ENV_IS_IN_SPI_FLASH diff --git a/include/configs/dbau1x00.h b/include/configs/dbau1x00.h index 68d9e36..68ff025 100644 --- a/include/configs/dbau1x00.h +++ b/include/configs/dbau1x00.h @@ -202,11 +202,4 @@ #define CONFIG_SYS_ATA_ALT_OFFSET 0x0100 #endif /* CONFIG_DBAU1550 */ -/*----------------------------------------------------------------------- - * Cache Configuration - */ -#define CONFIG_SYS_DCACHE_SIZE 16384 -#define CONFIG_SYS_ICACHE_SIZE 16384 -#define CONFIG_SYS_CACHELINE_SIZE 32 - #endif /* __CONFIG_H */ diff --git a/include/configs/malta.h b/include/configs/malta.h index a369678..fc4baba 100644 --- a/include/configs/malta.h +++ b/include/configs/malta.h @@ -39,14 +39,18 @@ */ #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE -#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */ +#ifdef CONFIG_64BIT +# define CONFIG_SYS_SDRAM_BASE 0xffffffff80000000 +#else +# define CONFIG_SYS_SDRAM_BASE 0x80000000 +#endif #define CONFIG_SYS_MEM_SIZE (256 * 1024 * 1024) #define CONFIG_SYS_INIT_SP_OFFSET 0x400000 -#define CONFIG_SYS_LOAD_ADDR 0x81000000 -#define CONFIG_SYS_MEMTEST_START 0x80100000 -#define CONFIG_SYS_MEMTEST_END 0x80800000 +#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x01000000) +#define CONFIG_SYS_MEMTEST_START (CONFIG_SYS_SDRAM_BASE + 0x00100000) +#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x00800000) #define CONFIG_SYS_MALLOC_LEN (128 * 1024) #define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024) @@ -69,7 +73,11 @@ /* * Flash configuration */ -#define CONFIG_SYS_FLASH_BASE 0xbe000000 +#ifdef CONFIG_64BIT +# define CONFIG_SYS_FLASH_BASE 0xffffffffbe000000 +#else +# define CONFIG_SYS_FLASH_BASE 0xbe000000 +#endif #define CONFIG_SYS_MAX_FLASH_BANKS 1 #define CONFIG_SYS_MAX_FLASH_SECT 128 #define CONFIG_SYS_FLASH_CFI diff --git a/include/configs/pb1x00.h b/include/configs/pb1x00.h index 869768a..b907419 100644 --- a/include/configs/pb1x00.h +++ b/include/configs/pb1x00.h @@ -144,12 +144,6 @@ #define CONFIG_SYS_ATA_ALT_OFFSET 0x0100 #endif -/*----------------------------------------------------------------------- - * Cache Configuration - */ -#define CONFIG_SYS_DCACHE_SIZE 16384 -#define CONFIG_SYS_ICACHE_SIZE 16384 -#define CONFIG_SYS_CACHELINE_SIZE 32 /* * BOOTP options diff --git a/include/configs/pic32mzdask.h b/include/configs/pic32mzdask.h index fb2e41f..319e3b5 100644 --- a/include/configs/pic32mzdask.h +++ b/include/configs/pic32mzdask.h @@ -100,7 +100,6 @@ * USB Configuration */ #define CONFIG_USB_MUSB_PIO_ONLY -#define CONFIG_SYS_CACHELINE_SIZE 16 /*----------------------------------------------------------------------- * File System Configuration diff --git a/include/configs/qemu-mips.h b/include/configs/qemu-mips.h index 246ee01..f58fc4c 100644 --- a/include/configs/qemu-mips.h +++ b/include/configs/qemu-mips.h @@ -132,11 +132,4 @@ #define CONFIG_LZMA -/*----------------------------------------------------------------------- - * Cache Configuration - */ -#define CONFIG_SYS_DCACHE_SIZE 16384 -#define CONFIG_SYS_ICACHE_SIZE 16384 -#define CONFIG_SYS_CACHELINE_SIZE 32 - #endif /* __CONFIG_H */ diff --git a/include/configs/qemu-mips64.h b/include/configs/qemu-mips64.h index 60a3a71..2190d16 100644 --- a/include/configs/qemu-mips64.h +++ b/include/configs/qemu-mips64.h @@ -132,11 +132,4 @@ #define CONFIG_LZMA -/*----------------------------------------------------------------------- - * Cache Configuration - */ -#define CONFIG_SYS_DCACHE_SIZE 16384 -#define CONFIG_SYS_ICACHE_SIZE 16384 -#define CONFIG_SYS_CACHELINE_SIZE 32 - #endif /* __CONFIG_H */ diff --git a/include/configs/tplink_wdr4300.h b/include/configs/tplink_wdr4300.h index 09a69fe..6273711 100644 --- a/include/configs/tplink_wdr4300.h +++ b/include/configs/tplink_wdr4300.h @@ -15,11 +15,6 @@ #define CONFIG_SYS_MHZ 280 #define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000) -/* Cache Configuration */ -#define CONFIG_SYS_DCACHE_SIZE 0x8000 -#define CONFIG_SYS_ICACHE_SIZE 0x10000 -#define CONFIG_SYS_CACHELINE_SIZE 32 - #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_MALLOC_LEN 0x40000 diff --git a/include/configs/vct.h b/include/configs/vct.h index 68eb089..cc5e354 100644 --- a/include/configs/vct.h +++ b/include/configs/vct.h @@ -204,13 +204,6 @@ #endif /* CONFIG_VCT_ONENAND */ /* - * Cache Configuration - */ -#define CONFIG_SYS_DCACHE_SIZE 16384 -#define CONFIG_SYS_ICACHE_SIZE 16384 -#define CONFIG_SYS_CACHELINE_SIZE 32 - -/* * I2C/EEPROM */ #define CONFIG_SYS_I2C |