diff --git a/Documentation/boards/arm-qemu-vexpress.rst b/Documentation/boards/arm-qemu-vexpress.rst new file mode 100644 index 0000000..dcbac8e --- /dev/null +++ b/Documentation/boards/arm-qemu-vexpress.rst @@ -0,0 +1,20 @@ +QEMU vexpress +======= + +ARM Qemu vexpress +----------------- + +Running barebox on QEMU vexpress machine +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Usage:: + + $ qemu-system-arm -m 1024M \ + -machine vexpress-a9 -cpu cortex-a9 \ + -nographic -no-reboot \ + -kernel images/barebox-vexpress-ca9.img + + $ qemu-system-arm -m 1024M \ + -machine vexpress-a15 -cpu cortex-a15 \ + -nographic -no-reboot \ + -kernel images/barebox-vexpress-ca15.img diff --git a/arch/arm/boards/vexpress/Makefile b/arch/arm/boards/vexpress/Makefile index c89d7bf..2da0494 100644 --- a/arch/arm/boards/vexpress/Makefile +++ b/arch/arm/boards/vexpress/Makefile @@ -1,4 +1,2 @@ obj-y += init.o - lwl-y += lowlevel.o -bbenv-$(CONFIG_DEFAULT_ENVIRONMENT_GENERIC) += defaultenv-vexpress diff --git a/arch/arm/boards/vexpress/defaultenv-vexpress/config b/arch/arm/boards/vexpress/defaultenv-vexpress/config deleted file mode 100644 index 6c0abda..0000000 --- a/arch/arm/boards/vexpress/defaultenv-vexpress/config +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# use 'dhcp' to do dhcp in barebox and in kernel -# use 'none' if you want to skip kernel ip autoconfiguration -ip=dhcp -global.dhcp.vendor_id=barebox-${global.hostname} - -# or set your networking parameters here -#eth0.ipaddr=a.b.c.d -#eth0.netmask=a.b.c.d -#eth0.gateway=a.b.c.d -#eth0.serverip=a.b.c.d - -# can be either 'nfs', 'tftp' or 'nor' -kernel_loc=tftp -# can be either 'net', 'nor' or 'initrd' -rootfs_loc=initrd - -# can be either 'jffs2' or 'ubifs' -rootfs_type=ubifs -rootfsimage=root.$rootfs_type - -kernelimage=zImage -#kernelimage=uImage -#kernelimage=Image -#kernelimage=Image.lzo - -nfsroot="$eth0.serverip:/opt/work/busybox/arm9/rootfs_arm" - -nor_parts="256k(barebox)ro,64k(bareboxenv),1536k(kernel),-(root)" -rootfs_mtdblock_nor=3 - -autoboot_timeout=3 - -bootargs="console=ttyAMA0,115200n8 CONSOLE=/dev/ttyAMA0" - -# set a fancy prompt (if support is compiled in) -PS1="\e[1;31m[barebox@\h]:\w\e[0m\n# " diff --git a/arch/arm/boards/vexpress/init.c b/arch/arm/boards/vexpress/init.c index f89dff9..9463853 100644 --- a/arch/arm/boards/vexpress/init.c +++ b/arch/arm/boards/vexpress/init.c @@ -11,129 +11,23 @@ #include #include #include -#include #include #include #include #include #include -#include - -struct vexpress_init { - void (*core_init)(void); - void (*mem_init)(void); - void (*console_init)(void); - void (*devices_init)(void); -}; - -struct mmci_platform_data mmci_plat = { - .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, - .clkdiv_init = SDI_CLKCR_CLKDIV_INIT, -}; - -struct vexpress_init *v2m_init; - -static void vexpress_ax_mem_init(void) -{ - vexpress_add_ddram(SZ_512M); -} #define V2M_SYS_FLASH 0x03c -static void vexpress_ax_devices_init(void) -{ - add_cfi_flash_device(0, 0x08000000, SZ_64M, 0); - add_cfi_flash_device(1, 0x0c000000, SZ_64M, 0); - vexpress_register_mmc(&mmci_plat); - add_generic_device("smc911x", DEVICE_ID_DYNAMIC, NULL, 0x1a000000, - 64 * 1024, IORESOURCE_MEM, NULL); -} - -static void vexpress_ax_console_init(void) -{ - vexpress_register_uart(0); - vexpress_register_uart(1); - vexpress_register_uart(2); - vexpress_register_uart(3); -} - -struct vexpress_init vexpress_init_ax = { - .core_init = vexpress_init, - .mem_init = vexpress_ax_mem_init, - .console_init = vexpress_ax_console_init, - .devices_init = vexpress_ax_devices_init, -}; - -static void vexpress_a9_legacy_mem_init(void) -{ - vexpress_a9_legacy_add_ddram(SZ_512M, SZ_512M); -} - -static void vexpress_a9_legacy_devices_init(void) -{ - add_cfi_flash_device(0, 0x40000000, SZ_64M, 0); - add_cfi_flash_device(1, 0x44000000, SZ_64M, 0); - add_generic_device("smc911x", DEVICE_ID_DYNAMIC, NULL, 0x4e000000, - 64 * 1024, IORESOURCE_MEM, NULL); - vexpress_a9_legacy_register_mmc(&mmci_plat); - armlinux_set_architecture(MACH_TYPE_VEXPRESS); -} - -static void vexpress_a9_legacy_console_init(void) -{ - vexpress_a9_legacy_register_uart(0); - vexpress_a9_legacy_register_uart(1); - vexpress_a9_legacy_register_uart(2); - vexpress_a9_legacy_register_uart(3); -} - -struct vexpress_init vexpress_init_a9_legacy = { - .core_init = vexpress_a9_legacy_init, - .mem_init = vexpress_a9_legacy_mem_init, - .console_init = vexpress_a9_legacy_console_init, - .devices_init = vexpress_a9_legacy_devices_init, -}; - -static int vexpress_mem_init(void) -{ - v2m_init->mem_init(); - - return 0; -} -mem_initcall(vexpress_mem_init); - -static int vexpress_devices_init(void) -{ - writel(1, v2m_sysreg_base + V2M_SYS_FLASH); - v2m_init->devices_init(); - - devfs_add_partition("nor0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self"); - devfs_add_partition("nor0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env0"); - - if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT_GENERIC)) - defaultenv_append_directory(defaultenv_vexpress); - - return 0; -} -device_initcall(vexpress_devices_init); - -static int vexpress_console_init(void) -{ - v2m_init->console_init(); - - return 0; -} -console_initcall(vexpress_console_init); - static int vexpress_core_init(void) { char *hostname = "vexpress-unknown"; if (amba_is_arm_sp804(IOMEM(0x10011000))) { - v2m_init = &vexpress_init_a9_legacy; + vexpress_a9_legacy_init(); hostname = "vexpress-a9-legacy"; } else { - v2m_init = &vexpress_init_ax; + vexpress_init(); if (cpu_is_cortex_a5()) hostname = "vexpress-a5"; else if (cpu_is_cortex_a7()) @@ -144,11 +38,39 @@ hostname = "vexpress-a15"; } - barebox_set_model("ARM Vexpress"); - barebox_set_hostname(hostname); + writel(1, v2m_sysreg_base + V2M_SYS_FLASH); - v2m_init->core_init(); + barebox_set_hostname(hostname); return 0; } postcore_initcall(vexpress_core_init); + +static int of_fixup_virtio_mmio(struct device_node *root, void *unused) +{ + struct device_node *barebox_root, *np, *parent; + + barebox_root = of_get_root_node(); + if (root == barebox_root) + return 0; + + for_each_compatible_node_from(np, barebox_root, NULL, "virtio,mmio") { + if (of_get_parent(np) == barebox_root) + parent = root; + else + parent = of_find_node_by_path_from(root, + of_get_parent(np)->full_name); + if (!parent) + return -EINVAL; + + of_copy_node(parent, np); + } + + return 0; +} + +static int of_register_virtio_mmio_fixup(void) +{ + return of_register_fixup(of_fixup_virtio_mmio, NULL); +} +late_initcall(of_register_virtio_mmio_fixup); diff --git a/arch/arm/boards/vexpress/lowlevel.c b/arch/arm/boards/vexpress/lowlevel.c index 204d29d..9fe7c83 100644 --- a/arch/arm/boards/vexpress/lowlevel.c +++ b/arch/arm/boards/vexpress/lowlevel.c @@ -9,14 +9,44 @@ #include #include #include +#include #include -void __naked barebox_arm_reset_vector(void) +static inline void start_vexpress_common(void *internal_dt) { + void *fdt = internal_dt - get_runtime_offset(); + unsigned long membase, memsize = SZ_512M; + arm_cpu_lowlevel_init(); if (amba_is_arm_sp804(IOMEM(0x10011000))) - barebox_arm_entry(0x60000000, SZ_512M, NULL); + membase = 0x60000000; else - barebox_arm_entry(0x80000000, SZ_512M, NULL); + membase = 0x80000000; + + /* QEMU may put a DTB at the start of RAM */ + if (IS_ENABLED(CONFIG_OFDEVICE) && + get_unaligned_be32((void*)membase) == FDT_MAGIC) { + fdt = (void*)membase; + /* + * Need to move membase a bit as the PBL wants to relocate + * to the start of RAM, which would overwrite the DTB. + */ + membase += SZ_4M; + memsize -= SZ_4M; + } + + barebox_arm_entry(membase, memsize, fdt); +} + +extern char __dtb_vexpress_v2p_ca9_start[]; +ENTRY_FUNCTION(start_vexpress_ca9, r0, r1, r2) +{ + start_vexpress_common(__dtb_vexpress_v2p_ca9_start); +} + +extern char __dtb_vexpress_v2p_ca15_start[]; +ENTRY_FUNCTION(start_vexpress_ca15, r0, r1, r2) +{ + start_vexpress_common(__dtb_vexpress_v2p_ca15_start); } diff --git a/arch/arm/configs/vexpress_ca9_defconfig b/arch/arm/configs/vexpress_ca9_defconfig deleted file mode 100644 index a1c4251..0000000 --- a/arch/arm/configs/vexpress_ca9_defconfig +++ /dev/null @@ -1,52 +0,0 @@ -CONFIG_ARCH_VEXPRESS=y -CONFIG_AEABI=y -CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y -CONFIG_TEXT_BASE=0x63f00000 -CONFIG_MALLOC_TLSF=y -CONFIG_PROMPT="vexpress: " -CONFIG_GLOB=y -CONFIG_HUSH_FANCY_PROMPT=y -CONFIG_CMDLINE_EDITING=y -CONFIG_AUTO_COMPLETE=y -CONFIG_MENU=y -CONFIG_BOOTM_SHOW_TYPE=y -CONFIG_BOOTM_VERBOSE=y -CONFIG_BOOTM_INITRD=y -CONFIG_PARTITION=y -CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y -CONFIG_LONGHELP=y -CONFIG_CMD_MEMINFO=y -# CONFIG_CMD_BOOTU is not set -CONFIG_CMD_GO=y -CONFIG_CMD_LOADB=y -CONFIG_CMD_RESET=y -CONFIG_CMD_UIMAGE=y -CONFIG_CMD_PARTITION=y -CONFIG_CMD_EXPORT=y -CONFIG_CMD_PRINTENV=y -CONFIG_CMD_SAVEENV=y -CONFIG_CMD_UNCOMPRESS=y -CONFIG_CMD_SLEEP=y -CONFIG_CMD_DHCP=y -CONFIG_CMD_PING=y -CONFIG_CMD_TFTP=y -CONFIG_CMD_ECHO_E=y -CONFIG_CMD_EDIT=y -CONFIG_CMD_LOGIN=y -CONFIG_CMD_MENU=y -CONFIG_CMD_MENU_MANAGEMENT=y -CONFIG_CMD_PASSWD=y -CONFIG_CMD_READLINE=y -CONFIG_CMD_TIMEOUT=y -CONFIG_CMD_CLK=y -CONFIG_CMD_OFTREE=y -CONFIG_NET=y -CONFIG_NET_NFS=y -CONFIG_NET_NETCONSOLE=y -CONFIG_NET_RESOLV=y -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_DRIVER_NET_SMC91111=y -# CONFIG_SPI is not set -CONFIG_FS_TFTP=y -CONFIG_DIGEST_SHA1_GENERIC=y -CONFIG_DIGEST_SHA256_GENERIC=y diff --git a/arch/arm/configs/vexpress_defconfig b/arch/arm/configs/vexpress_defconfig index 94fe1ea..f6a57de 100644 --- a/arch/arm/configs/vexpress_defconfig +++ b/arch/arm/configs/vexpress_defconfig @@ -1,9 +1,9 @@ CONFIG_ARCH_VEXPRESS=y CONFIG_AEABI=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_MALLOC_SIZE=0x0 CONFIG_MALLOC_TLSF=y CONFIG_PROMPT="vexpress: " -CONFIG_GLOB=y CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y @@ -11,9 +11,10 @@ CONFIG_BOOTM_SHOW_TYPE=y CONFIG_BOOTM_VERBOSE=y CONFIG_BOOTM_INITRD=y -CONFIG_PARTITION=y -CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y +CONFIG_CMD_DMESG=y CONFIG_LONGHELP=y +CONFIG_CMD_IOMEM=y CONFIG_CMD_MEMINFO=y # CONFIG_CMD_BOOTU is not set CONFIG_CMD_GO=y @@ -37,15 +38,25 @@ CONFIG_CMD_PASSWD=y CONFIG_CMD_READLINE=y CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y CONFIG_CMD_CLK=y +CONFIG_CMD_DETECT=y CONFIG_CMD_OFTREE=y CONFIG_NET=y CONFIG_NET_NFS=y CONFIG_NET_NETCONSOLE=y CONFIG_NET_RESOLV=y +CONFIG_OF_BAREBOX_DRIVERS=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_DRIVER_NET_SMC91111=y # CONFIG_SPI is not set +CONFIG_MTD=y +CONFIG_MTD_CONCAT=y +CONFIG_DRIVER_CFI=y +CONFIG_MCI=y +CONFIG_MCI_MMCI=y +# CONFIG_PINCTRL is not set CONFIG_FS_TFTP=y CONFIG_DIGEST_SHA1_GENERIC=y CONFIG_DIGEST_SHA256_GENERIC=y diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index cf9d8ea..b5601a6 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -91,6 +91,8 @@ pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o +pbl-dtb-$(CONFIG_MACH_VEXPRESS) += vexpress-v2p-ca9.dtb.o +pbl-dtb-$(CONFIG_MACH_VEXPRESS) += vexpress-v2p-ca15.dtb.o pbl-dtb-$(CONFIG_MACH_VSCOM_BALTOS) += am335x-baltos-minimal.dtb.o pbl-dtb-$(CONFIG_MACH_WARP7) += imx7s-warp.dtb.o pbl-dtb-$(CONFIG_MACH_VF610_TWR) += vf610-twr.dtb.o diff --git a/arch/arm/dts/socfpga_cyclone5_sockit.dts b/arch/arm/dts/socfpga_cyclone5_sockit.dts index 8df5ed4..7cb9b96 100644 --- a/arch/arm/dts/socfpga_cyclone5_sockit.dts +++ b/arch/arm/dts/socfpga_cyclone5_sockit.dts @@ -25,112 +25,4 @@ chosen { stdout-path = &uart0; }; - - leds: gpio-leds { - }; - - buttons: gpio-keys { - }; -}; - -&gpio1 { - status = "okay"; -}; - -&gpio2 { - status = "okay"; -}; - -&leds { - compatible = "gpio-leds"; - - led@0 { - label = "0"; - gpios = <&portb 24 0>; - linux,default-trigger = "heartbeat"; - }; - - led@1 { - label = "1"; - gpios = <&portb 25 0>; - }; - - led@2 { - label = "2"; - gpios = <&portb 26 0>; - }; - - led@3 { - label = "3"; - gpios = <&portb 27 0>; - }; -}; - -&buttons { - compatible = "gpio-keys"; - - key@0 { - label = "F1"; - gpios = <&portc 21 0>; - linux,code = <59>; - }; - - key@1 { - label = "F2"; - gpios = <&portc 22 0>; - linux,code = <60>; - }; - - key@2 { - label = "F3"; - gpios = <&portc 23 0>; - linux,code = <61>; - }; - - key@3 { - label = "F4"; - gpios = <&portc 24 0>; - linux,code = <62>; - }; -}; - -&i2c0 { - status = "disabled"; - - eeprom@51 { - compatible = "atmel,24c32"; - reg = <0x51>; - pagesize = <0x20>; - }; -}; - -&i2c1 { - status = "disabled"; - - adxl345@53 { - compatible = "adi,adxl34x"; - reg = <0x53>; - interrupt-parent = <0x2>; - interrupts = <0x0 0xa6 0x4>; - }; -}; - -&qspi { - status = "okay"; - - flash: flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "n25q00"; - reg = <0>; - spi-max-frequency = <108000000>; - m25p,fast-read; - cdns,page-size = <256>; - cdns,block-size = <16>; - cdns,read-delay = <4>; - cdns,tshsl-ns = <50>; - cdns,tsd2d-ns = <50>; - cdns,tchsh-ns = <4>; - cdns,tslch-ns = <4>; - }; }; diff --git a/arch/arm/dts/vexpress-v2p-ca15.dts b/arch/arm/dts/vexpress-v2p-ca15.dts new file mode 100644 index 0000000..211eacc --- /dev/null +++ b/arch/arm/dts/vexpress-v2p-ca15.dts @@ -0,0 +1,27 @@ +#include + +/ { + barebox_environment { + compatible = "barebox,environment"; + device-path = &barebox_env; + }; + + smb@8000000 { + motherboard { + flash@0,00000000 { + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0x80000>; + }; + + barebox_env: partition@80000 { + label = "barebox-environment"; + reg = <0x80000 0x80000>; + }; + }; + }; + }; +}; diff --git a/arch/arm/dts/vexpress-v2p-ca9.dts b/arch/arm/dts/vexpress-v2p-ca9.dts new file mode 100644 index 0000000..d097533 --- /dev/null +++ b/arch/arm/dts/vexpress-v2p-ca9.dts @@ -0,0 +1,90 @@ +#include + +/ { + barebox_environment { + compatible = "barebox,environment"; + device-path = &barebox_env; + }; + + aliases { + state = &state; + }; + + smb@4000000 { + motherboard { + flash@0,00000000 { + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0x80000>; + }; + + barebox_env: partition@80000 { + label = "barebox-environment"; + reg = <0x80000 0x80000>; + }; + + state_storage: partition@100000 { + label = "barebox-state"; + reg = <0x100000 0x100000>; + }; + }; + }; + }; + + /* State: mutable part */ + state: state { + magic = <0x4d433230>; + compatible = "barebox,state"; + backend-type = "raw"; + backend = <&state_storage>; + backend-stridesize = <0x40>; + backend-storage-type = "circular"; + #address-cells = <1>; + #size-cells = <1>; + + bootstate { + #address-cells = <1>; + #size-cells = <1>; + + system0 { /* the node's name here must match the subnode's name in the 'bootstate' node */ + #address-cells = <1>; + #size-cells = <1>; + + remaining_attempts@0 { + reg = <0x0 0x4>; + type = "uint32"; + default = <3>; + }; + priority@4 { + reg = <0x4 0x4>; + type = "uint32"; + default = <20>; + }; + }; + + system1 { /* the node's name here must match the subnode's name in the 'bootstate' node */ + #address-cells = <1>; + #size-cells = <1>; + + remaining_attempts@8 { + reg = <0x8 0x4>; + type = "uint32"; + default = <3>; + }; + priority@c { + reg = <0xC 0x4>; + type = "uint32"; + default = <20>; + }; + }; + + last_chosen@10 { + reg = <0x10 0x4>; + type = "uint32"; + }; + }; + }; +}; diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index bf1dd5a..aaa535f 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -2,13 +2,18 @@ config ARCH_TEXT_BASE hex - default 0x83f00000 + default 0x0 choice prompt "ARM Board type" config MACH_VEXPRESS bool "ARM Vexpress" + select RELOCATABLE + select HAVE_PBL_MULTI_IMAGES + select OFTREE + select OFDEVICE + select COMMON_CLK_OF_PROVIDER endchoice diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index 74b4a0f..9a06e64 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -1,3 +1,2 @@ obj-y += v2m.o -obj-y += devices.o obj-y += reset.o diff --git a/arch/arm/mach-vexpress/devices.c b/arch/arm/mach-vexpress/devices.c deleted file mode 100644 index 5b53011..0000000 --- a/arch/arm/mach-vexpress/devices.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD - * - * GPLv2 only - */ - -#include - -#include - -#include - -#include - -void vexpress_a9_legacy_add_ddram(u32 ddr0_size, u32 ddr1_size) -{ - arm_add_mem_device("ram0", 0x60000000, ddr0_size); - - if (ddr1_size) - arm_add_mem_device("ram1", 0x80000000, ddr1_size); -} - -void vexpress_a9_legacy_register_uart(unsigned id) -{ - resource_size_t start; - - switch (id) { - case 0: - start = 0x10009000; - break; - case 1: - start = 0x1000a000; - break; - case 2: - start = 0x1000b000; - break; - case 3: - start = 0x1000c000; - break; - default: - return; - } - amba_apb_device_add(NULL, "uart-pl011", id, start, 4096, NULL, 0); -} - -void vexpress_a9_legacy_register_mmc(struct mmci_platform_data *plat) -{ - amba_apb_device_add(NULL, "mmci-pl18x", DEVICE_ID_SINGLE, 0x10005000, - 4096, plat, 0); -} - -void vexpress_add_ddram(u32 size) -{ - arm_add_mem_device("ram1", 0x80000000, size); -} - -void vexpress_register_uart(unsigned id) -{ - resource_size_t start; - - switch (id) { - case 0: - start = 0x1c090000; - break; - case 1: - start = 0x1c0a0000; - break; - case 2: - start = 0x1c0b0000; - break; - case 3: - start = 0x1c0c0000; - break; - default: - return; - } - amba_apb_device_add(NULL, "uart-pl011", id, start, 4096, NULL, 0); -} - -void vexpress_register_mmc(struct mmci_platform_data *plat) -{ - amba_apb_device_add(NULL, "mmci-pl18x", DEVICE_ID_SINGLE, 0x1c050000, 4096, plat, 0); -} diff --git a/arch/arm/mach-vexpress/include/mach/devices.h b/arch/arm/mach-vexpress/include/mach/devices.h index 96d1400..bef8c8b 100644 --- a/arch/arm/mach-vexpress/include/mach/devices.h +++ b/arch/arm/mach-vexpress/include/mach/devices.h @@ -9,18 +9,9 @@ #include -void vexpress_a9_legacy_add_ddram(u32 ddr0_size, u32 ddr1_size); -void vexpress_add_ddram(u32 size); - -void vexpress_a9_legacy_register_uart(unsigned id); -void vexpress_register_uart(unsigned id); - void vexpress_a9_legacy_init(void); void vexpress_init(void); -void vexpress_a9_legacy_register_mmc(struct mmci_platform_data *plat); -void vexpress_register_mmc(struct mmci_platform_data *plat); - extern void *v2m_wdt_base; extern void *v2m_sysreg_base; diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 025bbb1..3535262 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -19,31 +19,6 @@ void __iomem *v2m_sysreg_base; -static const char *v2m_osc2_periphs[] = { - "mb:mmci", "mmci-pl18x", /* PL180 MMCI */ - "mb:uart0", "uart-pl0110", /* PL011 UART0 */ - "mb:uart1", "uart-pl0111", /* PL011 UART1 */ - "mb:uart2", "uart-pl0112", /* PL011 UART2 */ - "mb:uart3", "uart-pl0113", /* PL011 UART3 */ -}; - -static void v2m_clk_init(void) -{ - struct clk *clk; - int i; - - clk = clk_fixed("dummy_apb_pclk", 0); - clk_register_clkdev(clk, "apb_pclk", NULL); - - clk = clk_fixed("mb:sp804_clk", 1000000); - clk_register_clkdev(clk, NULL, "sp804"); - - clk = clk_fixed("mb:osc2", 24000000); - for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++) - clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i]); - -} - static void v2m_sysctl_init(void __iomem *base) { u32 scctrl; @@ -58,21 +33,11 @@ writel(scctrl, base + SCCTRL); } -static void __init v2m_sp804_init(void __iomem *base) -{ - writel(0, base + TIMER_1_BASE + TIMER_CTRL); - - amba_apb_device_add(NULL, "sp804", DEVICE_ID_SINGLE, (resource_size_t)base, 4096, NULL, 0); -} - void vexpress_a9_legacy_init(void) { v2m_wdt_base = IOMEM(0x1000f000); v2m_sysreg_base = IOMEM(0x10001000); v2m_sysctl_init(IOMEM(0x10001000)); - v2m_clk_init(); - - v2m_sp804_init(IOMEM(0x10011000)); } void vexpress_init(void) @@ -80,7 +45,4 @@ v2m_wdt_base = IOMEM(0x1c0f0000); v2m_sysreg_base = IOMEM(0x1c020000); v2m_sysctl_init(IOMEM(0x1c020000)); - v2m_clk_init(); - - v2m_sp804_init(IOMEM(0x1c110000)); } diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b5abe1c..a36a8db 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_MACH_MIPS_ATH79) += clk-ar933x.o obj-$(CONFIG_ARCH_IMX) += imx/ obj-$(CONFIG_COMMON_CLK_AT91) += at91/ +obj-$(CONFIG_MACH_VEXPRESS) += vexpress/ diff --git a/drivers/clk/vexpress/Makefile b/drivers/clk/vexpress/Makefile new file mode 100644 index 0000000..c6869ba --- /dev/null +++ b/drivers/clk/vexpress/Makefile @@ -0,0 +1 @@ +obj-y += clk-vexpress-osc.o clk-sp810.o diff --git a/drivers/clk/vexpress/clk-sp810.c b/drivers/clk/vexpress/clk-sp810.c new file mode 100644 index 0000000..af72c74 --- /dev/null +++ b/drivers/clk/vexpress/clk-sp810.c @@ -0,0 +1,136 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2013 ARM Limited + */ + +#include +#include +#include +#include +#include +#include + +/* sysctl registers offset */ +#define SCCTRL 0x000 +#define SCCTRL_TIMERENnSEL_SHIFT(n) (15 + ((n) * 2)) + +struct clk_sp810; + +struct clk_sp810_timerclken { + struct clk hw; + struct clk_sp810 *sp810; + int channel; +}; + +static inline struct clk_sp810_timerclken * +to_clk_sp810_timerclken(struct clk *clk) +{ + return container_of(clk, struct clk_sp810_timerclken, hw); +} + +struct clk_sp810 { + struct device_node *node; + void __iomem *base; + struct clk_sp810_timerclken timerclken[4]; +}; + +static int clk_sp810_timerclken_get_parent(struct clk *hw) +{ + struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); + u32 val = readl(timerclken->sp810->base + SCCTRL); + + return !!(val & (1 << SCCTRL_TIMERENnSEL_SHIFT(timerclken->channel))); +} + +static int clk_sp810_timerclken_set_parent(struct clk *hw, u8 index) +{ + struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); + struct clk_sp810 *sp810 = timerclken->sp810; + u32 val, shift = SCCTRL_TIMERENnSEL_SHIFT(timerclken->channel); + + if (WARN_ON(index > 1)) + return -EINVAL; + + val = readl(sp810->base + SCCTRL); + val &= ~(1 << shift); + val |= index << shift; + writel(val, sp810->base + SCCTRL); + + return 0; +} + +static const struct clk_ops clk_sp810_timerclken_ops = { + .get_parent = clk_sp810_timerclken_get_parent, + .set_parent = clk_sp810_timerclken_set_parent, +}; + +static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec, + void *data) +{ + struct clk_sp810 *sp810 = data; + + if (WARN_ON(clkspec->args_count != 1 || + clkspec->args[0] >= ARRAY_SIZE(sp810->timerclken))) + return NULL; + + return &sp810->timerclken[clkspec->args[0]].hw; +} + +static void clk_sp810_of_setup(struct device_node *node) +{ + struct clk_sp810 *sp810 = xzalloc(sizeof(*sp810)); + const char *parent_names[2]; + int num = ARRAY_SIZE(parent_names); + char name[12]; + static int instance; + int i; + bool deprecated; + + if (!sp810) + return; + + if (of_clk_parent_fill(node, parent_names, num) != num) { + pr_warn("Failed to obtain parent clocks for SP810!\n"); + kfree(sp810); + return; + } + + sp810->node = node; + sp810->base = of_iomap(node, 0); + + deprecated = !of_find_property(node, "assigned-clock-parents", NULL); + + for (i = 0; i < ARRAY_SIZE(sp810->timerclken); i++) { + snprintf(name, sizeof(name), "sp810_%d_%d", instance, i); + + sp810->timerclken[i].sp810 = sp810; + sp810->timerclken[i].channel = i; + sp810->timerclken[i].hw.name = strdup(name); + sp810->timerclken[i].hw.parent_names = parent_names; + sp810->timerclken[i].hw.num_parents = num; + sp810->timerclken[i].hw.ops = &clk_sp810_timerclken_ops; + + /* + * If DT isn't setting the parent, force it to be + * the 1 MHz clock without going through the framework. + * We do this before clk_register() so that it can determine + * the parent and setup the tree properly. + */ + if (deprecated) + clk_sp810_timerclken_set_parent(&sp810->timerclken[i].hw, 1); + + clk_register(&sp810->timerclken[i].hw); + } + + of_clk_add_provider(node, clk_sp810_timerclken_of_get, sp810); + instance++; +} +CLK_OF_DECLARE(sp810, "arm,sp810", clk_sp810_of_setup); diff --git a/drivers/clk/vexpress/clk-vexpress-osc.c b/drivers/clk/vexpress/clk-vexpress-osc.c new file mode 100644 index 0000000..c0d6e60 --- /dev/null +++ b/drivers/clk/vexpress/clk-vexpress-osc.c @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +/* + * This represents the vexpress-osc as a fixed clock, which isn't really + * accurate, as this clock allows rate changes in real implementations. As those + * would need access to the config bus, a whole lot more infrastructure would be + * needed. We skip this complication for now, as we don't have a use-case, yet. + */ +static int vexpress_osc_setup(struct device_node *node) +{ + struct clk *clk; + u32 range[2]; + const char *name; + + if (of_property_read_u32_array(node, "freq-range", range, + ARRAY_SIZE(range))) + return -EINVAL; + + if (of_property_read_string(node, "clock-output-names", &name)) + return -EINVAL; + + clk = clk_fixed(name, range[0]); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + return of_clk_add_provider(node, of_clk_src_simple_get, clk); +} +CLK_OF_DECLARE(vexpress_osc, "arm,vexpress-osc", vexpress_osc_setup); diff --git a/drivers/clocksource/amba-sp804.c b/drivers/clocksource/amba-sp804.c index c5ad994..66e3988 100644 --- a/drivers/clocksource/amba-sp804.c +++ b/drivers/clocksource/amba-sp804.c @@ -35,8 +35,8 @@ int ret; if (sp804_base) { - dev_err(&dev->dev, "single instance driver\n"); - return -EBUSY; + dev_dbg(&dev->dev, "skipping secondary instance\n"); + return 0; } sp804_clk = clk_get(&dev->dev, NULL); diff --git a/drivers/mci/mmci.c b/drivers/mci/mmci.c index 7489ee0..f45557d 100644 --- a/drivers/mci/mmci.c +++ b/drivers/mci/mmci.c @@ -532,9 +532,37 @@ udelay(CLK_CHANGE_DELAY); } +static int mmci_of_parse(struct device_node *np, + struct mmci_platform_data *plat) +{ + if (!IS_ENABLED(CONFIG_OFDEVICE)) + return 0; + + if (of_get_property(np, "st,sig-dir-dat0", NULL)) + plat->sigdir |= MCI_ST_DATA0DIREN; + if (of_get_property(np, "st,sig-dir-dat2", NULL)) + plat->sigdir |= MCI_ST_DATA2DIREN; + if (of_get_property(np, "st,sig-dir-dat31", NULL)) + plat->sigdir |= MCI_ST_DATA31DIREN; + if (of_get_property(np, "st,sig-dir-dat74", NULL)) + plat->sigdir |= MCI_ST_DATA74DIREN; + if (of_get_property(np, "st,sig-dir-cmd", NULL)) + plat->sigdir |= MCI_ST_CMDDIREN; + if (of_get_property(np, "st,sig-pin-fbclk", NULL)) + plat->sigdir |= MCI_ST_FBCLKEN; + + if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL)) + plat->capabilities |= MMC_CAP_MMC_HIGHSPEED; + if (of_get_property(np, "mmc-cap-sd-highspeed", NULL)) + plat->capabilities |= MMC_CAP_SD_HIGHSPEED; + + return 0; +} + static int mmci_probe(struct amba_device *dev, const struct amba_id *id) { struct device_d *hw_dev = &dev->dev; + struct device_node *np = hw_dev->device_node; struct mmci_platform_data *plat = hw_dev->platform_data; struct variant_data *variant = id->data; u32 sdi_u32; @@ -542,11 +570,16 @@ struct clk *clk; int ret; - if (!plat) { - dev_err(hw_dev, "missing platform data\n"); + if (!plat && !np) { + dev_err(hw_dev, "missing platform data or DT node\n"); return -EINVAL; } + if (!plat) + plat = xzalloc(sizeof(*plat)); + + mmci_of_parse(np, plat); + host = xzalloc(sizeof(*host)); host->base = amba_get_mem_region(dev); @@ -625,7 +658,7 @@ host->mci.max_req_size = (1 << variant->datalength_bits) - 1; host->mci.host_caps = plat->capabilities; - host->mci.voltages = plat->ocr_mask; + host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | plat->ocr_mask; mci_register(&host->mci); diff --git a/drivers/of/base.c b/drivers/of/base.c index 95bea4e..3ca13ae 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1938,8 +1938,8 @@ if (memory) of_add_memory(memory, false); - of_platform_populate(root_node, of_default_bus_match_table, NULL); of_clk_init(root_node, NULL); + of_platform_populate(root_node, of_default_bus_match_table, NULL); return 0; } @@ -1988,6 +1988,22 @@ return dn; } +struct device_node *of_copy_node(struct device_node *parent, const struct device_node *other) +{ + struct device_node *np, *child; + struct property *pp; + + np = of_new_node(parent, other->name); + + list_for_each_entry(pp, &other->properties, list) + of_new_property(np, pp->name, pp->value, pp->length); + + for_each_child_of_node(other, child) + of_copy_node(np, child); + + return np; +} + void of_delete_node(struct device_node *node) { struct device_node *n, *nt; diff --git a/images/Makefile b/images/Makefile index 705c8ad..5c4d99a 100644 --- a/images/Makefile +++ b/images/Makefile @@ -111,6 +111,7 @@ include $(srctree)/images/Makefile.rockchip include $(srctree)/images/Makefile.socfpga include $(srctree)/images/Makefile.tegra +include $(srctree)/images/Makefile.vexpress include $(srctree)/images/Makefile.at91 targets += $(image-y) pbl.lds barebox.x barebox.z diff --git a/images/Makefile.vexpress b/images/Makefile.vexpress new file mode 100644 index 0000000..0f12dc1 --- /dev/null +++ b/images/Makefile.vexpress @@ -0,0 +1,11 @@ +# +# barebox image generation Makefile for VExpress images +# + +pblx-$(CONFIG_MACH_VEXPRESS) += start_vexpress_ca9 +FILE_barebox-vexpress-ca9.img = start_vexpress_ca9.pblx +image-$(CONFIG_MACH_VEXPRESS) += barebox-vexpress-ca9.img + +pblx-$(CONFIG_MACH_VEXPRESS) += start_vexpress_ca15 +FILE_barebox-vexpress-ca15.img = start_vexpress_ca15.pblx +image-$(CONFIG_MACH_VEXPRESS) += barebox-vexpress-ca15.img diff --git a/include/of.h b/include/of.h index 9ba771a..18a4232 100644 --- a/include/of.h +++ b/include/of.h @@ -144,6 +144,8 @@ const char *name); extern struct device_node *of_create_node(struct device_node *root, const char *path); +extern struct device_node *of_copy_node(struct device_node *parent, + const struct device_node *other); extern void of_delete_node(struct device_node *node); extern int of_machine_is_compatible(const char *compat);