zynq_platform.c revision 1.2
11.2Sskrll/* $NetBSD: zynq_platform.c,v 1.2 2020/07/10 12:25:10 skrll Exp $ */ 21.1Sskrll 31.1Sskrll/*- 41.1Sskrll * Copyright (c) 2019 The NetBSD Foundation, Inc. 51.1Sskrll * All rights reserved. 61.1Sskrll * 71.1Sskrll * This code is derived from software contributed to The NetBSD Foundation 81.1Sskrll * by Nick Hudson 91.1Sskrll * 101.1Sskrll * Redistribution and use in source and binary forms, with or without 111.1Sskrll * modification, are permitted provided that the following conditions 121.1Sskrll * are met: 131.1Sskrll * 1. Redistributions of source code must retain the above copyright 141.1Sskrll * notice, this list of conditions and the following disclaimer. 151.1Sskrll * 2. Redistributions in binary form must reproduce the above copyright 161.1Sskrll * notice, this list of conditions and the following disclaimer in the 171.1Sskrll * documentation and/or other materials provided with the distribution. 181.1Sskrll * 191.1Sskrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201.1Sskrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211.1Sskrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221.1Sskrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 231.1Sskrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 241.1Sskrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251.1Sskrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261.1Sskrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271.1Sskrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281.1Sskrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291.1Sskrll * POSSIBILITY OF SUCH DAMAGE. 301.1Sskrll */ 311.1Sskrll 321.1Sskrll#include "opt_console.h" 331.1Sskrll#include "opt_soc.h" 341.1Sskrll 351.1Sskrll#include "arml2cc.h" 361.1Sskrll 371.1Sskrll#include <sys/cdefs.h> 381.2Sskrll__KERNEL_RCSID(0, "$NetBSD: zynq_platform.c,v 1.2 2020/07/10 12:25:10 skrll Exp $"); 391.1Sskrll 401.1Sskrll#include <sys/param.h> 411.1Sskrll#include <sys/bus.h> 421.1Sskrll#include <sys/cpu.h> 431.1Sskrll#include <sys/device.h> 441.1Sskrll 451.1Sskrll#include <dev/fdt/fdtvar.h> 461.1Sskrll#include <arm/fdt/arm_fdtvar.h> 471.1Sskrll 481.1Sskrll#include <uvm/uvm_extern.h> 491.1Sskrll 501.1Sskrll#include <machine/bootconfig.h> 511.1Sskrll 521.1Sskrll#include <arm/cortex/a9tmr_var.h> 531.1Sskrll#include <arm/xilinx/zynq_uartreg.h> 541.1Sskrll 551.1Sskrll#include <evbarm/fdt/platform.h> 561.1Sskrll 571.1Sskrll#include <libfdt.h> 581.1Sskrll 591.1Sskrll#include <arm/cortex/pl310_var.h> 601.1Sskrll 611.1Sskrll#define ZYNQ_REF_FREQ 24000000 621.1Sskrll 631.1Sskrll#define ZYNQ7000_DDR_PBASE 0x00000000 641.1Sskrll#define ZYNQ7000_DDR_SIZE 0x40000000 651.1Sskrll 661.1Sskrll#define ZYNQ_IOREG_VBASE KERNEL_IO_VBASE 671.1Sskrll#define ZYNQ_IOREG_PBASE 0xe0000000 681.1Sskrll#define ZYNQ_IOREG_SIZE 0x00200000 691.1Sskrll 701.1Sskrll#define ZYNQ_GPV_VBASE (ZYNQ_IOREG_VBASE + ZYNQ_IOREG_SIZE) 711.1Sskrll#define ZYNQ_GPV_PBASE 0xf8900000 721.1Sskrll#define ZYNQ_GPV_SIZE 0x00100000 731.1Sskrll 741.1Sskrll#define ZYNQ_ARMCORE_VBASE (ZYNQ_GPV_VBASE + ZYNQ_GPV_SIZE) 751.1Sskrll#define ZYNQ_ARMCORE_PBASE 0xf8f00000 761.1Sskrll#define ZYNQ_ARMCORE_SIZE 0x00003000 771.1Sskrll 781.1Sskrllextern struct bus_space arm_generic_bs_tag; 791.1Sskrllextern struct bus_space arm_generic_a4x_bs_tag; 801.1Sskrllextern struct arm32_bus_dma_tag arm_generic_dma_tag; 811.1Sskrll 821.1Sskrllvoid zynq_platform_early_putchar(char); 831.1Sskrll 841.1Sskrllstatic const struct pmap_devmap * 851.1Sskrllzynq_platform_devmap(void) 861.1Sskrll{ 871.1Sskrll static const struct pmap_devmap devmap[] = { 881.1Sskrll DEVMAP_ENTRY(ZYNQ_IOREG_VBASE, 891.1Sskrll ZYNQ_IOREG_PBASE, 901.1Sskrll ZYNQ_IOREG_SIZE), 911.1Sskrll DEVMAP_ENTRY(ZYNQ_GPV_VBASE, 921.1Sskrll ZYNQ_GPV_PBASE, 931.1Sskrll ZYNQ_GPV_SIZE), 941.1Sskrll DEVMAP_ENTRY(ZYNQ_ARMCORE_VBASE, 951.1Sskrll ZYNQ_ARMCORE_PBASE, 961.1Sskrll ZYNQ_ARMCORE_SIZE), 971.1Sskrll DEVMAP_ENTRY_END 981.1Sskrll }; 991.1Sskrll 1001.1Sskrll return devmap; 1011.1Sskrll} 1021.1Sskrll 1031.1Sskrllstatic void 1041.1Sskrllzynq_platform_init_attach_args(struct fdt_attach_args *faa) 1051.1Sskrll{ 1061.1Sskrll faa->faa_bst = &arm_generic_bs_tag; 1071.1Sskrll faa->faa_a4x_bst = &arm_generic_a4x_bs_tag; 1081.1Sskrll faa->faa_dmat = &arm_generic_dma_tag; 1091.1Sskrll} 1101.1Sskrll 1111.2Sskrllvoid __noasan 1121.1Sskrllzynq_platform_early_putchar(char c) 1131.1Sskrll{ 1141.1Sskrll#ifdef CONSADDR 1151.1Sskrll#define CONSADDR_VA ((CONSADDR - ZYNQ_IOREG_PBASE) + ZYNQ_IOREG_VBASE) 1161.1Sskrll volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? 1171.1Sskrll (volatile uint32_t *)CONSADDR_VA : 1181.1Sskrll (volatile uint32_t *)CONSADDR; 1191.1Sskrll 1201.1Sskrll /* QEMU needs CR_TXEN to be set and CR_TXDIS to be unset */ 1211.1Sskrll uartaddr[UART_CONTROL / 4] = CR_TXEN; 1221.1Sskrll while ((le32toh(uartaddr[UART_CHNL_INT_STS / 4]) & STS_TEMPTY) == 0) 1231.1Sskrll ; 1241.1Sskrll 1251.1Sskrll uartaddr[UART_TX_RX_FIFO / 4] = htole32(c); 1261.1Sskrll#endif 1271.1Sskrll} 1281.1Sskrll 1291.1Sskrllstatic void 1301.1Sskrllzynq_platform_device_register(device_t dev, void *aux) 1311.1Sskrll{ 1321.1Sskrll prop_dictionary_t dict = device_properties(dev); 1331.1Sskrll 1341.1Sskrll if (device_is_a(dev, "arma9tmr")) { 1351.1Sskrll prop_dictionary_set_uint32(dict, "frequency", 1361.1Sskrll ZYNQ_REF_FREQ / 4); 1371.1Sskrll } 1381.1Sskrll} 1391.1Sskrll 1401.1Sskrllstatic u_int 1411.1Sskrllzynq_platform_uart_freq(void) 1421.1Sskrll{ 1431.1Sskrll return ZYNQ_REF_FREQ; 1441.1Sskrll} 1451.1Sskrll 1461.1Sskrll#define ZYNQ_ARMCORE_L2C_BASE 0x00002000 1471.1Sskrll#define ZYNQ_ARM_PL310_BASE ZYNQ_ARMCORE_VBASE + ZYNQ_ARMCORE_L2C_BASE 1481.1Sskrll 1491.1Sskrllstatic void 1501.1Sskrllzynq_platform_bootstrap(void) 1511.1Sskrll{ 1521.1Sskrll#if NARML2CC > 0 1531.1Sskrll const bus_space_handle_t pl310_bh = ZYNQ_ARM_PL310_BASE; 1541.1Sskrll arml2cc_init(&arm_generic_bs_tag, pl310_bh, 0); 1551.1Sskrll#endif 1561.1Sskrll 1571.1Sskrll arm_fdt_cpu_bootstrap(); 1581.1Sskrll 1591.1Sskrll void *fdt_data = __UNCONST(fdtbus_get_data()); 1601.1Sskrll const int chosen_off = fdt_path_offset(fdt_data, "/chosen"); 1611.1Sskrll if (chosen_off < 0) 1621.1Sskrll return; 1631.1Sskrll 1641.1Sskrll if (match_bootconf_option(boot_args, "console", "fb")) { 1651.1Sskrll const int framebuffer_off = 1661.1Sskrll fdt_path_offset(fdt_data, "/chosen/framebuffer"); 1671.1Sskrll if (framebuffer_off >= 0) { 1681.1Sskrll const char *status = fdt_getprop(fdt_data, 1691.1Sskrll framebuffer_off, "status", NULL); 1701.1Sskrll if (status == NULL || strncmp(status, "ok", 2) == 0) { 1711.1Sskrll fdt_setprop_string(fdt_data, chosen_off, 1721.1Sskrll "stdout-path", "/chosen/framebuffer"); 1731.1Sskrll } 1741.1Sskrll } 1751.1Sskrll } else if (match_bootconf_option(boot_args, "console", "serial")) { 1761.1Sskrll fdt_setprop_string(fdt_data, chosen_off, 1771.1Sskrll "stdout-path", "serial0:115200n8"); 1781.1Sskrll } 1791.1Sskrll} 1801.1Sskrll 1811.1Sskrllstatic void 1821.1Sskrllzynq_platform_reset(void) 1831.1Sskrll{ 1841.1Sskrll 1851.1Sskrll} 1861.1Sskrll 1871.1Sskrllstatic const struct arm_platform zynq_platform = { 1881.1Sskrll .ap_devmap = zynq_platform_devmap, 1891.1Sskrll .ap_bootstrap = zynq_platform_bootstrap, 1901.1Sskrll .ap_init_attach_args = zynq_platform_init_attach_args, 1911.1Sskrll .ap_device_register = zynq_platform_device_register, 1921.1Sskrll .ap_reset = zynq_platform_reset, 1931.1Sskrll .ap_delay = a9tmr_delay, 1941.1Sskrll .ap_uart_freq = zynq_platform_uart_freq, 1951.1Sskrll#if 0 1961.1Sskrll .ap_mpstart = arm_fdt_cpu_mpstart, 1971.1Sskrll#endif 1981.1Sskrll}; 1991.1Sskrll 2001.1Sskrll 2011.1SskrllARM_PLATFORM(zynq, "xlnx,zynq-7000", &zynq_platform); 202