mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
Merge branch 'master' of git://git.denx.de/u-boot-mips
This commit is contained in:
commit
423620b9d4
57 changed files with 2120 additions and 185 deletions
|
@ -26,6 +26,8 @@ config TARGET_MALTA
|
|||
select DM
|
||||
select DM_SERIAL
|
||||
select DYNAMIC_IO_PORT_BASE
|
||||
select MIPS_CM
|
||||
select MIPS_L2_CACHE
|
||||
select OF_CONTROL
|
||||
select OF_ISA_BUS
|
||||
select SUPPORTS_BIG_ENDIAN
|
||||
|
@ -73,10 +75,43 @@ config MACH_PIC32
|
|||
select OF_CONTROL
|
||||
select DM
|
||||
|
||||
config TARGET_BOSTON
|
||||
bool "Support Boston"
|
||||
select DM
|
||||
select DM_SERIAL
|
||||
select OF_CONTROL
|
||||
select MIPS_CM
|
||||
select MIPS_L1_CACHE_SHIFT_6
|
||||
select MIPS_L2_CACHE
|
||||
select SUPPORTS_BIG_ENDIAN
|
||||
select SUPPORTS_LITTLE_ENDIAN
|
||||
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
|
||||
|
||||
config TARGET_XILFPGA
|
||||
bool "Support Imagination Xilfpga"
|
||||
select OF_CONTROL
|
||||
select DM
|
||||
select DM_SERIAL
|
||||
select DM_GPIO
|
||||
select DM_ETH
|
||||
select SUPPORTS_LITTLE_ENDIAN
|
||||
select SUPPORTS_CPU_MIPS32_R1
|
||||
select SUPPORTS_CPU_MIPS32_R2
|
||||
select MIPS_L1_CACHE_SHIFT_4
|
||||
help
|
||||
This supports IMGTEC MIPSfpga platform
|
||||
|
||||
endchoice
|
||||
|
||||
source "board/dbau1x00/Kconfig"
|
||||
source "board/imgtec/boston/Kconfig"
|
||||
source "board/imgtec/malta/Kconfig"
|
||||
source "board/imgtec/xilfpga/Kconfig"
|
||||
source "board/micronas/vct/Kconfig"
|
||||
source "board/pb1x00/Kconfig"
|
||||
source "board/qemu-mips/Kconfig"
|
||||
|
@ -300,9 +335,31 @@ config MIPS_L1_CACHE_SHIFT
|
|||
default "4" if MIPS_L1_CACHE_SHIFT_4
|
||||
default "5"
|
||||
|
||||
config MIPS_L2_CACHE
|
||||
bool
|
||||
help
|
||||
Select this if your system includes an L2 cache and you want U-Boot
|
||||
to initialise & maintain it.
|
||||
|
||||
config DYNAMIC_IO_PORT_BASE
|
||||
bool
|
||||
|
||||
config MIPS_CM
|
||||
bool
|
||||
help
|
||||
Select this if your system contains a MIPS Coherence Manager and you
|
||||
wish U-Boot to configure it or make use of it to retrieve system
|
||||
information such as cache configuration.
|
||||
|
||||
config MIPS_CM_BASE
|
||||
hex
|
||||
default 0x1fbf8000
|
||||
help
|
||||
The physical base address at which to map the MIPS Coherence Manager
|
||||
Global Configuration Registers (GCRs). This should be set such that
|
||||
the GCRs occupy a region of the physical address space which is
|
||||
otherwise unused, or at minimum that software doesn't need to access.
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -7,3 +7,5 @@ extra-y = start.o
|
|||
obj-y += time.o
|
||||
obj-y += interrupts.o
|
||||
obj-y += cpu.o
|
||||
|
||||
obj-$(CONFIG_MIPS_CM) += cm_init.o
|
||||
|
|
45
arch/mips/cpu/cm_init.S
Normal file
45
arch/mips/cpu/cm_init.S
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* MIPS Coherence Manager (CM) Initialisation
|
||||
*
|
||||
* Copyright (c) 2016 Imagination Technologies Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/cm.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/regdef.h>
|
||||
|
||||
LEAF(mips_cm_map)
|
||||
/* Config3 must exist for a CM to be present */
|
||||
mfc0 t0, CP0_CONFIG, 1
|
||||
bgez t0, 2f
|
||||
mfc0 t0, CP0_CONFIG, 2
|
||||
bgez t0, 2f
|
||||
|
||||
/* Check Config3.CMGCR to determine CM presence */
|
||||
mfc0 t0, CP0_CONFIG, 3
|
||||
and t0, t0, MIPS_CONF3_CMGCR
|
||||
beqz t0, 2f
|
||||
|
||||
/* Find the current physical GCR base address */
|
||||
1: MFC0 t0, CP0_CMGCRBASE
|
||||
PTR_SLL t0, t0, 4
|
||||
|
||||
/* If the GCRs are where we want, we're done */
|
||||
PTR_LI t1, CONFIG_MIPS_CM_BASE
|
||||
beq t0, t1, 2f
|
||||
|
||||
/* Move the GCRs to our configured base address */
|
||||
PTR_LI t2, CKSEG1
|
||||
PTR_ADDU t0, t0, t2
|
||||
sw zero, GCR_BASE_UPPER(t0)
|
||||
sw t1, GCR_BASE(t0)
|
||||
|
||||
/* Re-check the GCR base */
|
||||
b 1b
|
||||
|
||||
2: jr ra
|
||||
END(mips_cm_map)
|
|
@ -8,6 +8,7 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
|
@ -35,3 +36,9 @@ void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
|
|||
write_c0_index(index);
|
||||
tlb_write_indexed();
|
||||
}
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
mips_cache_probe();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,10 +12,6 @@
|
|||
#include <asm/regdef.h>
|
||||
#include <asm/mipsregs.h>
|
||||
|
||||
#ifndef CONFIG_SYS_MIPS_CACHE_MODE
|
||||
#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_INIT_SP_ADDR
|
||||
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + \
|
||||
CONFIG_SYS_INIT_SP_OFFSET)
|
||||
|
@ -112,9 +108,28 @@ ENTRY(_start)
|
|||
|
||||
.align 4
|
||||
reset:
|
||||
#if __mips_isa_rev >= 6
|
||||
mfc0 t0, CP0_CONFIG, 5
|
||||
and t0, t0, MIPS_CONF5_VP
|
||||
beqz t0, 1f
|
||||
nop
|
||||
|
||||
b 2f
|
||||
mfc0 t0, CP0_GLOBALNUMBER
|
||||
#endif
|
||||
|
||||
1: mfc0 t0, CP0_EBASE
|
||||
and t0, t0, EBASE_CPUNUM
|
||||
|
||||
/* Hang if this isn't the first CPU in the system */
|
||||
2: beqz t0, 4f
|
||||
nop
|
||||
3: wait
|
||||
b 3b
|
||||
nop
|
||||
|
||||
/* Clear watch registers */
|
||||
MTC0 zero, CP0_WATCHLO
|
||||
4: MTC0 zero, CP0_WATCHLO
|
||||
mtc0 zero, CP0_WATCHHI
|
||||
|
||||
/* WP(Watch Pending), SW0/1 should be cleared */
|
||||
|
@ -127,9 +142,11 @@ reset:
|
|||
mtc0 zero, CP0_COMPARE
|
||||
|
||||
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
|
||||
/* CONFIG0 register */
|
||||
li t0, CONF_CM_UNCACHED
|
||||
mfc0 t0, CP0_CONFIG
|
||||
and t0, t0, MIPS_CONF_IMPL
|
||||
or t0, t0, CONF_CM_UNCACHED
|
||||
mtc0 t0, CP0_CONFIG
|
||||
ehb
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -144,20 +161,31 @@ reset:
|
|||
1:
|
||||
PTR_L gp, 0(ra)
|
||||
|
||||
#ifdef CONFIG_MIPS_CM
|
||||
PTR_LA t9, mips_cm_map
|
||||
jalr t9
|
||||
nop
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
|
||||
# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
|
||||
/* Initialize any external memory */
|
||||
PTR_LA t9, lowlevel_init
|
||||
jalr t9
|
||||
nop
|
||||
# endif
|
||||
|
||||
/* Initialize caches... */
|
||||
PTR_LA t9, mips_cache_reset
|
||||
jalr t9
|
||||
nop
|
||||
|
||||
/* ... and enable them */
|
||||
li t0, CONFIG_SYS_MIPS_CACHE_MODE
|
||||
mtc0 t0, CP0_CONFIG
|
||||
# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
|
||||
/* Initialize any external memory */
|
||||
PTR_LA t9, lowlevel_init
|
||||
jalr t9
|
||||
nop
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Set up temporary stack */
|
||||
|
@ -214,12 +242,9 @@ ENTRY(relocate_code)
|
|||
PTR_LI t0, CONFIG_SYS_MONITOR_BASE
|
||||
PTR_SUB s1, s2, t0 # s1 <-- relocation offset
|
||||
|
||||
PTR_LA t3, in_ram
|
||||
PTR_L t2, -(3 * PTRSIZE)(t3) # t2 <-- __image_copy_end
|
||||
PTR_LA t2, __image_copy_end
|
||||
move t1, a2
|
||||
|
||||
PTR_ADD gp, s1 # adjust gp
|
||||
|
||||
/*
|
||||
* t0 = source address
|
||||
* t1 = target address
|
||||
|
@ -232,32 +257,14 @@ ENTRY(relocate_code)
|
|||
blt t0, t2, 1b
|
||||
PTR_ADDU t1, PTRSIZE
|
||||
|
||||
/* If caches were enabled, we would have to flush them here. */
|
||||
PTR_SUB a1, t1, s2 # a1 <-- size
|
||||
PTR_LA t9, flush_cache
|
||||
jalr t9
|
||||
move a0, s2 # a0 <-- destination address
|
||||
|
||||
/* Jump to where we've relocated ourselves */
|
||||
PTR_ADDIU t0, s2, in_ram - _start
|
||||
jr t0
|
||||
nop
|
||||
|
||||
PTR __rel_dyn_end
|
||||
PTR __rel_dyn_start
|
||||
PTR __image_copy_end
|
||||
PTR _GLOBAL_OFFSET_TABLE_
|
||||
PTR num_got_entries
|
||||
|
||||
in_ram:
|
||||
/*
|
||||
* Now we want to update GOT.
|
||||
*
|
||||
* GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
|
||||
* generated by GNU ld. Skip these reserved entries from relocation.
|
||||
*/
|
||||
PTR_L t3, -(1 * PTRSIZE)(t0) # t3 <-- num_got_entries
|
||||
PTR_L t8, -(2 * PTRSIZE)(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_
|
||||
PTR_LA t3, num_got_entries
|
||||
PTR_LA t8, _GLOBAL_OFFSET_TABLE_
|
||||
PTR_ADD t8, s1 # t8 now holds relocated _G_O_T_
|
||||
PTR_ADDIU t8, t8, 2 * PTRSIZE # skipping first two entries
|
||||
PTR_LI t2, 2
|
||||
|
@ -272,8 +279,8 @@ in_ram:
|
|||
PTR_ADDIU t8, PTRSIZE
|
||||
|
||||
/* Update dynamic relocations */
|
||||
PTR_L t1, -(4 * PTRSIZE)(t0) # t1 <-- __rel_dyn_start
|
||||
PTR_L t2, -(5 * PTRSIZE)(t0) # t2 <-- __rel_dyn_end
|
||||
PTR_LA t1, __rel_dyn_start
|
||||
PTR_LA t2, __rel_dyn_end
|
||||
|
||||
b 2f # skip first reserved entry
|
||||
PTR_ADDIU t1, 2 * PTRSIZE
|
||||
|
@ -297,6 +304,20 @@ in_ram:
|
|||
blt t1, t2, 1b
|
||||
PTR_ADDIU t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes
|
||||
|
||||
/*
|
||||
* Flush caches to ensure our newly modified instructions are visible
|
||||
* to the instruction cache. We're still running with the old GOT, so
|
||||
* apply the reloc offset to the start address.
|
||||
*/
|
||||
PTR_LA a0, __text_start
|
||||
PTR_LA a1, __text_end
|
||||
PTR_SUB a1, a1, a0
|
||||
PTR_LA t9, flush_cache
|
||||
jalr t9
|
||||
PTR_ADD a0, s1
|
||||
|
||||
PTR_ADD gp, s1 # adjust gp
|
||||
|
||||
/*
|
||||
* Clear BSS
|
||||
*
|
||||
|
|
|
@ -19,7 +19,9 @@ SECTIONS
|
|||
|
||||
. = ALIGN(4);
|
||||
.text : {
|
||||
__text_start = .;
|
||||
*(.text*)
|
||||
__text_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
|
||||
dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
|
||||
dtb-$(CONFIG_TARGET_AP143) += ap143.dtb
|
||||
dtb-$(CONFIG_TARGET_BOSTON) += img,boston.dtb
|
||||
dtb-$(CONFIG_TARGET_MALTA) += mti,malta.dtb
|
||||
dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
|
||||
dtb-$(CONFIG_TARGET_XILFPGA) += nexys4ddr.dtb
|
||||
dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb
|
||||
|
||||
targets += $(dtb-y)
|
||||
|
|
222
arch/mips/dts/img,boston.dts
Normal file
222
arch/mips/dts/img,boston.dts
Normal file
|
@ -0,0 +1,222 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/clock/boston-clock.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/mips-gic.h>
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "img,boston";
|
||||
|
||||
chosen {
|
||||
stdout-path = &uart0;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "img,mips";
|
||||
reg = <0>;
|
||||
clocks = <&clk_boston BOSTON_CLK_CPU>;
|
||||
};
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x10000000>;
|
||||
};
|
||||
|
||||
gic: interrupt-controller {
|
||||
compatible = "mti,gic";
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
|
||||
timer {
|
||||
compatible = "mti,gic-timer";
|
||||
interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
|
||||
clocks = <&clk_boston BOSTON_CLK_CPU>;
|
||||
};
|
||||
};
|
||||
|
||||
pci0: pci@10000000 {
|
||||
status = "disabled";
|
||||
compatible = "xlnx,axi-pcie-host-1.00.a";
|
||||
device_type = "pci";
|
||||
reg = <0x10000000 0x2000000>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SHARED 2 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
ranges = <0x02000000 0 0x40000000
|
||||
0x40000000 0 0x40000000>;
|
||||
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pci0_intc 0>,
|
||||
<0 0 0 2 &pci0_intc 1>,
|
||||
<0 0 0 3 &pci0_intc 2>,
|
||||
<0 0 0 4 &pci0_intc 3>;
|
||||
|
||||
pci0_intc: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pci@12000000 {
|
||||
status = "disabled";
|
||||
compatible = "xlnx,axi-pcie-host-1.00.a";
|
||||
device_type = "pci";
|
||||
reg = <0x12000000 0x2000000>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SHARED 1 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
ranges = <0x02000000 0 0x20000000
|
||||
0x20000000 0 0x20000000>;
|
||||
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pci1_intc 0>,
|
||||
<0 0 0 2 &pci1_intc 1>,
|
||||
<0 0 0 3 &pci1_intc 2>,
|
||||
<0 0 0 4 &pci1_intc 3>;
|
||||
|
||||
pci1_intc: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
pci2: pci@14000000 {
|
||||
compatible = "xlnx,axi-pcie-host-1.00.a";
|
||||
device_type = "pci";
|
||||
reg = <0x14000000 0x2000000>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SHARED 0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
ranges = <0x02000000 0 0x16000000
|
||||
0x16000000 0 0x100000>;
|
||||
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pci2_intc 0>,
|
||||
<0 0 0 2 &pci2_intc 1>,
|
||||
<0 0 0 3 &pci2_intc 2>,
|
||||
<0 0 0 4 &pci2_intc 3>;
|
||||
|
||||
pci2_intc: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
pci2_root@0,0,0 {
|
||||
compatible = "pci10ee,7021";
|
||||
reg = <0x00000000 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
eg20t_bridge@1,0,0 {
|
||||
compatible = "pci8086,8800";
|
||||
reg = <0x00010000 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
eg20t_mac@2,0,1 {
|
||||
compatible = "pci8086,8802";
|
||||
reg = <0x00020100 0 0 0 0>;
|
||||
phy-reset-gpios = <&eg20t_gpio 6 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
eg20t_gpio: eg20t_gpio@2,0,2 {
|
||||
compatible = "pci8086,8803";
|
||||
reg = <0x00020200 0 0 0 0>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
eg20t_i2c@2,12,2 {
|
||||
compatible = "pci8086,8817";
|
||||
reg = <0x00026200 0 0 0 0>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
rtc@0x68 {
|
||||
compatible = "st,m41t81s";
|
||||
reg = <0x68>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
plat_regs: system-controller@17ffd000 {
|
||||
compatible = "img,boston-platform-regs", "syscon";
|
||||
reg = <0x17ffd000 0x1000>;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
clk_boston: clock {
|
||||
compatible = "img,boston-clock";
|
||||
#clock-cells = <1>;
|
||||
regmap = <&plat_regs>;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
reboot: syscon-reboot {
|
||||
compatible = "syscon-reboot";
|
||||
regmap = <&plat_regs>;
|
||||
offset = <0x10>;
|
||||
mask = <0x10>;
|
||||
};
|
||||
|
||||
uart0: uart@17ffe000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x17ffe000 0x1000>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SHARED 3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
clocks = <&clk_boston BOSTON_CLK_SYS>;
|
||||
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
lcd: lcd@17fff000 {
|
||||
compatible = "img,boston-lcd";
|
||||
reg = <0x17fff000 0x8>;
|
||||
};
|
||||
|
||||
flash@18000000 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x18000000 0x8000000>;
|
||||
bank-width = <2>;
|
||||
};
|
||||
};
|
21
arch/mips/dts/microAptiv.dtsi
Normal file
21
arch/mips/dts/microAptiv.dtsi
Normal file
|
@ -0,0 +1,21 @@
|
|||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "img,xilfpga";
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "mips,m14Kc";
|
||||
clocks = <&ext>;
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
ext: ext {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
};
|
62
arch/mips/dts/nexys4ddr.dts
Normal file
62
arch/mips/dts/nexys4ddr.dts
Normal file
|
@ -0,0 +1,62 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "microAptiv.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "digilent,nexys4ddr";
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x08000000>;
|
||||
};
|
||||
|
||||
cpuintc: interrupt-controller@0 {
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
compatible = "mti,cpu-interrupt-controller";
|
||||
};
|
||||
|
||||
aliases {
|
||||
console = &axi_uart16550;
|
||||
};
|
||||
|
||||
axi_ethernetlite: ethernet@10e00000 {
|
||||
compatible = "xlnx,xps-ethernetlite-1.00.a";
|
||||
device_type = "network";
|
||||
local-mac-address = [08 86 4C 0D F7 09];
|
||||
phy-handle = <&phy0>;
|
||||
reg = <0x10e00000 0x10000>;
|
||||
xlnx,duplex = <0x1>;
|
||||
xlnx,include-global-buffers = <0x1>;
|
||||
xlnx,include-internal-loopback = <0x0>;
|
||||
xlnx,include-mdio = <0x1>;
|
||||
xlnx,instance = "axi_ethernetlite_inst";
|
||||
xlnx,rx-ping-pong = <0x1>;
|
||||
xlnx,s-axi-id-width = <0x1>;
|
||||
xlnx,tx-ping-pong = <0x1>;
|
||||
xlnx,use-internal = <0x0>;
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: phy@1 {
|
||||
compatible = <0x0007c0f0 0xfffffff0>;
|
||||
device_type = "ethernet-phy";
|
||||
reg = <1>;
|
||||
} ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
|
||||
axi_uart16550: serial@10400000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x10400000 0x10000>;
|
||||
|
||||
reg-shift = <2>;
|
||||
reg-offset = <0x1000>;
|
||||
|
||||
clock-frequency = <50000000>;
|
||||
|
||||
};
|
||||
};
|
||||
|
|
@ -19,4 +19,13 @@
|
|||
*/
|
||||
#define CONFIG_SYS_CACHELINE_SIZE ARCH_DMA_MINALIGN
|
||||
|
||||
/**
|
||||
* mips_cache_probe() - Probe the properties of the caches
|
||||
*
|
||||
* Call this to probe the properties such as line sizes of the caches
|
||||
* present in the system, if any. This must be done before cache maintenance
|
||||
* functions such as flush_cache may be called.
|
||||
*/
|
||||
void mips_cache_probe(void);
|
||||
|
||||
#endif /* __MIPS_CACHE_H__ */
|
||||
|
|
62
arch/mips/include/asm/cm.h
Normal file
62
arch/mips/include/asm/cm.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* MIPS Coherence Manager (CM) Register Definitions
|
||||
*
|
||||
* Copyright (c) 2016 Imagination Technologies Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#ifndef __MIPS_ASM_CM_H__
|
||||
#define __MIPS_ASM_CM_H__
|
||||
|
||||
/* Global Control Register (GCR) offsets */
|
||||
#define GCR_BASE 0x0008
|
||||
#define GCR_BASE_UPPER 0x000c
|
||||
#define GCR_REV 0x0030
|
||||
#define GCR_L2_CONFIG 0x0130
|
||||
#define GCR_L2_TAG_ADDR 0x0600
|
||||
#define GCR_L2_TAG_ADDR_UPPER 0x0604
|
||||
#define GCR_L2_TAG_STATE 0x0608
|
||||
#define GCR_L2_TAG_STATE_UPPER 0x060c
|
||||
#define GCR_L2_DATA 0x0610
|
||||
#define GCR_L2_DATA_UPPER 0x0614
|
||||
#define GCR_Cx_COHERENCE 0x2008
|
||||
|
||||
/* GCR_REV CM versions */
|
||||
#define GCR_REV_CM3 0x0800
|
||||
|
||||
/* GCR_L2_CONFIG fields */
|
||||
#define GCR_L2_CONFIG_ASSOC_SHIFT 0
|
||||
#define GCR_L2_CONFIG_ASSOC_BITS 8
|
||||
#define GCR_L2_CONFIG_LINESZ_SHIFT 8
|
||||
#define GCR_L2_CONFIG_LINESZ_BITS 4
|
||||
#define GCR_L2_CONFIG_SETSZ_SHIFT 12
|
||||
#define GCR_L2_CONFIG_SETSZ_BITS 4
|
||||
#define GCR_L2_CONFIG_BYPASS (1 << 20)
|
||||
|
||||
/* GCR_Cx_COHERENCE */
|
||||
#define GCR_Cx_COHERENCE_DOM_EN (0xff << 0)
|
||||
#define GCR_Cx_COHERENCE_EN (0x1 << 0)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
static inline void *mips_cm_base(void)
|
||||
{
|
||||
return (void *)CKSEG1ADDR(CONFIG_MIPS_CM_BASE);
|
||||
}
|
||||
|
||||
static inline unsigned long mips_cm_l2_line_size(void)
|
||||
{
|
||||
unsigned long l2conf, line_sz;
|
||||
|
||||
l2conf = __raw_readl(mips_cm_base() + GCR_L2_CONFIG);
|
||||
|
||||
line_sz = l2conf >> GCR_L2_CONFIG_LINESZ_SHIFT;
|
||||
line_sz &= GENMASK(GCR_L2_CONFIG_LINESZ_BITS - 1, 0);
|
||||
return line_sz ? (2 << line_sz) : 0;
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __MIPS_ASM_CM_H__ */
|
|
@ -21,6 +21,13 @@ struct arch_global_data {
|
|||
unsigned long rev;
|
||||
unsigned long ver;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
|
||||
unsigned short l1i_line_size;
|
||||
unsigned short l1d_line_size;
|
||||
#endif
|
||||
#ifdef CONFIG_MIPS_L2_CACHE
|
||||
unsigned short l2_line_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
#include <asm-generic/global_data.h>
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define CP0_ENTRYLO0 $2
|
||||
#define CP0_ENTRYLO1 $3
|
||||
#define CP0_CONF $3
|
||||
#define CP0_GLOBALNUMBER $3, 1
|
||||
#define CP0_CONTEXT $4
|
||||
#define CP0_PAGEMASK $5
|
||||
#define CP0_WIRED $6
|
||||
|
@ -360,6 +361,11 @@
|
|||
#define CAUSEB_BD 31
|
||||
#define CAUSEF_BD (_ULCAST_(1) << 31)
|
||||
|
||||
/*
|
||||
* Bits in the coprocessor 0 EBase register.
|
||||
*/
|
||||
#define EBASE_CPUNUM 0x3ff
|
||||
|
||||
/*
|
||||
* Bits in the coprocessor 0 config register.
|
||||
*/
|
||||
|
@ -450,6 +456,7 @@
|
|||
#define MIPS_CONF_MT_FTLB (_ULCAST_(4) << 7)
|
||||
#define MIPS_CONF_AR (_ULCAST_(7) << 10)
|
||||
#define MIPS_CONF_AT (_ULCAST_(3) << 13)
|
||||
#define MIPS_CONF_IMPL (_ULCAST_(0x1ff) << 16)
|
||||
#define MIPS_CONF_M (_ULCAST_(1) << 31)
|
||||
|
||||
/*
|
||||
|
@ -484,9 +491,13 @@
|
|||
#define MIPS_CONF1_TLBS_SIZE (6)
|
||||
#define MIPS_CONF1_TLBS (_ULCAST_(63) << MIPS_CONF1_TLBS_SHIFT)
|
||||
|
||||
#define MIPS_CONF2_SA_SHF 0
|
||||
#define MIPS_CONF2_SA (_ULCAST_(15) << 0)
|
||||
#define MIPS_CONF2_SL_SHF 4
|
||||
#define MIPS_CONF2_SL (_ULCAST_(15) << 4)
|
||||
#define MIPS_CONF2_SS_SHF 8
|
||||
#define MIPS_CONF2_SS (_ULCAST_(15) << 8)
|
||||
#define MIPS_CONF2_L2B (_ULCAST_(1) << 12)
|
||||
#define MIPS_CONF2_SU (_ULCAST_(15) << 12)
|
||||
#define MIPS_CONF2_TA (_ULCAST_(15) << 16)
|
||||
#define MIPS_CONF2_TL (_ULCAST_(15) << 20)
|
||||
|
@ -548,8 +559,10 @@
|
|||
#define MIPS_CONF5_MRP (_ULCAST_(1) << 3)
|
||||
#define MIPS_CONF5_LLB (_ULCAST_(1) << 4)
|
||||
#define MIPS_CONF5_MVH (_ULCAST_(1) << 5)
|
||||
#define MIPS_CONF5_VP (_ULCAST_(1) << 7)
|
||||
#define MIPS_CONF5_FRE (_ULCAST_(1) << 8)
|
||||
#define MIPS_CONF5_UFE (_ULCAST_(1) << 9)
|
||||
#define MIPS_CONF5_L2C (_ULCAST_(1) << 10)
|
||||
#define MIPS_CONF5_MSAEN (_ULCAST_(1) << 27)
|
||||
#define MIPS_CONF5_EVA (_ULCAST_(1) << 28)
|
||||
#define MIPS_CONF5_CV (_ULCAST_(1) << 29)
|
||||
|
|
|
@ -7,34 +7,85 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <asm/cacheops.h>
|
||||
#include <asm/cm.h>
|
||||
#include <asm/mipsregs.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static void probe_l2(void)
|
||||
{
|
||||
#ifdef CONFIG_MIPS_L2_CACHE
|
||||
unsigned long conf2, sl;
|
||||
bool l2c = false;
|
||||
|
||||
if (!(read_c0_config1() & MIPS_CONF_M))
|
||||
return;
|
||||
|
||||
conf2 = read_c0_config2();
|
||||
|
||||
if (__mips_isa_rev >= 6) {
|
||||
l2c = conf2 & MIPS_CONF_M;
|
||||
if (l2c)
|
||||
l2c = read_c0_config3() & MIPS_CONF_M;
|
||||
if (l2c)
|
||||
l2c = read_c0_config4() & MIPS_CONF_M;
|
||||
if (l2c)
|
||||
l2c = read_c0_config5() & MIPS_CONF5_L2C;
|
||||
}
|
||||
|
||||
if (l2c && config_enabled(CONFIG_MIPS_CM)) {
|
||||
gd->arch.l2_line_size = mips_cm_l2_line_size();
|
||||
} else if (l2c) {
|
||||
/* We don't know how to retrieve L2 config on this system */
|
||||
BUG();
|
||||
} else {
|
||||
sl = (conf2 & MIPS_CONF2_SL) >> MIPS_CONF2_SL_SHF;
|
||||
gd->arch.l2_line_size = sl ? (2 << sl) : 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void mips_cache_probe(void)
|
||||
{
|
||||
#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
|
||||
unsigned long conf1, il, dl;
|
||||
|
||||
conf1 = read_c0_config1();
|
||||
|
||||
il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF;
|
||||
dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF;
|
||||
|
||||
gd->arch.l1i_line_size = il ? (2 << il) : 0;
|
||||
gd->arch.l1d_line_size = dl ? (2 << dl) : 0;
|
||||
#endif
|
||||
probe_l2();
|
||||
}
|
||||
|
||||
static inline unsigned long icache_line_size(void)
|
||||
{
|
||||
unsigned long conf1, il;
|
||||
|
||||
if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO))
|
||||
return CONFIG_SYS_ICACHE_LINE_SIZE;
|
||||
|
||||
conf1 = read_c0_config1();
|
||||
il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF;
|
||||
if (!il)
|
||||
return 0;
|
||||
return 2 << il;
|
||||
#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
|
||||
return gd->arch.l1i_line_size;
|
||||
#else
|
||||
return CONFIG_SYS_ICACHE_LINE_SIZE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned long dcache_line_size(void)
|
||||
{
|
||||
unsigned long conf1, dl;
|
||||
#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
|
||||
return gd->arch.l1d_line_size;
|
||||
#else
|
||||
return CONFIG_SYS_DCACHE_LINE_SIZE;
|
||||
#endif
|
||||
}
|
||||
|
||||
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)
|
||||
return 0;
|
||||
return 2 << dl;
|
||||
static inline unsigned long scache_line_size(void)
|
||||
{
|
||||
#ifdef CONFIG_MIPS_L2_CACHE
|
||||
return gd->arch.l2_line_size;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define cache_loop(start, end, lsize, ops...) do { \
|
||||
|
@ -53,12 +104,13 @@ void flush_cache(ulong start_addr, ulong size)
|
|||
{
|
||||
unsigned long ilsize = icache_line_size();
|
||||
unsigned long dlsize = dcache_line_size();
|
||||
unsigned long slsize = scache_line_size();
|
||||
|
||||
/* aend will be miscalculated when size is zero, so we return here */
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
if (ilsize == dlsize) {
|
||||
if ((ilsize == dlsize) && !slsize) {
|
||||
/* flush I-cache & D-cache simultaneously */
|
||||
cache_loop(start_addr, start_addr + size, ilsize,
|
||||
HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I);
|
||||
|
@ -68,6 +120,11 @@ void flush_cache(ulong start_addr, ulong size)
|
|||
/* flush D-cache */
|
||||
cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D);
|
||||
|
||||
/* flush L2 cache */
|
||||
if (slsize)
|
||||
cache_loop(start_addr, start_addr + size, slsize,
|
||||
HIT_WRITEBACK_INV_SD);
|
||||
|
||||
/* flush I-cache */
|
||||
cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I);
|
||||
}
|
||||
|
@ -75,21 +132,31 @@ void flush_cache(ulong start_addr, ulong size)
|
|||
void flush_dcache_range(ulong start_addr, ulong stop)
|
||||
{
|
||||
unsigned long lsize = dcache_line_size();
|
||||
unsigned long slsize = scache_line_size();
|
||||
|
||||
/* aend will be miscalculated when size is zero, so we return here */
|
||||
if (start_addr == stop)
|
||||
return;
|
||||
|
||||
cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D);
|
||||
|
||||
/* flush L2 cache */
|
||||
if (slsize)
|
||||
cache_loop(start_addr, stop, slsize, HIT_WRITEBACK_INV_SD);
|
||||
}
|
||||
|
||||
void invalidate_dcache_range(ulong start_addr, ulong stop)
|
||||
{
|
||||
unsigned long lsize = dcache_line_size();
|
||||
unsigned long slsize = scache_line_size();
|
||||
|
||||
/* aend will be miscalculated when size is zero, so we return here */
|
||||
if (start_addr == stop)
|
||||
return;
|
||||
|
||||
/* invalidate L2 cache */
|
||||
if (slsize)
|
||||
cache_loop(start_addr, stop, slsize, HIT_INVALIDATE_SD);
|
||||
|
||||
cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_D);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <asm/mipsregs.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/cacheops.h>
|
||||
#include <asm/cm.h>
|
||||
|
||||
#ifndef CONFIG_SYS_MIPS_CACHE_MODE
|
||||
#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
|
||||
|
@ -95,22 +96,147 @@
|
|||
* with good parity is available. This routine will initialise an area of
|
||||
* memory starting at location zero to be used as a source of parity.
|
||||
*
|
||||
* Note that this function does not follow the standard calling convention &
|
||||
* may clobber typically callee-saved registers.
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
*/
|
||||
#define R_RETURN s0
|
||||
#define R_IC_SIZE s1
|
||||
#define R_IC_LINE s2
|
||||
#define R_DC_SIZE s3
|
||||
#define R_DC_LINE s4
|
||||
#define R_L2_SIZE s5
|
||||
#define R_L2_LINE s6
|
||||
#define R_L2_BYPASSED s7
|
||||
#define R_L2_L2C t8
|
||||
LEAF(mips_cache_reset)
|
||||
#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
|
||||
li t2, CONFIG_SYS_ICACHE_SIZE
|
||||
li t8, CONFIG_SYS_ICACHE_LINE_SIZE
|
||||
#else
|
||||
l1_info t2, t8, MIPS_CONF1_IA_SHF
|
||||
move R_RETURN, ra
|
||||
|
||||
#ifdef CONFIG_MIPS_L2_CACHE
|
||||
/*
|
||||
* For there to be an L2 present, Config2 must be present. If it isn't
|
||||
* then we proceed knowing there's no L2 cache.
|
||||
*/
|
||||
move R_L2_SIZE, zero
|
||||
move R_L2_LINE, zero
|
||||
move R_L2_BYPASSED, zero
|
||||
move R_L2_L2C, zero
|
||||
mfc0 t0, CP0_CONFIG, 1
|
||||
bgez t0, l2_probe_done
|
||||
|
||||
/*
|
||||
* From MIPSr6 onwards the L2 cache configuration might not be reported
|
||||
* by Config2. The Config5.L2C bit indicates whether this is the case,
|
||||
* and if it is then we need knowledge of where else to look. For cores
|
||||
* from Imagination Technologies this is a CM GCR.
|
||||
*/
|
||||
# if __mips_isa_rev >= 6
|
||||
/* Check that Config5 exists */
|
||||
mfc0 t0, CP0_CONFIG, 2
|
||||
bgez t0, l2_probe_cop0
|
||||
mfc0 t0, CP0_CONFIG, 3
|
||||
bgez t0, l2_probe_cop0
|
||||
mfc0 t0, CP0_CONFIG, 4
|
||||
bgez t0, l2_probe_cop0
|
||||
|
||||
/* Check Config5.L2C is set */
|
||||
mfc0 t0, CP0_CONFIG, 5
|
||||
and R_L2_L2C, t0, MIPS_CONF5_L2C
|
||||
beqz R_L2_L2C, l2_probe_cop0
|
||||
|
||||
/* Config5.L2C is set */
|
||||
# ifdef CONFIG_MIPS_CM
|
||||
/* The CM will provide L2 configuration */
|
||||
PTR_LI t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
|
||||
lw t1, GCR_L2_CONFIG(t0)
|
||||
bgez t1, l2_probe_done
|
||||
|
||||
ext R_L2_LINE, t1, \
|
||||
GCR_L2_CONFIG_LINESZ_SHIFT, GCR_L2_CONFIG_LINESZ_BITS
|
||||
beqz R_L2_LINE, l2_probe_done
|
||||
li t2, 2
|
||||
sllv R_L2_LINE, t2, R_L2_LINE
|
||||
|
||||
ext t2, t1, GCR_L2_CONFIG_ASSOC_SHIFT, GCR_L2_CONFIG_ASSOC_BITS
|
||||
addiu t2, t2, 1
|
||||
mul R_L2_SIZE, R_L2_LINE, t2
|
||||
|
||||
ext t2, t1, GCR_L2_CONFIG_SETSZ_SHIFT, GCR_L2_CONFIG_SETSZ_BITS
|
||||
sllv R_L2_SIZE, R_L2_SIZE, t2
|
||||
li t2, 64
|
||||
mul R_L2_SIZE, R_L2_SIZE, t2
|
||||
|
||||
/* Bypass the L2 cache so that we can init the L1s early */
|
||||
or t1, t1, GCR_L2_CONFIG_BYPASS
|
||||
sw t1, GCR_L2_CONFIG(t0)
|
||||
sync
|
||||
li R_L2_BYPASSED, 1
|
||||
|
||||
/* Zero the L2 tag registers */
|
||||
sw zero, GCR_L2_TAG_ADDR(t0)
|
||||
sw zero, GCR_L2_TAG_ADDR_UPPER(t0)
|
||||
sw zero, GCR_L2_TAG_STATE(t0)
|
||||
sw zero, GCR_L2_TAG_STATE_UPPER(t0)
|
||||
sw zero, GCR_L2_DATA(t0)
|
||||
sw zero, GCR_L2_DATA_UPPER(t0)
|
||||
sync
|
||||
# else
|
||||
/* We don't know how to retrieve L2 configuration on this system */
|
||||
# endif
|
||||
b l2_probe_done
|
||||
# endif
|
||||
|
||||
/*
|
||||
* For pre-r6 systems, or r6 systems with Config5.L2C==0, probe the L2
|
||||
* cache configuration from the cop0 Config2 register.
|
||||
*/
|
||||
l2_probe_cop0:
|
||||
mfc0 t0, CP0_CONFIG, 2
|
||||
|
||||
srl R_L2_LINE, t0, MIPS_CONF2_SL_SHF
|
||||
andi R_L2_LINE, R_L2_LINE, MIPS_CONF2_SL >> MIPS_CONF2_SL_SHF
|
||||
beqz R_L2_LINE, l2_probe_done
|
||||
li t1, 2
|
||||
sllv R_L2_LINE, t1, R_L2_LINE
|
||||
|
||||
srl t1, t0, MIPS_CONF2_SA_SHF
|
||||
andi t1, t1, MIPS_CONF2_SA >> MIPS_CONF2_SA_SHF
|
||||
addiu t1, t1, 1
|
||||
mul R_L2_SIZE, R_L2_LINE, t1
|
||||
|
||||
srl t1, t0, MIPS_CONF2_SS_SHF
|
||||
andi t1, t1, MIPS_CONF2_SS >> MIPS_CONF2_SS_SHF
|
||||
sllv R_L2_SIZE, R_L2_SIZE, t1
|
||||
li t1, 64
|
||||
mul R_L2_SIZE, R_L2_SIZE, t1
|
||||
|
||||
/* Attempt to bypass the L2 so that we can init the L1s early */
|
||||
or t0, t0, MIPS_CONF2_L2B
|
||||
mtc0 t0, CP0_CONFIG, 2
|
||||
ehb
|
||||
mfc0 t0, CP0_CONFIG, 2
|
||||
and R_L2_BYPASSED, t0, MIPS_CONF2_L2B
|
||||
|
||||
/* Zero the L2 tag registers */
|
||||
mtc0 zero, CP0_TAGLO, 4
|
||||
ehb
|
||||
l2_probe_done:
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
|
||||
li t3, CONFIG_SYS_DCACHE_SIZE
|
||||
li t9, CONFIG_SYS_DCACHE_LINE_SIZE
|
||||
li R_IC_SIZE, CONFIG_SYS_ICACHE_SIZE
|
||||
li R_IC_LINE, CONFIG_SYS_ICACHE_LINE_SIZE
|
||||
#else
|
||||
l1_info t3, t9, MIPS_CONF1_DA_SHF
|
||||
l1_info R_IC_SIZE, R_IC_LINE, MIPS_CONF1_IA_SHF
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_CACHE_SIZE_AUTO
|
||||
li R_DC_SIZE, CONFIG_SYS_DCACHE_SIZE
|
||||
li R_DC_LINE, CONFIG_SYS_DCACHE_LINE_SIZE
|
||||
#else
|
||||
l1_info R_DC_SIZE, R_DC_LINE, MIPS_CONF1_DA_SHF
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
|
||||
|
@ -123,9 +249,9 @@ LEAF(mips_cache_reset)
|
|||
li v0, CONFIG_SYS_DCACHE_SIZE
|
||||
#endif
|
||||
#else
|
||||
move v0, t2
|
||||
sltu t1, t2, t3
|
||||
movn v0, t3, t1
|
||||
move v0, R_IC_SIZE
|
||||
sltu t1, R_IC_SIZE, R_DC_SIZE
|
||||
movn v0, R_DC_SIZE, t1
|
||||
#endif
|
||||
/*
|
||||
* Now clear that much memory starting from zero.
|
||||
|
@ -138,13 +264,36 @@ LEAF(mips_cache_reset)
|
|||
|
||||
#endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */
|
||||
|
||||
#ifdef CONFIG_MIPS_L2_CACHE
|
||||
/*
|
||||
* If the L2 is bypassed, init the L1 first so that we can execute the
|
||||
* rest of the cache initialisation using the L1 instruction cache.
|
||||
*/
|
||||
bnez R_L2_BYPASSED, l1_init
|
||||
|
||||
l2_init:
|
||||
PTR_LI t0, INDEX_BASE
|
||||
PTR_ADDU t1, t0, R_L2_SIZE
|
||||
1: cache INDEX_STORE_TAG_SD, 0(t0)
|
||||
PTR_ADDU t0, t0, R_L2_LINE
|
||||
bne t0, t1, 1b
|
||||
|
||||
/*
|
||||
* If the L2 was bypassed then we already initialised the L1s before
|
||||
* the L2, so we are now done.
|
||||
*/
|
||||
bnez R_L2_BYPASSED, l2_unbypass
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The TagLo registers used depend upon the CPU implementation, but the
|
||||
* architecture requires that it is safe for software to write to both
|
||||
* TagLo selects 0 & 2 covering supported cases.
|
||||
*/
|
||||
l1_init:
|
||||
mtc0 zero, CP0_TAGLO
|
||||
mtc0 zero, CP0_TAGLO, 2
|
||||
ehb
|
||||
|
||||
/*
|
||||
* The caches are probably in an indeterminate state, so we force good
|
||||
|
@ -158,40 +307,122 @@ LEAF(mips_cache_reset)
|
|||
/*
|
||||
* Initialize the I-cache first,
|
||||
*/
|
||||
blez t2, 1f
|
||||
blez R_IC_SIZE, 1f
|
||||
PTR_LI t0, INDEX_BASE
|
||||
PTR_ADDU t1, t0, t2
|
||||
PTR_ADDU t1, t0, R_IC_SIZE
|
||||
/* clear tag to invalidate */
|
||||
cache_loop t0, t1, t8, INDEX_STORE_TAG_I
|
||||
cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I
|
||||
#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
|
||||
/* fill once, so data field parity is correct */
|
||||
PTR_LI t0, INDEX_BASE
|
||||
cache_loop t0, t1, t8, FILL
|
||||
cache_loop t0, t1, R_IC_LINE, FILL
|
||||
/* invalidate again - prudent but not strictly neccessary */
|
||||
PTR_LI t0, INDEX_BASE
|
||||
cache_loop t0, t1, t8, INDEX_STORE_TAG_I
|
||||
cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I
|
||||
#endif
|
||||
|
||||
/* Enable use of the I-cache by setting Config.K0 */
|
||||
sync
|
||||
mfc0 t0, CP0_CONFIG
|
||||
li t1, CONFIG_SYS_MIPS_CACHE_MODE
|
||||
#if __mips_isa_rev >= 2
|
||||
ins t0, t1, 0, 3
|
||||
#else
|
||||
ori t0, t0, CONF_CM_CMASK
|
||||
xori t0, t0, CONF_CM_CMASK
|
||||
or t0, t0, t1
|
||||
#endif
|
||||
mtc0 t0, CP0_CONFIG
|
||||
|
||||
/*
|
||||
* then initialize D-cache.
|
||||
*/
|
||||
1: blez t3, 3f
|
||||
1: blez R_DC_SIZE, 3f
|
||||
PTR_LI t0, INDEX_BASE
|
||||
PTR_ADDU t1, t0, t3
|
||||
PTR_ADDU t1, t0, R_DC_SIZE
|
||||
/* clear all tags */
|
||||
cache_loop t0, t1, t9, INDEX_STORE_TAG_D
|
||||
cache_loop t0, t1, R_DC_LINE, INDEX_STORE_TAG_D
|
||||
#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
|
||||
/* load from each line (in cached space) */
|
||||
PTR_LI t0, INDEX_BASE
|
||||
2: LONG_L zero, 0(t0)
|
||||
PTR_ADDU t0, t9
|
||||
PTR_ADDU t0, R_DC_LINE
|
||||
bne t0, t1, 2b
|
||||
/* clear all tags */
|
||||
PTR_LI t0, INDEX_BASE
|
||||
cache_loop t0, t1, t9, INDEX_STORE_TAG_D
|
||||
cache_loop t0, t1, R_DC_LINE, INDEX_STORE_TAG_D
|
||||
#endif
|
||||
3:
|
||||
|
||||
#ifdef CONFIG_MIPS_L2_CACHE
|
||||
/* If the L2 isn't bypassed then we're done */
|
||||
beqz R_L2_BYPASSED, return
|
||||
|
||||
/* The L2 is bypassed - go initialise it */
|
||||
b l2_init
|
||||
|
||||
l2_unbypass:
|
||||
# if __mips_isa_rev >= 6
|
||||
beqz R_L2_L2C, 1f
|
||||
|
||||
li t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
|
||||
lw t1, GCR_L2_CONFIG(t0)
|
||||
xor t1, t1, GCR_L2_CONFIG_BYPASS
|
||||
sw t1, GCR_L2_CONFIG(t0)
|
||||
sync
|
||||
ehb
|
||||
b 2f
|
||||
# endif
|
||||
1: mfc0 t0, CP0_CONFIG, 2
|
||||
xor t0, t0, MIPS_CONF2_L2B
|
||||
mtc0 t0, CP0_CONFIG, 2
|
||||
ehb
|
||||
|
||||
2:
|
||||
# ifdef CONFIG_MIPS_CM
|
||||
/* Config3 must exist for a CM to be present */
|
||||
mfc0 t0, CP0_CONFIG, 1
|
||||
bgez t0, 2f
|
||||
mfc0 t0, CP0_CONFIG, 2
|
||||
bgez t0, 2f
|
||||
|
||||
/* Check Config3.CMGCR to determine CM presence */
|
||||
mfc0 t0, CP0_CONFIG, 3
|
||||
and t0, t0, MIPS_CONF3_CMGCR
|
||||
beqz t0, 2f
|
||||
|
||||
/* Change Config.K0 to a coherent CCA */
|
||||
mfc0 t0, CP0_CONFIG
|
||||
li t1, CONF_CM_CACHABLE_COW
|
||||
#if __mips_isa_rev >= 2
|
||||
ins t0, t1, 0, 3
|
||||
#else
|
||||
ori t0, t0, CONF_CM_CMASK
|
||||
xori t0, t0, CONF_CM_CMASK
|
||||
or t0, t0, t1
|
||||
#endif
|
||||
mtc0 t0, CP0_CONFIG
|
||||
|
||||
/*
|
||||
* Join the coherent domain such that the caches of this core are kept
|
||||
* coherent with those of other cores.
|
||||
*/
|
||||
PTR_LI t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
|
||||
lw t1, GCR_REV(t0)
|
||||
li t2, GCR_REV_CM3
|
||||
li t3, GCR_Cx_COHERENCE_EN
|
||||
bge t1, t2, 1f
|
||||
li t3, GCR_Cx_COHERENCE_DOM_EN
|
||||
1: sw t3, GCR_Cx_COHERENCE(t0)
|
||||
ehb
|
||||
2:
|
||||
# endif
|
||||
#endif
|
||||
|
||||
3: jr ra
|
||||
return:
|
||||
/* Ensure all cache operations complete before returning */
|
||||
sync
|
||||
jr ra
|
||||
END(mips_cache_reset)
|
||||
|
||||
/*
|
||||
|
|
|
@ -46,7 +46,7 @@ static const struct ath79_soc_desc desc[] = {
|
|||
{ATH79_SOC_QCA9561, "9561", REV_ID_MAJOR_QCA9561, 0},
|
||||
};
|
||||
|
||||
int arch_cpu_init(void)
|
||||
int mach_cpu_init(void)
|
||||
{
|
||||
void __iomem *base;
|
||||
enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;
|
||||
|
|
16
board/imgtec/boston/Kconfig
Normal file
16
board/imgtec/boston/Kconfig
Normal file
|
@ -0,0 +1,16 @@
|
|||
if TARGET_BOSTON
|
||||
|
||||
config SYS_BOARD
|
||||
default "boston"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "imgtec"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "boston"
|
||||
|
||||
config SYS_TEXT_BASE
|
||||
default 0x9fc00000 if 32BIT
|
||||
default 0xffffffff9fc00000 if 64BIT
|
||||
|
||||
endif
|
6
board/imgtec/boston/MAINTAINERS
Normal file
6
board/imgtec/boston/MAINTAINERS
Normal file
|
@ -0,0 +1,6 @@
|
|||
BOSTON BOARD
|
||||
M: Paul Burton <paul.burton@imgtec.com>
|
||||
S: Maintained
|
||||
F: board/imgtec/boston/
|
||||
F: include/configs/boston.h
|
||||
F: configs/boston_defconfig
|
9
board/imgtec/boston/Makefile
Normal file
9
board/imgtec/boston/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Copyright (C) 2016 Imagination Technologies
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
|
||||
obj-y += checkboard.o
|
||||
obj-y += ddr.o
|
||||
obj-y += lowlevel_init.o
|
21
board/imgtec/boston/boston-lcd.h
Normal file
21
board/imgtec/boston/boston-lcd.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef __BOARD_BOSTON_LCD_H__
|
||||
#define __BOARD_BOSTON_LCD_H__
|
||||
|
||||
/**
|
||||
* lowlevel_display() - Display a message on Boston's LCD
|
||||
* @msg: The string to display
|
||||
*
|
||||
* Display the string @msg on the 7 character LCD display of the Boston board.
|
||||
* This is typically used for debug or to present some form of status
|
||||
* indication to the user, allowing faults to be identified when things go
|
||||
* wrong early enough that the UART isn't up.
|
||||
*/
|
||||
void lowlevel_display(const char msg[static 8]);
|
||||
|
||||
#endif /* __BOARD_BOSTON_LCD_H__ */
|
26
board/imgtec/boston/boston-regs.h
Normal file
26
board/imgtec/boston/boston-regs.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef __BOARD_BOSTON_REGS_H__
|
||||
#define __BOARD_BOSTON_REGS_H__
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#define BOSTON_PLAT_BASE CKSEG1ADDR(0x17ffd000)
|
||||
#define BOSTON_LCD_BASE CKSEG1ADDR(0x17fff000)
|
||||
|
||||
/*
|
||||
* Platform Register Definitions
|
||||
*/
|
||||
#define BOSTON_PLAT_CORE_CL (BOSTON_PLAT_BASE + 0x04)
|
||||
|
||||
#define BOSTON_PLAT_DDR3STAT (BOSTON_PLAT_BASE + 0x14)
|
||||
# define BOSTON_PLAT_DDR3STAT_CALIB (1 << 2)
|
||||
|
||||
#define BOSTON_PLAT_DDRCONF0 (BOSTON_PLAT_BASE + 0x38)
|
||||
# define BOSTON_PLAT_DDRCONF0_SIZE (0xf << 0)
|
||||
|
||||
#endif /* __BOARD_BOSTON_REGS_H__ */
|
30
board/imgtec/boston/checkboard.c
Normal file
30
board/imgtec/boston/checkboard.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/mipsregs.h>
|
||||
|
||||
#include "boston-lcd.h"
|
||||
#include "boston-regs.h"
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
u32 changelist;
|
||||
|
||||
lowlevel_display("U-boot ");
|
||||
|
||||
printf("Board: MIPS Boston\n");
|
||||
|
||||
printf("CPU: 0x%08x", read_c0_prid());
|
||||
changelist = __raw_readl((uint32_t *)BOSTON_PLAT_CORE_CL);
|
||||
if (changelist > 1)
|
||||
printf(" cl%x", changelist);
|
||||
putc('\n');
|
||||
|
||||
return 0;
|
||||
}
|
30
board/imgtec/boston/ddr.c
Normal file
30
board/imgtec/boston/ddr.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "boston-regs.h"
|
||||
|
||||
phys_size_t initdram(int board_type)
|
||||
{
|
||||
u32 ddrconf0 = __raw_readl((uint32_t *)BOSTON_PLAT_DDRCONF0);
|
||||
|
||||
return (phys_size_t)(ddrconf0 & BOSTON_PLAT_DDRCONF0_SIZE) << 30;
|
||||
}
|
||||
|
||||
ulong board_get_usable_ram_top(ulong total_size)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
if (gd->ram_top < CONFIG_SYS_SDRAM_BASE) {
|
||||
/* 2GB wrapped around to 0 */
|
||||
return CKSEG0ADDR(256 << 20);
|
||||
}
|
||||
|
||||
return min_t(unsigned long, gd->ram_top, CKSEG0ADDR(256 << 20));
|
||||
}
|
56
board/imgtec/boston/lowlevel_init.S
Normal file
56
board/imgtec/boston/lowlevel_init.S
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/regdef.h>
|
||||
|
||||
#include "boston-regs.h"
|
||||
|
||||
.data
|
||||
|
||||
msg_ddr_cal: .ascii "DDR Cal "
|
||||
msg_ddr_ok: .ascii "DDR OK "
|
||||
|
||||
.text
|
||||
|
||||
LEAF(lowlevel_init)
|
||||
move s0, ra
|
||||
|
||||
PTR_LA a0, msg_ddr_cal
|
||||
bal lowlevel_display
|
||||
|
||||
PTR_LI t0, BOSTON_PLAT_DDR3STAT
|
||||
1: lw t1, 0(t0)
|
||||
andi t1, t1, BOSTON_PLAT_DDR3STAT_CALIB
|
||||
beqz t1, 1b
|
||||
|
||||
PTR_LA a0, msg_ddr_ok
|
||||
bal lowlevel_display
|
||||
|
||||
move v0, zero
|
||||
jr s0
|
||||
END(lowlevel_init)
|
||||
|
||||
LEAF(lowlevel_display)
|
||||
.set push
|
||||
.set noat
|
||||
PTR_LI AT, BOSTON_LCD_BASE
|
||||
#ifdef CONFIG_64BIT
|
||||
ld k1, 0(a0)
|
||||
sd k1, 0(AT)
|
||||
#else
|
||||
lw k1, 0(a0)
|
||||
sw k1, 0(AT)
|
||||
lw k1, 4(a0)
|
||||
sw k1, 4(AT)
|
||||
#endif
|
||||
.set pop
|
||||
1: jr ra
|
||||
END(lowlevel_display)
|
|
@ -28,12 +28,6 @@
|
|||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
/* disable any L2 cache for now */
|
||||
sync
|
||||
mfc0 t0, CP0_CONFIG, 2
|
||||
ori t0, t0, 0x1 << 12
|
||||
mtc0 t0, CP0_CONFIG, 2
|
||||
|
||||
/* detect the core card */
|
||||
PTR_LI t0, CKSEG1ADDR(MALTA_REVISION)
|
||||
lw t0, 0(t0)
|
||||
|
|
15
board/imgtec/xilfpga/Kconfig
Normal file
15
board/imgtec/xilfpga/Kconfig
Normal file
|
@ -0,0 +1,15 @@
|
|||
if TARGET_XILFPGA
|
||||
|
||||
config SYS_BOARD
|
||||
default "xilfpga"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "imgtec"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "imgtec_xilfpga"
|
||||
|
||||
config SYS_TEXT_BASE
|
||||
default 0x80C00000
|
||||
|
||||
endif
|
6
board/imgtec/xilfpga/MAINTAINERS
Normal file
6
board/imgtec/xilfpga/MAINTAINERS
Normal file
|
@ -0,0 +1,6 @@
|
|||
XILFPGA BOARD
|
||||
M: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
|
||||
S: Maintained
|
||||
F: board/imgtec/xilfpga
|
||||
F: include/configs/xilfpga.h
|
||||
F: configs/imgtec_xilfpga_defconfig
|
7
board/imgtec/xilfpga/Makefile
Normal file
7
board/imgtec/xilfpga/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
# Copyright (C) 2016, Imagination Technologies Ltd.
|
||||
# Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
obj-y := xilfpga.o
|
55
board/imgtec/xilfpga/README
Normal file
55
board/imgtec/xilfpga/README
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Imagination Technologies Ltd.
|
||||
*
|
||||
* Zubair Lutfullah Kakakhel, Zubair.Kakakhel@imgtec.com
|
||||
*/
|
||||
|
||||
MIPSfpga
|
||||
=======================================
|
||||
|
||||
MIPSfpga is an FPGA based development platform by Imagination Technologies
|
||||
As we are dealing with a MIPS core instantiated on an FPGA, specifications
|
||||
are fluid and can be varied in RTL.
|
||||
|
||||
The example project provided by IMGTEC runs on the Nexys4DDR board by
|
||||
Digilent powered by the ARTIX-7 FPGA by Xilinx. Relevant details about
|
||||
the example project and the Nexys4DDR board:
|
||||
|
||||
- microAptiv UP core m14Kc
|
||||
- 50MHz clock speed
|
||||
- 128Mbyte DDR RAM at 0x0000_0000
|
||||
- 8Kbyte RAM at 0x1000_0000
|
||||
- axi_intc at 0x1020_0000
|
||||
- axi_uart16550 at 0x1040_0000
|
||||
- axi_gpio at 0x1060_0000
|
||||
- axi_i2c at 0x10A0_0000
|
||||
- custom_gpio at 0x10C0_0000
|
||||
- axi_ethernetlite at 0x10E0_0000
|
||||
- 8Kbyte BootRAM at 0x1FC0_0000
|
||||
- 16Mbyte QPI at 0x1D00_0000
|
||||
|
||||
Boot protocol:
|
||||
--------------
|
||||
|
||||
The BootRAM is a writeable "RAM" in FPGA at 0x1FC0_0000.
|
||||
This is for easy reprogrammibility via JTAG.
|
||||
|
||||
DDR initialization is already handled by a HW IP block.
|
||||
|
||||
When the example project bitstream is loaded, the cpu_reset button
|
||||
needs to be pressed.
|
||||
|
||||
The bootram initializes the cache and axi_uart
|
||||
Then checks if there is anything non 0xffff_ffff at location 0x1D40_0000
|
||||
|
||||
If there is, then that is considered as u-boot. u-boot is copied from
|
||||
0x1D40_0000 to memory and the bootram jumps into u-boot code.
|
||||
|
||||
At this point, the board is ready to load the Linux kernel + buildroot initramfs
|
||||
|
||||
This can be done in multiple ways:
|
||||
|
||||
1- JTAG load the binary and jump into it.
|
||||
2- Load kernel stored in the QSPI flash at 0x1D80_0000
|
||||
3- Load uImage via tftp. Ethernet works in u-boot.
|
||||
e.g. env set server ip 192.168.154.45; dhcp uImage; bootm
|
20
board/imgtec/xilfpga/xilfpga.c
Normal file
20
board/imgtec/xilfpga/xilfpga.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Imagination Technologies MIPSfpga platform code
|
||||
*
|
||||
* Copyright (C) 2016, Imagination Technologies Ltd.
|
||||
*
|
||||
* Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/* initialize the DDR Controller and PHY */
|
||||
phys_size_t initdram(int board_type)
|
||||
{
|
||||
/* MIG IP block is smart and doesn't need SW
|
||||
* to do any init */
|
||||
return CONFIG_SYS_SDRAM_SIZE; /* in bytes */
|
||||
}
|
|
@ -290,6 +290,11 @@ __weak int arch_cpu_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
__weak int mach_cpu_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SANDBOX
|
||||
static int setup_ram_buf(void)
|
||||
{
|
||||
|
@ -860,6 +865,7 @@ static init_fnc_t init_sequence_f[] = {
|
|||
x86_fsp_init,
|
||||
#endif
|
||||
arch_cpu_init, /* basic arch cpu dependent setup */
|
||||
mach_cpu_init, /* SoC/machine dependent CPU setup */
|
||||
initf_dm,
|
||||
arch_cpu_init_dm,
|
||||
mark_bootstage, /* need timer, go after init dm */
|
||||
|
|
41
configs/boston32r2_defconfig
Normal file
41
configs/boston32r2_defconfig
Normal file
|
@ -0,0 +1,41 @@
|
|||
CONFIG_MIPS=y
|
||||
CONFIG_TARGET_BOSTON=y
|
||||
CONFIG_SYS_TEXT_BASE=0x9fc00000
|
||||
# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
|
||||
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
|
||||
CONFIG_MIPS_BOOT_FDT=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="img,boston"
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_FIT_BEST_MATCH=y
|
||||
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
||||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_SYS_PROMPT="boston # "
|
||||
# CONFIG_CMD_ELF is not set
|
||||
# CONFIG_CMD_IMLS is not set
|
||||
CONFIG_CMD_GREPENV=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
# CONFIG_CMD_LOADB is not set
|
||||
# CONFIG_CMD_LOADS is not set
|
||||
# CONFIG_CMD_FPGA is not set
|
||||
CONFIG_CMD_DHCP=y
|
||||
CONFIG_CMD_PING=y
|
||||
CONFIG_CMD_SNTP=y
|
||||
CONFIG_CMD_DNS=y
|
||||
CONFIG_CMD_LINK_LOCAL=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_EXT4=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_FAT=y
|
||||
CONFIG_CMD_FS_GENERIC=y
|
||||
CONFIG_OF_EMBED=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_CFI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_PCH_GBE=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_PCI_XILINX=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_LZ4=y
|
42
configs/boston32r2el_defconfig
Normal file
42
configs/boston32r2el_defconfig
Normal file
|
@ -0,0 +1,42 @@
|
|||
CONFIG_MIPS=y
|
||||
CONFIG_TARGET_BOSTON=y
|
||||
CONFIG_SYS_TEXT_BASE=0x9fc00000
|
||||
CONFIG_SYS_LITTLE_ENDIAN=y
|
||||
# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
|
||||
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
|
||||
CONFIG_MIPS_BOOT_FDT=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="img,boston"
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_FIT_BEST_MATCH=y
|
||||
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
||||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_SYS_PROMPT="boston # "
|
||||
# CONFIG_CMD_ELF is not set
|
||||
# CONFIG_CMD_IMLS is not set
|
||||
CONFIG_CMD_GREPENV=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
# CONFIG_CMD_LOADB is not set
|
||||
# CONFIG_CMD_LOADS is not set
|
||||
# CONFIG_CMD_FPGA is not set
|
||||
CONFIG_CMD_DHCP=y
|
||||
CONFIG_CMD_PING=y
|
||||
CONFIG_CMD_SNTP=y
|
||||
CONFIG_CMD_DNS=y
|
||||
CONFIG_CMD_LINK_LOCAL=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_EXT4=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_FAT=y
|
||||
CONFIG_CMD_FS_GENERIC=y
|
||||
CONFIG_OF_EMBED=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_CFI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_PCH_GBE=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_PCI_XILINX=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_LZ4=y
|
41
configs/boston64r2_defconfig
Normal file
41
configs/boston64r2_defconfig
Normal file
|
@ -0,0 +1,41 @@
|
|||
CONFIG_MIPS=y
|
||||
CONFIG_TARGET_BOSTON=y
|
||||
CONFIG_CPU_MIPS64_R2=y
|
||||
# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
|
||||
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
|
||||
CONFIG_MIPS_BOOT_FDT=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="img,boston"
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_FIT_BEST_MATCH=y
|
||||
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
||||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_SYS_PROMPT="boston # "
|
||||
# CONFIG_CMD_ELF is not set
|
||||
# CONFIG_CMD_IMLS is not set
|
||||
CONFIG_CMD_GREPENV=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
# CONFIG_CMD_LOADB is not set
|
||||
# CONFIG_CMD_LOADS is not set
|
||||
# CONFIG_CMD_FPGA is not set
|
||||
CONFIG_CMD_DHCP=y
|
||||
CONFIG_CMD_PING=y
|
||||
CONFIG_CMD_SNTP=y
|
||||
CONFIG_CMD_DNS=y
|
||||
CONFIG_CMD_LINK_LOCAL=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_EXT4=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_FAT=y
|
||||
CONFIG_CMD_FS_GENERIC=y
|
||||
CONFIG_OF_EMBED=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_CFI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_PCH_GBE=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_PCI_XILINX=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_LZ4=y
|
42
configs/boston64r2el_defconfig
Normal file
42
configs/boston64r2el_defconfig
Normal file
|
@ -0,0 +1,42 @@
|
|||
CONFIG_MIPS=y
|
||||
CONFIG_TARGET_BOSTON=y
|
||||
CONFIG_SYS_LITTLE_ENDIAN=y
|
||||
CONFIG_CPU_MIPS64_R2=y
|
||||
# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
|
||||
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
|
||||
CONFIG_MIPS_BOOT_FDT=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="img,boston"
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_FIT_BEST_MATCH=y
|
||||
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
||||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_SYS_PROMPT="boston # "
|
||||
# CONFIG_CMD_ELF is not set
|
||||
# CONFIG_CMD_IMLS is not set
|
||||
CONFIG_CMD_GREPENV=y
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
# CONFIG_CMD_LOADB is not set
|
||||
# CONFIG_CMD_LOADS is not set
|
||||
# CONFIG_CMD_FPGA is not set
|
||||
CONFIG_CMD_DHCP=y
|
||||
CONFIG_CMD_PING=y
|
||||
CONFIG_CMD_SNTP=y
|
||||
CONFIG_CMD_DNS=y
|
||||
CONFIG_CMD_LINK_LOCAL=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_EXT4=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_FAT=y
|
||||
CONFIG_CMD_FS_GENERIC=y
|
||||
CONFIG_OF_EMBED=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_CFI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_PCH_GBE=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_PCI_XILINX=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_LZ4=y
|
25
configs/imgtec_xilfpga_defconfig
Normal file
25
configs/imgtec_xilfpga_defconfig
Normal file
|
@ -0,0 +1,25 @@
|
|||
CONFIG_MIPS=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x600
|
||||
CONFIG_TARGET_XILFPGA=y
|
||||
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
|
||||
CONFIG_MIPS_BOOT_FDT=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="nexys4ddr"
|
||||
CONFIG_BOOTDELAY=5
|
||||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_SYS_PROMPT="MIPSfpga # "
|
||||
# CONFIG_CMD_IMLS is not set
|
||||
# CONFIG_CMD_SAVEENV is not set
|
||||
CONFIG_CMD_MEMINFO=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
# CONFIG_CMD_FPGA is not set
|
||||
CONFIG_CMD_DHCP=y
|
||||
CONFIG_CMD_MII=y
|
||||
CONFIG_CMD_PING=y
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_OF_EMBED=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_XILINX_EMACLITE=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_CMD_DHRYSTONE=y
|
58
doc/README.boston
Normal file
58
doc/README.boston
Normal file
|
@ -0,0 +1,58 @@
|
|||
MIPS Boston Development Board
|
||||
|
||||
---------
|
||||
About
|
||||
---------
|
||||
|
||||
The MIPS Boston development board is built around an FPGA & 3 PCIe controllers,
|
||||
one of which is connected to an Intel EG20T Platform Controller Hub which
|
||||
provides most connectivity to the board. It is used during the development &
|
||||
testing of both new CPUs and the software support for them. It is essentially
|
||||
the successor of the older MIPS Malta board.
|
||||
|
||||
--------
|
||||
QEMU
|
||||
--------
|
||||
|
||||
U-Boot can be run on a currently out-of-tree branch of QEMU with support for
|
||||
the Boston board added. This QEMU code can currently be found in the "boston"
|
||||
branch of git://git.linux-mips.org/pub/scm/paul/qemu.git and used like so:
|
||||
|
||||
$ git clone git://git.linux-mips.org/pub/scm/paul/qemu.git -b boston
|
||||
$ cd qemu
|
||||
$ ./configure --target-list=mips64el-softmmu
|
||||
$ make
|
||||
$ ./mips64el-softmmu/qemu-system-mips64el -M boston -m 2G \
|
||||
-bios u-boot.bin -serial stdio
|
||||
|
||||
Please note that QEMU will default to emulating the I6400 CPU which implements
|
||||
the MIPS64r6 ISA, and at the time of writing doesn't implement any earlier CPUs
|
||||
with support for the CPS features the Boston board relies upon. You will
|
||||
therefore need to configure U-Boot to build for MIPSr6 in order to obtain a
|
||||
binary that will work in QEMU.
|
||||
|
||||
-------------
|
||||
Toolchain
|
||||
-------------
|
||||
|
||||
If building for MIPSr6 then you will need a toolchain including GCC 5.x or
|
||||
newer, or the Codescape toolchain available for download from Imagination
|
||||
Technologies:
|
||||
|
||||
http://codescape-mips-sdk.imgtec.com/components/toolchain/2015.06-05/
|
||||
|
||||
The "IMG GNU Linux Toolchain" is capable of building for all current MIPS ISAs,
|
||||
architecture revisions & both endiannesses.
|
||||
|
||||
--------
|
||||
TODO
|
||||
--------
|
||||
|
||||
- AHCI support
|
||||
- CPU driver
|
||||
- Exception handling (+UHI?)
|
||||
- Flash support
|
||||
- IOCU support
|
||||
- L2 cache support
|
||||
- More general LCD display driver
|
||||
- Multi-arch-variant multi-endian fat binary
|
|
@ -20,6 +20,14 @@ config SPL_CLK
|
|||
setting up clocks within SPL, and allows the same drivers to be
|
||||
used as U-Boot proper.
|
||||
|
||||
config CLK_BOSTON
|
||||
def_bool y if TARGET_BOSTON
|
||||
depends on CLK
|
||||
select REGMAP
|
||||
select SYSCON
|
||||
help
|
||||
Enable this to support the clocks
|
||||
|
||||
source "drivers/clk/tegra/Kconfig"
|
||||
source "drivers/clk/uniphier/Kconfig"
|
||||
source "drivers/clk/exynos/Kconfig"
|
||||
|
|
|
@ -15,3 +15,4 @@ obj-y += tegra/
|
|||
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_CLK_EXYNOS) += exynos/
|
||||
obj-$(CONFIG_CLK_AT91) += at91/
|
||||
obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
|
||||
|
|
97
drivers/clk/clk_boston.c
Normal file
97
drivers/clk/clk_boston.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <dt-bindings/clock/boston-clock.h>
|
||||
#include <regmap.h>
|
||||
#include <syscon.h>
|
||||
|
||||
struct clk_boston {
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
#define BOSTON_PLAT_MMCMDIV 0x30
|
||||
# define BOSTON_PLAT_MMCMDIV_CLK0DIV (0xff << 0)
|
||||
# define BOSTON_PLAT_MMCMDIV_INPUT (0xff << 8)
|
||||
# define BOSTON_PLAT_MMCMDIV_MUL (0xff << 16)
|
||||
# define BOSTON_PLAT_MMCMDIV_CLK1DIV (0xff << 24)
|
||||
|
||||
static uint32_t ext_field(uint32_t val, uint32_t mask)
|
||||
{
|
||||
return (val & mask) >> (ffs(mask) - 1);
|
||||
}
|
||||
|
||||
static ulong clk_boston_get_rate(struct clk *clk)
|
||||
{
|
||||
struct clk_boston *state = dev_get_platdata(clk->dev);
|
||||
uint32_t in_rate, mul, div;
|
||||
uint mmcmdiv;
|
||||
int err;
|
||||
|
||||
err = regmap_read(state->regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv);
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
in_rate = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_INPUT);
|
||||
mul = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_MUL);
|
||||
|
||||
switch (clk->id) {
|
||||
case BOSTON_CLK_SYS:
|
||||
div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK0DIV);
|
||||
break;
|
||||
case BOSTON_CLK_CPU:
|
||||
div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK1DIV);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (in_rate * mul * 1000000) / div;
|
||||
}
|
||||
|
||||
const struct clk_ops clk_boston_ops = {
|
||||
.get_rate = clk_boston_get_rate,
|
||||
};
|
||||
|
||||
static int clk_boston_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct clk_boston *state = dev_get_platdata(dev);
|
||||
struct udevice *syscon;
|
||||
int err;
|
||||
|
||||
err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
|
||||
"regmap", &syscon);
|
||||
if (err) {
|
||||
error("unable to find syscon device\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
state->regmap = syscon_get_regmap(syscon);
|
||||
if (!state->regmap) {
|
||||
error("unable to find regmap\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id clk_boston_match[] = {
|
||||
{
|
||||
.compatible = "img,boston-clock",
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(clk_boston) = {
|
||||
.name = "boston_clock",
|
||||
.id = UCLASS_CLK,
|
||||
.of_match = clk_boston_match,
|
||||
.ofdata_to_platdata = clk_boston_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct clk_boston),
|
||||
.ops = &clk_boston_ops,
|
||||
};
|
|
@ -101,36 +101,24 @@ int device_bind_driver_to_node(struct udevice *parent, const char *drv_name,
|
|||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
|
||||
/**
|
||||
* driver_check_compatible() - Check if a driver is compatible with this node
|
||||
* driver_check_compatible() - Check if a driver matches a compatible string
|
||||
*
|
||||
* @param blob: Device tree pointer
|
||||
* @param offset: Offset of node in device tree
|
||||
* @param of_match: List of compatible strings to match
|
||||
* @param of_idp: Returns the match that was found
|
||||
* @return 0 if there is a match, -ENOENT if no match, -ENODEV if the node
|
||||
* does not have a compatible string, other error <0 if there is a device
|
||||
* tree error
|
||||
* @param compat: The compatible string to search for
|
||||
* @return 0 if there is a match, -ENOENT if no match
|
||||
*/
|
||||
static int driver_check_compatible(const void *blob, int offset,
|
||||
const struct udevice_id *of_match,
|
||||
const struct udevice_id **of_idp)
|
||||
static int driver_check_compatible(const struct udevice_id *of_match,
|
||||
const struct udevice_id **of_idp,
|
||||
const char *compat)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*of_idp = NULL;
|
||||
if (!of_match)
|
||||
return -ENOENT;
|
||||
|
||||
while (of_match->compatible) {
|
||||
ret = fdt_node_check_compatible(blob, offset,
|
||||
of_match->compatible);
|
||||
if (!ret) {
|
||||
if (!strcmp(of_match->compatible, compat)) {
|
||||
*of_idp = of_match;
|
||||
return 0;
|
||||
} else if (ret == -FDT_ERR_NOTFOUND) {
|
||||
return -ENODEV;
|
||||
} else if (ret < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
of_match++;
|
||||
}
|
||||
|
@ -147,28 +135,46 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
|
|||
struct driver *entry;
|
||||
struct udevice *dev;
|
||||
bool found = false;
|
||||
const char *name;
|
||||
const char *name, *compat_list, *compat;
|
||||
int compat_length, i;
|
||||
int result = 0;
|
||||
int ret = 0;
|
||||
|
||||
dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL));
|
||||
name = fdt_get_name(blob, offset, NULL);
|
||||
dm_dbg("bind node %s\n", name);
|
||||
if (devp)
|
||||
*devp = NULL;
|
||||
for (entry = driver; entry != driver + n_ents; entry++) {
|
||||
ret = driver_check_compatible(blob, offset, entry->of_match,
|
||||
&id);
|
||||
name = fdt_get_name(blob, offset, NULL);
|
||||
if (ret == -ENOENT) {
|
||||
continue;
|
||||
} else if (ret == -ENODEV) {
|
||||
|
||||
compat_list = fdt_getprop(blob, offset, "compatible", &compat_length);
|
||||
if (!compat_list) {
|
||||
if (compat_length == -FDT_ERR_NOTFOUND) {
|
||||
dm_dbg("Device '%s' has no compatible string\n", name);
|
||||
break;
|
||||
} else if (ret) {
|
||||
dm_warn("Device tree error at offset %d\n", offset);
|
||||
result = ret;
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_warn("Device tree error at offset %d\n", offset);
|
||||
return compat_length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk through the compatible string list, attempting to match each
|
||||
* compatible string in order such that we match in order of priority
|
||||
* from the first string to the last.
|
||||
*/
|
||||
for (i = 0; i < compat_length; i += strlen(compat) + 1) {
|
||||
compat = compat_list + i;
|
||||
dm_dbg(" - attempt to match compatible string '%s'\n",
|
||||
compat);
|
||||
|
||||
for (entry = driver; entry != driver + n_ents; entry++) {
|
||||
ret = driver_check_compatible(entry->of_match, &id,
|
||||
compat);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
if (entry == driver + n_ents)
|
||||
continue;
|
||||
|
||||
dm_dbg(" - found match at '%s'\n", entry->name);
|
||||
ret = device_bind_with_driver_data(parent, entry, name,
|
||||
id->data, offset, &dev);
|
||||
|
@ -188,10 +194,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!found && !result && ret != -ENODEV) {
|
||||
dm_dbg("No match for node '%s'\n",
|
||||
fdt_get_name(blob, offset, NULL));
|
||||
}
|
||||
if (!found && !result && ret != -ENODEV)
|
||||
dm_dbg("No match for node '%s'\n", name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <mapmem.h>
|
||||
#include <regmap.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static struct regmap *regmap_alloc_count(int count)
|
||||
|
@ -117,3 +119,21 @@ int regmap_uninit(struct regmap *map)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regmap_read(struct regmap *map, uint offset, uint *valp)
|
||||
{
|
||||
uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
|
||||
|
||||
*valp = le32_to_cpu(readl(ptr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regmap_write(struct regmap *map, uint offset, uint val)
|
||||
{
|
||||
uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
|
||||
|
||||
writel(cpu_to_le32(val), ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -95,3 +95,14 @@ UCLASS_DRIVER(syscon) = {
|
|||
.per_device_auto_alloc_size = sizeof(struct syscon_uc_info),
|
||||
.pre_probe = syscon_pre_probe,
|
||||
};
|
||||
|
||||
static const struct udevice_id generic_syscon_ids[] = {
|
||||
{ .compatible = "syscon" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(generic_syscon) = {
|
||||
.name = "syscon",
|
||||
.id = UCLASS_SYSCON,
|
||||
.of_match = generic_syscon_ids,
|
||||
};
|
||||
|
|
|
@ -175,7 +175,7 @@ config XILINX_AXIEMAC
|
|||
This MAC is present in Xilinx Microblaze, Zynq and ZynqMP SoCs.
|
||||
|
||||
config XILINX_EMACLITE
|
||||
depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
|
||||
depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP || MIPS)
|
||||
select PHYLIB
|
||||
select MII
|
||||
bool "Xilinx Ethernetlite"
|
||||
|
|
|
@ -118,14 +118,14 @@ static void pch_gbe_rx_descs_init(struct udevice *dev)
|
|||
memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM);
|
||||
for (i = 0; i < PCH_GBE_DESC_NUM; i++)
|
||||
rx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev,
|
||||
(u32)(priv->rx_buff[i]));
|
||||
(ulong)(priv->rx_buff[i]));
|
||||
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (u32)rx_desc),
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (ulong)rx_desc),
|
||||
&mac_regs->rx_dsc_base);
|
||||
writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1),
|
||||
&mac_regs->rx_dsc_size);
|
||||
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_desc + 1)),
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (ulong)(rx_desc + 1)),
|
||||
&mac_regs->rx_dsc_sw_p);
|
||||
}
|
||||
|
||||
|
@ -137,11 +137,11 @@ static void pch_gbe_tx_descs_init(struct udevice *dev)
|
|||
|
||||
memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM);
|
||||
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (u32)tx_desc),
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (ulong)tx_desc),
|
||||
&mac_regs->tx_dsc_base);
|
||||
writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1),
|
||||
&mac_regs->tx_dsc_size);
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_desc + 1)),
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (ulong)(tx_desc + 1)),
|
||||
&mac_regs->tx_dsc_sw_p);
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length)
|
|||
if (length < 64)
|
||||
frame_ctrl |= PCH_GBE_TXD_CTRL_APAD;
|
||||
|
||||
tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (u32)packet);
|
||||
tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (ulong)packet);
|
||||
tx_desc->length = length;
|
||||
tx_desc->tx_words_eob = length + 3;
|
||||
tx_desc->tx_frame_ctrl = frame_ctrl;
|
||||
|
@ -262,7 +262,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length)
|
|||
if (++priv->tx_idx >= PCH_GBE_DESC_NUM)
|
||||
priv->tx_idx = 0;
|
||||
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_head + priv->tx_idx)),
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (ulong)(tx_head + priv->tx_idx)),
|
||||
&mac_regs->tx_dsc_sw_p);
|
||||
|
||||
start = get_timer(0);
|
||||
|
@ -283,7 +283,7 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp)
|
|||
struct pch_gbe_priv *priv = dev_get_priv(dev);
|
||||
struct pch_gbe_regs *mac_regs = priv->mac_regs;
|
||||
struct pch_gbe_rx_desc *rx_desc;
|
||||
u32 hw_desc, buffer_addr, length;
|
||||
ulong hw_desc, buffer_addr, length;
|
||||
|
||||
rx_desc = &priv->rx_desc[priv->rx_idx];
|
||||
|
||||
|
@ -291,7 +291,7 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp)
|
|||
hw_desc = readl(&mac_regs->rx_dsc_hw_p_hld);
|
||||
|
||||
/* Just return if not receiving any packet */
|
||||
if ((u32)rx_desc == hw_desc)
|
||||
if ((ulong)rx_desc == hw_desc)
|
||||
return -EAGAIN;
|
||||
|
||||
buffer_addr = dm_pci_mem_to_phys(priv->dev, rx_desc->buffer_addr);
|
||||
|
@ -315,7 +315,7 @@ static int pch_gbe_free_pkt(struct udevice *dev, uchar *packet, int length)
|
|||
if (++rx_swp >= PCH_GBE_DESC_NUM)
|
||||
rx_swp = 0;
|
||||
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_head + rx_swp)),
|
||||
writel(dm_pci_phys_to_mem(priv->dev, (ulong)(rx_head + rx_swp)),
|
||||
&mac_regs->rx_dsc_sw_p);
|
||||
|
||||
return 0;
|
||||
|
@ -421,7 +421,7 @@ int pch_gbe_probe(struct udevice *dev)
|
|||
{
|
||||
struct pch_gbe_priv *priv;
|
||||
struct eth_pdata *plat = dev_get_platdata(dev);
|
||||
u32 iobase;
|
||||
void *iobase;
|
||||
|
||||
/*
|
||||
* The priv structure contains the descriptors and frame buffers which
|
||||
|
@ -432,11 +432,9 @@ int pch_gbe_probe(struct udevice *dev)
|
|||
|
||||
priv->dev = dev;
|
||||
|
||||
dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase);
|
||||
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
|
||||
iobase = dm_pci_mem_to_phys(dev, iobase);
|
||||
iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM);
|
||||
|
||||
plat->iobase = iobase;
|
||||
plat->iobase = (ulong)iobase;
|
||||
priv->mac_regs = (struct pch_gbe_regs *)iobase;
|
||||
|
||||
/* Read MAC address from SROM and initialize dev->enetaddr with it */
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <fdtdec.h>
|
||||
#include <asm-generic/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -154,7 +155,7 @@ static int wait_for_bit(const char *func, u32 *reg, const u32 mask,
|
|||
unsigned long start = get_timer(0);
|
||||
|
||||
while (1) {
|
||||
val = readl(reg);
|
||||
val = __raw_readl(reg);
|
||||
|
||||
if (!set)
|
||||
val = ~val;
|
||||
|
@ -193,16 +194,17 @@ static u32 phyread(struct xemaclite *emaclite, u32 phyaddress, u32 registernum,
|
|||
if (mdio_wait(regs))
|
||||
return 1;
|
||||
|
||||
u32 ctrl_reg = in_be32(®s->mdioctrl);
|
||||
out_be32(®s->mdioaddr, XEL_MDIOADDR_OP_MASK |
|
||||
((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT) | registernum));
|
||||
out_be32(®s->mdioctrl, ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
|
||||
u32 ctrl_reg = __raw_readl(®s->mdioctrl);
|
||||
__raw_writel(XEL_MDIOADDR_OP_MASK
|
||||
| ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
|
||||
| registernum), ®s->mdioaddr);
|
||||
__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, ®s->mdioctrl);
|
||||
|
||||
if (mdio_wait(regs))
|
||||
return 1;
|
||||
|
||||
/* Read data */
|
||||
*data = in_be32(®s->mdiord);
|
||||
*data = __raw_readl(®s->mdiord);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -220,11 +222,12 @@ static u32 phywrite(struct xemaclite *emaclite, u32 phyaddress, u32 registernum,
|
|||
* Data register. Finally, set the Status bit in the MDIO Control
|
||||
* register to start a MDIO write transaction.
|
||||
*/
|
||||
u32 ctrl_reg = in_be32(®s->mdioctrl);
|
||||
out_be32(®s->mdioaddr, ~XEL_MDIOADDR_OP_MASK &
|
||||
((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT) | registernum));
|
||||
out_be32(®s->mdiowr, data);
|
||||
out_be32(®s->mdioctrl, ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
|
||||
u32 ctrl_reg = __raw_readl(®s->mdioctrl);
|
||||
__raw_writel(~XEL_MDIOADDR_OP_MASK
|
||||
& ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
|
||||
| registernum), ®s->mdioaddr);
|
||||
__raw_writel(data, ®s->mdiowr);
|
||||
__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, ®s->mdioctrl);
|
||||
|
||||
if (mdio_wait(regs))
|
||||
return 1;
|
||||
|
@ -327,27 +330,27 @@ static int emaclite_start(struct udevice *dev)
|
|||
* TX - TX_PING & TX_PONG initialization
|
||||
*/
|
||||
/* Restart PING TX */
|
||||
out_be32(®s->tx_ping_tsr, 0);
|
||||
__raw_writel(0, ®s->tx_ping_tsr);
|
||||
/* Copy MAC address */
|
||||
xemaclite_alignedwrite(pdata->enetaddr, ®s->tx_ping,
|
||||
ENET_ADDR_LENGTH);
|
||||
/* Set the length */
|
||||
out_be32(®s->tx_ping_tplr, ENET_ADDR_LENGTH);
|
||||
__raw_writel(ENET_ADDR_LENGTH, ®s->tx_ping_tplr);
|
||||
/* Update the MAC address in the EMAC Lite */
|
||||
out_be32(®s->tx_ping_tsr, XEL_TSR_PROG_MAC_ADDR);
|
||||
__raw_writel(XEL_TSR_PROG_MAC_ADDR, ®s->tx_ping_tsr);
|
||||
/* Wait for EMAC Lite to finish with the MAC address update */
|
||||
while ((in_be32 (®s->tx_ping_tsr) &
|
||||
while ((__raw_readl(®s->tx_ping_tsr) &
|
||||
XEL_TSR_PROG_MAC_ADDR) != 0)
|
||||
;
|
||||
|
||||
if (emaclite->txpp) {
|
||||
/* The same operation with PONG TX */
|
||||
out_be32(®s->tx_pong_tsr, 0);
|
||||
__raw_writel(0, ®s->tx_pong_tsr);
|
||||
xemaclite_alignedwrite(pdata->enetaddr, ®s->tx_pong,
|
||||
ENET_ADDR_LENGTH);
|
||||
out_be32(®s->tx_pong_tplr, ENET_ADDR_LENGTH);
|
||||
out_be32(®s->tx_pong_tsr, XEL_TSR_PROG_MAC_ADDR);
|
||||
while ((in_be32(®s->tx_pong_tsr) &
|
||||
__raw_writel(ENET_ADDR_LENGTH, ®s->tx_pong_tplr);
|
||||
__raw_writel(XEL_TSR_PROG_MAC_ADDR, ®s->tx_pong_tsr);
|
||||
while ((__raw_readl(®s->tx_pong_tsr) &
|
||||
XEL_TSR_PROG_MAC_ADDR) != 0)
|
||||
;
|
||||
}
|
||||
|
@ -356,13 +359,13 @@ static int emaclite_start(struct udevice *dev)
|
|||
* RX - RX_PING & RX_PONG initialization
|
||||
*/
|
||||
/* Write out the value to flush the RX buffer */
|
||||
out_be32(®s->rx_ping_rsr, XEL_RSR_RECV_IE_MASK);
|
||||
__raw_writel(XEL_RSR_RECV_IE_MASK, ®s->rx_ping_rsr);
|
||||
|
||||
if (emaclite->rxpp)
|
||||
out_be32(®s->rx_pong_rsr, XEL_RSR_RECV_IE_MASK);
|
||||
__raw_writel(XEL_RSR_RECV_IE_MASK, ®s->rx_pong_rsr);
|
||||
|
||||
out_be32(®s->mdioctrl, XEL_MDIOCTRL_MDIOEN_MASK);
|
||||
if (in_be32(®s->mdioctrl) & XEL_MDIOCTRL_MDIOEN_MASK)
|
||||
__raw_writel(XEL_MDIOCTRL_MDIOEN_MASK, ®s->mdioctrl);
|
||||
if (__raw_readl(®s->mdioctrl) & XEL_MDIOCTRL_MDIOEN_MASK)
|
||||
if (!setup_phy(dev))
|
||||
return -1;
|
||||
|
||||
|
@ -379,9 +382,9 @@ static int xemaclite_txbufferavailable(struct xemaclite *emaclite)
|
|||
* Read the other buffer register
|
||||
* and determine if the other buffer is available
|
||||
*/
|
||||
tmp = ~in_be32(®s->tx_ping_tsr);
|
||||
tmp = ~__raw_readl(®s->tx_ping_tsr);
|
||||
if (emaclite->txpp)
|
||||
tmp |= ~in_be32(®s->tx_pong_tsr);
|
||||
tmp |= ~__raw_readl(®s->tx_pong_tsr);
|
||||
|
||||
return !(tmp & XEL_TSR_XMIT_BUSY_MASK);
|
||||
}
|
||||
|
@ -405,40 +408,42 @@ static int emaclite_send(struct udevice *dev, void *ptr, int len)
|
|||
if (!maxtry) {
|
||||
printf("Error: Timeout waiting for ethernet TX buffer\n");
|
||||
/* Restart PING TX */
|
||||
out_be32(®s->tx_ping_tsr, 0);
|
||||
__raw_writel(0, ®s->tx_ping_tsr);
|
||||
if (emaclite->txpp) {
|
||||
out_be32(®s->tx_pong_tsr, 0);
|
||||
__raw_writel(0, ®s->tx_pong_tsr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Determine if the expected buffer address is empty */
|
||||
reg = in_be32(®s->tx_ping_tsr);
|
||||
reg = __raw_readl(®s->tx_ping_tsr);
|
||||
if ((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) {
|
||||
debug("Send packet from tx_ping buffer\n");
|
||||
/* Write the frame to the buffer */
|
||||
xemaclite_alignedwrite(ptr, ®s->tx_ping, len);
|
||||
out_be32(®s->tx_ping_tplr, len &
|
||||
(XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO));
|
||||
reg = in_be32(®s->tx_ping_tsr);
|
||||
__raw_writel(len
|
||||
& (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO),
|
||||
®s->tx_ping_tplr);
|
||||
reg = __raw_readl(®s->tx_ping_tsr);
|
||||
reg |= XEL_TSR_XMIT_BUSY_MASK;
|
||||
out_be32(®s->tx_ping_tsr, reg);
|
||||
__raw_writel(reg, ®s->tx_ping_tsr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (emaclite->txpp) {
|
||||
/* Determine if the expected buffer address is empty */
|
||||
reg = in_be32(®s->tx_pong_tsr);
|
||||
reg = __raw_readl(®s->tx_pong_tsr);
|
||||
if ((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) {
|
||||
debug("Send packet from tx_pong buffer\n");
|
||||
/* Write the frame to the buffer */
|
||||
xemaclite_alignedwrite(ptr, ®s->tx_pong, len);
|
||||
out_be32(®s->tx_pong_tplr, len &
|
||||
__raw_writel(len &
|
||||
(XEL_TPLR_LENGTH_MASK_HI |
|
||||
XEL_TPLR_LENGTH_MASK_LO));
|
||||
reg = in_be32(®s->tx_pong_tsr);
|
||||
XEL_TPLR_LENGTH_MASK_LO),
|
||||
®s->tx_pong_tplr);
|
||||
reg = __raw_readl(®s->tx_pong_tsr);
|
||||
reg |= XEL_TSR_XMIT_BUSY_MASK;
|
||||
out_be32(®s->tx_pong_tsr, reg);
|
||||
__raw_writel(reg, ®s->tx_pong_tsr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -458,7 +463,7 @@ static int emaclite_recv(struct udevice *dev, int flags, uchar **packetp)
|
|||
|
||||
try_again:
|
||||
if (!emaclite->use_rx_pong_buffer_next) {
|
||||
reg = in_be32(®s->rx_ping_rsr);
|
||||
reg = __raw_readl(®s->rx_ping_rsr);
|
||||
debug("Testing data at rx_ping\n");
|
||||
if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
|
||||
debug("Data found in rx_ping buffer\n");
|
||||
|
@ -478,7 +483,7 @@ try_again:
|
|||
goto try_again;
|
||||
}
|
||||
} else {
|
||||
reg = in_be32(®s->rx_pong_rsr);
|
||||
reg = __raw_readl(®s->rx_pong_rsr);
|
||||
debug("Testing data at rx_pong\n");
|
||||
if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
|
||||
debug("Data found in rx_pong buffer\n");
|
||||
|
@ -525,9 +530,9 @@ try_again:
|
|||
length - first_read);
|
||||
|
||||
/* Acknowledge the frame */
|
||||
reg = in_be32(ack);
|
||||
reg = __raw_readl(ack);
|
||||
reg &= ~XEL_RSR_RECV_DONE_MASK;
|
||||
out_be32(ack, reg);
|
||||
__raw_writel(reg, ack);
|
||||
|
||||
debug("Packet receive from 0x%p, length %dB\n", addr, length);
|
||||
*packetp = etherrxbuff;
|
||||
|
@ -595,7 +600,8 @@ static int emaclite_ofdata_to_platdata(struct udevice *dev)
|
|||
int offset = 0;
|
||||
|
||||
pdata->iobase = (phys_addr_t)dev_get_addr(dev);
|
||||
emaclite->regs = (struct emaclite_regs *)pdata->iobase;
|
||||
emaclite->regs = (struct emaclite_regs *)ioremap_nocache(pdata->iobase,
|
||||
0x10000);
|
||||
|
||||
emaclite->phyaddr = -1;
|
||||
|
||||
|
|
|
@ -39,4 +39,11 @@ config PCI_TEGRA
|
|||
with a total of 5 lanes. Some boards require this for Ethernet
|
||||
support to work (e.g. beaver, jetson-tk1).
|
||||
|
||||
config PCI_XILINX
|
||||
bool "Xilinx AXI Bridge for PCI Express"
|
||||
depends on DM_PCI
|
||||
help
|
||||
Enable support for the Xilinx AXI bridge for PCI express, an IP block
|
||||
which can be used on some generations of Xilinx FPGAs.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -31,3 +31,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o
|
|||
obj-$(CONFIG_TSI108_PCI) += tsi108_pci.o
|
||||
obj-$(CONFIG_WINBOND_83C553) += w83c553f.o
|
||||
obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
|
||||
obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o
|
||||
|
|
|
@ -837,7 +837,7 @@ static int pci_uclass_pre_probe(struct udevice *bus)
|
|||
hose = bus->uclass_priv;
|
||||
|
||||
/* For bridges, use the top-level PCI controller */
|
||||
if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) {
|
||||
if (!device_is_on_pci_bus(bus)) {
|
||||
hose->ctlr = bus;
|
||||
ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset,
|
||||
bus->of_offset);
|
||||
|
|
220
drivers/pci/pcie_xilinx.c
Normal file
220
drivers/pci/pcie_xilinx.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Xilinx AXI Bridge for PCI Express Driver
|
||||
*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <pci.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
/**
|
||||
* struct xilinx_pcie - Xilinx PCIe controller state
|
||||
* @hose: The parent classes PCI controller state
|
||||
* @cfg_base: The base address of memory mapped configuration space
|
||||
*/
|
||||
struct xilinx_pcie {
|
||||
struct pci_controller hose;
|
||||
void *cfg_base;
|
||||
};
|
||||
|
||||
/* Register definitions */
|
||||
#define XILINX_PCIE_REG_PSCR 0x144
|
||||
#define XILINX_PCIE_REG_PSCR_LNKUP BIT(11)
|
||||
|
||||
/**
|
||||
* pcie_xilinx_link_up() - Check whether the PCIe link is up
|
||||
* @pcie: Pointer to the PCI controller state
|
||||
*
|
||||
* Checks whether the PCIe link for the given device is up or down.
|
||||
*
|
||||
* Return: true if the link is up, else false
|
||||
*/
|
||||
static bool pcie_xilinx_link_up(struct xilinx_pcie *pcie)
|
||||
{
|
||||
uint32_t pscr = __raw_readl(pcie->cfg_base + XILINX_PCIE_REG_PSCR);
|
||||
|
||||
return pscr & XILINX_PCIE_REG_PSCR_LNKUP;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_xilinx_config_address() - Calculate the address of a config access
|
||||
* @pcie: Pointer to the PCI controller state
|
||||
* @bdf: Identifies the PCIe device to access
|
||||
* @offset: The offset into the device's configuration space
|
||||
* @paddress: Pointer to the pointer to write the calculates address to
|
||||
*
|
||||
* Calculates the address that should be accessed to perform a PCIe
|
||||
* configuration space access for a given device identified by the PCIe
|
||||
* controller device @pcie and the bus, device & function numbers in @bdf. If
|
||||
* access to the device is not valid then the function will return an error
|
||||
* code. Otherwise the address to access will be written to the pointer pointed
|
||||
* to by @paddress.
|
||||
*
|
||||
* Return: 0 on success, else -ENODEV
|
||||
*/
|
||||
static int pcie_xilinx_config_address(struct xilinx_pcie *pcie, pci_dev_t bdf,
|
||||
uint offset, void **paddress)
|
||||
{
|
||||
unsigned int bus = PCI_BUS(bdf);
|
||||
unsigned int dev = PCI_DEV(bdf);
|
||||
unsigned int func = PCI_FUNC(bdf);
|
||||
void *addr;
|
||||
|
||||
if ((bus > 0) && !pcie_xilinx_link_up(pcie))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Busses 0 (host-PCIe bridge) & 1 (its immediate child) are
|
||||
* limited to a single device each.
|
||||
*/
|
||||
if ((bus < 2) && (dev > 0))
|
||||
return -ENODEV;
|
||||
|
||||
addr = pcie->cfg_base;
|
||||
addr += bus << 20;
|
||||
addr += dev << 15;
|
||||
addr += func << 12;
|
||||
addr += offset;
|
||||
*paddress = addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_xilinx_read_config() - Read from configuration space
|
||||
* @pcie: Pointer to the PCI controller state
|
||||
* @bdf: Identifies the PCIe device to access
|
||||
* @offset: The offset into the device's configuration space
|
||||
* @valuep: A pointer at which to store the read value
|
||||
* @size: Indicates the size of access to perform
|
||||
*
|
||||
* Read a value of size @size from offset @offset within the configuration
|
||||
* space of the device identified by the bus, device & function numbers in @bdf
|
||||
* on the PCI bus @bus.
|
||||
*
|
||||
* Return: 0 on success, else -ENODEV or -EINVAL
|
||||
*/
|
||||
static int pcie_xilinx_read_config(struct udevice *bus, pci_dev_t bdf,
|
||||
uint offset, ulong *valuep,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
struct xilinx_pcie *pcie = dev_get_priv(bus);
|
||||
void *address;
|
||||
int err;
|
||||
|
||||
err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
|
||||
if (err < 0) {
|
||||
*valuep = pci_get_ff(size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case PCI_SIZE_8:
|
||||
*valuep = __raw_readb(address);
|
||||
return 0;
|
||||
case PCI_SIZE_16:
|
||||
*valuep = __raw_readw(address);
|
||||
return 0;
|
||||
case PCI_SIZE_32:
|
||||
*valuep = __raw_readl(address);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_xilinx_write_config() - Write to configuration space
|
||||
* @pcie: Pointer to the PCI controller state
|
||||
* @bdf: Identifies the PCIe device to access
|
||||
* @offset: The offset into the device's configuration space
|
||||
* @value: The value to write
|
||||
* @size: Indicates the size of access to perform
|
||||
*
|
||||
* Write the value @value of size @size from offset @offset within the
|
||||
* configuration space of the device identified by the bus, device & function
|
||||
* numbers in @bdf on the PCI bus @bus.
|
||||
*
|
||||
* Return: 0 on success, else -ENODEV or -EINVAL
|
||||
*/
|
||||
static int pcie_xilinx_write_config(struct udevice *bus, pci_dev_t bdf,
|
||||
uint offset, ulong value,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
struct xilinx_pcie *pcie = dev_get_priv(bus);
|
||||
void *address;
|
||||
int err;
|
||||
|
||||
err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
|
||||
if (err < 0)
|
||||
return 0;
|
||||
|
||||
switch (size) {
|
||||
case PCI_SIZE_8:
|
||||
__raw_writeb(value, address);
|
||||
return 0;
|
||||
case PCI_SIZE_16:
|
||||
__raw_writew(value, address);
|
||||
return 0;
|
||||
case PCI_SIZE_32:
|
||||
__raw_writel(value, address);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_xilinx_ofdata_to_platdata() - Translate from DT to device state
|
||||
* @dev: A pointer to the device being operated on
|
||||
*
|
||||
* Translate relevant data from the device tree pertaining to device @dev into
|
||||
* state that the driver will later make use of. This state is stored in the
|
||||
* device's private data structure.
|
||||
*
|
||||
* Return: 0 on success, else -EINVAL
|
||||
*/
|
||||
static int pcie_xilinx_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct xilinx_pcie *pcie = dev_get_priv(dev);
|
||||
struct fdt_resource reg_res;
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
int err;
|
||||
|
||||
err = fdt_get_resource(gd->fdt_blob, dev->of_offset, "reg",
|
||||
0, ®_res);
|
||||
if (err < 0) {
|
||||
error("\"reg\" resource not found\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
pcie->cfg_base = map_physmem(reg_res.start,
|
||||
fdt_resource_size(®_res),
|
||||
MAP_NOCACHE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_pci_ops pcie_xilinx_ops = {
|
||||
.read_config = pcie_xilinx_read_config,
|
||||
.write_config = pcie_xilinx_write_config,
|
||||
};
|
||||
|
||||
static const struct udevice_id pcie_xilinx_ids[] = {
|
||||
{ .compatible = "xlnx,axi-pcie-host-1.00.a" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pcie_xilinx) = {
|
||||
.name = "pcie_xilinx",
|
||||
.id = UCLASS_PCI,
|
||||
.of_match = pcie_xilinx_ids,
|
||||
.ops = &pcie_xilinx_ops,
|
||||
.ofdata_to_platdata = pcie_xilinx_ofdata_to_platdata,
|
||||
.priv_auto_alloc_size = sizeof(struct xilinx_pcie),
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
|
@ -352,6 +353,8 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
|
|||
{
|
||||
struct ns16550_platdata *plat = dev->platdata;
|
||||
fdt_addr_t addr;
|
||||
struct clk clk;
|
||||
int err;
|
||||
|
||||
/* try Processor Local Bus device first */
|
||||
addr = dev_get_addr(dev);
|
||||
|
@ -397,9 +400,21 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
|
|||
"reg-offset", 0);
|
||||
plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"reg-shift", 0);
|
||||
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"clock-frequency",
|
||||
CONFIG_SYS_NS16550_CLK);
|
||||
|
||||
err = clk_get_by_index(dev, 0, &clk);
|
||||
if (!err) {
|
||||
err = clk_get_rate(&clk);
|
||||
if (!IS_ERR_VALUE(err))
|
||||
plat->clock = err;
|
||||
} else if (err != -ENODEV && err != -ENOSYS) {
|
||||
debug("ns16550 failed to get clock\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!plat->clock)
|
||||
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"clock-frequency",
|
||||
CONFIG_SYS_NS16550_CLK);
|
||||
if (!plat->clock) {
|
||||
debug("ns16550 clock not defined\n");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -59,7 +59,7 @@ struct clk {
|
|||
unsigned long id;
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK)
|
||||
struct phandle_2_cell;
|
||||
int clk_get_by_index_platdata(struct udevice *dev, int index,
|
||||
struct phandle_2_cell *cells, struct clk *clk);
|
||||
|
|
81
include/configs/boston.h
Normal file
81
include/configs/boston.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef __CONFIGS_BOSTON_H__
|
||||
#define __CONFIGS_BOSTON_H__
|
||||
|
||||
/*
|
||||
* General board configuration
|
||||
*/
|
||||
#define CONFIG_DISPLAY_BOARDINFO
|
||||
|
||||
/*
|
||||
* CPU
|
||||
*/
|
||||
#define CONFIG_SYS_MIPS_TIMER_FREQ 30000000
|
||||
|
||||
/*
|
||||
* PCI
|
||||
*/
|
||||
#define CONFIG_PCI
|
||||
#define CONFIG_PCI_PNP
|
||||
#define CONFIG_CMD_PCI
|
||||
|
||||
/*
|
||||
* Memory map
|
||||
*/
|
||||
#ifdef CONFIG_64BIT
|
||||
# define CONFIG_SYS_SDRAM_BASE 0xffffffff80000000
|
||||
#else
|
||||
# define CONFIG_SYS_SDRAM_BASE 0x80000000
|
||||
#endif
|
||||
|
||||
#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
|
||||
|
||||
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
|
||||
|
||||
#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x100000)
|
||||
|
||||
#define CONFIG_SYS_MEMTEST_START (CONFIG_SYS_SDRAM_BASE + 0)
|
||||
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x10000000)
|
||||
|
||||
#define CONFIG_SYS_MALLOC_LEN (256 * 1024)
|
||||
|
||||
/*
|
||||
* Console
|
||||
*/
|
||||
#define CONFIG_SYS_MAXARGS 16
|
||||
#define CONFIG_SYS_CBSIZE 256
|
||||
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
|
||||
sizeof(CONFIG_SYS_PROMPT) + 16)
|
||||
#define CONFIG_SYS_LONGHELP
|
||||
#define CONFIG_BAUDRATE 115200
|
||||
|
||||
/*
|
||||
* Flash
|
||||
*/
|
||||
#define CONFIG_FLASH_CFI_DRIVER
|
||||
#define CONFIG_SYS_FLASH_CFI
|
||||
#define CONFIG_SYS_FLASH_PROTECTION
|
||||
#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
|
||||
#define CONFIG_SYS_MAX_FLASH_BANKS_DETECT 1
|
||||
#define CONFIG_SYS_MAX_FLASH_SECT 1024
|
||||
|
||||
/*
|
||||
* Environment
|
||||
*/
|
||||
#define CONFIG_ENV_IS_IN_FLASH
|
||||
#define CONFIG_ENV_SECT_SIZE 0x20000
|
||||
#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
|
||||
#ifdef CONFIG_64BIT
|
||||
# define CONFIG_ENV_ADDR \
|
||||
(0xffffffffb8000000 + (128 << 20) - CONFIG_ENV_SIZE)
|
||||
#else
|
||||
# define CONFIG_ENV_ADDR \
|
||||
(0xb8000000 + (128 << 20) - CONFIG_ENV_SIZE)
|
||||
#endif
|
||||
|
||||
#endif /* __CONFIGS_BOSTON_H__ */
|
68
include/configs/imgtec_xilfpga.h
Normal file
68
include/configs/imgtec_xilfpga.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Imagination Technologies Ltd.
|
||||
*
|
||||
* Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Imagination Technologies Ltd. MIPSfpga
|
||||
*/
|
||||
|
||||
#ifndef __XILFPGA_CONFIG_H
|
||||
#define __XILFPGA_CONFIG_H
|
||||
|
||||
/* BootROM + MIG is pretty smart. DDR and Cache initialized */
|
||||
#define CONFIG_SKIP_LOWLEVEL_INIT
|
||||
|
||||
/*--------------------------------------------
|
||||
* CPU configuration
|
||||
*/
|
||||
/* CPU Timer rate */
|
||||
#define CONFIG_SYS_MIPS_TIMER_FREQ 50000000
|
||||
|
||||
/* Cache Configuration */
|
||||
#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Memory Layout
|
||||
*/
|
||||
|
||||
/* SDRAM Configuration (for final code, data, stack, heap) */
|
||||
#define CONFIG_SYS_SDRAM_BASE 0x80000000
|
||||
#define CONFIG_SYS_SDRAM_SIZE 0x08000000 /* 128 Mbytes */
|
||||
#define CONFIG_SYS_INIT_SP_ADDR \
|
||||
(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE - 0x1000)
|
||||
|
||||
#define CONFIG_SYS_MALLOC_LEN (256 << 10)
|
||||
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
|
||||
#define CONFIG_SYS_LOAD_ADDR 0x80500000 /* default load address */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Commands
|
||||
*/
|
||||
#define CONFIG_SYS_LONGHELP /* undef to save memory */
|
||||
|
||||
/*-------------------------------------------------
|
||||
* FLASH configuration
|
||||
*/
|
||||
#define CONFIG_SYS_NO_FLASH
|
||||
|
||||
/*------------------------------------------------------------
|
||||
* Console Configuration
|
||||
*/
|
||||
#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */
|
||||
#define CONFIG_SYS_MAXARGS 16 /* max number of command args*/
|
||||
#define CONFIG_BAUDRATE 115200
|
||||
|
||||
/* -------------------------------------------------
|
||||
* Environment
|
||||
*/
|
||||
#define CONFIG_ENV_IS_NOWHERE 1
|
||||
#define CONFIG_ENV_SIZE 0x4000
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Board boot configuration
|
||||
*/
|
||||
#define CONFIG_TIMESTAMP /* Print image info with timestamp */
|
||||
|
||||
#endif /* __XILFPGA_CONFIG_H */
|
13
include/dt-bindings/clock/boston-clock.h
Normal file
13
include/dt-bindings/clock/boston-clock.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Imagination Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__
|
||||
#define __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__
|
||||
|
||||
#define BOSTON_CLK_SYS 0
|
||||
#define BOSTON_CLK_CPU 1
|
||||
|
||||
#endif /* __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__ */
|
9
include/dt-bindings/interrupt-controller/mips-gic.h
Normal file
9
include/dt-bindings/interrupt-controller/mips-gic.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_MIPS_GIC_H
|
||||
#define _DT_BINDINGS_INTERRUPT_CONTROLLER_MIPS_GIC_H
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
#define GIC_SHARED 0
|
||||
#define GIC_LOCAL 1
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue