diff --git a/Documentation/boards/imx.rst b/Documentation/boards/imx.rst index 60cdcf0..b6e6506 100644 --- a/Documentation/boards/imx.rst +++ b/Documentation/boards/imx.rst @@ -20,6 +20,7 @@ * i.MX51 * i.MX53 * i.MX6 +* i.MX7 With the Internal Boot Mode, the images contain a header which describes where the binary shall be loaded and started. These headers also contain diff --git a/Documentation/boards/imx/Element14-WaRP7.rst b/Documentation/boards/imx/Element14-WaRP7.rst new file mode 100644 index 0000000..d4e5e79 --- /dev/null +++ b/Documentation/boards/imx/Element14-WaRP7.rst @@ -0,0 +1,54 @@ +element14 WaRP7 +=============== + +This CPU card is based on an NXP i.MX7S SoC. + +Supported hardware +================== + +- NXP PMIC PFUZE3000 +- Kingston 08EMCP04-EL3AV100 eMCP (eMMC and LPDDR3 memory in one package) + - 8 GiB eMMC Triple-Level cell NAND flash, eMMC standard 5.0 (HS400) + - 512 MiB LPDDR3 SDRAM starting at address 0x80000000 + +Bootstrapping barebox +===================== + +The device boots in internal boot mode from eMMC and is shipped with a +vendor modified u-boot imximage. + +Barebox can be used as a drop-in replacement for the shipped bootloader. + +The WaRP7 IO Board has a double DIP switch where switch number two defines the +boot source of the i.MX7 SoC: + + +-----+ + | | + | | O | <--- on = high level + | | | | + | O | | <--- off = low level + | | + | 1 2 | + +-----+ + +Bootsource is the internal eMMC: + + +-----+ + | | + | O | | + | | | | + | | O | <---- eMMC + | | + | 1 2 | + +-----+ + +Bootsource is the USB: + + +-----+ + | | + | O O | <---- USB + | | | | + | | | | + | | + | 1 2 | + +-----+ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3e8ccf7..e4663ea 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -383,6 +383,29 @@ the data on the host computer connected to the target via debugging channel (JTAG, SWD). If unsure say N +config ARM_SECURE_MONITOR + bool + +config ARM_PSCI + bool "enable Power State Coordination Interface (PSCI) support" + depends on CPU_V7 + select ARM_SECURE_MONITOR + help + PSCI is used for controlling secondary CPU cores on some systems. Say + yes here if you have one of these. + +config ARM_PSCI_DEBUG + bool "Enable PSCI debugging" + depends on ARM_PSCI + help + This enables debug output from the PSCI functions during runtime of the + Kernel. This needs board specific help, the board needs to provide a putc + function using psci_set_putc(). This putc function will then be called + during runtime of the Kernel, so it must be able to cope with that. It may + happen for example that the Kernel has turned off some clocks needed in the + putc function. + Only use for debugging. + endmenu source common/Kconfig diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile index ff0a86f..250ccb8 100644 --- a/arch/arm/boards/Makefile +++ b/arch/arm/boards/Makefile @@ -140,4 +140,7 @@ obj-$(CONFIG_MACH_VARISCITE_MX6) += variscite-mx6/ obj-$(CONFIG_MACH_VSCOM_BALTOS) += vscom-baltos/ obj-$(CONFIG_MACH_QEMU_VIRT64) += qemu-virt64/ +obj-$(CONFIG_MACH_WARP7) += element14-warp7/ obj-$(CONFIG_MACH_VF610_TWR) += freescale-vf610-twr/ +obj-$(CONFIG_MACH_ZII_RDU2) += zii-imx6q-rdu2/ +obj-$(CONFIG_MACH_ZII_VF610_DEV) += zii-vf610-dev/ diff --git a/arch/arm/boards/element14-warp7/Makefile b/arch/arm/boards/element14-warp7/Makefile new file mode 100644 index 0000000..01c7a25 --- /dev/null +++ b/arch/arm/boards/element14-warp7/Makefile @@ -0,0 +1,2 @@ +obj-y += board.o +lwl-y += lowlevel.o diff --git a/arch/arm/boards/element14-warp7/board.c b/arch/arm/boards/element14-warp7/board.c new file mode 100644 index 0000000..84fc885 --- /dev/null +++ b/arch/arm/boards/element14-warp7/board.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int warp7_devices_init(void) +{ + if (!of_machine_is_compatible("warp,imx7s-warp")) + return 0; + + imx6_bbu_internal_mmc_register_handler("mmc", "/dev/mmc2.boot0.barebox", + BBU_HANDLER_FLAG_DEFAULT); + + return 0; +} +device_initcall(warp7_devices_init); diff --git a/arch/arm/boards/element14-warp7/flash-header-mx7-warp.imxcfg b/arch/arm/boards/element14-warp7/flash-header-mx7-warp.imxcfg new file mode 100644 index 0000000..a338921 --- /dev/null +++ b/arch/arm/boards/element14-warp7/flash-header-mx7-warp.imxcfg @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2016 NXP Semiconductors + * + * SPDX-License-Identifier: GPL-2.0 + * + * Refer docs/README.imxmage for more details about how-to configure + * and create imximage boot image + * + * The syntax is taken as close as possible with the kwbimage + */ + +soc imx7 +loadaddr 0x80000000 +dcdofs 0x400 + +wm 32 0x30340004 0x4F400005 + +wm 32 0x30391000 0x00000002 +wm 32 0x307a0000 0x03040008 +wm 32 0x307a0064 0x00200038 +wm 32 0x307a0490 0x00000001 +wm 32 0x307a00d0 0x00350001 +wm 32 0x307a00dc 0x00c3000a +wm 32 0x307a00e0 0x00010000 +wm 32 0x307a00e4 0x00110006 +wm 32 0x307a00f4 0x0000033f +wm 32 0x307a0100 0x0a0e110b +wm 32 0x307a0104 0x00020211 +wm 32 0x307a0108 0x03060708 +wm 32 0x307a010c 0x00a0500c +wm 32 0x307a0110 0x05020307 +wm 32 0x307a0114 0x02020404 +wm 32 0x307a0118 0x02020003 +wm 32 0x307a011c 0x00000202 +wm 32 0x307a0120 0x00000202 + +wm 32 0x307a0180 0x00600018 +wm 32 0x307a0184 0x00e00100 +wm 32 0x307a0190 0x02098205 +wm 32 0x307a0194 0x00060303 +wm 32 0x307a01a0 0x80400003 +wm 32 0x307a01a4 0x00100020 +wm 32 0x307a01a8 0x80100004 + +wm 32 0x307a0200 0x00000015 +wm 32 0x307a0204 0x00161616 +wm 32 0x307a0210 0x00000f0f +wm 32 0x307a0214 0x04040404 +wm 32 0x307a0218 0x0f0f0404 + +wm 32 0x307a0240 0x06000600 +wm 32 0x307a0244 0x00000000 +wm 32 0x30391000 0x00000000 +wm 32 0x30790000 0x17421e40 +wm 32 0x30790004 0x10210100 +wm 32 0x30790008 0x00010000 +wm 32 0x30790010 0x0007080c +wm 32 0x307900b0 0x1010007e + +wm 32 0x3079001C 0x01010000 +wm 32 0x3079009c 0x00000d6e + +wm 32 0x30790030 0x06060606 +wm 32 0x30790020 0x0a0a0a0a +wm 32 0x30790050 0x01000008 +wm 32 0x30790050 0x00000008 +wm 32 0x30790018 0x0000000f +wm 32 0x307900c0 0x0e487304 +wm 32 0x307900c0 0x0e4c7304 +wm 32 0x307900c0 0x0e4c7306 +wm 32 0x307900c0 0x0e4c7304 + +check 32 while_any_bit_clear 0x307900c4 0x1 + +wm 32 0x307900c0 0x0e487304 + +wm 32 0x30384130 0x00000000 +wm 32 0x30340020 0x00000178 +wm 32 0x30384130 0x00000002 + +check 32 while_any_bit_clear 0x307a0004 0x1 diff --git a/arch/arm/boards/element14-warp7/lowlevel.c b/arch/arm/boards/element14-warp7/lowlevel.c new file mode 100644 index 0000000..38b7745 --- /dev/null +++ b/arch/arm/boards/element14-warp7/lowlevel.c @@ -0,0 +1,48 @@ +#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include + +extern char __dtb_imx7s_warp_start[]; + +static noinline void warp7_start(void) +{ + void __iomem *iomuxbase = IOMEM(MX7_IOMUXC_BASE_ADDR); + void __iomem *uart = IOMEM(MX7_UART1_BASE_ADDR); + void __iomem *ccmbase = IOMEM(MX7_CCM_BASE_ADDR); + void *fdt; + + writel(0x3, ccmbase + 0x4000 + 16 * 148 + 0x8); + writel(0x10000000, ccmbase + 0x8000 + 128 * 95); + writel(0x3, ccmbase + 0x4000 + 16 * 148 + 0x4); + writel(0x0, iomuxbase + 0x128); + writel(0x0, iomuxbase + 0x12c); + + imx7_uart_setup(uart); + + pbl_set_putc(imx_uart_putc, uart); + + pr_debug("Element14 i.MX7 Warp\n"); + + fdt = __dtb_imx7s_warp_start - get_runtime_offset(); + + barebox_arm_entry(0x80000000, SZ_512M, fdt); +} + +ENTRY_FUNCTION(start_imx7s_element14_warp7, r0, r1, r2) +{ + imx7_cpu_lowlevel_init(); + + arm_early_mmu_cache_invalidate(); + + relocate_to_current_adr(); + setup_c(); + barrier(); + + warp7_start(); +} \ No newline at end of file diff --git a/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c b/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c index b329f46..5743dbc 100644 --- a/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c +++ b/arch/arm/boards/freescale-mx6-sabresd/lowlevel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -11,12 +12,8 @@ imx6_ungate_all_peripherals(); - writel(0x1b0b1, iomuxbase + 0x0650); - writel(3, iomuxbase + 0x0280); - - writel(0x1b0b1, iomuxbase + 0x0654); - writel(3, iomuxbase + 0x0284); - writel(1, iomuxbase + 0x0920); + imx_setup_pad(iomuxbase, MX6Q_PAD_CSI0_DAT10__UART1_TXD); + imx_setup_pad(iomuxbase, MX6Q_PAD_CSI0_DAT11__UART1_RXD); imx6_uart_setup_ll(); diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c index 6504273..53c7b3a 100644 --- a/arch/arm/boards/freescale-vf610-twr/lowlevel.c +++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c @@ -27,16 +27,10 @@ ENTRY_FUNCTION(start_vf610_twr, r0, r1, r2) { - int i; void *fdt; - void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR); vf610_cpu_lowlevel_init(); - for (i = 0; i < VF610_MSCM_IRSPRC_NUM; i++) - writew(VF610_MSCM_IRSPRC_CP0_EN, - mscm + VF610_MSCM_IRSPRC(i)); - if (IS_ENABLED(CONFIG_DEBUG_LL)) setup_uart(); diff --git a/arch/arm/boards/zii-imx6q-rdu2/Makefile b/arch/arm/boards/zii-imx6q-rdu2/Makefile new file mode 100644 index 0000000..01c7a25 --- /dev/null +++ b/arch/arm/boards/zii-imx6q-rdu2/Makefile @@ -0,0 +1,2 @@ +obj-y += board.o +lwl-y += lowlevel.o diff --git a/arch/arm/boards/zii-imx6q-rdu2/board.c b/arch/arm/boards/zii-imx6q-rdu2/board.c new file mode 100644 index 0000000..ee04517 --- /dev/null +++ b/arch/arm/boards/zii-imx6q-rdu2/board.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2016 Zodiac Inflight Innovation + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RDU2_DAC1_RESET IMX_GPIO_NR(1, 0) +#define RDU2_DAC2_RESET IMX_GPIO_NR(1, 2) +#define RDU2_RST_TOUCH IMX_GPIO_NR(1, 7) +#define RDU2_NFC_RESET IMX_GPIO_NR(1, 17) +#define RDU2_HPA1_SDn IMX_GPIO_NR(1, 4) +#define RDU2_HPA2_SDn IMX_GPIO_NR(1, 5) + +static const struct gpio rdu2_reset_gpios[] = { + { + .gpio = RDU2_DAC1_RESET, + .flags = GPIOF_OUT_INIT_LOW, + .label = "dac1-reset", + }, + { + .gpio = RDU2_DAC2_RESET, + .flags = GPIOF_OUT_INIT_LOW, + .label = "dac2-reset", + }, + { + .gpio = RDU2_RST_TOUCH, + .flags = GPIOF_OUT_INIT_LOW, + .label = "rst-touch#", + }, + { + .gpio = RDU2_NFC_RESET, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "nfc-reset", + }, + { + .gpio = RDU2_HPA1_SDn, + .flags = GPIOF_OUT_INIT_LOW, + .label = "hpa1-sd-n", + }, + { + .gpio = RDU2_HPA2_SDn, + .flags = GPIOF_OUT_INIT_LOW, + .label = "hpa2n-sd-n", + }, +}; + +static int rdu2_reset_audio_touchscreen_nfc(void) +{ + int ret; + + if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") && + !of_machine_is_compatible("zii,imx6qp-zii-rdu2")) + return 0; + + ret = gpio_request_array(rdu2_reset_gpios, + ARRAY_SIZE(rdu2_reset_gpios)); + if (ret) { + pr_err("Failed to request RDU2 reset gpios: %s\n", + strerror(-ret)); + return ret; + } + + mdelay(100); + + gpio_direction_output(RDU2_DAC1_RESET, 1); + gpio_direction_output(RDU2_DAC2_RESET, 1); + gpio_direction_output(RDU2_RST_TOUCH, 1); + gpio_direction_output(RDU2_NFC_RESET, 0); + gpio_direction_output(RDU2_HPA1_SDn, 1); + gpio_direction_output(RDU2_HPA2_SDn, 1); + + mdelay(100); + + return 0; +} +/* + * When this function is called "hog" pingroup in device tree needs to + * be already initialized + */ +late_initcall(rdu2_reset_audio_touchscreen_nfc); + +static const struct gpio rdu2_front_panel_usb_gpios[] = { + { + .gpio = IMX_GPIO_NR(3, 19), + .flags = GPIOF_OUT_INIT_LOW, + .label = "usb-emulation", + }, + { + .gpio = IMX_GPIO_NR(3, 20), + .flags = GPIOF_OUT_INIT_HIGH, + .label = "usb-mode1", + }, + { + .gpio = IMX_GPIO_NR(3, 22), + .flags = GPIOF_OUT_INIT_LOW, + .label = "usb-pwr-ctrl-enn", + }, + { + .gpio = IMX_GPIO_NR(3, 23), + .flags = GPIOF_OUT_INIT_HIGH, + .label = "usb-mode2", + }, +}; + +static int rdu2_enable_front_panel_usb(void) +{ + int ret; + + if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") && + !of_machine_is_compatible("zii,imx6qp-zii-rdu2")) + return 0; + + ret = gpio_request_array(rdu2_front_panel_usb_gpios, + ARRAY_SIZE(rdu2_front_panel_usb_gpios)); + if (ret) { + pr_err("Failed to request RDU2 front panel USB gpios: %s\n", + strerror(-ret)); + + } + + return ret; +} +late_initcall(rdu2_enable_front_panel_usb); + +static int rdu2_devices_init(void) +{ + if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") && + !of_machine_is_compatible("zii,imx6qp-zii-rdu2")) + return 0; + + barebox_set_hostname("rdu2"); + + imx6_bbu_internal_spi_i2c_register_handler("SPI", "/dev/m25p0.barebox", + BBU_HANDLER_FLAG_DEFAULT); + + imx6_bbu_internal_mmc_register_handler("eMMC", "/dev/mmc3", 0); + + return 0; +} +device_initcall(rdu2_devices_init); diff --git a/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/init/automount b/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/init/automount new file mode 100644 index 0000000..6c04eb4 --- /dev/null +++ b/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/init/automount @@ -0,0 +1,17 @@ +#!/bin/sh + +# automount tftp server based on $eth0.serverip + +mkdir -p /mnt/tftp +automount /mnt/tftp 'ifup eth1 && mount -t tftp $eth1.serverip /mnt/tftp' + +# automount nfs server's nfsroot + +mkdir -p /mnt/nfs +automount /mnt/nfs 'ifup eth1 && mount -t nfs ${eth1.serverip}:/home/${global.user}/nfsroot/${global.hostname} /mnt/nfs' + + +# FAT on usb disk example + +#mkdir -p /mnt/fat +#automount -d /mnt/fat 'usb && [ -e /dev/disk0.0 ] && mount /dev/disk0.0 /mnt/fat' diff --git a/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth1 b/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth1 new file mode 100644 index 0000000..33fe7c1 --- /dev/null +++ b/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/network/eth1 @@ -0,0 +1,18 @@ +#!/bin/sh + +# ip setting (static/dhcp) +ip=dhcp +global.dhcp.vendor_id=barebox-${global.hostname} + +# static setup used if ip=static +ipaddr= +netmask= +gateway= +serverip= + +# MAC address if needed +#ethaddr=xx:xx:xx:xx:xx:xx + +# put code to discover eth0 (i.e. 'usb') to /env/network/eth0-discover + +exit 0 diff --git a/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/nv/boot.default b/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/nv/boot.default new file mode 100644 index 0000000..3cfe9ba --- /dev/null +++ b/arch/arm/boards/zii-imx6q-rdu2/defaultenv-rdu2/nv/boot.default @@ -0,0 +1 @@ +mmc1 \ No newline at end of file diff --git a/arch/arm/boards/zii-imx6q-rdu2/flash-header-imx6q-rdu2.imxcfg b/arch/arm/boards/zii-imx6q-rdu2/flash-header-imx6q-rdu2.imxcfg new file mode 100644 index 0000000..e37db50 --- /dev/null +++ b/arch/arm/boards/zii-imx6q-rdu2/flash-header-imx6q-rdu2.imxcfg @@ -0,0 +1,87 @@ +loadaddr 0x10000000 +soc imx6 +dcdofs 0x400 + +wm 32 0x020e0798 0x000C0000 +wm 32 0x020e0758 0x00000000 +wm 32 0x020e0588 0x00000030 +wm 32 0x020e0594 0x00000030 +wm 32 0x020e056c 0x00000030 +wm 32 0x020e0578 0x00000030 +wm 32 0x020e074c 0x00000030 +wm 32 0x020e057c 0x00000030 +wm 32 0x020e058c 0x00000000 +wm 32 0x020e059c 0x00000030 +wm 32 0x020e05a0 0x00000030 +wm 32 0x020e078c 0x00000030 +wm 32 0x020e0750 0x00020000 +wm 32 0x020e05a8 0x00000028 +wm 32 0x020e05b0 0x00000028 +wm 32 0x020e0524 0x00000028 +wm 32 0x020e051c 0x00000028 +wm 32 0x020e0518 0x00000028 +wm 32 0x020e050c 0x00000028 +wm 32 0x020e05b8 0x00000028 +wm 32 0x020e05c0 0x00000028 +wm 32 0x020e0774 0x00020000 +wm 32 0x020e0784 0x00000028 +wm 32 0x020e0788 0x00000028 +wm 32 0x020e0794 0x00000028 +wm 32 0x020e079c 0x00000028 +wm 32 0x020e07a0 0x00000028 +wm 32 0x020e07a4 0x00000028 +wm 32 0x020e07a8 0x00000028 +wm 32 0x020e0748 0x00000028 +wm 32 0x020e05ac 0x00000028 +wm 32 0x020e05b4 0x00000028 +wm 32 0x020e0528 0x00000028 +wm 32 0x020e0520 0x00000028 +wm 32 0x020e0514 0x00000028 +wm 32 0x020e0510 0x00000028 +wm 32 0x020e05bc 0x00000028 +wm 32 0x020e05c4 0x00000028 +wm 32 0x021b0800 0xa1390003 +wm 32 0x021b080c 0x001F001F +wm 32 0x021b0810 0x001F001F +wm 32 0x021b480c 0x001F001F +wm 32 0x021b4810 0x001F001F +wm 32 0x021b083c 0x43260335 +wm 32 0x021b0840 0x031A030B +wm 32 0x021b483c 0x4323033B +wm 32 0x021b4840 0x0323026F +wm 32 0x021b0848 0x483D4545 +wm 32 0x021b4848 0x44433E48 +wm 32 0x021b0850 0x41444840 +wm 32 0x021b4850 0x4835483E +wm 32 0x021b081c 0x33333333 +wm 32 0x021b0820 0x33333333 +wm 32 0x021b0824 0x33333333 +wm 32 0x021b0828 0x33333333 +wm 32 0x021b481c 0x33333333 +wm 32 0x021b4820 0x33333333 +wm 32 0x021b4824 0x33333333 +wm 32 0x021b4828 0x33333333 +wm 32 0x021b08b8 0x00000800 +wm 32 0x021b48b8 0x00000800 +wm 32 0x021b0004 0x00020036 +wm 32 0x021b0008 0x09444040 +wm 32 0x021b000c 0x8A8F7955 +wm 32 0x021b0010 0xFF328F64 +wm 32 0x021b0014 0x01FF00DB +wm 32 0x021b0018 0x00001740 +wm 32 0x021b001c 0x00008000 +wm 32 0x021b002c 0x000026d2 +wm 32 0x021b0030 0x008F1023 +wm 32 0x021b0040 0x00000047 +wm 32 0x021b0000 0x841A0000 +wm 32 0x021b001c 0x04088032 +wm 32 0x021b001c 0x00008033 +wm 32 0x021b001c 0x00048031 +wm 32 0x021b001c 0x09408030 +wm 32 0x021b001c 0x04008040 +wm 32 0x021b0020 0x00005800 +wm 32 0x021b0818 0x00011117 +wm 32 0x021b4818 0x00011117 +wm 32 0x021b0004 0x00025576 +wm 32 0x021b0404 0x00011006 +wm 32 0x021b001c 0x00000000 diff --git a/arch/arm/boards/zii-imx6q-rdu2/flash-header-imx6qp-rdu2.imxcfg b/arch/arm/boards/zii-imx6q-rdu2/flash-header-imx6qp-rdu2.imxcfg new file mode 100644 index 0000000..03e764b --- /dev/null +++ b/arch/arm/boards/zii-imx6q-rdu2/flash-header-imx6qp-rdu2.imxcfg @@ -0,0 +1,132 @@ +loadaddr 0x10000000 +soc imx6 +dcdofs 0x400 + +wm 32 0x020e0798 0x000C0000 +wm 32 0x020e0758 0x00000000 + +wm 32 0x020e0588 0x00020030 +wm 32 0x020e0594 0x00020030 + +wm 32 0x020e056c 0x00020030 +wm 32 0x020e0578 0x00020030 +wm 32 0x020e074c 0x00020030 + +wm 32 0x020e057c 0x00020030 +wm 32 0x020e058c 0x00000000 +wm 32 0x020e059c 0x00020030 +wm 32 0x020e05a0 0x00020030 +wm 32 0x020e078c 0x00020030 + +wm 32 0x020e0750 0x00020000 +wm 32 0x020e05a8 0x00020030 +wm 32 0x020e05b0 0x00020030 +wm 32 0x020e0524 0x00020030 +wm 32 0x020e051c 0x00020030 +wm 32 0x020e0518 0x00020030 +wm 32 0x020e050c 0x00020030 +wm 32 0x020e05b8 0x00020030 +wm 32 0x020e05c0 0x00020030 + +wm 32 0x020e0534 0x00018200 +wm 32 0x020e0538 0x00008000 +wm 32 0x020e053c 0x00018200 +wm 32 0x020e0540 0x00018200 +wm 32 0x020e0544 0x00018200 +wm 32 0x020e0548 0x00018200 +wm 32 0x020e054c 0x00018200 +wm 32 0x020e0550 0x00018200 + +wm 32 0x020e0774 0x00020000 +wm 32 0x020e0784 0x00020030 +wm 32 0x020e0788 0x00020030 +wm 32 0x020e0794 0x00020030 +wm 32 0x020e079c 0x00020030 +wm 32 0x020e07a0 0x00020030 +wm 32 0x020e07a4 0x00020030 +wm 32 0x020e07a8 0x00020030 +wm 32 0x020e0748 0x00020030 + +wm 32 0x020e05ac 0x00020030 +wm 32 0x020e05b4 0x00020030 +wm 32 0x020e0528 0x00020030 +wm 32 0x020e0520 0x00020030 +wm 32 0x020e0514 0x00020030 +wm 32 0x020e0510 0x00020030 +wm 32 0x020e05bc 0x00020030 +wm 32 0x020e05c4 0x00020030 + +wm 32 0x021b001c 0x00008000 + +wm 32 0x021b0800 0xA1390003 + +wm 32 0x021b080c 0x002A001F +wm 32 0x021b0810 0x002F002A +wm 32 0x021b480c 0x001F0031 +wm 32 0x021b4810 0x001B0022 + +wm 32 0x021b083c 0x433C0354 +wm 32 0x021b0840 0x03380330 +wm 32 0x021b483c 0x43440358 +wm 32 0x021b4840 0x03340300 + +wm 32 0x021b0848 0x483A4040 +wm 32 0x021b4848 0x3E383648 + +wm 32 0x021b0850 0x3C424048 +wm 32 0x021b4850 0x4C425042 + +wm 32 0x021b081c 0x33333333 +wm 32 0x021b0820 0x33333333 +wm 32 0x021b0824 0x33333333 +wm 32 0x021b0828 0x33333333 +wm 32 0x021b481c 0x33333333 +wm 32 0x021b4820 0x33333333 +wm 32 0x021b4824 0x33333333 +wm 32 0x021b4828 0x33333333 + +wm 32 0x021b08c0 0x24912489 +wm 32 0x021b48c0 0x24914452 + +wm 32 0x021b08b8 0x00000800 +wm 32 0x021b48b8 0x00000800 + +wm 32 0x021b0004 0x00020036 +wm 32 0x021b0008 0x09444040 +wm 32 0x021b000c 0x898E7955 +wm 32 0x021b0010 0xFF328F64 +wm 32 0x021b0014 0x01FF00DB + +wm 32 0x021b0018 0x00011740 +wm 32 0x021b001c 0x00008000 +wm 32 0x021b002c 0x000026D2 +wm 32 0x021b0030 0x008E1023 +wm 32 0x021b0040 0x00000047 + +wm 32 0x021b0400 0x14420000 +wm 32 0x021b0000 0x841A0000 +wm 32 0x021b0890 0x00400c58 + +wm 32 0x00bb0008 0x00000000 +wm 32 0x00bb000c 0x2891E41A +wm 32 0x00bb0038 0x00000564 +wm 32 0x00bb0014 0x00000040 +wm 32 0x00bb0028 0x00000020 +wm 32 0x00bb002c 0x00000020 + +wm 32 0x021b001c 0x02088032 +wm 32 0x021b001c 0x00008033 +wm 32 0x021b001c 0x00048031 +wm 32 0x021b001c 0x19408030 +wm 32 0x021b001c 0x04008040 + +wm 32 0x021b0020 0x00007800 + +wm 32 0x021b0818 0x00022227 +wm 32 0x021b4818 0x00022227 + +wm 32 0x021b0004 0x00025576 + +wm 32 0x021b0404 0x00011006 + +wm 32 0x021b001c 0x00000000 diff --git a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c new file mode 100644 index 0000000..0d3520d --- /dev/null +++ b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 Zodiac Inflight Innovation + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +static inline void setup_uart(void) +{ + void __iomem *iomuxbase = IOMEM(MX6_IOMUXC_BASE_ADDR); + + imx6_ungate_all_peripherals(); + + writel(0x1b0b1, iomuxbase + 0x0650); + writel(3, iomuxbase + 0x0280); + + writel(0x1b0b1, iomuxbase + 0x0654); + writel(3, iomuxbase + 0x0284); + writel(1, iomuxbase + 0x0920); + + imx6_uart_setup_ll(); + + putc_ll('>'); +} + +extern char __dtb_imx6q_zii_rdu2_start[]; +extern char __dtb_imx6qp_zii_rdu2_start[]; + +ENTRY_FUNCTION(start_imx6q_zii_rdu2, r0, r1, r2) +{ + void *fdt = __dtb_imx6q_zii_rdu2_start; + + imx6_cpu_lowlevel_init(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) + setup_uart(); + + imx6q_barebox_entry(fdt - get_runtime_offset()); +} + +ENTRY_FUNCTION(start_imx6qp_zii_rdu2, r0, r1, r2) +{ + void *fdt = __dtb_imx6qp_zii_rdu2_start; + + imx6_cpu_lowlevel_init(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) + setup_uart(); + + imx6q_barebox_entry(fdt - get_runtime_offset()); +} diff --git a/arch/arm/boards/zii-vf610-dev/Makefile b/arch/arm/boards/zii-vf610-dev/Makefile new file mode 100644 index 0000000..1297d81 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/Makefile @@ -0,0 +1,3 @@ +obj-y += board.o +lwl-y += lowlevel.o +bbenv-y += defaultenv-zii-vf610-dev diff --git a/arch/arm/boards/zii-vf610-dev/board.c b/arch/arm/boards/zii-vf610-dev/board.c new file mode 100644 index 0000000..eea3828 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/board.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2016 Zodiac Inflight Innovation + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + + +static int expose_signals(const struct gpio *signals, + size_t signal_num) +{ + int ret, i; + + ret = gpio_request_array(signals, signal_num); + if (ret) + return ret; + + for (i = 0; i < signal_num; i++) + export_env_ull(signals[i].label, signals[i].gpio); + + return 0; +} + +static int zii_vf610_cfu1_expose_signals(void) +{ + static const struct gpio signals[] = { + { + .gpio = 132, + .flags = GPIOF_IN, + .label = "fim_sd", + }, + { + .gpio = 118, + .flags = GPIOF_OUT_INIT_LOW, + .label = "fim_tdis", + }, + }; + + if (!of_machine_is_compatible("zii,vf610cfu1-a")) + return 0; + + return expose_signals(signals, ARRAY_SIZE(signals)); +} +late_initcall(zii_vf610_cfu1_expose_signals); + +static int zii_vf610_cfu1_spu3_expose_signals(void) +{ + static const struct gpio signals[] = { + { + .gpio = 107, + .flags = GPIOF_OUT_INIT_LOW, + .label = "soc_sw_rstn", + }, + { + .gpio = 98, + .flags = GPIOF_IN, + .label = "e6352_intn", + }, + }; + + if (!of_machine_is_compatible("zii,vf610spu3-a") && + !of_machine_is_compatible("zii,vf610cfu1-a")) + return 0; + + return expose_signals(signals, ARRAY_SIZE(signals)); +} +late_initcall(zii_vf610_cfu1_spu3_expose_signals); + +static int zii_vf610_dev_print_clocks(void) +{ + int i; + struct clk *clk; + struct device_node *ccm_np; + const unsigned long MHz = 1000000; + const char *clk_names[] = { "cpu", "ddr", "bus", "ipg" }; + + if (!of_machine_is_compatible("zii,vf610dev")) + return 0; + + ccm_np = of_find_compatible_node(NULL, NULL, "fsl,vf610-ccm"); + if (!ccm_np) { + pr_err("Couln't get CCM node\n"); + return -ENOENT; + } + + for (i = 0; i < ARRAY_SIZE(clk_names); i++) { + unsigned long rate; + const char *name = clk_names[i]; + + clk = of_clk_get_by_name(ccm_np, name); + if (IS_ERR(clk)) { + pr_err("Failed to get '%s' clock (%ld)\n", + name, PTR_ERR(clk)); + return PTR_ERR(clk); + } + + rate = clk_get_rate(clk); + + pr_info("%s clock : %8lu MHz\n", name, rate / MHz); + } + + return 0; +} +late_initcall(zii_vf610_dev_print_clocks); + +static int zii_vf610_dev_set_hostname(void) +{ + size_t i; + static const struct { + const char *compatible; + const char *hostname; + } boards[] = { + { "zii,vf610spu3-a", "spu3-rev-a" }, + { "zii,vf610cfu1-a", "cfu1-rev-a" }, + { "zii,vf610dev-b", "dev-rev-b" }, + { "zii,vf610dev-c", "dev-rev-c" }, + { "zii,vf610scu4-aib-c", "scu4-aib-rev-c" }, + }; + + if (!of_machine_is_compatible("zii,vf610dev")) + return 0; + + for (i = 0; i < ARRAY_SIZE(boards); i++) { + if (of_machine_is_compatible(boards[i].compatible)) { + barebox_set_hostname(boards[i].hostname); + break; + } + } + + defaultenv_append_directory(defaultenv_zii_vf610_dev); + return 0; +} +late_initcall(zii_vf610_dev_set_hostname); diff --git a/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/boot/sd b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/boot/sd new file mode 100644 index 0000000..cf8eec3 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/boot/sd @@ -0,0 +1,4 @@ +#!/bin/sh + +global.bootm.image=/mnt/sd/zImage +global.bootm.oftree=/mnt/sd/${global.bootm.oftree} diff --git a/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/automount-sd b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/automount-sd new file mode 100644 index 0000000..f44dab3 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/automount-sd @@ -0,0 +1,13 @@ +#!/bin/sh + +if [ x${global.hostname} = xdev-rev-b -o x${global.hostname} = xdev-rev-c ]; +then + global sd=0 +else + global sd=1 +fi + +mkdir -p /mnt/sd +automount /mnt/sd 'mci${global.sd}.probe=1 && mount /dev/disk${global.sd}.0 /mnt/sd' + +exit 0 diff --git a/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/choose-dtb b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/choose-dtb new file mode 100644 index 0000000..41a74c3 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/choose-dtb @@ -0,0 +1,4 @@ +#!/bin/sh + +global.bootm.oftree=vf610-zii-${global.hostname}.dtb + diff --git a/arch/arm/boards/zii-vf610-dev/flash-header-zii-vf610-dev.imxcfg b/arch/arm/boards/zii-vf610-dev/flash-header-zii-vf610-dev.imxcfg new file mode 100644 index 0000000..177f4e8 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/flash-header-zii-vf610-dev.imxcfg @@ -0,0 +1,243 @@ +soc vf610 +loadaddr 0x80000000 +dcdofs 0x400 + +#define VF610_DDR_PAD_CTRL 0x00000180 /* 25 Ohm drive strength */ +#define VF610_DDR_PAD_CTRL_1 0x00010180 /* 25 Ohm drive strength + differential input */ + +#define DDRMC_PHY_DQ_TIMING 0x00002613 +#define DDRMC_PHY_DQS_TIMING 0x00002615 +#define DDRMC_PHY_CTRL 0x00210000 +#define DDRMC_PHY_MASTER_CTRL 0x0001012a +#define DDRMC_PHY_SLAVE_CTRL 0x00002000 +#define DDRMC_PHY_OFF 0x00000000 +#define DDRMC_PHY_PROC_PAD_ODT 0x00010101 + +#define CHECKPOINT(n) wm 32 0x3f000000 n + +CHECKPOINT(1) + +/* ======================= Clock initialization =======================*/ + +/* + * Ungate all IP block clocks + */ +wm 32 0x4006b040 0xffffffff +wm 32 0x4006b044 0xffffffff +wm 32 0x4006b048 0xffffffff +wm 32 0x4006b04c 0xffffffff +wm 32 0x4006b050 0xffffffff +wm 32 0x4006b058 0xffffffff +wm 32 0x4006b05c 0xffffffff +wm 32 0x4006b060 0xffffffff +wm 32 0x4006b064 0xffffffff +wm 32 0x4006b068 0xffffffff +wm 32 0x4006b06c 0xffffffff + + +/* + * Turn PLL2 on + */ +wm 32 0x40050030 0x00002001 /* Fout = Fin * 22 */ + +CHECKPOINT(2) + +/* + * Wait for PLLs to lock + */ +check 32 while_any_bit_clear 0x40050030 0x80000000 + + +CHECKPOINT(3) + +clear_bits 32 0x4006b008 0x00000040 +set_bits 32 0x4006b008 0x00002000 + + + +/* ======================= DDR IOMUX =======================*/ + +CHECKPOINT(4) + +wm 32 0x40048220 0x00000180 +wm 32 0x40048224 0x00000180 +wm 32 0x40048228 0x00000180 +wm 32 0x4004822c 0x00000180 +wm 32 0x40048230 0x00000180 +wm 32 0x40048234 0x00000180 +wm 32 0x40048238 0x00000180 +wm 32 0x4004823c 0x00000180 +wm 32 0x40048240 0x00000180 +wm 32 0x40048244 0x00000180 +wm 32 0x40048248 0x00000180 +wm 32 0x4004824c 0x00000180 +wm 32 0x40048250 0x00000180 +wm 32 0x40048254 0x00000180 +wm 32 0x40048258 0x00000180 +wm 32 0x4004825c 0x00000180 +wm 32 0x40048260 0x00000180 +wm 32 0x40048264 0x00000180 +wm 32 0x40048268 0x00000180 +wm 32 0x4004826c 0x00000180 +wm 32 0x40048270 0x00000180 +wm 32 0x40048274 0x00000180 +wm 32 0x40048278 0x00000180 +wm 32 0x4004827c 0x00010180 +wm 32 0x40048280 0x00010180 +wm 32 0x40048284 0x00010180 +wm 32 0x40048288 0x00010180 +wm 32 0x4004828c 0x00010180 +wm 32 0x40048290 0x00010180 +wm 32 0x40048294 0x00010180 +wm 32 0x40048298 0x00010180 +wm 32 0x4004829c 0x00010180 +wm 32 0x400482a0 0x00010180 +wm 32 0x400482a4 0x00010180 +wm 32 0x400482a8 0x00010180 +wm 32 0x400482ac 0x00010180 +wm 32 0x400482b0 0x00010180 +wm 32 0x400482b4 0x00010180 +wm 32 0x400482b8 0x00010180 +wm 32 0x400482bc 0x00010180 +wm 32 0x400482c0 0x00010180 +wm 32 0x400482c4 0x00010180 +wm 32 0x400482c8 0x00010180 +wm 32 0x400482cc 0x00000180 +wm 32 0x400482d0 0x00000180 +wm 32 0x400482d4 0x00000180 +wm 32 0x400482d8 0x00000180 +wm 32 0x4004821c 0x00000180 + +/* ======================= DDR Controller =======================*/ + +CHECKPOINT(5) +wm 32 0x400ae000 0x00000600 +wm 32 0x400ae008 0x00000005 +wm 32 0x400ae028 0x00013880 +wm 32 0x400ae02c 0x00030d40 +wm 32 0x400ae030 0x00000506 +wm 32 0x400ae034 0x06040400 +wm 32 0x400ae038 0x1006040e +wm 32 0x400ae040 0x04040000 +wm 32 0x400ae044 0x006db00c +wm 32 0x400ae048 0x00000403 +wm 32 0x400ae050 0x01000000 +wm 32 0x400ae054 0x00060001 +wm 32 0x400ae058 0x000c0000 +wm 32 0x400ae05c 0x03000200 +wm 32 0x400ae060 0x00000006 +wm 32 0x400ae064 0x00010000 +wm 32 0x400ae068 0x0c300068 +wm 32 0x400ae070 0x00000000 +wm 32 0x400ae074 0x00000003 +wm 32 0x400ae078 0x0000000a +wm 32 0x400ae07c 0x006c0200 +wm 32 0x400ae084 0x00010000 +wm 32 0x400ae088 0x00050500 +wm 32 0x400ae098 0x00000000 +wm 32 0x400ae09c 0x04001002 +wm 32 0x400ae0a4 0x00000001 +wm 32 0x400ae0c0 0x00460420 +wm 32 0x400ae0c4 0x00000000 +wm 32 0x400ae0cc 0x00000000 +wm 32 0x400ae0e4 0x02000000 +wm 32 0x400ae108 0x01000200 +wm 32 0x400ae10c 0x00000040 +wm 32 0x400ae114 0x00000200 +wm 32 0x400ae118 0x00000040 +wm 32 0x400ae120 0x00000000 +wm 32 0x400ae124 0x0a010100 +wm 32 0x400ae128 0x01014040 +wm 32 0x400ae12c 0x01010101 +wm 32 0x400ae130 0x03030000 +wm 32 0x400ae134 0x01000101 +wm 32 0x400ae138 0x0700000c +wm 32 0x400ae13c 0x00000000 +wm 32 0x400ae148 0x10000000 +wm 32 0x400ae15c 0x01000000 +wm 32 0x400ae160 0x00040000 +wm 32 0x400ae164 0x00000002 +wm 32 0x400ae16c 0x00020000 +wm 32 0x400ae180 0x00002819 +wm 32 0x400ae184 0x01000000 +wm 32 0x400ae188 0x00000000 +wm 32 0x400ae18c 0x00000000 +wm 32 0x400ae198 0x00000000 +wm 32 0x400ae1a4 0x00000c00 +wm 32 0x400ae1a8 0x00000000 +wm 32 0x400ae1b8 0x0000000c +wm 32 0x400ae1c8 0x00000000 +wm 32 0x400ae1cc 0x00000000 +wm 32 0x400ae1d4 0x00000000 +wm 32 0x400ae1d8 0x01010000 +wm 32 0x400ae1e0 0x02020000 +wm 32 0x400ae1e4 0x00000202 +wm 32 0x400ae1e8 0x01010064 +wm 32 0x400ae1ec 0x00010101 +wm 32 0x400ae1f0 0x00000064 +wm 32 0x400ae1f8 0x00000800 +wm 32 0x400ae210 0x00000506 +wm 32 0x400ae224 0x00020000 +wm 32 0x400ae228 0x01000000 +wm 32 0x400ae22c 0x04070303 +wm 32 0x400ae230 0x00000040 +wm 32 0x400ae23c 0x06000080 +wm 32 0x400ae240 0x04070303 +wm 32 0x400ae244 0x00000040 +wm 32 0x400ae248 0x00000040 +wm 32 0x400ae24c 0x000f0000 +wm 32 0x400ae250 0x000f0000 +wm 32 0x400ae25c 0x00000101 +wm 32 0x400ae268 0x682c4000 +wm 32 0x400ae26c 0x00000012 +wm 32 0x400ae278 0x00000006 +wm 32 0x400ae284 0x00010202 + +/* ======================= DDR PHY =======================*/ + +CHECKPOINT(6) + +wm 32 0x400ae400 0x00002613 +wm 32 0x400ae440 0x00002613 +wm 32 0x400ae480 0x00002613 +wm 32 0x400ae404 0x00002615 +wm 32 0x400ae444 0x00002615 +wm 32 0x400ae408 0x00210000 +wm 32 0x400ae448 0x00210000 +wm 32 0x400ae488 0x00210000 +wm 32 0x400ae40c 0x0001012a +wm 32 0x400ae44c 0x0001012a +wm 32 0x400ae48c 0x0001012a +wm 32 0x400ae410 0x00002000 +wm 32 0x400ae450 0x00002000 +wm 32 0x400ae490 0x00002000 +wm 32 0x400ae4c4 0x00000000 +wm 32 0x400ae4c8 0x00001100 +wm 32 0x400ae4d0 0x00010101 +wm 32 0x400ae000 0x00000601 + +CHECKPOINT(7) + +check 32 while_any_bit_clear 0x400ae140 0x100 +# check 32 while_any_bit_clear 0x400ae42c 0x1 +# check 32 while_any_bit_clear 0x400ae46c 0x1 +# check 32 while_any_bit_clear 0x400ae4ac 0x1 + +CHECKPOINT(8) + +wm 32 0x80000000 0xa5a5a5a5 +check 32 while_any_bit_clear 0x80000000 0xa5a5a5a5 + +wm 32 0x400ae000 0x00000600 +wm 32 0x400ae000 0x00000601 + +check 32 while_any_bit_clear 0x400ae140 0x100 +# check 32 while_any_bit_clear 0x400ae42c 0x1 +# check 32 while_any_bit_clear 0x400ae46c 0x1 +# check 32 while_any_bit_clear 0x400ae4ac 0x1 + +/* wm 32 0x3f040000 0xf0 + check 32 while_any_bit_clear 0x3f040000 0x0f */ + + +CHECKPOINT(9) diff --git a/arch/arm/boards/zii-vf610-dev/lowlevel.c b/arch/arm/boards/zii-vf610-dev/lowlevel.c new file mode 100644 index 0000000..95b68d5 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/lowlevel.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2016 Zodiac Inflight Innovation + * Author: Andrey Smirnov + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline void setup_uart(void) +{ + void __iomem *iomux = IOMEM(VF610_IOMUXC_BASE_ADDR); + + vf610_ungate_all_peripherals(); + vf610_setup_pad(iomux, VF610_PAD_PTB10__UART0_TX); + vf610_uart_setup_ll(); + + putc_ll('>'); +} + +enum zii_platform_vf610_type { + ZII_PLATFORM_VF610_DEV_REV_B = 0x01, + ZII_PLATFORM_VF610_SCU4_AIB = 0x02, + ZII_PLATFORM_VF610_SPU3 = 0x03, + ZII_PLATFORM_VF610_CFU1 = 0x04, + ZII_PLATFORM_VF610_DEV_REV_C = 0x05, +}; + +unsigned int get_system_type(void) +{ +#define GPIO_PDIR 0x10 + + u32 pdir; + void __iomem *gpio2 = IOMEM(VF610_GPIO2_BASE_ADDR); + void __iomem *iomux = IOMEM(VF610_IOMUXC_BASE_ADDR); + unsigned low, high; + + /* + * System type is encoded as a 4-bit number specified by the + * following pins (pulled up or down with resistors on the + * board). + */ + vf610_setup_pad(iomux, VF610_PAD_PTD16__GPIO_78); + vf610_setup_pad(iomux, VF610_PAD_PTD17__GPIO_77); + vf610_setup_pad(iomux, VF610_PAD_PTD18__GPIO_76); + vf610_setup_pad(iomux, VF610_PAD_PTD19__GPIO_75); + + pdir = readl(gpio2 + GPIO_PDIR); + + low = 75 % 32; + high = 78 % 32; + + pdir &= GENMASK(high, low); + pdir >>= low; + + return pdir; +} + +extern char __dtb_vf610_zii_dev_rev_b_start[]; +extern char __dtb_vf610_zii_dev_rev_c_start[]; +extern char __dtb_vf610_zii_cfu1_rev_a_start[]; +extern char __dtb_vf610_zii_spu3_rev_a_start[]; +extern char __dtb_vf610_zii_scu4_aib_rev_c_start[]; + +ENTRY_FUNCTION(start_zii_vf610_dev, r0, r1, r2) +{ + void *fdt; + const unsigned int system_type = get_system_type(); + + vf610_cpu_lowlevel_init(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) + setup_uart(); + + switch (system_type) { + default: + /* + * GCC can be smart enough to, when DEBUG_LL is + * disabled, reduce this switch statement to a LUT + * fetch. Unfortunately here, this early in the boot + * process before any relocation/address fixups could + * happen, the address of that LUT used by the code is + * incorrect and any access to it would result in + * bogus values. + * + * Adding the following barrier() statement seem to + * force the compiler to always translate this block + * to a sequence of consecutive checks and jumps with + * relative fetches, which should work with or without + * relocation/fixups. + */ + barrier(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) { + relocate_to_current_adr(); + setup_c(); + puts_ll("*********************************\n"); + puts_ll("* Unknown system type: "); + puthex_ll(system_type); + puts_ll("\n* Assuming devboard revision B\n"); + puts_ll("*********************************\n"); + } + case ZII_PLATFORM_VF610_DEV_REV_B: /* FALLTHROUGH */ + fdt = __dtb_vf610_zii_dev_rev_b_start; + break; + case ZII_PLATFORM_VF610_SCU4_AIB: + fdt = __dtb_vf610_zii_scu4_aib_rev_c_start; + break; + case ZII_PLATFORM_VF610_DEV_REV_C: + fdt = __dtb_vf610_zii_dev_rev_c_start; + break; + case ZII_PLATFORM_VF610_CFU1: + fdt = __dtb_vf610_zii_cfu1_rev_a_start; + break; + case ZII_PLATFORM_VF610_SPU3: + fdt = __dtb_vf610_zii_spu3_rev_a_start; + break; + } + + barebox_arm_entry(0x80000000, SZ_512M, fdt - get_runtime_offset()); +} diff --git a/arch/arm/configs/zii_vf610_dev_defconfig b/arch/arm/configs/zii_vf610_dev_defconfig new file mode 100644 index 0000000..bda6044 --- /dev/null +++ b/arch/arm/configs/zii_vf610_dev_defconfig @@ -0,0 +1,165 @@ +CONFIG_ARCH_IMX=y +CONFIG_IMX_MULTI_BOARDS=y +CONFIG_MACH_SABRESD=y +CONFIG_MACH_ZII_VF610_DEV=y +CONFIG_IMX_IIM=y +CONFIG_IMX_IIM_FUSE_BLOW=y +CONFIG_THUMB2_BAREBOX=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_ARM_UNWIND=y +CONFIG_MMU=y +CONFIG_TEXT_BASE=0x0 +CONFIG_MALLOC_SIZE=0x0 +CONFIG_MALLOC_TLSF=y +CONFIG_KALLSYMS=y +CONFIG_RELOCATABLE=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_BOOTM_OFTREE=y +CONFIG_BOOTM_OFTREE_UIMAGE=y +CONFIG_BLSPEC=y +CONFIG_PARTITION_DISK_EFI=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y +CONFIG_RESET_SOURCE=y +CONFIG_CMD_DMESG=y +CONFIG_LONGHELP=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_IMD=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_ARM_MMUINFO=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_MMC_EXTCSD=y +# CONFIG_CMD_BOOTU is not set +CONFIG_CMD_GO=y +CONFIG_CMD_RESET=y +CONFIG_CMD_UIMAGE=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_UBIFORMAT=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_MAGICVAR=y +CONFIG_CMD_MAGICVAR_HELP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_FILETYPE=y +CONFIG_CMD_LN=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_LET=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_READF=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_PING=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_MENUTREE=y +CONFIG_CMD_SPLASH=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MM=y +CONFIG_CMD_CLK=y +CONFIG_CMD_DETECT=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_LED=y +CONFIG_CMD_NANDTEST=y +CONFIG_CMD_SPI=y +CONFIG_CMD_LED_TRIGGER=y +CONFIG_CMD_USBGADGET=y +CONFIG_CMD_WD=y +CONFIG_CMD_BAREBOX_UPDATE=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_TIME=y +CONFIG_NET=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_OF_BAREBOX_DRIVERS=y +CONFIG_DRIVER_NET_FEC_IMX=y +CONFIG_AT803X_PHY=y +CONFIG_MICREL_PHY=y +CONFIG_NET_USB=y +CONFIG_NET_USB_ASIX=y +CONFIG_NET_USB_SMSC95XX=y +CONFIG_DRIVER_SPI_IMX=y +CONFIG_DRIVER_SPI_DSPI=y +CONFIG_I2C=y +CONFIG_I2C_IMX=y +CONFIG_MTD=y +CONFIG_MTD_RAW_DEVICE=y +CONFIG_MTD_DATAFLASH=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_SST25L=y +CONFIG_NAND=y +CONFIG_NAND_ALLOW_ERASE_BAD=y +CONFIG_NAND_IMX=y +CONFIG_NAND_IMX_BBM=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_DISK_AHCI=y +CONFIG_DISK_AHCI_IMX=y +CONFIG_DISK_INTF_PLATFORM_IDE=y +CONFIG_DISK_PATA_IMX=y +CONFIG_USB_HOST=y +CONFIG_USB_IMX_CHIPIDEA=y +CONFIG_USB_EHCI=y +CONFIG_USB_ULPI=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DFU=y +CONFIG_USB_GADGET_SERIAL=y +CONFIG_USB_GADGET_FASTBOOT=y +CONFIG_VIDEO=y +CONFIG_DRIVER_VIDEO_IMX_IPUV3=y +CONFIG_DRIVER_VIDEO_IMX_IPUV3_LVDS=y +CONFIG_DRIVER_VIDEO_IMX_IPUV3_HDMI=y +CONFIG_DRIVER_VIDEO_SIMPLEFB=y +CONFIG_DRIVER_VIDEO_EDID=y +CONFIG_MCI=y +CONFIG_MCI_MMC_BOOT_PARTITIONS=y +CONFIG_MCI_IMX_ESDHC=y +CONFIG_MFD_MC13XXX=y +CONFIG_MFD_MC34704=y +CONFIG_MFD_MC9SDZ60=y +CONFIG_MFD_STMPE=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_GPIO_OF=y +CONFIG_LED_TRIGGERS=y +CONFIG_EEPROM_AT25=y +CONFIG_EEPROM_AT24=y +CONFIG_KEYBOARD_GPIO=y +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_IMX=y +CONFIG_PWM=y +CONFIG_PWM_IMX=y +CONFIG_GPIO_STMPE=y +CONFIG_GPIO_SX150X=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED=y +CONFIG_GENERIC_PHY=y +CONFIG_USB_NOP_XCEIV=y +CONFIG_FS_EXT4=y +CONFIG_FS_TFTP=y +CONFIG_FS_NFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y +CONFIG_FS_UBIFS=y +CONFIG_FS_UBIFS_COMPRESSION_LZO=y +CONFIG_PNG=y diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index d8cb187..13b4f95 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -34,6 +34,10 @@ obj-y += no-mmu.o endif +obj-$(CONFIG_ARM_PSCI) += psci.o +obj-$(CONFIG_ARM_SECURE_MONITOR) += smccc-call.o +obj-$(CONFIG_ARM_SECURE_MONITOR) += sm.o sm_as.o + obj-$(CONFIG_CPU_32v4T) += cache-armv4.o pbl-$(CONFIG_CPU_32v4T) += cache-armv4.o obj-$(CONFIG_CPU_32v5) += cache-armv5.o diff --git a/arch/arm/cpu/psci.c b/arch/arm/cpu/psci.c new file mode 100644 index 0000000..d650c23 --- /dev/null +++ b/arch/arm/cpu/psci.c @@ -0,0 +1,311 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2. + * + * 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. + */ + +#define pr_fmt(fmt) "psci: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARM_PSCI_DEBUG + +/* + * PSCI debugging functions. Board code can specify a putc() function + * which is used for debugging output. Beware that this function is + * called while the kernel is running. This means the kernel could have + * turned off clocks, configured other baudrates and other stuff that + * might confuse the putc function. So it can well be that the debugging + * code itself is the problem when somethings not working. You have been + * warned. + */ + +static void (*__putc)(void *ctx, int c); +static void *putc_ctx; + +void psci_set_putc(void (*putcf)(void *ctx, int c), void *ctx) +{ + __putc = putcf; + putc_ctx = ctx; +} + +void psci_putc(char c) +{ + if (__putc) + __putc(putc_ctx, c); +} + +int psci_puts(const char *str) +{ + int n = 0; + + while (*str) { + if (*str == '\n') + psci_putc('\r'); + + psci_putc(*str); + str++; + n++; + } + + return n; +} + +int psci_printf(const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[128]; + + va_start(args, fmt); + i = vsprintf(printbuffer, fmt, args); + va_end(args); + + psci_puts(printbuffer); + + return i; +} +#endif + +static struct psci_ops *psci_ops; + +void psci_set_ops(struct psci_ops *ops) +{ + psci_ops = ops; +} + +static unsigned long psci_version(void) +{ + psci_printf("%s\n", __func__); + return ARM_PSCI_VER_1_0; +} + +static unsigned long psci_cpu_suspend(u32 power_state, unsigned long entry, + u32 context_id) +{ + psci_printf("%s\n", __func__); + + if (psci_ops->cpu_off) + return psci_ops->cpu_suspend(power_state, entry, context_id); + + return ARM_PSCI_RET_NOT_SUPPORTED; +} + +static unsigned long psci_cpu_off(void) +{ + psci_printf("%s\n", __func__); + + if (psci_ops->cpu_off) + return psci_ops->cpu_off(); + + return ARM_PSCI_RET_NOT_SUPPORTED; +} + +static unsigned long cpu_entry[ARM_SECURE_MAX_CPU]; +static unsigned long context[ARM_SECURE_MAX_CPU]; + +static unsigned long psci_cpu_on(u32 cpu_id, unsigned long entry, u32 context_id) +{ + psci_printf("%s: %d 0x%08lx\n", __func__, cpu_id, entry); + + if (cpu_id >= ARM_SECURE_MAX_CPU) + return ARM_PSCI_RET_INVAL; + + cpu_entry[cpu_id] = entry; + context[cpu_id] = context_id; + dsb(); + + if (psci_ops->cpu_on) + return psci_ops->cpu_on(cpu_id); + + return ARM_PSCI_RET_NOT_SUPPORTED; +} + +static unsigned long psci_system_off(void) +{ + psci_printf("%s\n", __func__); + + if (psci_ops->system_reset) + psci_ops->system_reset(); + + while(1); + + return 0; +} + +static unsigned long psci_system_reset(void) +{ + psci_printf("%s\n", __func__); + + if (psci_ops->system_reset) + psci_ops->system_reset(); + + restart_machine(); +} + +void psci_entry(u32 r0, u32 r1, u32 r2, u32 r3, u32 r4, u32 r5, u32 r6, + struct arm_smccc_res *res) +{ + int mmuon; + unsigned long ttb; + + mmuon = get_cr() & CR_M; + asm volatile ("mrc p15, 0, %0, c2, c0, 0" : "=r"(ttb)); + + psci_printf("%s entry, function: 0x%08x\n", __func__, r0); + + switch (r0) { + case ARM_PSCI_0_2_FN_PSCI_VERSION: + res->a0 = psci_version(); + break; + case ARM_PSCI_0_2_FN_CPU_SUSPEND: + res->a0 = psci_cpu_suspend(r1, r2, r3); + break; + case ARM_PSCI_0_2_FN_CPU_OFF: + res->a0 = psci_cpu_off(); + break; + case ARM_PSCI_0_2_FN_CPU_ON: + res->a0 = psci_cpu_on(r1, r2, r3); + break; + case ARM_PSCI_0_2_FN_SYSTEM_OFF: + psci_system_off(); + break; + case ARM_PSCI_0_2_FN_SYSTEM_RESET: + psci_system_reset(); + break; + default: + res->a0 = ARM_PSCI_RET_NOT_SUPPORTED; + break; + } +} + +static int of_psci_fixup(struct device_node *root, void *unused) +{ + struct device_node *psci; + int ret; + + if (bootm_arm_security_state() < ARM_STATE_NONSECURE) + return 0; + + psci = of_create_node(root, "/psci"); + if (!psci) + return -EINVAL; + + ret = of_set_property(psci, "compatible", "arm,psci-1.0", + strlen("arm,psci-1.0") + 1, 1); + if (ret) + return ret; + + ret = of_set_property(psci, "method", "smc", + strlen("smc") + 1, 1); + if (ret) + return ret; + + return 0; +} + +int psci_cpu_entry_c(void) +{ + void (*entry)(u32 context); + int cpu; + u32 context_id; + + __armv7_secure_monitor_install(); + cpu = psci_get_cpu_id(); + entry = (void *)cpu_entry[cpu]; + context_id = context[cpu]; + + if (bootm_arm_security_state() == ARM_STATE_HYP) + armv7_switch_to_hyp(); + + psci_printf("core #%d enter function 0x%p\n", cpu, entry); + + entry(context_id); + + while (1); +} + +static int armv7_psci_init(void) +{ + return of_register_fixup(of_psci_fixup, NULL); +} +device_initcall(armv7_psci_init); + +#ifdef DEBUG + +#include +#include +#include "mmu.h" + +void second_entry(void) +{ + struct arm_smccc_res res; + + psci_printf("2nd CPU online, now turn off again\n"); + + arm_smccc_smc(ARM_PSCI_0_2_FN_CPU_OFF, + 0, 0, 0, 0, 0, 0, 0, &res); + + psci_printf("2nd CPU still alive?\n"); + + while (1); +} + +static int do_smc(int argc, char *argv[]) +{ + int opt; + struct arm_smccc_res res = { + .a0 = 0xdeadbee0, + .a1 = 0xdeadbee1, + .a2 = 0xdeadbee2, + .a3 = 0xdeadbee3, + }; + + while ((opt = getopt(argc, argv, "nicz")) > 0) { + switch (opt) { + case 'n': + armv7_secure_monitor_install(); + break; + case 'i': + arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, + 0, 0, 0, 0, 0, 0, 0, &res); + printf("found psci version %ld.%ld\n", res.a0 >> 16, res.a0 & 0xffff); + break; + case 'c': + arm_smccc_smc(ARM_PSCI_0_2_FN_CPU_ON, + 1, (unsigned long)second_entry, 0, 0, 0, 0, 0, &res); + break; + } + } + + + return 0; +} +BAREBOX_CMD_HELP_START(smc) +BAREBOX_CMD_HELP_TEXT("Secure monitor code test command") +BAREBOX_CMD_HELP_TEXT("") +BAREBOX_CMD_HELP_TEXT("Options:") +BAREBOX_CMD_HELP_OPT ("-n", "Install secure monitor and switch to nonsecure mode") +BAREBOX_CMD_HELP_OPT ("-i", "Show information about installed PSCI version") +BAREBOX_CMD_HELP_OPT ("-c", "Start secondary CPU core") +BAREBOX_CMD_HELP_OPT ("-z", "Turn off secondary CPU core") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(smc) + .cmd = do_smc, + BAREBOX_CMD_DESC("secure monitor test command") +BAREBOX_CMD_END +#endif \ No newline at end of file diff --git a/arch/arm/cpu/sm.c b/arch/arm/cpu/sm.c new file mode 100644 index 0000000..5808dfd --- /dev/null +++ b/arch/arm/cpu/sm.c @@ -0,0 +1,266 @@ +/* + * (C) Copyright 2013 + * Andre Przywara, Linaro + * + * Routines to transition ARMv7 processors from secure into non-secure state + * and from non-secure SVC into HYP mode + * needed to enable ARMv7 virtualization for current hypervisors + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#define pr_fmt(fmt) "secure: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmu.h" + +/* valid bits in CBAR register / PERIPHBASE value */ +#define CBAR_MASK 0xFFFF8000 + +static unsigned int read_id_pfr1(void) +{ + unsigned int reg; + + asm("mrc p15, 0, %0, c0, c1, 1\n" : "=r"(reg)); + return reg; +} + +static u32 read_nsacr(void) +{ + unsigned int reg; + + asm("mrc p15, 0, %0, c1, c1, 2\n" : "=r"(reg)); + return reg; +} + +static void write_nsacr(u32 val) +{ + asm("mcr p15, 0, %0, c1, c1, 2" : : "r"(val)); +} + +static void write_mvbar(u32 val) +{ + asm("mcr p15, 0, %0, c12, c0, 1" : : "r"(val)); +} + +static unsigned long get_cbar(void) +{ + unsigned periphbase; + + /* get the GIC base address from the CBAR register */ + asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase)); + + /* the PERIPHBASE can be mapped above 4 GB (lower 8 bits used to + * encode this). Bail out here since we cannot access this without + * enabling paging. + */ + if ((periphbase & 0xff) != 0) { + pr_err("PERIPHBASE is above 4 GB, no access.\n"); + return -1; + } + + return periphbase & CBAR_MASK; +} + +static unsigned long get_gicd_base_address(void) +{ + return get_cbar() + GIC_DIST_OFFSET; +} + +static int cpu_is_virt_capable(void) +{ + return read_id_pfr1() & (1 << 12); +} + +static unsigned long get_gicc_base_address(void) +{ + unsigned long adr = get_cbar(); + + if (cpu_is_virt_capable()) + adr += GIC_CPU_OFFSET_A15; + else + adr += GIC_CPU_OFFSET_A9; + + return adr; +} + +#define GICD_IGROUPRn 0x0080 + +int armv7_init_nonsec(void) +{ + void __iomem *gicd = IOMEM(get_gicd_base_address()); + unsigned itlinesnr, i; + u32 val; + + /* + * the SCR register will be set directly in the monitor mode handler, + * according to the spec one should not tinker with it in secure state + * in SVC mode. Do not try to read it once in non-secure state, + * any access to it will trap. + */ + + /* enable the GIC distributor */ + val = readl(gicd + GICD_CTLR); + val |= 0x3; + writel(val, gicd + GICD_CTLR); + + /* TYPER[4:0] contains an encoded number of available interrupts */ + itlinesnr = readl(gicd + GICD_TYPER) & 0x1f; + + /* + * Set all bits in the GIC group registers to one to allow access + * from non-secure state. The first 32 interrupts are private per + * CPU and will be set later when enabling the GIC for each core + */ + for (i = 1; i <= itlinesnr; i++) + writel(0xffffffff, gicd + GICD_IGROUPRn + 4 * i); + + return 0; +} + +/* + * armv7_secure_monitor_install - install secure monitor + * + * This function is entered in secure mode. It installs the secure + * monitor code and enters it using a smc call. This function is executed + * on every CPU. We leave this function returns in nonsecure mode. + */ +int __armv7_secure_monitor_install(void) +{ + struct arm_smccc_res res; + void __iomem *gicd = IOMEM(get_gicd_base_address()); + void __iomem *gicc = IOMEM(get_gicc_base_address()); + u32 nsacr; + + writel(0xffffffff, gicd + GICD_IGROUPRn); + + writel(0x3, gicc + GICC_CTLR); + writel(0xff, gicc + GICC_PMR); + + nsacr = read_nsacr(); + nsacr |= 0x00043fff; /* all copros allowed in non-secure mode */ + write_nsacr(nsacr); + + write_mvbar((unsigned long)secure_monitor_init_vectors); + + isb(); + + /* Initialize the secure monitor */ + arm_smccc_smc(0, 0, 0, 0, 0, 0, 0, 0, &res); + + /* We're in nonsecure mode now */ + + return 0; +} + +static bool armv7_have_security_extensions(void) +{ + return (read_id_pfr1() & 0xf0) != 0; +} + +/* + * armv7_secure_monitor_install - install secure monitor + * + * This function is entered in secure mode. It installs the secure + * monitor code and enters it using a smc call. This function is executed + * once on the primary CPU only. We leave this function returns in nonsecure + * mode. + */ +int armv7_secure_monitor_install(void) +{ + int mmuon; + unsigned long ttb, vbar; + + if (!armv7_have_security_extensions()) { + pr_err("Security extensions not implemented.\n"); + return -EINVAL; + } + + mmuon = get_cr() & CR_M; + + vbar = get_vbar(); + + asm volatile ("mrc p15, 0, %0, c2, c0, 0" : "=r"(ttb)); + + armv7_init_nonsec(); + __armv7_secure_monitor_install(); + + asm volatile ("mcr p15, 0, %0, c2, c0, 0" : : "r"(ttb)); + + set_vbar(vbar); + + if (mmuon) { + /* + * If the MMU was already turned on in secure mode, enable it in + * non-secure mode aswell + */ + __mmu_cache_on(); + } + + pr_debug("Initialized secure monitor\n"); + + return 0; +} + +/* + * of_secure_monitor_fixup - reserve memory region for secure monitor + * + * We currently do not support putting the secure monitor into onchip RAM, + * hence it runs in SDRAM and we must reserve the memory region so that we + * won't get overwritten from the Kernel. + * Beware: despite the name this is not secure in any way. The Kernel obeys + * the reserve map, but only because it's nice. It could always overwrite the + * secure monitor and hijack secure mode. + */ +static int of_secure_monitor_fixup(struct device_node *root, void *unused) +{ + unsigned long res_start, res_end; + + res_start = (unsigned long)_stext; + res_end = (unsigned long)__bss_stop; + + of_add_reserve_entry(res_start, res_end); + + pr_debug("Reserved memory range from 0x%08lx to 0x%08lx\n", res_start, res_end); + + return 0; +} + +static enum arm_security_state bootm_secure_state; + +static const char * const bootm_secure_state_names[] = { + [ARM_STATE_SECURE] = "secure", + [ARM_STATE_NONSECURE] = "nonsecure", + [ARM_STATE_HYP] = "hyp", +}; + +enum arm_security_state bootm_arm_security_state(void) +{ + return bootm_secure_state; +} + +const char *bootm_arm_security_state_name(enum arm_security_state state) +{ + return bootm_secure_state_names[state]; +} + +static int sm_init(void) +{ + of_register_fixup(of_secure_monitor_fixup, NULL); + + globalvar_add_simple_enum("bootm.secure_state", + (unsigned int *)&bootm_secure_state, + bootm_secure_state_names, + ARRAY_SIZE(bootm_secure_state_names)); + + return 0; +} +device_initcall(sm_init); \ No newline at end of file diff --git a/arch/arm/cpu/sm_as.S b/arch/arm/cpu/sm_as.S new file mode 100644 index 0000000..09580e7 --- /dev/null +++ b/arch/arm/cpu/sm_as.S @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include + +.arch_extension sec +.arch_extension virt + + .section ".text","ax" + .arm + + .align 5 +.globl secure_monitor_init_vectors +secure_monitor_init_vectors: +1: b 1b /* reset */ +1: b 1b /* undefined instruction */ + b secure_monitor_init /* software interrupt (SWI) */ +1: b 1b /* prefetch abort */ +1: b 1b /* data abort */ +1: b 1b /* (reserved) */ +1: b 1b /* irq (interrupt) */ +1: b 1b /* fiq (fast interrupt) */ + +#define CPUID_ARM_GENTIMER_MASK (0xF << CPUID_ARM_GENTIMER_SHIFT) +#define CPUID_ARM_GENTIMER_SHIFT 16 + +#define CPUID_ARM_VIRT_MASK (0xF << CPUID_ARM_VIRT_SHIFT) +#define CPUID_ARM_VIRT_SHIFT 12 + +.macro is_cpu_virt_capable tmp + mrc p15, 0, \tmp, c0, c1, 1 @ read ID_PFR1 + and \tmp, \tmp, #CPUID_ARM_VIRT_MASK @ mask virtualization bits + cmp \tmp, #(1 << CPUID_ARM_VIRT_SHIFT) +.endm + +@ Requires dense and single-cluster CPU ID space +ENTRY(psci_get_cpu_id) + mrc p15, 0, r0, c0, c0, 5 /* read MPIDR */ + and r0, r0, #0xff /* return CPU ID in cluster */ + bx lr +ENDPROC(psci_get_cpu_id) + +ENTRY(secure_monitor_stack_setup) + mrc p15, 0, r0, c0, c0, 5 /* read MPIDR */ + and r0, r0, #0xff /* CPU ID => r0 */ + + @ stack top = __secure_stack_end - (cpuid << ARM_PSCI_STACK_SHIFT) + ldr r1, =__secure_stack_end + sub r0, r1, r0, LSL #ARM_SECURE_STACK_SHIFT + sub r0, r0, #4 @ Save space for target PC + + mov sp, r0 + bx lr +ENDPROC(secure_monitor_stack_setup) + +secure_monitor_init: + mov r3, lr + + bl secure_monitor_stack_setup + + push {r4-r7} + mov r7, r3 + ldr r5, =secure_monitor_vectors @ Switch MVBAR to secure_monitor_vectors + mcr p15, 0, r5, c12, c0, 1 + isb + +#ifdef CONFIG_MMU + mrc p15, 0, r5, c1, c0, 0 + tst r5, #CR_M + beq 1f + bl __mmu_cache_off +1: +#endif + mrc p15, 0, r5, c1, c1, 0 @ read SCR + bic r5, r5, #0x4a @ clear IRQ, EA, nET bits + orr r5, r5, #0x31 @ enable NS, AW, FW bits + @ FIQ preserved for secure mode + mov r6, #SVC_MODE @ default mode is SVC + + is_cpu_virt_capable r4 + + orreq r5, r5, #0x100 @ allow HVC instruction + + mcr p15, 0, r5, c1, c1, 0 @ write SCR (with NS bit set) + isb + + mrceq p15, 0, r0, c12, c0, 1 @ get MVBAR value + mcreq p15, 4, r0, c12, c0, 0 @ write HVBAR + + bne 1f + + @ Reset CNTVOFF to 0 before leaving monitor mode + mrc p15, 0, r4, c0, c1, 1 @ read ID_PFR1 + ands r4, r4, #CPUID_ARM_GENTIMER_MASK @ test arch timer bits + movne r4, #0 + mcrrne p15, 4, r4, r4, c14 @ Reset CNTVOFF to zero +1: + mov lr, r7 + mov ip, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT) @ Set A, I and F + tst lr, #1 @ Check for Thumb PC + orrne ip, ip, #PSR_T_BIT @ Set T if Thumb + orr ip, ip, r6 @ Slot target mode in + msr spsr_cxfs, ip @ Set full SPSR + pop {r4-r7} + movs pc, lr @ ERET to non-secure + + .align 5 +secure_monitor_vectors: +1: b 1b /* reset */ +1: b 1b /* undefined instruction */ + b secure_monitor /* software interrupt (SWI) */ +1: b 1b /* prefetch abort */ +1: b 1b /* data abort */ +1: b hyp_trap /* (reserved) */ +1: b 1b /* irq (interrupt) */ +1: b 1b /* fiq (fast interrupt) */ + +secure_monitor: + push {r4-r7,lr} + + @ Switch to secure mode + mrc p15, 0, r7, c1, c1, 0 + bic r4, r7, #1 + mcr p15, 0, r4, c1, c1, 0 + isb + + /* r0-r6: Arguments */ + sub sp, sp, #4*4 @ allocate result structure on stack + mov r12, sp + push {r4-r6, r12} + bl psci_entry + pop {r4-r6, r12} + ldm r12, {r0-r3} + add sp, sp, #4*4 + /* r0-r3: results, r4-r14: preserved */ + + @ back to non-secure + mcr p15, 0, r7, c1, c1, 0 + + pop {r4-r7, lr} + movs pc, lr + +hyp_trap: + mrs lr, elr_hyp @ for older asm: .byte 0x00, 0xe3, 0x0e, 0xe1 + mov pc, lr @ do no switch modes, but + @ return to caller + +ENTRY(armv7_switch_to_hyp) + mov r0, lr + mov r1, sp @ save SVC copy of LR and SP + isb + hvc #0 @ for older asm: .byte 0x70, 0x00, 0x40, 0xe1 + mov sp, r1 + mov lr, r0 @ restore SVC copy of LR and SP + + bx lr +ENDPROC(armv7_switch_to_hyp) + +ENTRY(psci_cpu_entry) + mrc p15, 0, r0, c1, c0, 1 @ ACTLR + orr r0, r0, #(1 << 6) @ Set SMP bit + mcr p15, 0, r0, c1, c0, 1 @ ACTLR + + bl secure_monitor_stack_setup + bl psci_cpu_entry_c + +ENDPROC(psci_cpu_entry) diff --git a/arch/arm/cpu/smccc-call.S b/arch/arm/cpu/smccc-call.S new file mode 100644 index 0000000..c2781b1 --- /dev/null +++ b/arch/arm/cpu/smccc-call.S @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, Linaro Limited + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 + + .arch_extension sec + .arch_extension virt + .arm + + /* + * Wrap c macros in asm macros to delay expansion until after the + * SMCCC asm macro is expanded. + */ + .macro SMCCC_SMC + smc #0 + .endm + + .macro SMCCC_HVC + hvc #0 + .endm + + .macro SMCCC instr +UNWIND( .fnstart) + mov r12, sp + push {r4-r7} +UNWIND( .save {r4-r7}) + ldm r12, {r4-r7} + \instr + pop {r4-r7} + ldr r12, [sp, #(4 * 4)] + stm r12, {r0-r3} + bx lr +UNWIND( .fnend) + .endm + +/* + * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, + * unsigned long a3, unsigned long a4, unsigned long a5, + * unsigned long a6, unsigned long a7, struct arm_smccc_res *res) + */ +ENTRY(arm_smccc_smc) + SMCCC SMCCC_SMC +ENDPROC(arm_smccc_smc) + +/* + * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, + * unsigned long a3, unsigned long a4, unsigned long a5, + * unsigned long a6, unsigned long a7, struct arm_smccc_res *res) + */ +ENTRY(arm_smccc_hvc) + SMCCC SMCCC_HVC +ENDPROC(arm_smccc_hvc) diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 8ba9957..70359d8 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -79,6 +79,15 @@ 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_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 +pbl-dtb-$(CONFIG_MACH_ZII_RDU2) += imx6q-zii-rdu2.dtb.o imx6qp-zii-rdu2.dtb.o +pbl-dtb-$(CONFIG_MACH_ZII_VF610_DEV) += \ + vf610-zii-dev-rev-b.dtb.o \ + vf610-zii-dev-rev-c.dtb.o \ + vf610-zii-cfu1-rev-a.dtb.o \ + vf610-zii-spu3-rev-a.dtb.o \ + vf610-zii-scu4-aib-rev-c.dtb.o + clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.lzo diff --git a/arch/arm/dts/imx6q-zii-rdu2.dts b/arch/arm/dts/imx6q-zii-rdu2.dts new file mode 100644 index 0000000..db75e29 --- /dev/null +++ b/arch/arm/dts/imx6q-zii-rdu2.dts @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Zodiac Inflight Innovations + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include +#include "imx6q.dtsi" +#include "imx6qdl-zii-rdu2.dtsi" + +/ { + model = "ZII RDU2 Board"; + compatible = "zii,imx6q-zii-rdu2", "fsl,imx6q"; +}; diff --git a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi new file mode 100644 index 0000000..5b255e9 --- /dev/null +++ b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi @@ -0,0 +1,541 @@ +/* + * Copyright 2016 Zodiac Inflight Innovations + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +/ { + chosen { + linux,stdout-path = &uart1; + + environment@0 { + compatible = "barebox,environment"; + device-path = &nor_flash, "partname:barebox-environment"; + }; + }; + + mdio { + compatible = "virtual,mdio-gpio"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mdio1>; + gpios = <&gpio6 5 GPIO_ACTIVE_HIGH + &gpio6 4 GPIO_ACTIVE_HIGH>; + }; + + reg_28p0v: 28p0v { + /* main power in */ + compatible = "regulator-fixed"; + regulator-name = "28P0V"; + regulator-min-microvolt = <28000000>; + regulator-max-microvolt = <28000000>; + regulator-always-on; + }; + + reg_12p0v: 12p0v { + /* main internal power */ + compatible = "regulator-fixed"; + vin-supply = <®_28p0v>; + regulator-name = "12P0V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + }; + + reg_12p0v_periph: 12p0vperiph { + compatible = "regulator-fixed"; + vin-supply = <®_28p0v>; + regulator-name = "12P0V-PERIPH"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + /* controlled via "environment processor" */ + regulator-always-on; + }; + + reg_5p0v_main: 5p0vmain { + compatible = "regulator-fixed"; + vin-supply = <®_12p0v>; + regulator-name = "5P0MAIN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + /* controlled via "environment processor" */ + regulator-always-on; + }; + + reg_usb_otg_vbus: regulator@0 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_otg_supply>; + vin-supply = <®_5p0v_main>; + regulator-name = "usb_otg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 22 GPIO_ACTIVE_LOW>; + startup-delay-us = <1000>; + }; + + reg_usb_h1_vbus: regulator@1 { + compatible = "regulator-fixed"; + vin-supply = <®_5p0v_main>; + regulator-name = "usb_h1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + + imx6qdl-sabresd { + pinctrl_hog: hoggrp { + fsl,pins = < + /* USB Charging Controller */ + MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0 /*USB_ATT_DETn*/ + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0 /*USB_EMULATION*/ + MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x1b0b0 /*USB_MODE1*/ + MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x1b0b0 /*USB_ALERTn*/ + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0 /*USB_PWR_CTRL_ENn*/ + MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x1b0b0 /*USB_MODE2*/ + + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13020 /*USB_OTG_ID*/ + + MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0 /*INT_TOUCH_N*/ + + /* DAC */ + MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0 /*DAC1_RESET*/ + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0 /*DAC2_RESET*/ + + /* Need to Place */ + MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x1b0b0 /*RMII_INTRPT*/ + MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x1b8b0 /*SD_CARD_RESET - Open Drain Output*/ + + /* Test Points */ + MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b0 /*TP20*/ + MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /*TP21*/ + MX6QDL_PAD_SD3_DAT6__GPIO6_IO18 0x1b0b0 /*TP22*/ + MX6QDL_PAD_SD3_DAT7__GPIO6_IO17 0x1b0b0 /*TP23*/ + MX6QDL_PAD_KEY_ROW2__GPIO4_IO11 0x1b0b0 /*TP19*/ + MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x1b0b0 /*TP26*/ + MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0 /*TP27*/ + MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x1b0b0 /*TP28*/ + MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /*TP29*/ + MX6QDL_PAD_NANDF_D7__GPIO2_IO07 0x1b0b0 /*TP30*/ + MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x1b0b0 /*TP25*/ + MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19 0x1b0b0 /*TP39*/ + MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 0x1b0b0 /*TP40*/ + MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x1b0b0 /*TP42*/ + MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b0b0 /*TP43*/ + MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x1b0b0 /*TP44*/ + MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x1b0b0 /*TP45*/ + MX6QDL_PAD_CSI0_DAT16__GPIO6_IO02 0x1b0b0 /*TP46*/ + MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x1b0b0 /*TP41*/ + + /* System Type */ + MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x1b0b0 /*SYS_TYPE_3*/ + MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x1b0b0 /*SYS_TYPE_2*/ + MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b0 /*SYS_TYPE_1*/ + MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0 /*SYS_TYPE_0*/ + + /* Boot Mode Selection Pins */ + MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x1b0b0 /*BT_CFG1_0*/ + MX6QDL_PAD_EIM_DA1__GPIO3_IO01 0x1b0b0 /*BT_CFG1_1*/ + MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x1b0b0 /*BT_CFG1_2*/ + MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x1b0b0 /*BT_CFG1_3*/ + MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x1b0b0 /*BT_CFG1_4*/ + MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x1b0b0 /*BT_CFG1_5*/ + MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x1b0b0 /*BT_CFG1_6*/ + MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x1b0b0 /*BT_CFG1_7*/ + + MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x1b0b0 /*BT_CFG2_0*/ + MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x1b0b0 /*BT_CFG2_1*/ + MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x1b0b0 /*BT_CFG2_2*/ + MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x1b0b0 /*BT_CFG2_3*/ + MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x1b0b0 /*BT_CFG2_4*/ + MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x1b0b0 /*BT_CFG2_5*/ + MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x1b0b0 /*BT_CFG2_6*/ + MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x1b0b0 /*BT_CFG2_7*/ + + MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b0 /*BT_CFG3_0*/ + MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b0 /*BT_CFG3_1*/ + MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b0 /*BT_CFG3_2*/ + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b0b0 /*BT_CFG3_3*/ + MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x1b0b0 /*BT_CFG3_4*/ + MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x1b0b0 /*BT_CFG3_5*/ + MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x1b0b0 /*BT_CFG3_6*/ + MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x1b0b0 /*BT_CFG3_7*/ + + MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x1b0b0 /*BT_CFG4_0*/ + MX6QDL_PAD_EIM_WAIT__GPIO5_IO00 0x1b0b0 /*BT_CFG4_1*/ + MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x1b0b0 /*BT_CFG4_2*/ + MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x1b0b0 /*BT_CFG4_3*/ + MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x1b0b0 /*BT_CFG4_4*/ + MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x1b0b0 /*BT_CFG4_5*/ + MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b0 /*BT_CFG4_7*/ + + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* HPA1_SDn */ + MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b0 /* HPA2_SDn */ + MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* RST_TOUCH# */ + MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b0b0 /* NFC_RESET */ + >; + }; + + pinctrl_usb_otg_supply: usbotggrp { + fsl,pins = < + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x40000038 + >; + }; + + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + /*MX6QDL_PAD_EIM_D17__GPIO3_IO17 0x1b0b0*/ + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 + /*MX6QDL_PAD_EIM_EB2__ECSPI1_SS0 0x100b1*/ + MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b1 + /*MX6QDL_PAD_KEY_COL2__ECSPI1_SS1 0x1b0b1 + MX6QDL_PAD_KEY_COL2__GPIO4_IO10*/ + >; + }; + + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0 + MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0 + MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 + MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0 + MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0 + MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0 + MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0 + + MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23 0x1b0b0 + >; + }; + + pinctrl_ssi2: ssi3grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0 + MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x130b0 + MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1 + MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c3_gpio: i2c3grp_gpio { + fsl,pins = < + MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b0b1 + MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b1 + >; + }; + + pinctrl_pcie: pciegrp { + fsl,pins = < + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 + MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1 + MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17069 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x17069 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17069 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17069 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17069 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17069 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17069 + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x17069 + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17069 + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17069 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17069 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17069 + >; + }; + + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 + MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059 + MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059 + MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059 + MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 + MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x1b0b1 + >; + }; + + pinctrl_mdio1: bitbangmdiogrp { + fsl,pins = < + /* Bitbang MDIO for DEB Switch */ + MX6QDL_PAD_CSI0_DAT19__GPIO6_IO05 0x1b030 /*SWITCH_MDC*/ + MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x18830 /*SWITCH_MDIO*/ + >; + }; + }; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; +}; + +&ecspi1 { + fsl,spi-num-chipselects = <1>; + cs-gpios = <&gpio2 30 0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + status = "okay"; + + nor_flash: m25p128@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p128"; + spi-max-frequency = <20000000>; + reg = <0>; + + partition@0 { + label = "barebox"; + reg = <0x0 0xc0000>; + }; + + partition@e0000 { + label = "barebox-environment"; + reg = <0xc0000 0x40000>; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; +}; + +&tempmon { + barebox,sensor-name = "TEMPMON"; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + lm75@48 { + compatible = "national,lm75"; + reg = <0x48>; + barebox,sensor-name = "Temp Sensor 1"; + }; + + rtc: ds1341@68 { + compatible = "dallas,ds1341"; + reg = <0x68>; + }; + + mx6_eeprom: at24@54 { + compatible = "at,24c128"; + pagesize = <32>; /* TODO: VERIFY PAGE SIZE */ + reg = <0x54>; + }; +}; + +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + scl-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + sda-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&ldb { + status = "okay"; + + lvds-channel@0 { + fsl,data-mapping = "spwg"; + fsl,data-width = <24>; + status = "okay"; + + display-timings { + native-mode = <&timing_innolux_10_1>; + timing_innolux_10_1: innolux_10_1 { + clock-frequency = <71100000>; + hactive = <1280>; + vactive = <800>; + hback-porch = <40>; + hfront-porch = <40>; + vback-porch = <10>; + vfront-porch = <3>; + hsync-len = <80>; + vsync-len = <10>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + reset-gpio = <&gpio7 12 0>; + status = "okay"; +}; + + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + bus-width = <4>; + cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + bus-width = <4>; + cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4>; + bus-width = <8>; + non-removable; + no-1-8-v; + status = "okay"; +}; + +&usbh1 { + vbus-supply = <®_usb_h1_vbus>; + status = "okay"; +}; + +&usbotg { + vbus-supply = <®_usb_otg_vbus>; + disable-over-current; + dr_mode = "otg"; + status = "okay"; +}; + +&sata { + status = "okay"; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rmii"; + phy-reset-gpios = <&gpio1 23 0>; + status = "okay"; + + fixed-link { + speed = <100>; + full-duplex; + }; +}; diff --git a/arch/arm/dts/imx6qp-zii-rdu2.dts b/arch/arm/dts/imx6qp-zii-rdu2.dts new file mode 100644 index 0000000..fcf2ee5 --- /dev/null +++ b/arch/arm/dts/imx6qp-zii-rdu2.dts @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Zodiac Inflight Innovations + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include +#include "imx6q.dtsi" +#include "imx6qdl-zii-rdu2.dtsi" + +/ { + model = "ZII RDU2+ Board"; + compatible = "zii,imx6qp-zii-rdu2", "fsl,imx6qp"; +}; diff --git a/arch/arm/dts/imx7s-warp.dts b/arch/arm/dts/imx7s-warp.dts new file mode 100644 index 0000000..a59823d --- /dev/null +++ b/arch/arm/dts/imx7s-warp.dts @@ -0,0 +1,62 @@ +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include "imx7s.dtsi" + +/ { + chosen { + stdout-path = &uart1; + + environment@0 { + compatible = "barebox,environment"; + device-path = &bareboxenv; + }; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x20000000>; + }; +}; + +&usdhc3 { + boot0-partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + barebox@0 { + label = "barebox"; + reg = <0x0 0x300000>; + }; + + bareboxenv: bareboxenv@300000 { + label = "bareboxenv"; + reg = <0x300000 0x0>; + }; + }; +}; + +/* +/* The watchdog pinctrl is attached to the wrong iomux controller in + * the upstream dts file. This can be removed once we pull in the + * corresponding fix from the upstream dts files. + */ +&wdog1 { + pinctrl-0 = <&pinctrl_wdog_lpsr>; +}; + +&iomuxc_lpsr { + pinctrl_wdog_lpsr: wdoggrp { + fsl,pins = < + MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B 0x74 + >; + }; +}; diff --git a/arch/arm/dts/imx7s.dtsi b/arch/arm/dts/imx7s.dtsi new file mode 100644 index 0000000..95c7907 --- /dev/null +++ b/arch/arm/dts/imx7s.dtsi @@ -0,0 +1,4 @@ +&gpt1 { + clocks = <&clks IMX7D_GPT1_ROOT_CLK>, + <&clks IMX7D_GPT1_ROOT_CLK>; +}; \ No newline at end of file diff --git a/arch/arm/dts/vf610-zii-cfu1-rev-a.dts b/arch/arm/dts/vf610-zii-cfu1-rev-a.dts new file mode 100644 index 0000000..4147d13 --- /dev/null +++ b/arch/arm/dts/vf610-zii-cfu1-rev-a.dts @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2015, 2016 Zodiac Inflight Innovations + * + * Based on an original 'vf610-twr.dts' which is Copyright 2015, + * Freescale Semiconductor, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + + +/dts-v1/; +#include "vf610-zii-dev.dtsi" + +/ { + model = "ZII VF610 CFU1 Switch Management Board"; + compatible = "zii,vf610cfu1-a", "zii,vf610dev", "fsl,vf610"; + + aliases { + /delete-property/ serial1; + /delete-property/ serial2; + }; + + gpio-leds { + debug { + gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>; + }; + + fail { + label = "zii_fail"; + gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; + default-state = "off"; + max-brightness = <1>; + }; + + status { + label = "zii_status"; + gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; + default-state = "off"; + max-brightness = <1>; + }; + + status_a { + label = "zii_status_a"; + gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>; + default-state = "off"; + max-brightness = <1>; + }; + + status_b { + label = "zii_status_b"; + gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>; + default-state = "on"; + max-brightness = <1>; + }; + }; +}; + +&dspi1 { + bus-num = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dspi1>; + status = "okay"; + + m25p128@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p128", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partition@0 { + label = "m25p128-0"; + reg = <0x0 0x01000000>; + }; + }; +}; + +&esdhc0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_esdhc0>; + bus-width = <8>; + status = "okay"; +}; + +&fec0 { + status = "disabled"; +}; + +&i2c0 { + clock-frequency = <400000>; + + pca9554@22 { + compatible = "nxp,pca9554"; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +/delete-node/ &i2c1; +/delete-node/ &i2c2; +/delete-node/ &uart1; +/delete-node/ &uart2; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + fsl,pins = < + VF610_PAD_PTE2__GPIO_107 0x31c2 /* SOC_SW_RSTn */ + VF610_PAD_PTB28__GPIO_98 0x31c1 /* E6352_INTn */ + + /* PTE27 is wired to signal SD on part CONN + * SFF-F4 via net FIM_DS. An active high + * on this indicates a received optical + * signal + + * SPEED=0b11 HIGH, SRE=0b0, ODE=0b0, HYS=0b0 + * DSE=0b001 150Ohm, PUS=0b10 100k UP + * PKE=0b0, PUE=0b0, OBE=0b0, IBE=0b1 + */ + VF610_PAD_PTE27__GPIO_132 0x3061 + + /* + * PTE13 is wired to signal T_DIS on part CONN + * SFF-F4 via net FIM_TDIS. Setting this high + * will disable optical output from the SFF-F4 + + * SPEED=0b11 HIGH, SRE=0b0, ODE=0b0, HYS=0b0 + * DSE=0b001 150Ohm, PUS=0b00 100k DOWN + * PKE=0b0, PUE=0b0, OBE=0b1, IBE=0b1 + * TODO: probably want IBE=0b0 + */ + VF610_PAD_PTE13__GPIO_118 0x3043 + >; + }; + + pinctrl_dspi1: dspi1grp { + fsl,pins = < + VF610_PAD_PTD5__DSPI1_CS0 0x1182 + VF610_PAD_PTC6__DSPI1_SIN 0x1181 + VF610_PAD_PTC7__DSPI1_SOUT 0x1182 + VF610_PAD_PTC8__DSPI1_SCK 0x1182 + >; + }; + + pinctrl_esdhc0: esdhc0grp { + fsl,pins = < + VF610_PAD_PTC0__ESDHC0_CLK 0x31ef + VF610_PAD_PTC1__ESDHC0_CMD 0x31ef + VF610_PAD_PTC2__ESDHC0_DAT0 0x31ef + VF610_PAD_PTC3__ESDHC0_DAT1 0x31ef + VF610_PAD_PTC4__ESDHC0_DAT2 0x31ef + VF610_PAD_PTC5__ESDHC0_DAT3 0x31ef + VF610_PAD_PTD23__ESDHC0_DAT4 0x31ef + VF610_PAD_PTD22__ESDHC0_DAT5 0x31ef + VF610_PAD_PTD21__ESDHC0_DAT6 0x31ef + VF610_PAD_PTD20__ESDHC0_DAT7 0x31ef + >; + }; + + pinctrl_leds_debug: pinctrl-leds-debug { + fsl,pins = < + VF610_PAD_PTD3__GPIO_82 0x31c2 + VF610_PAD_PTE3__GPIO_108 0x31c2 + VF610_PAD_PTE4__GPIO_109 0x31c2 + VF610_PAD_PTE5__GPIO_110 0x31c2 + VF610_PAD_PTE6__GPIO_111 0x31c2 + >; + }; +}; diff --git a/arch/arm/dts/vf610-zii-dev-rev-b.dts b/arch/arm/dts/vf610-zii-dev-rev-b.dts new file mode 100644 index 0000000..bf0a010 --- /dev/null +++ b/arch/arm/dts/vf610-zii-dev-rev-b.dts @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2015, 2016 Zodiac Inflight Innovations + * + * Based on an original 'vf610-twr.dts' which is Copyright 2015, + * Freescale Semiconductor, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "vf610-zii-dev.dtsi" + +/* + * ============================================================= + * The following code is shared with Linux kernel and should be + * removed once it trickles down from there eventually + * ============================================================= + */ + +/ { + model = "ZII VF610 Development Board, Rev B"; + compatible = "zii,vf610dev-b", "zii,vf610dev", "fsl,vf610"; + + mdio-mux { + compatible = "mdio-mux-gpio"; + pinctrl-0 = <&pinctrl_mdio_mux>; + pinctrl-names = "default"; + gpios = <&gpio0 8 GPIO_ACTIVE_HIGH + &gpio0 9 GPIO_ACTIVE_HIGH + &gpio0 24 GPIO_ACTIVE_HIGH + &gpio0 25 GPIO_ACTIVE_HIGH>; + mdio-parent-bus = <&mdio1>; + #address-cells = <1>; + #size-cells = <0>; + + mdio_mux_1: mdio@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + switch0: switch0@0 { + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + dsa,member = <0 0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + label = "lan0"; + }; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + switch0port5: port@5 { + reg = <5>; + label = "dsa"; + phy-mode = "rgmii-txid"; + link = <&switch1port6 + &switch2port9>; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&fec1>; + fixed-link { + speed = <100>; + full-duplex; + }; + }; + }; + }; + }; + + mdio_mux_2: mdio@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + switch1: switch1@0 { + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + dsa,member = <0 1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + label = "lan3"; + phy-handle = <&switch1phy0>; + }; + + port@1 { + reg = <1>; + label = "lan4"; + phy-handle = <&switch1phy1>; + }; + + port@2 { + reg = <2>; + label = "lan5"; + phy-handle = <&switch1phy2>; + }; + + switch1port5: port@5 { + reg = <5>; + label = "dsa"; + link = <&switch2port9>; + phy-mode = "rgmii-txid"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + switch1port6: port@6 { + reg = <6>; + label = "dsa"; + phy-mode = "rgmii-txid"; + link = <&switch0port5>; + }; + }; + mdio { + #address-cells = <1>; + #size-cells = <0>; + switch1phy0: switch1phy0@0 { + reg = <0>; + }; + switch1phy1: switch1phy0@1 { + reg = <1>; + }; + switch1phy2: switch1phy0@2 { + reg = <2>; + }; + }; + }; + }; + + mdio_mux_4: mdio@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + + switch2: switch2@0 { + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + dsa,member = <0 2>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + label = "lan6"; + }; + + port@1 { + reg = <1>; + label = "lan7"; + }; + + port@2 { + reg = <2>; + label = "lan8"; + }; + + port@3 { + reg = <3>; + label = "optical3"; + fixed-link { + speed = <1000>; + full-duplex; + link-gpios = <&gpio6 2 + GPIO_ACTIVE_HIGH>; + }; + }; + + port@4 { + reg = <4>; + label = "optical4"; + fixed-link { + speed = <1000>; + full-duplex; + link-gpios = <&gpio6 3 + GPIO_ACTIVE_HIGH>; + }; + }; + + switch2port9: port@9 { + reg = <9>; + label = "dsa"; + phy-mode = "rgmii-txid"; + link = <&switch1port5 + &switch0port5>; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; + }; + + mdio_mux_8: mdio@8 { + reg = <8>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + spi0 { + compatible = "spi-gpio"; + pinctrl-0 = <&pinctrl_gpio_spi0>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + gpio-sck = <&gpio1 12 GPIO_ACTIVE_HIGH>; + gpio-mosi = <&gpio1 11 GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio1 10 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH + &gpio1 8 GPIO_ACTIVE_HIGH>; + num-chipselects = <2>; + + m25p128@0 { + compatible = "m25p128", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <1000000>; + }; + + at93c46d@1 { + compatible = "atmel,at93c46d"; + pinctrl-0 = <&pinctrl_gpio_e6185_eeprom_sel>; + pinctrl-names = "default"; + #address-cells = <0>; + #size-cells = <0>; + reg = <1>; + spi-max-frequency = <500000>; + spi-cs-high; + data-size = <16>; + select-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&i2c0 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0>; + status = "okay"; + + gpio5: pca9554@20 { + compatible = "nxp,pca9554"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + + }; + + gpio6: pca9554@22 { + compatible = "nxp,pca9554"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pca9554_22>; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio2>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + tca9548@70 { + compatible = "nxp,pca9548"; + pinctrl-0 = <&pinctrl_i2c_mux_reset>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + sfp1: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + sfp2: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + sfp3: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + sfp4: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + }; +}; + + +&iomuxc { + pinctrl_gpio_e6185_eeprom_sel: pinctrl-gpio-e6185-eeprom-spi0 { + fsl,pins = < + VF610_PAD_PTE27__GPIO_132 0x33e2 + >; + }; + + pinctrl_gpio_spi0: pinctrl-gpio-spi0 { + fsl,pins = < + VF610_PAD_PTB22__GPIO_44 0x33e2 + VF610_PAD_PTB21__GPIO_43 0x33e2 + VF610_PAD_PTB20__GPIO_42 0x33e1 + VF610_PAD_PTB19__GPIO_41 0x33e2 + VF610_PAD_PTB18__GPIO_40 0x33e2 + >; + }; + + pinctrl_mdio_mux: pinctrl-mdio-mux { + fsl,pins = < + VF610_PAD_PTA18__GPIO_8 0x31c2 + VF610_PAD_PTA19__GPIO_9 0x31c2 + VF610_PAD_PTB2__GPIO_24 0x31c2 + VF610_PAD_PTB3__GPIO_25 0x31c2 + >; + }; + + pinctrl_pca9554_22: pinctrl-pca95540-22 { + fsl,pins = < + VF610_PAD_PTB28__GPIO_98 0x219d + >; + }; +}; + +/* + * ============================================================= + * End of shared part + * ============================================================= +*/ diff --git a/arch/arm/dts/vf610-zii-dev-rev-c.dts b/arch/arm/dts/vf610-zii-dev-rev-c.dts new file mode 100644 index 0000000..5228942 --- /dev/null +++ b/arch/arm/dts/vf610-zii-dev-rev-c.dts @@ -0,0 +1,445 @@ +/* + * Copyright (C) 2015, 2016 Zodiac Inflight Innovations + * + * Based on an original 'vf610-twr.dts' which is Copyright 2015, + * Freescale Semiconductor, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "vf610-zii-dev.dtsi" + +/* + * ============================================================= + * The following code is shared with Linux kernel and should be + * removed once it trickles down from there eventually + * ============================================================= + */ + +/ { + model = "ZII VF610 Development Board, Rev C"; + compatible = "zii,vf610dev-c", "zii,vf610dev", "fsl,vf610"; + + mdio-mux { + compatible = "mdio-mux-gpio"; + pinctrl-0 = <&pinctrl_mdio_mux>; + pinctrl-names = "default"; + gpios = <&gpio0 8 GPIO_ACTIVE_HIGH + &gpio0 9 GPIO_ACTIVE_HIGH + &gpio0 25 GPIO_ACTIVE_HIGH>; + mdio-parent-bus = <&mdio1>; + #address-cells = <1>; + #size-cells = <0>; + + mdio_mux_1: mdio@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + switch0: switch0@0 { + compatible = "marvell,mv88e6190"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + dsa,member = <0 0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "cpu"; + ethernet = <&fec1>; + fixed-link { + speed = <100>; + full-duplex; + }; + }; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + port@4 { + reg = <4>; + label = "lan4"; + }; + + switch0port10: port@10 { + reg = <10>; + label = "dsa"; + phy-mode = "xgmii"; + link = <&switch1port10>; + }; + }; + }; + }; + + mdio_mux_2: mdio@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + switch1: switch1@0 { + compatible = "marvell,mv88e6190"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + dsa,member = <0 1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan5"; + }; + + port@2 { + reg = <2>; + label = "lan6"; + }; + + port@3 { + reg = <3>; + label = "lan7"; + }; + + port@4 { + reg = <4>; + label = "lan8"; + }; + + + switch1port10: port@10 { + reg = <10>; + label = "dsa"; + phy-mode = "xgmii"; + link = <&switch0port10>; + }; + }; + }; + }; + + mdio_mux_4: mdio@4 { + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; + +&dspi0 { + bus-num = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dspi0>; + status = "okay"; + spi-num-chipselects = <2>; + + m25p128@0 { + compatible = "m25p128", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <50000000>; + }; + + atzb-rf-233@1 { + compatible = "atmel,at86rf233"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctr_atzb_rf_233>; + + spi-max-frequency = <7500000>; + reg = <1>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&gpio3>; + xtal-trim = /bits/ 8 <0x06>; + + sleep-gpio = <&gpio0 24 GPIO_ACTIVE_HIGH>; + reset-gpio = <&gpio6 10 GPIO_ACTIVE_HIGH>; + + fsl,spi-cs-sck-delay = <180>; + fsl,spi-sck-cs-delay = <250>; + }; +}; + +&dspi2 { + bus-num = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dspi2>; + status = "okay"; + spi-num-chipselects = <2>; +}; + +&i2c0 { + /* + * U712 + * + * Exposed signals: + * P1 - WE2_CMD + * P2 - WE2_CLK + */ + gpio5: pca9557@18 { + compatible = "nxp,pca9557"; + reg = <0x18>; + gpio-controller; + #gpio-cells = <2>; + }; + + /* + * U121 + * + * Exposed signals: + * I/O0 - ENET_SWR_EN + * I/O1 - ESW1_RESETn + * I/O2 - ARINC_RESET + * I/O3 - DD1_IO_RESET + * I/O4 - ESW2_RESETn + * I/O5 - ESW3_RESETn + * I/O6 - ESW4_RESETn + * I/O8 - TP909 + * I/O9 - FEM_SEL + * I/O10 - WIFI_RESETn + * I/O11 - PHY_RSTn + * I/O12 - OPT1_SD + * I/O13 - OPT2_SD + * I/O14 - OPT1_TX_DIS + * I/O15 - OPT2_TX_DIS + */ + gpio6: sx1503@20 { + compatible = "semtech,sx1503q"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sx1503_20>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <23 IRQ_TYPE_EDGE_FALLING>; + gpio-controller; + interrupt-controller; + + enet_swr_en { + gpio-hog; + gpios = <0 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "enet-swr-en"; + }; + }; + + /* + * U715 + * + * Exposed signals: + * IO0 - WE1_CLK + * IO1 - WE1_CMD + */ + gpio7: pca9554@22 { + compatible = "nxp,pca9554"; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + + }; +}; + +&i2c1 { + at24mac602@00 { + compatible = "atmel,24c02"; + reg = <0x50>; + read-only; + }; +}; + +&i2c2 { + tca9548@70 { + compatible = "nxp,pca9548"; + pinctrl-0 = <&pinctrl_i2c_mux_reset>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + sfp2: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + sfp3: at24c04@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; +}; + +&gpio0 { + eth0_intrp { + gpio-hog; + gpios = <23 GPIO_ACTIVE_HIGH>; + input; + line-name = "sx1503-irq"; + }; +}; + +&gpio3 { + eth0_intrp { + gpio-hog; + gpios = <2 GPIO_ACTIVE_HIGH>; + input; + line-name = "eth0-intrp"; + }; +}; + +&fec0 { + mdio { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec0_phy_int>; + + interrupt-parent = <&gpio3>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + reg = <0>; + }; + }; +}; + +&iomuxc { + pinctr_atzb_rf_233: pinctrl-atzb-rf-233 { + fsl,pins = < + VF610_PAD_PTB2__GPIO_24 0x31c2 + VF610_PAD_PTE27__GPIO_132 0x33e2 + >; + }; + + + pinctrl_sx1503_20: pinctrl-sx1503-20 { + fsl,pins = < + VF610_PAD_PTB1__GPIO_23 0x219d + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + VF610_PAD_PTA20__UART3_TX 0x21a2 + VF610_PAD_PTA21__UART3_RX 0x21a1 + >; + }; + + pinctrl_mdio_mux: pinctrl-mdio-mux { + fsl,pins = < + VF610_PAD_PTA18__GPIO_8 0x31c2 + VF610_PAD_PTA19__GPIO_9 0x31c2 + VF610_PAD_PTB3__GPIO_25 0x31c2 + >; + }; + + pinctrl_fec0_phy_int: pinctrl-fec0-phy-int { + fsl,pins = < + VF610_PAD_PTB28__GPIO_98 0x219d + >; + }; +}; + +/* + * ============================================================= + * End of shared part + * ============================================================= + */ + + +&dspi0 { + m25p128@0 { + partition@0 { + label = "bootloader"; + reg = <0x0 0x100000>; + }; + }; +}; diff --git a/arch/arm/dts/vf610-zii-dev.dtsi b/arch/arm/dts/vf610-zii-dev.dtsi new file mode 100644 index 0000000..dae077c --- /dev/null +++ b/arch/arm/dts/vf610-zii-dev.dtsi @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2015, 2016 Zodiac Inflight Innovations + * + * Based on an original 'vf610-twr.dts' which is Copyright 2015, + * Freescale Semiconductor, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use +n * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * ============================================================= + * The following code is shared with Linux kernel and should be + * removed once it trickles down from there eventually + * ============================================================= + */ + +#include + +/ { + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0x80000000 0x20000000>; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&pinctrl_leds_debug>; + pinctrl-names = "default"; + + debug { + label = "zii:green:debug1"; + gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + reg_vcc_3v3_mcu: regulator-vcc-3v3-mcu { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_mcu"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + usb0_vbus: regulator-usb0-vbus { + compatible = "regulator-fixed"; + pinctrl-0 = <&pinctrl_usb_vbus>; + regulator-name = "usb_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 6 0>; + }; +}; + +&adc0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc0_ad5>; + vref-supply = <®_vcc_3v3_mcu>; + status = "okay"; +}; + +&edma0 { + status = "okay"; +}; + +&esdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_esdhc1>; + bus-width = <4>; + status = "okay"; +}; + +&fec0 { + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec0>; + status = "okay"; +}; + +&fec1 { + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; + status = "okay"; + + fixed-link { + speed = <100>; + full-duplex; + }; + + mdio1: mdio { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + }; +}; + +&i2c0 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c0>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + scl-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + sda-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + status = "okay"; + + lm75@48 { + compatible = "national,lm75"; + reg = <0x48>; + }; + + at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + + at24c04@52 { + compatible = "atmel,24c04"; + reg = <0x52>; + }; + + ds1682@6b { + compatible = "dallas,ds1682"; + reg = <0x6b>; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&usbdev0 { + disable-over-current; + vbus-supply = <&usb0_vbus>; + dr_mode = "host"; + status = "okay"; +}; + +&usbh1 { + disable-over-current; + status = "okay"; +}; + +&usbmisc0 { + status = "okay"; +}; + +&usbmisc1 { + status = "okay"; +}; + +&usbphy0 { + status = "okay"; +}; + +&usbphy1 { + status = "okay"; +}; + +&iomuxc { + pinctrl_adc0_ad5: adc0ad5grp { + fsl,pins = < + VF610_PAD_PTC30__ADC0_SE5 0x00a1 + >; + }; + + pinctrl_dspi0: dspi0grp { + fsl,pins = < + VF610_PAD_PTB18__DSPI0_CS1 0x1182 + VF610_PAD_PTB19__DSPI0_CS0 0x1182 + VF610_PAD_PTB20__DSPI0_SIN 0x1181 + VF610_PAD_PTB21__DSPI0_SOUT 0x1182 + VF610_PAD_PTB22__DSPI0_SCK 0x1182 + >; + }; + + pinctrl_dspi2: dspi2grp { + fsl,pins = < + VF610_PAD_PTD31__DSPI2_CS1 0x1182 + VF610_PAD_PTD30__DSPI2_CS0 0x1182 + VF610_PAD_PTD29__DSPI2_SIN 0x1181 + VF610_PAD_PTD28__DSPI2_SOUT 0x1182 + VF610_PAD_PTD27__DSPI2_SCK 0x1182 + >; + }; + + pinctrl_esdhc1: esdhc1grp { + fsl,pins = < + VF610_PAD_PTA24__ESDHC1_CLK 0x31ef + VF610_PAD_PTA25__ESDHC1_CMD 0x31ef + VF610_PAD_PTA26__ESDHC1_DAT0 0x31ef + VF610_PAD_PTA27__ESDHC1_DAT1 0x31ef + VF610_PAD_PTA28__ESDHC1_DATA2 0x31ef + VF610_PAD_PTA29__ESDHC1_DAT3 0x31ef + VF610_PAD_PTA7__GPIO_134 0x219d + >; + }; + + pinctrl_fec0: fec0grp { + fsl,pins = < + VF610_PAD_PTC0__ENET_RMII0_MDC 0x30d2 + VF610_PAD_PTC1__ENET_RMII0_MDIO 0x30d3 + VF610_PAD_PTC2__ENET_RMII0_CRS 0x30d1 + VF610_PAD_PTC3__ENET_RMII0_RXD1 0x30d1 + VF610_PAD_PTC4__ENET_RMII0_RXD0 0x30d1 + VF610_PAD_PTC5__ENET_RMII0_RXER 0x30d1 + VF610_PAD_PTC6__ENET_RMII0_TXD1 0x30d2 + VF610_PAD_PTC7__ENET_RMII0_TXD0 0x30d2 + VF610_PAD_PTC8__ENET_RMII0_TXEN 0x30d2 + >; + }; + + pinctrl_fec1: fec1grp { + fsl,pins = < + VF610_PAD_PTA6__RMII_CLKIN 0x30d1 + VF610_PAD_PTC9__ENET_RMII1_MDC 0x30d2 + VF610_PAD_PTC10__ENET_RMII1_MDIO 0x30d3 + VF610_PAD_PTC11__ENET_RMII1_CRS 0x30d1 + VF610_PAD_PTC12__ENET_RMII1_RXD1 0x30d1 + VF610_PAD_PTC13__ENET_RMII1_RXD0 0x30d1 + VF610_PAD_PTC14__ENET_RMII1_RXER 0x30d1 + VF610_PAD_PTC15__ENET_RMII1_TXD1 0x30d2 + VF610_PAD_PTC16__ENET_RMII1_TXD0 0x30d2 + VF610_PAD_PTC17__ENET_RMII1_TXEN 0x30d2 + >; + }; + + pinctrl_gpio_spi0: pinctrl-gpio-spi0 { + fsl,pins = < + VF610_PAD_PTB22__GPIO_44 0x33e2 + VF610_PAD_PTB21__GPIO_43 0x33e2 + VF610_PAD_PTB20__GPIO_42 0x33e1 + VF610_PAD_PTB19__GPIO_41 0x33e2 + VF610_PAD_PTB18__GPIO_40 0x33e2 + >; + }; + + pinctrl_i2c_mux_reset: pinctrl-i2c-mux-reset { + fsl,pins = < + VF610_PAD_PTE14__GPIO_119 0x31c2 + >; + }; + + pinctrl_i2c0: i2c0grp { + fsl,pins = < + VF610_PAD_PTB14__I2C0_SCL 0x37ff + VF610_PAD_PTB15__I2C0_SDA 0x37ff + >; + }; + + pinctrl_i2c0_gpio: i2c0grp-gpio { + fsl,pins = < + VF610_PAD_PTB14__GPIO_36 0x31c2 + VF610_PAD_PTB15__GPIO_37 0x31c2 + >; + }; + + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + VF610_PAD_PTB16__I2C1_SCL 0x37ff + VF610_PAD_PTB17__I2C1_SDA 0x37ff + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + VF610_PAD_PTA22__I2C2_SCL 0x37ff + VF610_PAD_PTA23__I2C2_SDA 0x37ff + >; + }; + + pinctrl_leds_debug: pinctrl-leds-debug { + fsl,pins = < + VF610_PAD_PTD20__GPIO_74 0x31c2 + >; + }; + + pinctrl_qspi0: qspi0grp { + fsl,pins = < + VF610_PAD_PTD7__QSPI0_B_QSCK 0x31c3 + VF610_PAD_PTD8__QSPI0_B_CS0 0x31ff + VF610_PAD_PTD9__QSPI0_B_DATA3 0x31c3 + VF610_PAD_PTD10__QSPI0_B_DATA2 0x31c3 + VF610_PAD_PTD11__QSPI0_B_DATA1 0x31c3 + VF610_PAD_PTD12__QSPI0_B_DATA0 0x31c3 + >; + }; + + pinctrl_uart0: uart0grp { + fsl,pins = < + VF610_PAD_PTB10__UART0_TX 0x21a2 + VF610_PAD_PTB11__UART0_RX 0x21a1 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + VF610_PAD_PTB23__UART1_TX 0x21a2 + VF610_PAD_PTB24__UART1_RX 0x21a1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + VF610_PAD_PTD0__UART2_TX 0x21a2 + VF610_PAD_PTD1__UART2_RX 0x21a1 + >; + }; + + pinctrl_usb_vbus: pinctrl-usb-vbus { + fsl,pins = < + VF610_PAD_PTA16__GPIO_6 0x31c2 + >; + }; + + pinctrl_usb0_host: usb0-host-grp { + fsl,pins = < + VF610_PAD_PTD6__GPIO_85 0x0062 + >; + }; +}; + +/* + * ============================================================= + * End of shared part + * ============================================================= + */ + +/ { + audio_ext: mclk_osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + enet_ext: eth_osc { + compatible = "fixed-clock"; + clock-output-names = "enet_ext"; + #clock-cells = <0>; + clock-frequency = <50000000>; + }; + + anaclk1: anaclk1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; +}; + +&clks { + clocks = <&sxosc>, <&fxosc>, <&enet_ext>, <&audio_ext>, <&anaclk1>, + <&clks VF610_CLK_SYS_BUS>, <&clks VF610_CLK_PLATFORM_BUS>, + <&clks VF610_CLK_IPG_BUS>, <&clks VF610_CLK_DDRMC>; + clock-names = "sxosc", "fxosc", "enet_ext", "audio_ext", "anaclk1", + "cpu", "bus", "ipg", "ddr"; + + assigned-clocks = <&clks VF610_CLK_ENET_SEL>, + <&clks VF610_CLK_ENET_TS_SEL>; + assigned-clock-parents = <&clks VF610_CLK_ENET_EXT>, + <&clks VF610_CLK_ENET_EXT>; +}; + +&ocotp { + barebox,provide-mac-address = <&fec0 0x620>, + <&fec1 0x640>; +}; diff --git a/arch/arm/dts/vf610-zii-scu4-aib-rev-c.dts b/arch/arm/dts/vf610-zii-scu4-aib-rev-c.dts new file mode 100644 index 0000000..d10f460 --- /dev/null +++ b/arch/arm/dts/vf610-zii-scu4-aib-rev-c.dts @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2015, 2016 Zodiac Inflight Innovations + * + * Based on an original 'vf610-twr.dts' which is Copyright 2015, + * Freescale Semiconductor, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "vf610-zii-dev.dtsi" + +/ { + model = "ZII VF610 SCU4 AIB, Rev C"; + compatible = "zii,vf610scu4-aib-c", "zii,vf610dev", "fsl,vf610"; + + chosen { + bootargs = "console=ttyLP0,115200n8"; + }; + + gpio-leds { + debug { + gpios = <&gpio3 0 GPIO_ACTIVE_HIGH>; + }; + }; + + mdio-mux { + compatible = "mdio-mux-gpio"; + pinctrl-0 = <&pinctrl_mdio_mux>; + pinctrl-names = "default"; + gpios = <&gpio4 4 GPIO_ACTIVE_HIGH + &gpio4 5 GPIO_ACTIVE_HIGH + &gpio3 30 GPIO_ACTIVE_HIGH + &gpio3 31 GPIO_ACTIVE_HIGH>; + mdio-parent-bus = <&mdio1>; + #address-cells = <1>; + #size-cells = <0>; + + mdio_mux_1: mdio@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio_mux_2: mdio@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio_mux_4: mdio@4 { + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio_mux_8: mdio@8 { + reg = <8>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + spi2 { + compatible = "spi-gpio"; + pinctrl-0 = <&pinctrl_dspi2>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + + gpio-sck = <&gpio2 3 GPIO_ACTIVE_HIGH>; + gpio-mosi = <&gpio2 2 GPIO_ACTIVE_HIGH>; + gpio-miso = <&gpio2 1 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; + num-chipselects = <1>; + + at93c46d@0 { + compatible = "atmel,at93c46d"; + #address-cells = <0>; + #size-cells = <0>; + reg = <0>; + spi-max-frequency = <500000>; + spi-cs-high; + data-size = <16>; + select-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&dspi0 { + pinctrl-0 = <&pinctrl_dspi0>, <&pinctrl_dspi0_cs_4_5>; + pinctrl-names = "default"; + status = "okay"; +}; + +&dspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dspi1>; + status = "okay"; + + m25p128@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p128", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partition@0 { + label = "m25p128-0"; + reg = <0x0 0x01000000>; + }; + }; + + m25p128@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p128", "jedec,spi-nor"; + reg = <1>; + spi-max-frequency = <50000000>; + + partition@0 { + label = "m25p128-1"; + reg = <0x0 0x01000000>; + }; + }; +}; + +&esdhc0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_esdhc0>; + bus-width = <8>; + status = "okay"; +}; + +&fec0 { + status = "disabled"; +}; + +&i2c0 { + /* Reset Signals */ + gpio5: pca9505@20 { + compatible = "nxp,pca9554"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; + + /* Board Revision */ + gpio6: pca9505@22 { + compatible = "nxp,pca9554"; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +&i2c1 { + /* Wireless 2 */ + gpio8: pca9554@18 { + compatible = "nxp,pca9557"; + reg = <0x18>; + gpio-controller; + #gpio-cells = <2>; + }; + + /* Wireless 1 */ + gpio7: pca9554@24 { + compatible = "nxp,pca9554"; + reg = <0x24>; + gpio-controller; + #gpio-cells = <2>; + }; + + /* AIB voltage monitor */ + adt7411@4a { + compatible = "adi,adt7411"; + reg = <0x4a>; + }; +}; + +&i2c2 { + /* FIB voltage monitor */ + adt7411@4a { + compatible = "adi,adt7411"; + reg = <0x4a>; + }; + + lm75_swb { + compatible = "national,lm75"; + reg = <0x4e>; + }; + + lm75_swa { + compatible = "national,lm75"; + reg = <0x4f>; + }; + + /* FIB Nameplate */ + at24c08@57 { + compatible = "atmel,24c08"; + reg = <0x57>; + }; + + tca9548@70 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + sff0: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + sff1: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + sff2: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + + sff3: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + + i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + + sff4: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + }; + + + tca9548@71 { + compatible = "nxp,pca9548"; + reg = <0x71>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + sff5: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + sff6: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + sff7: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + + }; + + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + + sff8: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + + i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + + sff9: at24c04@50 { + compatible = "atmel,24c04"; + reg = <0x50>; + }; + }; + }; +}; + +&uart1 { + linux,rs485-enabled-at-boot-time; + pinctrl-0 = <&pinctrl_uart1>, <&pinctrl_uart1_rts>; +}; + +&uart2 { + linux,rs485-enabled-at-boot-time; + pinctrl-0 = <&pinctrl_uart2>, <&pinctrl_uart2_rts>; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpo_public>; + + + pinctrl_gpo_public: gpopubgrp { + fsl,pins = < + VF610_PAD_PTE2__GPIO_107 0x2062 + VF610_PAD_PTE3__GPIO_108 0x2062 + VF610_PAD_PTE4__GPIO_109 0x2062 + VF610_PAD_PTE5__GPIO_110 0x2062 + VF610_PAD_PTE6__GPIO_111 0x2062 + >; + }; + + pinctrl_dspi0_cs_4_5: dspi0grp-cs-4-5 { + fsl,pins = < + VF610_PAD_PTB13__DSPI0_CS4 0x1182 + VF610_PAD_PTB12__DSPI0_CS5 0x1182 + >; + }; + + pinctrl_dspi1: dspi1grp { + fsl,pins = < + VF610_PAD_PTD5__DSPI1_CS0 0x1182 + VF610_PAD_PTD4__DSPI1_CS1 0x1182 + VF610_PAD_PTC6__DSPI1_SIN 0x1181 + VF610_PAD_PTC7__DSPI1_SOUT 0x1182 + VF610_PAD_PTC8__DSPI1_SCK 0x1182 + >; + }; + + pinctrl_esdhc0: esdhc0grp { + fsl,pins = < + VF610_PAD_PTC0__ESDHC0_CLK 0x31ef + VF610_PAD_PTC1__ESDHC0_CMD 0x31ef + VF610_PAD_PTC2__ESDHC0_DAT0 0x31ef + VF610_PAD_PTC3__ESDHC0_DAT1 0x31ef + VF610_PAD_PTC4__ESDHC0_DAT2 0x31ef + VF610_PAD_PTC5__ESDHC0_DAT3 0x31ef + VF610_PAD_PTD23__ESDHC0_DAT4 0x31ef + VF610_PAD_PTD22__ESDHC0_DAT5 0x31ef + VF610_PAD_PTD21__ESDHC0_DAT6 0x31ef + VF610_PAD_PTD20__ESDHC0_DAT7 0x31ef + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + VF610_PAD_PTA30__I2C3_SCL 0x37ff + VF610_PAD_PTA31__I2C3_SDA 0x37ff + >; + }; + + pinctrl_leds_debug: pinctrl-leds-debug { + fsl,pins = < + VF610_PAD_PTB26__GPIO_96 0x31c2 + >; + }; + + pinctrl_uart1_rts: uart1grp-rts { + fsl,pins = < + VF610_PAD_PTB25__UART1_RTS 0x2062 + >; + }; + + pinctrl_uart2_rts: uart2grp-rts { + fsl,pins = < + VF610_PAD_PTD2__UART2_RTS 0x2062 + >; + }; + + pinctrl_mdio_mux: pinctrl-mdio-mux { + fsl,pins = < + VF610_PAD_PTE27__GPIO_132 0x31c2 + VF610_PAD_PTE28__GPIO_133 0x31c2 + VF610_PAD_PTE21__GPIO_126 0x31c2 + VF610_PAD_PTE22__GPIO_127 0x31c2 + >; + }; +}; diff --git a/arch/arm/dts/vf610-zii-spu3-rev-a.dts b/arch/arm/dts/vf610-zii-spu3-rev-a.dts new file mode 100644 index 0000000..25ab26d --- /dev/null +++ b/arch/arm/dts/vf610-zii-spu3-rev-a.dts @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2015, 2016 Zodiac Inflight Innovations + * + * Based on an original 'vf610-twr.dts' which is Copyright 2015, + * Freescale Semiconductor, Inc. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "vf610-zii-dev.dtsi" + + +/ { + model = "ZII VF610 SPU3 Switch Management Board"; + compatible = "zii,vf610spu3-a", "zii,vf610dev", "fsl,vf610"; + + aliases { + /delete-property/ serial2; + }; + + gpio-leds { + debug { + gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&dspi1 { + bus-num = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dspi1>; + status = "okay"; + + m25p128@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p128", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partition@0 { + label = "m25p128-0"; + reg = <0x0 0x01000000>; + }; + }; +}; + +&esdhc0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_esdhc0>; + bus-width = <8>; + status = "okay"; +}; + +&fec0 { + status = "disabled"; +}; + +&i2c0 { + /* Board Revision */ + gpio6: pca9505@22 { + compatible = "nxp,pca9554"; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +/delete-node/ &i2c1; +/delete-node/ &i2c2; +/delete-node/ &uart2; + +&iomuxc { + pinctrl_dspi1: dspi1grp { + fsl,pins = < + VF610_PAD_PTD5__DSPI1_CS0 0x1182 + VF610_PAD_PTD4__DSPI1_CS1 0x1182 + VF610_PAD_PTC6__DSPI1_SIN 0x1181 + VF610_PAD_PTC7__DSPI1_SOUT 0x1182 + VF610_PAD_PTC8__DSPI1_SCK 0x1182 + >; + }; + + pinctrl_esdhc0: esdhc0grp { + fsl,pins = < + VF610_PAD_PTC0__ESDHC0_CLK 0x31ef + VF610_PAD_PTC1__ESDHC0_CMD 0x31ef + VF610_PAD_PTC2__ESDHC0_DAT0 0x31ef + VF610_PAD_PTC3__ESDHC0_DAT1 0x31ef + VF610_PAD_PTC4__ESDHC0_DAT2 0x31ef + VF610_PAD_PTC5__ESDHC0_DAT3 0x31ef + VF610_PAD_PTD23__ESDHC0_DAT4 0x31ef + VF610_PAD_PTD22__ESDHC0_DAT5 0x31ef + VF610_PAD_PTD21__ESDHC0_DAT6 0x31ef + VF610_PAD_PTD20__ESDHC0_DAT7 0x31ef + >; + }; + + pinctrl_leds_debug: pinctrl-leds-debug { + fsl,pins = < + VF610_PAD_PTD3__GPIO_82 0x31c2 + >; + }; +}; diff --git a/arch/arm/include/asm/arm-smccc.h b/arch/arm/include/asm/arm-smccc.h new file mode 100644 index 0000000..b5abfda --- /dev/null +++ b/arch/arm/include/asm/arm-smccc.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, Linaro Limited + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ +#ifndef __LINUX_ARM_SMCCC_H +#define __LINUX_ARM_SMCCC_H + +#include +#include + +/* + * This file provides common defines for ARM SMC Calling Convention as + * specified in + * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + */ + +#define ARM_SMCCC_STD_CALL 0 +#define ARM_SMCCC_FAST_CALL 1 +#define ARM_SMCCC_TYPE_SHIFT 31 + +#define ARM_SMCCC_SMC_32 0 +#define ARM_SMCCC_SMC_64 1 +#define ARM_SMCCC_CALL_CONV_SHIFT 30 + +#define ARM_SMCCC_OWNER_MASK 0x3F +#define ARM_SMCCC_OWNER_SHIFT 24 + +#define ARM_SMCCC_FUNC_MASK 0xFFFF + +#define ARM_SMCCC_IS_FAST_CALL(smc_val) \ + ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT)) +#define ARM_SMCCC_IS_64(smc_val) \ + ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT)) +#define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK) +#define ARM_SMCCC_OWNER_NUM(smc_val) \ + (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK) + +#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \ + (((type) << ARM_SMCCC_TYPE_SHIFT) | \ + ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \ + (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \ + ((func_num) & ARM_SMCCC_FUNC_MASK)) + +#define ARM_SMCCC_OWNER_ARCH 0 +#define ARM_SMCCC_OWNER_CPU 1 +#define ARM_SMCCC_OWNER_SIP 2 +#define ARM_SMCCC_OWNER_OEM 3 +#define ARM_SMCCC_OWNER_STANDARD 4 +#define ARM_SMCCC_OWNER_TRUSTED_APP 48 +#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49 +#define ARM_SMCCC_OWNER_TRUSTED_OS 50 +#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63 + +/** + * struct arm_smccc_res - Result from SMC/HVC call + * @a0-a3 result values from registers 0 to 3 + */ +struct arm_smccc_res { + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; +}; + +/** + * arm_smccc_smc() - make SMC calls + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * + * This function is used to make SMC calls following SMC Calling Convention. + * The content of the supplied param are copied to registers 0 to 7 prior + * to the SMC instruction. The return values are updated with the content + * from register 0 to 3 on return from the SMC instruction. + */ +asmlinkage void arm_smccc_smc(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long a6, unsigned long a7, + struct arm_smccc_res *res); + +/** + * arm_smccc_hvc() - make HVC calls + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * + * This function is used to make HVC calls following SMC Calling + * Convention. The content of the supplied param are copied to registers 0 + * to 7 prior to the HVC instruction. The return values are updated with + * the content from register 0 to 3 on return from the HVC instruction. + */ +asmlinkage void arm_smccc_hvc(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long a6, unsigned long a7, + struct arm_smccc_res *res); + +#endif /*__LINUX_ARM_SMCCC_H*/ diff --git a/arch/arm/include/asm/armlinux.h b/arch/arm/include/asm/armlinux.h index 07479fb..5c39200 100644 --- a/arch/arm/include/asm/armlinux.h +++ b/arch/arm/include/asm/armlinux.h @@ -3,6 +3,7 @@ #include #include +#include #if defined CONFIG_ARM_LINUX void armlinux_set_bootparams(void *params); @@ -38,6 +39,7 @@ struct image_data; void start_linux(void *adr, int swap, unsigned long initrd_address, - unsigned long initrd_size, void *oftree); + unsigned long initrd_size, void *oftree, + enum arm_security_state); #endif /* __ARCH_ARMLINUX_H */ diff --git a/arch/arm/include/asm/gic.h b/arch/arm/include/asm/gic.h new file mode 100644 index 0000000..bd3a80c --- /dev/null +++ b/arch/arm/include/asm/gic.h @@ -0,0 +1,110 @@ +#ifndef __GIC_H__ +#define __GIC_H__ + +/* Register offsets for the ARM generic interrupt controller (GIC) */ + +#define GIC_DIST_OFFSET 0x1000 +#define GIC_CPU_OFFSET_A9 0x0100 +#define GIC_CPU_OFFSET_A15 0x2000 + +/* Distributor Registers */ +#define GICD_CTLR 0x0000 +#define GICD_TYPER 0x0004 +#define GICD_IIDR 0x0008 +#define GICD_STATUSR 0x0010 +#define GICD_SETSPI_NSR 0x0040 +#define GICD_CLRSPI_NSR 0x0048 +#define GICD_SETSPI_SR 0x0050 +#define GICD_CLRSPI_SR 0x0058 +#define GICD_SEIR 0x0068 +#define GICD_IGROUPRn 0x0080 +#define GICD_ISENABLERn 0x0100 +#define GICD_ICENABLERn 0x0180 +#define GICD_ISPENDRn 0x0200 +#define GICD_ICPENDRn 0x0280 +#define GICD_ISACTIVERn 0x0300 +#define GICD_ICACTIVERn 0x0380 +#define GICD_IPRIORITYRn 0x0400 +#define GICD_ITARGETSRn 0x0800 +#define GICD_ICFGR 0x0c00 +#define GICD_IGROUPMODRn 0x0d00 +#define GICD_NSACRn 0x0e00 +#define GICD_SGIR 0x0f00 +#define GICD_CPENDSGIRn 0x0f10 +#define GICD_SPENDSGIRn 0x0f20 +#define GICD_IROUTERn 0x6000 + +/* Cpu Interface Memory Mapped Registers */ +#define GICC_CTLR 0x0000 +#define GICC_PMR 0x0004 +#define GICC_BPR 0x0008 +#define GICC_IAR 0x000C +#define GICC_EOIR 0x0010 +#define GICC_RPR 0x0014 +#define GICC_HPPIR 0x0018 +#define GICC_ABPR 0x001c +#define GICC_AIAR 0x0020 +#define GICC_AEOIR 0x0024 +#define GICC_AHPPIR 0x0028 +#define GICC_APRn 0x00d0 +#define GICC_NSAPRn 0x00e0 +#define GICC_IIDR 0x00fc +#define GICC_DIR 0x1000 + +/* ReDistributor Registers for Control and Physical LPIs */ +#define GICR_CTLR 0x0000 +#define GICR_IIDR 0x0004 +#define GICR_TYPER 0x0008 +#define GICR_STATUSR 0x0010 +#define GICR_WAKER 0x0014 +#define GICR_SETLPIR 0x0040 +#define GICR_CLRLPIR 0x0048 +#define GICR_SEIR 0x0068 +#define GICR_PROPBASER 0x0070 +#define GICR_PENDBASER 0x0078 +#define GICR_INVLPIR 0x00a0 +#define GICR_INVALLR 0x00b0 +#define GICR_SYNCR 0x00c0 +#define GICR_MOVLPIR 0x0100 +#define GICR_MOVALLR 0x0110 + +/* ReDistributor Registers for SGIs and PPIs */ +#define GICR_IGROUPRn 0x0080 +#define GICR_ISENABLERn 0x0100 +#define GICR_ICENABLERn 0x0180 +#define GICR_ISPENDRn 0x0200 +#define GICR_ICPENDRn 0x0280 +#define GICR_ISACTIVERn 0x0300 +#define GICR_ICACTIVERn 0x0380 +#define GICR_IPRIORITYRn 0x0400 +#define GICR_ICFGR0 0x0c00 +#define GICR_ICFGR1 0x0c04 +#define GICR_IGROUPMODRn 0x0d00 +#define GICR_NSACRn 0x0e00 + +/* Cpu Interface System Registers */ +#define ICC_IAR0_EL1 S3_0_C12_C8_0 +#define ICC_IAR1_EL1 S3_0_C12_C12_0 +#define ICC_EOIR0_EL1 S3_0_C12_C8_1 +#define ICC_EOIR1_EL1 S3_0_C12_C12_1 +#define ICC_HPPIR0_EL1 S3_0_C12_C8_2 +#define ICC_HPPIR1_EL1 S3_0_C12_C12_2 +#define ICC_BPR0_EL1 S3_0_C12_C8_3 +#define ICC_BPR1_EL1 S3_0_C12_C12_3 +#define ICC_DIR_EL1 S3_0_C12_C11_1 +#define ICC_PMR_EL1 S3_0_C4_C6_0 +#define ICC_RPR_EL1 S3_0_C12_C11_3 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_SRE_EL1 S3_0_C12_C12_5 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6 +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7 +#define ICC_SEIEN_EL1 S3_0_C12_C13_0 +#define ICC_SGI0R_EL1 S3_0_C12_C11_7 +#define ICC_SGI1R_EL1 S3_0_C12_C11_5 +#define ICC_ASGI1R_EL1 S3_0_C12_C11_6 + +#endif /* __GIC_H__ */ diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h new file mode 100644 index 0000000..e0c4525 --- /dev/null +++ b/arch/arm/include/asm/psci.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2013 - ARM Ltd + * Author: Marc Zyngier + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ARM_PSCI_H__ +#define __ARM_PSCI_H__ + +#define ARM_PSCI_VER_1_0 (0x00010000) +#define ARM_PSCI_VER_0_2 (0x00000002) + +/* PSCI 0.1 interface */ +#define ARM_PSCI_FN_BASE 0x95c1ba5e +#define ARM_PSCI_FN(n) (ARM_PSCI_FN_BASE + (n)) + +#define ARM_PSCI_FN_CPU_SUSPEND ARM_PSCI_FN(0) +#define ARM_PSCI_FN_CPU_OFF ARM_PSCI_FN(1) +#define ARM_PSCI_FN_CPU_ON ARM_PSCI_FN(2) +#define ARM_PSCI_FN_MIGRATE ARM_PSCI_FN(3) + +#define ARM_PSCI_RET_SUCCESS 0 +#define ARM_PSCI_RET_NOT_SUPPORTED (-1) +#define ARM_PSCI_RET_INVAL (-2) +#define ARM_PSCI_RET_DENIED (-3) +#define ARM_PSCI_RET_ALREADY_ON (-4) +#define ARM_PSCI_RET_ON_PENDING (-5) +#define ARM_PSCI_RET_INTERNAL_FAILURE (-6) +#define ARM_PSCI_RET_NOT_PRESENT (-7) +#define ARM_PSCI_RET_DISABLED (-8) +#define ARM_PSCI_RET_INVALID_ADDRESS (-9) + +/* PSCI 0.2 interface */ +#define ARM_PSCI_0_2_FN_BASE 0x84000000 +#define ARM_PSCI_0_2_FN(n) (ARM_PSCI_0_2_FN_BASE + (n)) + +#define ARM_PSCI_0_2_FN64_BASE 0xC4000000 +#define ARM_PSCI_0_2_FN64(n) (ARM_PSCI_0_2_FN64_BASE + (n)) + +#define ARM_PSCI_0_2_FN_PSCI_VERSION ARM_PSCI_0_2_FN(0) +#define ARM_PSCI_0_2_FN_CPU_SUSPEND ARM_PSCI_0_2_FN(1) +#define ARM_PSCI_0_2_FN_CPU_OFF ARM_PSCI_0_2_FN(2) +#define ARM_PSCI_0_2_FN_CPU_ON ARM_PSCI_0_2_FN(3) +#define ARM_PSCI_0_2_FN_AFFINITY_INFO ARM_PSCI_0_2_FN(4) +#define ARM_PSCI_0_2_FN_MIGRATE ARM_PSCI_0_2_FN(5) +#define ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE ARM_PSCI_0_2_FN(6) +#define ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU ARM_PSCI_0_2_FN(7) +#define ARM_PSCI_0_2_FN_SYSTEM_OFF ARM_PSCI_0_2_FN(8) +#define ARM_PSCI_0_2_FN_SYSTEM_RESET ARM_PSCI_0_2_FN(9) + +#define ARM_PSCI_0_2_FN64_CPU_SUSPEND ARM_PSCI_0_2_FN64(1) +#define ARM_PSCI_0_2_FN64_CPU_ON ARM_PSCI_0_2_FN64(3) +#define ARM_PSCI_0_2_FN64_AFFINITY_INFO ARM_PSCI_0_2_FN64(4) +#define ARM_PSCI_0_2_FN64_MIGRATE ARM_PSCI_0_2_FN64(5) +#define ARM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU ARM_PSCI_0_2_FN64(7) + +/* PSCI 1.0 interface */ +#define ARM_PSCI_1_0_FN_PSCI_FEATURES ARM_PSCI_0_2_FN(10) +#define ARM_PSCI_1_0_FN_CPU_FREEZE ARM_PSCI_0_2_FN(11) +#define ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND ARM_PSCI_0_2_FN(12) +#define ARM_PSCI_1_0_FN_NODE_HW_STATE ARM_PSCI_0_2_FN(13) +#define ARM_PSCI_1_0_FN_SYSTEM_SUSPEND ARM_PSCI_0_2_FN(14) +#define ARM_PSCI_1_0_FN_SET_SUSPEND_MODE ARM_PSCI_0_2_FN(15) +#define ARM_PSCI_1_0_FN_STAT_RESIDENCY ARM_PSCI_0_2_FN(16) +#define ARM_PSCI_1_0_FN_STAT_COUNT ARM_PSCI_0_2_FN(17) + +#define ARM_PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND ARM_PSCI_0_2_FN64(12) +#define ARM_PSCI_1_0_FN64_NODE_HW_STATE ARM_PSCI_0_2_FN64(13) +#define ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND ARM_PSCI_0_2_FN64(14) +#define ARM_PSCI_1_0_FN64_STAT_RESIDENCY ARM_PSCI_0_2_FN64(16) +#define ARM_PSCI_1_0_FN64_STAT_COUNT ARM_PSCI_0_2_FN64(17) + +/* PSCI affinity level state returned by AFFINITY_INFO */ +#define PSCI_AFFINITY_LEVEL_ON 0 +#define PSCI_AFFINITY_LEVEL_OFF 1 +#define PSCI_AFFINITY_LEVEL_ON_PENDING 2 + +struct psci_ops { + int (*cpu_suspend)(u32 power_state, unsigned long entry, u32 context_id); + int (*cpu_off)(void); + int (*cpu_on)(u32 cpu_id); + int (*affinity_info)(u32 affinity, u32 lowest_affinity_level); + int (*migrate)(u32 cpu_id); + int (*migrate_info_type)(void); + int (*migrate_info_up_cpu)(void); + void (*system_off)(void); + void (*system_reset)(void); +}; + +#ifdef CONFIG_ARM_PSCI +void psci_set_ops(struct psci_ops *ops); +#else +static inline void psci_set_ops(struct psci_ops *ops) +{ +} +#endif + +void psci_cpu_entry(void); + +#ifdef CONFIG_ARM_PSCI_DEBUG +void psci_set_putc(void (*putcf)(void *ctx, int c), void *ctx); +void psci_putc(char c); +int psci_puts(const char *str); +int psci_printf(const char *fmt, ...) + __attribute__ ((format(__printf__, 1, 2))); +#else + +static inline void psci_set_putc(void (*putcf)(void *ctx, int c), void *ctx) +{ +} + +static inline void psci_putc(char c) +{ +} + +static inline int psci_puts(const char *str) +{ + return 0; +} + +static inline int psci_printf(const char *fmt, ...) +{ + return 0; +} +#endif + +int psci_get_cpu_id(void); + +#endif /* __ARM_PSCI_H__ */ diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 022d365..6520a0a 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -32,6 +32,7 @@ #define IRQ_MODE 0x00000012 #define SVC_MODE 0x00000013 #define ABT_MODE 0x00000017 +#define HYP_MODE 0x0000001a #define UND_MODE 0x0000001b #define SYSTEM_MODE 0x0000001f #define MODE32_BIT 0x00000010 diff --git a/arch/arm/include/asm/secure.h b/arch/arm/include/asm/secure.h new file mode 100644 index 0000000..a4cb1f6 --- /dev/null +++ b/arch/arm/include/asm/secure.h @@ -0,0 +1,39 @@ +#ifndef __ASM_ARM_SECURE_H +#define __ASM_ARM_SECURE_H + +#ifndef __ASSEMBLY__ + +int armv7_secure_monitor_install(void); +int __armv7_secure_monitor_install(void); +void armv7_switch_to_hyp(void); + +extern unsigned char secure_monitor_init_vectors[]; + +enum arm_security_state { + ARM_STATE_SECURE, + ARM_STATE_NONSECURE, + ARM_STATE_HYP, +}; + +#ifdef CONFIG_ARM_SECURE_MONITOR +enum arm_security_state bootm_arm_security_state(void); +const char *bootm_arm_security_state_name(enum arm_security_state state); +#else +static inline enum arm_security_state bootm_arm_security_state(void) +{ + return ARM_STATE_SECURE; +} + +static inline const char *bootm_arm_security_state_name( + enum arm_security_state state) +{ + return "secure"; +} +#endif + +#endif /* __ASSEMBLY__ */ + +#define ARM_SECURE_STACK_SHIFT 10 +#define ARM_SECURE_MAX_CPU 8 + +#endif /* __ASM_ARM_SECURE_H */ diff --git a/arch/arm/include/asm/unwind.h b/arch/arm/include/asm/unwind.h index 311ad3d..a6f3a91 100644 --- a/arch/arm/include/asm/unwind.h +++ b/arch/arm/include/asm/unwind.h @@ -48,4 +48,10 @@ #endif /* !__ASSEMBLY__ */ +#ifdef CONFIG_ARM_UNWIND +#define UNWIND(code...) code +#else +#define UNWIND(code...) +#endif + #endif /* __ASM_UNWIND_H */ diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 9bd92f6..8068a53 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -133,6 +134,7 @@ { unsigned long kernel; unsigned long initrd_start = 0, initrd_size = 0, initrd_end = 0; + enum arm_security_state state = bootm_arm_security_state(); int ret; kernel = data->os_res->start + data->os_entry; @@ -174,10 +176,20 @@ printf("...\n"); } + if (IS_ENABLED(CONFIG_ARM_SECURE_MONITOR)) { + if (file_detect_type((void *)data->os_res->start, 0x100) == + filetype_arm_barebox) + state = ARM_STATE_SECURE; + + printf("Starting kernel in %s mode\n", + bootm_arm_security_state_name(state)); + } + if (data->dryrun) return 0; - start_linux((void *)kernel, swap, initrd_start, initrd_size, data->oftree); + start_linux((void *)kernel, swap, initrd_start, initrd_size, data->oftree, + state); restart_machine(); diff --git a/arch/arm/lib/bootu.c b/arch/arm/lib/bootu.c index 19009c8..d811da3 100644 --- a/arch/arm/lib/bootu.c +++ b/arch/arm/lib/bootu.c @@ -26,7 +26,7 @@ oftree = of_get_fixed_tree(NULL); #endif - start_linux(kernel, 0, 0, 0, oftree); + start_linux(kernel, 0, 0, 0, oftree, ARM_STATE_SECURE); return 1; } diff --git a/arch/arm/lib32/armlinux.c b/arch/arm/lib32/armlinux.c index 6c7bd10..2520fe2 100644 --- a/arch/arm/lib32/armlinux.c +++ b/arch/arm/lib32/armlinux.c @@ -38,6 +38,7 @@ #include #include #include +#include static struct tag *params; static void *armlinux_bootparams = NULL; @@ -258,11 +259,19 @@ } void start_linux(void *adr, int swap, unsigned long initrd_address, - unsigned long initrd_size, void *oftree) + unsigned long initrd_size, void *oftree, + enum arm_security_state state) { void (*kernel)(int zero, int arch, void *params) = adr; void *params = NULL; int architecture; + int ret; + + if (IS_ENABLED(CONFIG_ARM_SECURE_MONITOR) && state > ARM_STATE_SECURE) { + ret = armv7_secure_monitor_install(); + if (ret) + pr_err("Failed to install secure monitor\n"); + } if (oftree) { pr_debug("booting kernel with devicetree\n"); @@ -274,6 +283,10 @@ architecture = armlinux_get_architecture(); shutdown_barebox(); + + if (IS_ENABLED(CONFIG_ARM_SECURE_MONITOR) && state == ARM_STATE_HYP) + armv7_switch_to_hyp(); + if (swap) { u32 reg; __asm__ __volatile__("mrc p15, 0, %0, c1, c0" : "=r" (reg)); diff --git a/arch/arm/lib32/barebox.lds.S b/arch/arm/lib32/barebox.lds.S index 5fd39dc..b49c269 100644 --- a/arch/arm/lib32/barebox.lds.S +++ b/arch/arm/lib32/barebox.lds.S @@ -19,6 +19,7 @@ */ #include +#include OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) @@ -123,6 +124,15 @@ __bss_start = .; .bss : { *(.bss*) } __bss_stop = .; + +#ifdef CONFIG_ARM_SECURE_MONITOR + . = ALIGN(16); + __secure_stack_start = .; + . = . + (ARM_SECURE_MAX_CPU << ARM_SECURE_STACK_SHIFT); + __secure_stack_end = .; + __secure_end = .; +#endif + _end = .; _barebox_image_size = __bss_start - TEXT_BASE; } diff --git a/arch/arm/lib32/bootz.c b/arch/arm/lib32/bootz.c index 5167c9d..c0ffd93 100644 --- a/arch/arm/lib32/bootz.c +++ b/arch/arm/lib32/bootz.c @@ -112,7 +112,7 @@ oftree = of_get_fixed_tree(NULL); #endif - start_linux(zimage, swap, 0, 0, oftree); + start_linux(zimage, swap, 0, 0, oftree, ARM_STATE_SECURE); return 0; diff --git a/arch/arm/lib64/armlinux.c b/arch/arm/lib64/armlinux.c index 020e6d7..54ce6ca 100644 --- a/arch/arm/lib64/armlinux.c +++ b/arch/arm/lib64/armlinux.c @@ -40,7 +40,8 @@ #include void start_linux(void *adr, int swap, unsigned long initrd_address, - unsigned long initrd_size, void *oftree) + unsigned long initrd_size, void *oftree, + enum arm_security_state bootm_secure_state) { void (*kernel)(void *dtb) = adr; diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 9dbe31c..f83aedc 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -39,6 +39,7 @@ default 0x4fc00000 if MACH_UDOO default 0x4fc00000 if MACH_VARISCITE_MX6 default 0x4fc00000 if MACH_PHYTEC_SOM_IMX6 + default 0x9fc00000 if MACH_WARP7 config ARCH_IMX_IMXIMAGE bool @@ -147,6 +148,10 @@ select COMMON_CLK_OF_PROVIDER select HW_HAS_PCI +config ARCH_IMX6SL + bool + select ARCH_IMX6 + config ARCH_IMX6SX bool select ARCH_IMX6 @@ -157,6 +162,12 @@ bool select ARCH_IMX6 +config ARCH_IMX7 + bool + select CPU_V7 + select OFTREE + select COMMON_CLK_OF_PROVIDER + config ARCH_VF610 bool select ARCH_HAS_L2X0 @@ -166,6 +177,7 @@ select OFTREE select COMMON_CLK select COMMON_CLK_OF_PROVIDER + select IMX_OCOTP # Needed for clock adjustement config IMX_MULTI_BOARDS bool "Allow multiple boards to be selected" @@ -346,10 +358,23 @@ bool "CM FX6" select ARCH_IMX6 +config MACH_WARP7 + bool "NXP i.MX7: element 14 WaRP7 Board" + select ARCH_IMX7 + config MACH_VF610_TWR bool "Freescale VF610 Tower Board" select ARCH_VF610 +config MACH_ZII_RDU2 + bool "ZII i.MX6Q(+) RDU2" + select ARCH_IMX6 + +config MACH_ZII_VF610_DEV + bool "Zodiac VF610 Dev Family" + select ARCH_VF610 + select CLKDEV_LOOKUP + endif # ---------------------------------------------------------- diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index d0fe7ab..fc5305f 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -13,6 +13,7 @@ pbl-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o +obj-$(CONFIG_ARCH_IMX7) += imx7.o obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_IMX_OCOTP) += ocotp.o diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c index 4893060..72597f5 100644 --- a/arch/arm/mach-imx/boot.c +++ b/arch/arm/mach-imx/boot.c @@ -25,6 +25,7 @@ #include #include #include +#include /* [CTRL][TYPE] */ static const enum bootsource locations[4][4] = { @@ -346,3 +347,72 @@ bootsource_set(src); bootsource_set_instance(instance); } + +#define IMX7_SRC_SBMR1 0x58 +#define IMX7_SRC_SBMR2 0x70 + +void imx7_get_boot_source(enum bootsource *src, int *instance) +{ + void __iomem *src_base = IOMEM(MX7_SRC_BASE_ADDR); + uint32_t sbmr1 = readl(src_base + IMX7_SRC_SBMR1); + uint32_t sbmr2 = readl(src_base + IMX7_SRC_SBMR2); + int boot_mode; + + /* BMOD[1:0] */ + boot_mode = (sbmr2 >> 24) & 0x3; + + switch (boot_mode) { + case 0: /* Fuses, fall through */ + case 2: /* internal boot */ + goto internal_boot; + case 1: /* Serial Downloader */ + *src = BOOTSOURCE_SERIAL; + break; + case 3: /* reserved */ + break; + }; + + return; + +internal_boot: + + switch ((sbmr1 >> 12) & 0xf) { + case 1: + case 2: + *src = BOOTSOURCE_MMC; + *instance = (sbmr1 >> 10 & 0x3); + break; + case 3: + *src = BOOTSOURCE_NAND; + break; + case 4: + *src = BOOTSOURCE_SPI_NOR, + *instance = (sbmr1 >> 9 & 0x7); + break; + case 6: + *src = BOOTSOURCE_SPI; /* Really: qspi */ + break; + case 5: + *src = BOOTSOURCE_NOR; + break; + default: + break; + } + + /* BOOT_CFG1[7:0] */ + if (sbmr1 & (1 << 7)) + *src = BOOTSOURCE_NAND; + + return; +} + +void imx7_boot_save_loc(void) +{ + enum bootsource src = BOOTSOURCE_UNKNOWN; + int instance = BOOTSOURCE_INSTANCE_UNKNOWN; + + imx7_get_boot_source(&src, &instance); + + bootsource_set(src); + bootsource_set_instance(instance); +} diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c index 8d00bbb..8482abd 100644 --- a/arch/arm/mach-imx/clocksource.c +++ b/arch/arm/mach-imx/clocksource.c @@ -155,6 +155,9 @@ .compatible = "fsl,imx6ul-gpt", .data = ®s_imx31, }, { + .compatible = "fsl,imx7d-gpt", + .data = ®s_imx31, + }, { /* sentinel */ } }; diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c index 6971d89..2b388ca 100644 --- a/arch/arm/mach-imx/cpu_init.c +++ b/arch/arm/mach-imx/cpu_init.c @@ -34,6 +34,11 @@ enable_arm_errata_845369_war(); } +void imx7_cpu_lowlevel_init(void) +{ + arm_cpu_lowlevel_init(); +} + void vf610_cpu_lowlevel_init(void) { arm_cpu_lowlevel_init(); diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c index ffe708f..1eebc77 100644 --- a/arch/arm/mach-imx/esdctl.c +++ b/arch/arm/mach-imx/esdctl.c @@ -432,6 +432,9 @@ static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = { { + .compatible = "fsl,imx6sl-mmdc", + .data = &imx6ul_data + }, { .compatible = "fsl,imx6ul-mmdc", .data = &imx6ul_data }, { diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c index 952db00..1990739 100644 --- a/arch/arm/mach-imx/imx.c +++ b/arch/arm/mach-imx/imx.c @@ -61,10 +61,16 @@ return IMX_CPU_IMX6; if (of_machine_is_compatible("fsl,imx6sx")) return IMX_CPU_IMX6; + if (of_machine_is_compatible("fsl,imx6sl")) + return IMX_CPU_IMX6; if (of_machine_is_compatible("fsl,imx6qp")) return IMX_CPU_IMX6; if (of_machine_is_compatible("fsl,imx6ul")) return IMX_CPU_IMX6; + if (of_machine_is_compatible("fsl,imx7s")) + return IMX_CPU_IMX7; + if (of_machine_is_compatible("fsl,imx7d")) + return IMX_CPU_IMX7; if (of_machine_is_compatible("fsl,vf610")) return IMX_CPU_VF610; @@ -103,6 +109,8 @@ ret = imx53_init(); else if (cpu_is_mx6()) ret = imx6_init(); + else if (cpu_is_mx7()) + ret = imx7_init(); else if (cpu_is_vf610()) ret = 0; else diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index b2979b0..44a8dbe 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -151,6 +151,9 @@ case IMX6_CPUTYPE_IMX6S: cputypestr = "i.MX6 Solo"; break; + case IMX6_CPUTYPE_IMX6SL: + cputypestr = "i.MX6 SoloLite"; + break; case IMX6_CPUTYPE_IMX6SX: cputypestr = "i.MX6 SoloX"; break; diff --git a/arch/arm/mach-imx/imx7.c b/arch/arm/mach-imx/imx7.c new file mode 100644 index 0000000..4eef99c --- /dev/null +++ b/arch/arm/mach-imx/imx7.c @@ -0,0 +1,202 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void imx7_init_lowlevel(void) +{ + void __iomem *aips1 = IOMEM(MX7_AIPS1_CONFIG_BASE_ADDR); + void __iomem *aips2 = IOMEM(MX7_AIPS2_CONFIG_BASE_ADDR); + + /* + * Set all MPROTx to be non-bufferable, trusted for R/W, + * not forced to user-mode. + */ + writel(0x77777777, aips1); + writel(0x77777777, aips1 + 0x4); + writel(0, aips1 + 0x40); + writel(0, aips1 + 0x44); + writel(0, aips1 + 0x48); + writel(0, aips1 + 0x4c); + writel(0, aips1 + 0x50); + + writel(0x77777777, aips2); + writel(0x77777777, aips2 + 0x4); + writel(0, aips2 + 0x40); + writel(0, aips2 + 0x44); + writel(0, aips2 + 0x48); + writel(0, aips2 + 0x4c); + writel(0, aips2 + 0x50); +} + +#define SC_CNTCR 0x0 +#define SC_CNTSR 0x4 +#define SC_CNTCV1 0x8 +#define SC_CNTCV2 0xc +#define SC_CNTFID0 0x20 +#define SC_CNTFID1 0x24 +#define SC_CNTFID2 0x28 +#define SC_counterid 0xfcc + +#define SC_CNTCR_ENABLE (1 << 0) +#define SC_CNTCR_HDBG (1 << 1) +#define SC_CNTCR_FREQ0 (1 << 8) +#define SC_CNTCR_FREQ1 (1 << 9) + +static int imx7_timer_init(void) +{ + void __iomem *sctr = IOMEM(MX7_SYSCNT_CTRL_BASE_ADDR); + unsigned long val, freq; + + freq = 8000000; + asm("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq)); + + writel(freq, sctr + SC_CNTFID0); + + /* Enable system counter */ + val = readl(sctr + SC_CNTCR); + val &= ~(SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1); + val |= SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG; + writel(val, sctr + SC_CNTCR); + + return 0; +} + +#define CSU_NUM_REGS 64 +#define CSU_INIT_SEC_LEVEL0 0x00FF00FF + +static void imx7_init_csu(void) +{ + void __iomem *csu = IOMEM(MX7_CSU_BASE_ADDR); + int i = 0; + + for (i = 0; i < CSU_NUM_REGS; i++) + writel(CSU_INIT_SEC_LEVEL0, csu + i * 4); +} + +#define GPC_CPU_PGC_SW_PDN_REQ 0xfc +#define GPC_CPU_PGC_SW_PUP_REQ 0xf0 +#define GPC_PGC_C1 0x840 +#define GPC_PGC(n) (0x800 + (n) * 0x40) + +#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2 + +#define PGC_CTRL 0x0 + +/* below is for i.MX7D */ +#define SRC_GPR1_MX7D 0x074 +#define SRC_A7RCR1 0x008 + +static void imx_gpcv2_set_core_power(int core, bool pdn) +{ + void __iomem *gpc = IOMEM(MX7_GPC_BASE_ADDR); + void __iomem *pgc = gpc + GPC_PGC(core); + + u32 reg = pdn ? GPC_CPU_PGC_SW_PUP_REQ : GPC_CPU_PGC_SW_PDN_REQ; + u32 val; + + writel(1, pgc + PGC_CTRL); + + val = readl(gpc + reg); + val |= 1 << core; + writel(val, gpc + reg); + + while (readl(gpc + reg) & (1 << core)); + + writel(0, pgc + PGC_CTRL); +} + +static int imx7_cpu_on(u32 cpu_id) +{ + void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR); + u32 val; + + writel(psci_cpu_entry, src + cpu_id * 8 + SRC_GPR1_MX7D); + imx_gpcv2_set_core_power(cpu_id, true); + + val = readl(src + SRC_A7RCR1); + val |= 1 << cpu_id; + writel(val, src + SRC_A7RCR1); + + return 0; +} + +static int imx7_cpu_off(void) +{ + void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR); + u32 val; + int cpu_id = psci_get_cpu_id(); + + val = readl(src + SRC_A7RCR1); + val &= ~(1 << cpu_id); + writel(val, src + SRC_A7RCR1); + + /* + * FIXME: This reads nice and symmetrically to cpu_on above, + * but of course this will never be reached as we have just + * put the CPU we are currently running on into reset. + */ + + imx_gpcv2_set_core_power(cpu_id, false); + + while (1); + + return 0; +} + +static struct psci_ops imx7_psci_ops = { + .cpu_on = imx7_cpu_on, + .cpu_off = imx7_cpu_off, +}; + +int imx7_init(void) +{ + const char *cputypestr; + u32 imx7_silicon_revision; + + imx7_init_lowlevel(); + + imx7_init_csu(); + + imx7_timer_init(); + + imx7_boot_save_loc(); + + imx7_silicon_revision = imx7_cpu_revision(); + + psci_set_ops(&imx7_psci_ops); + + switch (imx7_cpu_type()) { + case IMX7_CPUTYPE_IMX7D: + cputypestr = "i.MX7d"; + break; + case IMX7_CPUTYPE_IMX7S: + cputypestr = "i.MX7s"; + break; + default: + cputypestr = "unknown i.MX7"; + break; + } + + imx_set_silicon_revision(cputypestr, imx7_silicon_revision); + + return 0; +} diff --git a/arch/arm/mach-imx/include/mach/debug_ll.h b/arch/arm/mach-imx/include/mach/debug_ll.h index a132f3c..39d710f 100644 --- a/arch/arm/mach-imx/include/mach/debug_ll.h +++ b/arch/arm/mach-imx/include/mach/debug_ll.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,8 @@ #define IMX_DEBUG_SOC MX53 #elif defined CONFIG_DEBUG_IMX6Q_UART #define IMX_DEBUG_SOC MX6 +#elif defined CONFIG_DEBUG_IMX7D_UART +#define IMX_DEBUG_SOC MX7 #elif defined CONFIG_DEBUG_VF610_UART #define IMX_DEBUG_SOC VF610 #else diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h index 3419450..73be9ce 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -14,12 +14,14 @@ void imx51_boot_save_loc(void); void imx53_boot_save_loc(void); void imx6_boot_save_loc(void); +void imx7_boot_save_loc(void); void imx25_get_boot_source(enum bootsource *src, int *instance); void imx35_get_boot_source(enum bootsource *src, int *instance); void imx51_get_boot_source(enum bootsource *src, int *instance); void imx53_get_boot_source(enum bootsource *src, int *instance); void imx6_get_boot_source(enum bootsource *src, int *instance); +void imx7_get_boot_source(enum bootsource *src, int *instance); int imx1_init(void); int imx21_init(void); @@ -31,6 +33,7 @@ int imx51_init(void); int imx53_init(void); int imx6_init(void); +int imx7_init(void); int imx1_devices_init(void); int imx21_devices_init(void); @@ -45,6 +48,7 @@ void imx5_cpu_lowlevel_init(void); void imx6_cpu_lowlevel_init(void); +void imx7_cpu_lowlevel_init(void); void vf610_cpu_lowlevel_init(void); /* There's a off-by-one betweem the gpio bank number and the gpiochip */ @@ -174,6 +178,18 @@ # define cpu_is_mx6() (0) #endif +#ifdef CONFIG_ARCH_IMX7 +# ifdef imx_cpu_type +# undef imx_cpu_type +# define imx_cpu_type __imx_cpu_type +# else +# define imx_cpu_type IMX_CPU_IMX7 +# endif +# define cpu_is_mx7() (imx_cpu_type == IMX_CPU_IMX7) +#else +# define cpu_is_mx7() (0) +#endif + #ifdef CONFIG_ARCH_VF610 # ifdef imx_cpu_type # undef imx_cpu_type diff --git a/arch/arm/mach-imx/include/mach/imx6-fusemap.h b/arch/arm/mach-imx/include/mach/imx6-fusemap.h index 5fdd904..e14044e 100644 --- a/arch/arm/mach-imx/include/mach/imx6-fusemap.h +++ b/arch/arm/mach-imx/include/mach/imx6-fusemap.h @@ -1,62 +1,22 @@ #ifndef __MACH_IMX_IMX6_OCOTP_H #define __MACH_IMX_IMX6_OCOTP_H -#include +#include -#define IMX6_OCOTP_TESTER_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(0) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_BOOT_CFG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(2) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_MEM_TRIM_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(4) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_SJC_RESP_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(6) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_MAC_ADDR_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(8) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_GP1_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(10) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_GP2_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(12) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_SRK_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(14) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_ANALOG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(18) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_MISC_CONF_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(22) | OCOTP_WIDTH(1)) - -/* 0 <= n <= 1 */ -#define IMX6_OCOTP_UNIQUE_ID(n) (OCOTP_WORD(0x410 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) #define IMX6_OCOTP_SI_REV (OCOTP_WORD(0x430) | OCOTP_BIT(16) | OCOTP_WIDTH(4)) -#define IMX6_OCOTP_NUM_CORES (OCOTP_WORD(0x430) | OCOTP_BIT(20) | OCOTP_WIDTH(2)) #define IMX6_OCOTP_SATA_RST_SRC (OCOTP_WORD(0x430) | OCOTP_BIT(24) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_MLB_DISABLE (OCOTP_WORD(0x430) | OCOTP_BIT(26) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_VPU_DISABLE (OCOTP_WORD(0x440) | OCOTP_BIT(15) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_SPEED_GRADING (OCOTP_WORD(0x440) | OCOTP_BIT(16) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_BOOT_CFG1 (OCOTP_WORD(0x450) | OCOTP_BIT(0) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_BOOT_CFG2 (OCOTP_WORD(0x450) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_BOOT_CFG3 (OCOTP_WORD(0x450) | OCOTP_BIT(16) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_BOOT_CFG4 (OCOTP_WORD(0x450) | OCOTP_BIT(24) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_SEC_CONFIG (OCOTP_WORD(0x460) | OCOTP_BIT(1) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_DIR_BT_DIS (OCOTP_WORD(0x460) | OCOTP_BIT(3) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_BT_FUSE_SEL (OCOTP_WORD(0x460) | OCOTP_BIT(4) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_DDR3_CONFIG (OCOTP_WORD(0x460) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) #define IMX6_OCOTP_HDCP (OCOTP_WORD(0x460) | OCOTP_BIT(16) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_SJC_DISABLE (OCOTP_WORD(0x460) | OCOTP_BIT(20) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_WDOG_ENABLE (OCOTP_WORD(0x460) | OCOTP_BIT(21) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_JTAG_SMODE (OCOTP_WORD(0x460) | OCOTP_BIT(22) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_KTE (OCOTP_WORD(0x460) | OCOTP_BIT(26) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_JTAG_HEO (OCOTP_WORD(0x460) | OCOTP_BIT(27) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_TZASC_ENABLE (OCOTP_WORD(0x460) | OCOTP_BIT(28) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_SDMMC_HYS_EN (OCOTP_WORD(0x460) | OCOTP_BIT(29) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_eMMC_RESET_EN (OCOTP_WORD(0x460) | OCOTP_BIT(30) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_NAND_READ_CMD_CODE1 (OCOTP_WORD(0x470) | OCOTP_BIT(0) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_NAND_READ_CMD_CODE2 (OCOTP_WORD(0x470) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) #define IMX6_OCOTP_BT_LPB_POLARITY (OCOTP_WORD(0x470) | OCOTP_BIT(20) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_LPB_BOOT (OCOTP_WORD(0x470) | OCOTP_BIT(21) | OCOTP_WIDTH(2)) #define IMX6_OCOTP_MMC_DLL_DLY (OCOTP_WORD(0x470) | OCOTP_BIT(24) | OCOTP_WIDTH(7)) #define IMX6_OCOTP_TEMPERATURE_GRADE (OCOTP_WORD(0x480) | OCOTP_BIT(6) | OCOTP_WIDTH(2)) #define IMX6_OCOTP_POWER_GATE_CORES (OCOTP_WORD(0x4d0) | OCOTP_BIT(31) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_USB_VID (OCOTP_WORD(0x4f0) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) -#define IMX6_OCOTP_USB_PID (OCOTP_WORD(0x4f0) | OCOTP_BIT(16) | OCOTP_WIDTH(16)) -/* 0 <= n <= 7 */ -#define IMX6_OCOTP_SRK_HASH(n) (OCOTP_WORD(0x580 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_SJC_RESP_31_0 (OCOTP_WORD(0x600) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_SJC_RESP_55_32 (OCOTP_WORD(0x610) | OCOTP_BIT(0) | OCOTP_WIDTH(24)) -#define IMX6_OCOTP_MAC_ADDR_31_0 (OCOTP_WORD(0x620) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_MAC_ADDR_47_32 (OCOTP_WORD(0x630) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) -#define IMX6_OCOTP_GP1 (OCOTP_WORD(0x660) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_GP2 (OCOTP_WORD(0x670) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_PAD_SETTINGS (OCOTP_WORD(0x6d0) | OCOTP_BIT(0) | OCOTP_WIDTH(6)) #define IMX6DQ_OCOTP_TEST_PORT_DISABLE (OCOTP_WORD(0x6e0) | OCOTP_BIT(1) | OCOTP_WIDTH(1)) #define IMX6SDL_OCOTP_FIELD_RETURN (OCOTP_WORD(0x6e0) | OCOTP_BIT(0) | OCOTP_WIDTH(1)) diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h index 8c169f1..327676b 100644 --- a/arch/arm/mach-imx/include/mach/imx6.h +++ b/arch/arm/mach-imx/include/mach/imx6.h @@ -9,7 +9,9 @@ void imx6_init_lowlevel(void); #define IMX6_ANATOP_SI_REV 0x260 +#define IMX6SL_ANATOP_SI_REV 0x280 +#define IMX6_CPUTYPE_IMX6SL 0x160 #define IMX6_CPUTYPE_IMX6S 0x161 #define IMX6_CPUTYPE_IMX6DL 0x261 #define IMX6_CPUTYPE_IMX6SX 0x462 @@ -36,6 +38,16 @@ val = readl(MX6_ANATOP_BASE_ADDR + IMX6_ANATOP_SI_REV); val = (val >> 16) & 0xff; + /* non-MX6-standard SI_REV reg offset for MX6SL */ + if (IS_ENABLED(CONFIG_ARCH_IMX6SL) && + val < (IMX6_CPUTYPE_IMX6S & 0xff)) { + uint32_t tmp; + tmp = readl(MX6_ANATOP_BASE_ADDR + IMX6SL_ANATOP_SI_REV); + tmp = (tmp >> 16) & 0xff; + if ((IMX6_CPUTYPE_IMX6SL & 0xff) == tmp) + /* intentionally skip scu_get_core_count() for MX6SL */ + return IMX6_CPUTYPE_IMX6SL; + } val |= scu_get_core_count() << 8; @@ -50,12 +62,37 @@ return __imx6_cpu_type(); } +#define DEFINE_MX6_CPU_TYPE(str, type) \ + static inline int cpu_mx6_is_##str(void) \ + { \ + return __imx6_cpu_type() == type; \ + } \ + \ + static inline int cpu_is_##str(void) \ + { \ + if (!cpu_is_mx6()) \ + return 0; \ + return cpu_mx6_is_##str(); \ + } + +DEFINE_MX6_CPU_TYPE(mx6s, IMX6_CPUTYPE_IMX6S); +DEFINE_MX6_CPU_TYPE(mx6dl, IMX6_CPUTYPE_IMX6DL); +DEFINE_MX6_CPU_TYPE(mx6q, IMX6_CPUTYPE_IMX6Q); +DEFINE_MX6_CPU_TYPE(mx6d, IMX6_CPUTYPE_IMX6D); +DEFINE_MX6_CPU_TYPE(mx6sx, IMX6_CPUTYPE_IMX6SX); +DEFINE_MX6_CPU_TYPE(mx6sl, IMX6_CPUTYPE_IMX6SL); +DEFINE_MX6_CPU_TYPE(mx6ul, IMX6_CPUTYPE_IMX6UL); + static inline int __imx6_cpu_revision(void) { uint32_t rev; + uint32_t si_rev_offset = IMX6_ANATOP_SI_REV; - rev = readl(MX6_ANATOP_BASE_ADDR + IMX6_ANATOP_SI_REV); + if (IS_ENABLED(CONFIG_ARCH_IMX6SL) && cpu_mx6_is_mx6sl()) + si_rev_offset = IMX6SL_ANATOP_SI_REV; + + rev = readl(MX6_ANATOP_BASE_ADDR + si_rev_offset); switch (rev & 0xfff) { case 0x00: @@ -85,24 +122,4 @@ return __imx6_cpu_revision(); } -#define DEFINE_MX6_CPU_TYPE(str, type) \ - static inline int cpu_mx6_is_##str(void) \ - { \ - return __imx6_cpu_type() == type; \ - } \ - \ - static inline int cpu_is_##str(void) \ - { \ - if (!cpu_is_mx6()) \ - return 0; \ - return cpu_mx6_is_##str(); \ - } - -DEFINE_MX6_CPU_TYPE(mx6s, IMX6_CPUTYPE_IMX6S); -DEFINE_MX6_CPU_TYPE(mx6dl, IMX6_CPUTYPE_IMX6DL); -DEFINE_MX6_CPU_TYPE(mx6q, IMX6_CPUTYPE_IMX6Q); -DEFINE_MX6_CPU_TYPE(mx6d, IMX6_CPUTYPE_IMX6D); -DEFINE_MX6_CPU_TYPE(mx6sx, IMX6_CPUTYPE_IMX6SX); -DEFINE_MX6_CPU_TYPE(mx6ul, IMX6_CPUTYPE_IMX6UL); - #endif /* __MACH_IMX6_H */ diff --git a/arch/arm/mach-imx/include/mach/imx7-regs.h b/arch/arm/mach-imx/include/mach/imx7-regs.h new file mode 100644 index 0000000..8774c32 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/imx7-regs.h @@ -0,0 +1,119 @@ +#ifndef __MACH_IMX7_REGS_H +#define __MACH_IMX7_REGS_H + +/* Defines for Blocks connected via AIPS */ +#define MX7_AIPS1_BASE_ADDR 0x30000000 +#define MX7_AIPS2_BASE_ADDR 0x30400000 +#define MX7_AIPS3_BASE_ADDR 0x30800000 + +/* ATZ#1- On Platform */ +#define MX7_DAP_BASE_ADDR (MX7_AIPS1_BASE_ADDR) +#define MX7_AIPS1_CONFIG_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x1F0000) + +/* ATZ#1- Off Platform */ +#define MX7_GPIO1_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x200000) +#define MX7_GPIO2_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x210000) +#define MX7_GPIO3_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x220000) +#define MX7_GPIO4_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x230000) +#define MX7_GPIO5_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x240000) +#define MX7_GPIO6_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x250000) +#define MX7_GPIO7_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x260000) +#define MX7_IOMUXC_LPSR_GPR_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x270000) +#define MX7_WDOG1_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x280000) +#define MX7_WDOG2_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x290000) +#define MX7_WDOG3_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2A0000) +#define MX7_WDOG4_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2B0000) +#define MX7_IOMUXC_LPSR_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2C0000) +#define MX7_GPT1_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2D0000) +#define MX7_GPT2_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2E0000) +#define MX7_GPT3_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2F0000) +#define MX7_GPT4_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x300000) +#define MX7_ROMCP_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x310000) +#define MX7_KPP_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x320000) +#define MX7_IOMUXC_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x330000) +#define MX7_IOMUXC_GPR_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x340000) +#define MX7_OCOTP_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x350000) +#define MX7_ANATOP_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x360000) +#define MX7_SNVS_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x370000) +#define MX7_CCM_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x380000) +#define MX7_SRC_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x390000) +#define MX7_GPC_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3A0000) +#define MX7_SEMAPHORE1_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3B0000) +#define MX7_SEMAPHORE2_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3C0000) +#define MX7_RDC_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3D0000) +#define MX7_CSU_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3E0000) + +/* ATZ#2- On Platform */ +#define MX7_AIPS2_CONFIG_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x1F0000) + +/* ATZ#2- Off Platform */ +#define MX7_ADC1_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x230000) +#define MX7_ADC2_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x230000) +#define MX7_ECSPI4_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x230000) +#define MX7_FTM1_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x240000) +#define MX7_FTM2_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x250000) +#define MX7_PWM1_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x260000) +#define MX7_PWM2_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x270000) +#define MX7_PWM3_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x280000) +#define MX7_PWM4_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x290000) +#define MX7_SYSCNT_RD_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2A0000) +#define MX7_SYSCNT_CMP_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2B0000) +#define MX7_SYSCNT_CTRL_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2C0000) +#define MX7_PCIE_PHY_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2D0000) +#define MX7_EPDC_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2F0000) +#define MX7_PXP_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x300000) +#define MX7_CSI_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x310000) +#define MX7_LCDIF_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x330000) +#define MX7_MIPI_CSI_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x350000) +#define MX7_MIPI_DSI_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x360000) +#define MX7_TZASC_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x380000) +#define MX7_DDRPHY_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x390000) +#define MX7_DDRC_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x3A0000) +#define MX7_IP2APB_PERFMON1_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x3C0000) +#define MX7_IP2APB_PERFMON2_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x3D0000) +#define MX7_AXI_DEBUG_MON_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x3E0000) + +/* ATZ#3- On Platform */ +#define MX7_ECSPI1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x20000) +#define MX7_ECSPI2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x30000) +#define MX7_ECSPI3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x40000) +#define MX7_UART1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x60000) +#define MX7_UART2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x70000) +#define MX7_UART3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x80000) +#define MX7_SAI1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0xA0000) +#define MX7_SAI2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0xB0000) +#define MX7_SAI3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0xC0000) +#define MX7_SPBA_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x90000) +#define MX7_CAAM_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x100000) +#define MX7_AIPS3_CONFIG_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x1F0000) + +/* ATZ#3- Off Platform */ +#define MX7_CAN1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x200000) +#define MX7_CAN2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x210000) +#define MX7_I2C1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x220000) +#define MX7_I2C2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x230000) +#define MX7_I2C3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x240000) +#define MX7_I2C4_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x250000) +#define MX7_UART4_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x260000) +#define MX7_UART5_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x270000) +#define MX7_UART6_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x280000) +#define MX7_UART7_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x290000) +#define MX7_MU_A_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x2A0000) +#define MX7_MU_B_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x2B0000) +#define MX7_SEM_HS_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x2C0000) +#define MX7_USBOH2_PL301_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x2D0000) +#define MX7_OTG1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x310000) +#define MX7_OTG2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x320000) +#define MX7_USBOH3_USB_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x330000) +#define MX7_USDHC1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x340000) +#define MX7_USDHC2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x350000) +#define MX7_USDHC3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x360000) +#define MX7_SIM1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x390000) +#define MX7_SIM2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3A0000) +#define MX7_QSPI_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3B0000) +#define MX7_WEIM_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3C0000) +#define MX7_SDMA_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3D0000) +#define MX7_ENET1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3E0000) +#define MX7_ENET2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3F0000) + +#endif /* __MACH_IMX7_REGS_H */ diff --git a/arch/arm/mach-imx/include/mach/imx7.h b/arch/arm/mach-imx/include/mach/imx7.h new file mode 100644 index 0000000..8518935 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/imx7.h @@ -0,0 +1,59 @@ +#ifndef __MACH_IMX7_H +#define __MACH_IMX7_H + +#include +#include +#include +#include + +void imx7_init_lowlevel(void); + +#define ANADIG_DIGPROG_IMX7 0x800 + +#define IMX7_CPUTYPE_IMX7S 0x71 +#define IMX7_CPUTYPE_IMX7D 0x72 + +static inline int __imx7_cpu_type(void) +{ + void __iomem *ocotp = IOMEM(MX7_OCOTP_BASE_ADDR); + + if (readl(ocotp + 0x450) & 1) + return IMX7_CPUTYPE_IMX7S; + else + return IMX7_CPUTYPE_IMX7D; +} + +static inline int imx7_cpu_type(void) +{ + if (!cpu_is_mx7()) + return 0; + + return __imx7_cpu_type(); +} + +static inline int imx7_cpu_revision(void) +{ + if (!cpu_is_mx7()) + return IMX_CHIP_REV_UNKNOWN; + + /* register value has the format of the IMX_CHIP_REV_* macros */ + return readl(MX7_ANATOP_BASE_ADDR + ANADIG_DIGPROG_IMX7) & 0xff; +} + +#define DEFINE_MX7_CPU_TYPE(str, type) \ + static inline int cpu_mx7_is_##str(void) \ + { \ + return __imx7_cpu_type() == type; \ + } \ + \ + static inline int cpu_is_##str(void) \ + { \ + if (!cpu_is_mx7()) \ + return 0; \ + return cpu_mx7_is_##str(); \ + } + +DEFINE_MX7_CPU_TYPE(mx7s, IMX7_CPUTYPE_IMX7S); +DEFINE_MX7_CPU_TYPE(mx7d, IMX7_CPUTYPE_IMX7D); + +#endif /* __MACH_IMX7_H */ \ No newline at end of file diff --git a/arch/arm/mach-imx/include/mach/imx_cpu_types.h b/arch/arm/mach-imx/include/mach/imx_cpu_types.h index 50be0b6..f95ef6f 100644 --- a/arch/arm/mach-imx/include/mach/imx_cpu_types.h +++ b/arch/arm/mach-imx/include/mach/imx_cpu_types.h @@ -11,6 +11,7 @@ #define IMX_CPU_IMX51 51 #define IMX_CPU_IMX53 53 #define IMX_CPU_IMX6 6 +#define IMX_CPU_IMX7 7 #define IMX_CPU_VF610 610 #endif /* __MACH_IMX_CPU_TYPES_H */ diff --git a/arch/arm/mach-imx/include/mach/iomux-v3.h b/arch/arm/mach-imx/include/mach/iomux-v3.h index b8cc9af..271fe94 100644 --- a/arch/arm/mach-imx/include/mach/iomux-v3.h +++ b/arch/arm/mach-imx/include/mach/iomux-v3.h @@ -16,6 +16,8 @@ #ifndef __MACH_IOMUX_V3_H__ #define __MACH_IOMUX_V3_H__ +#include + /* * build IOMUX_PAD structure * @@ -76,6 +78,14 @@ ((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \ ((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT)) +#define IOMUX_PAD_FIELD(name, pad) (((pad) & name##_MASK) >> name##_SHIFT) +#define IOMUX_CTRL_OFS(pad) IOMUX_PAD_FIELD(MUX_CTRL_OFS, pad) +#define IOMUX_MODE(pad) IOMUX_PAD_FIELD(MUX_MODE, pad) +#define IOMUX_SEL_INPUT_OFS(pad) IOMUX_PAD_FIELD(MUX_SEL_INPUT_OFS, pad) +#define IOMUX_SEL_INPUT(pad) IOMUX_PAD_FIELD(MUX_SEL_INPUT, pad) +#define IOMUX_PAD_CTRL_OFS(pad) IOMUX_PAD_FIELD(MUX_PAD_CTRL_OFS, pad) +#define IOMUX_PAD_CTRL(pad) IOMUX_PAD_FIELD(MUX_PAD_CTRL, pad) + #define NEW_PAD_CTRL(cfg, pad) (((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad)) /* * Use to set PAD control @@ -104,6 +114,57 @@ #define IOMUX_CONFIG_SION (0x1 << 4) +#define SHARE_MUX_CONF_REG 0x1 +#define ZERO_OFFSET_VALID 0x2 +#define IMX7_PINMUX_LPSR 0x4 + +static inline void iomux_v3_setup_pad(void __iomem *iomux, unsigned int flags, + u32 mux_reg, u32 conf_reg, u32 input_reg, + u32 mux_val, u32 conf_val, u32 input_val) +{ + const bool mux_ok = !!mux_reg || (flags & ZERO_OFFSET_VALID); + const bool conf_ok = !!conf_reg; + const bool input_ok = !!input_reg; + + /* + * The sel_input registers for the LPSR controller pins are in the regular pinmux + * controller, so bend the register offset over to the other controller. + */ + if (flags & IMX7_PINMUX_LPSR) + input_reg += 0x70000; + + if (flags & SHARE_MUX_CONF_REG) { + mux_val |= conf_val; + } else { + if (conf_ok) + writel(conf_val, iomux + conf_reg); + } + + if (mux_ok) + writel(mux_val, iomux + mux_reg); + + if (input_ok) + writel(input_val, iomux + input_reg); +} + +static inline void imx_setup_pad(void __iomem *iomux, iomux_v3_cfg_t pad) +{ + uint32_t pad_ctrl; + + pad_ctrl = IOMUX_PAD_CTRL(pad); + pad_ctrl = (pad_ctrl & NO_PAD_CTRL) ? 0 : pad_ctrl, + + iomux_v3_setup_pad(iomux, 0, + IOMUX_CTRL_OFS(pad), + IOMUX_PAD_CTRL_OFS(pad), + IOMUX_SEL_INPUT_OFS(pad), + IOMUX_MODE(pad), + pad_ctrl, + IOMUX_SEL_INPUT(pad)); +} + + + /* * setups a single pad in the iomuxer */ diff --git a/arch/arm/mach-imx/include/mach/iomux-vf610.h b/arch/arm/mach-imx/include/mach/iomux-vf610.h index 1535628..b9e509b 100644 --- a/arch/arm/mach-imx/include/mach/iomux-vf610.h +++ b/arch/arm/mach-imx/include/mach/iomux-vf610.h @@ -163,9 +163,13 @@ VF610_PAD_PTD22__NF_IO6 = IOMUX_PAD(0x0120, 0x0120, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), VF610_PAD_PTD21__NF_IO5 = IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), VF610_PAD_PTD20__NF_IO4 = IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), + VF610_PAD_PTD19__GPIO_75 = IOMUX_PAD(0x012C, 0x012C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL), VF610_PAD_PTD19__NF_IO3 = IOMUX_PAD(0x012c, 0x012c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), + VF610_PAD_PTD18__GPIO_76 = IOMUX_PAD(0x0120, 0x0130, 0, __NA_, 0, VF610_GPIO_PAD_CTRL), VF610_PAD_PTD18__NF_IO2 = IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), + VF610_PAD_PTD17__GPIO_77 = IOMUX_PAD(0x0134, 0x0134, 0, __NA_, 0, VF610_GPIO_PAD_CTRL), VF610_PAD_PTD17__NF_IO1 = IOMUX_PAD(0x0134, 0x0134, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), + VF610_PAD_PTD16__GPIO_78 = IOMUX_PAD(0x0138, 0x0138, 0, __NA_, 0, VF610_GPIO_PAD_CTRL), VF610_PAD_PTD16__NF_IO0 = IOMUX_PAD(0x0138, 0x0138, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), VF610_PAD_PTB24__NF_WE_B = IOMUX_PAD(0x0178, 0x0178, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL), VF610_PAD_PTB25__NF_CE0_B = IOMUX_PAD(0x017c, 0x017c, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL), @@ -223,4 +227,19 @@ VF610_PAD_DDR_ODT0__DDR_ODT_1 = IOMUX_PAD(0x02d8, 0x02d8, 0, __NA_, 0, VF610_DDR_PAD_CTRL), }; +#define PINCTRL_VF610_MUX_SHIFT 20 + + +static inline void vf610_setup_pad(void __iomem *iomux, iomux_v3_cfg_t pad) +{ + iomux_v3_setup_pad(iomux, SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID, + IOMUX_CTRL_OFS(pad), + IOMUX_PAD_CTRL_OFS(pad), + IOMUX_SEL_INPUT_OFS(pad), + IOMUX_MODE(pad) << PINCTRL_VF610_MUX_SHIFT, + IOMUX_PAD_CTRL(pad), + IOMUX_SEL_INPUT(pad)); +} + + #endif /* __IOMUX_VF610_H__ */ diff --git a/arch/arm/mach-imx/include/mach/ocotp-fusemap.h b/arch/arm/mach-imx/include/mach/ocotp-fusemap.h new file mode 100644 index 0000000..44b58ca --- /dev/null +++ b/arch/arm/mach-imx/include/mach/ocotp-fusemap.h @@ -0,0 +1,49 @@ +#ifndef __MACH_IMX_OCOTP_FUSEMAP_H +#define __MACH_IMX_OCOTP_FUSEMAP_H + +#include + +#define OCOTP_TESTER_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(0) | OCOTP_WIDTH(2)) +#define OCOTP_BOOT_CFG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(2) | OCOTP_WIDTH(2)) +#define OCOTP_MEM_TRIM_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(4) | OCOTP_WIDTH(2)) +#define OCOTP_SJC_RESP_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(6) | OCOTP_WIDTH(1)) +#define OCOTP_MAC_ADDR_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(8) | OCOTP_WIDTH(2)) +#define OCOTP_GP1_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(10) | OCOTP_WIDTH(2)) +#define OCOTP_GP2_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(12) | OCOTP_WIDTH(2)) +#define OCOTP_SRK_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(14) | OCOTP_WIDTH(1)) +#define OCOTP_ANALOG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(18) | OCOTP_WIDTH(2)) +#define OCOTP_MISC_CONF_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(22) | OCOTP_WIDTH(1)) + +/* 0 <= n <= 1 */ +#define OCOTP_UNIQUE_ID(n) (OCOTP_WORD(0x410 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_NUM_CORES (OCOTP_WORD(0x430) | OCOTP_BIT(20) | OCOTP_WIDTH(2)) +#define OCOTP_MLB_DISABLE (OCOTP_WORD(0x430) | OCOTP_BIT(26) | OCOTP_WIDTH(1)) + +#define OCOTP_BOOT_CFG1 (OCOTP_WORD(0x450) | OCOTP_BIT(0) | OCOTP_WIDTH(8)) +#define OCOTP_BOOT_CFG2 (OCOTP_WORD(0x450) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) +#define OCOTP_BOOT_CFG3 (OCOTP_WORD(0x450) | OCOTP_BIT(16) | OCOTP_WIDTH(8)) +#define OCOTP_BOOT_CFG4 (OCOTP_WORD(0x450) | OCOTP_BIT(24) | OCOTP_WIDTH(8)) +#define OCOTP_SEC_CONFIG_1 (OCOTP_WORD(0x460) | OCOTP_BIT(1) | OCOTP_WIDTH(1)) +#define OCOTP_DIR_BT_DIS (OCOTP_WORD(0x460) | OCOTP_BIT(3) | OCOTP_WIDTH(1)) +#define OCOTP_BT_FUSE_SEL (OCOTP_WORD(0x460) | OCOTP_BIT(4) | OCOTP_WIDTH(1)) +#define OCOTP_SJC_DISABLE (OCOTP_WORD(0x460) | OCOTP_BIT(20) | OCOTP_WIDTH(1)) +#define OCOTP_WDOG_ENABLE (OCOTP_WORD(0x460) | OCOTP_BIT(21) | OCOTP_WIDTH(1)) +#define OCOTP_JTAG_SMODE (OCOTP_WORD(0x460) | OCOTP_BIT(22) | OCOTP_WIDTH(2)) +#define OCOTP_KTE (OCOTP_WORD(0x460) | OCOTP_BIT(26) | OCOTP_WIDTH(1)) +#define OCOTP_JTAG_HEO (OCOTP_WORD(0x460) | OCOTP_BIT(27) | OCOTP_WIDTH(1)) +#define OCOTP_NAND_READ_CMD_CODE1 (OCOTP_WORD(0x470) | OCOTP_BIT(0) | OCOTP_WIDTH(8)) +#define OCOTP_NAND_READ_CMD_CODE2 (OCOTP_WORD(0x470) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) +#define OCOTP_TEMP_SENSE (OCOTP_WORD(0x4e0) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_USB_VID (OCOTP_WORD(0x4f0) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) +#define OCOTP_USB_PID (OCOTP_WORD(0x4f0) | OCOTP_BIT(16) | OCOTP_WIDTH(16)) +/* 0 <= n <= 7 */ +#define OCOTP_SRK_HASH(n) (OCOTP_WORD(0x580 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_SJC_RESP_31_0 (OCOTP_WORD(0x600) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_SJC_RESP_55_32 (OCOTP_WORD(0x610) | OCOTP_BIT(0) | OCOTP_WIDTH(24)) +#define OCOTP_MAC_ADDR_31_0 (OCOTP_WORD(0x620) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_MAC_ADDR_47_32 (OCOTP_WORD(0x630) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) +#define OCOTP_GP1 (OCOTP_WORD(0x660) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_GP2 (OCOTP_WORD(0x670) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_PAD_SETTINGS (OCOTP_WORD(0x6d0) | OCOTP_BIT(0) | OCOTP_WIDTH(6)) + +#endif /* __MACH_IMX_OCOTP_FUSEMAP_H */ diff --git a/arch/arm/mach-imx/include/mach/ocotp.h b/arch/arm/mach-imx/include/mach/ocotp.h index 430bc75..5474c27 100644 --- a/arch/arm/mach-imx/include/mach/ocotp.h +++ b/arch/arm/mach-imx/include/mach/ocotp.h @@ -16,5 +16,6 @@ int imx_ocotp_read_field(uint32_t field, unsigned *value); int imx_ocotp_write_field(uint32_t field, unsigned value); int imx_ocotp_permanent_write(int enable); +bool imx_ocotp_sense_enable(bool enable); #endif /* __MACH_IMX_OCOTP_H */ diff --git a/arch/arm/mach-imx/include/mach/vf610-fusemap.h b/arch/arm/mach-imx/include/mach/vf610-fusemap.h new file mode 100644 index 0000000..a56faf1 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/vf610-fusemap.h @@ -0,0 +1,15 @@ +#ifndef __MACH_VF610_OCOTP_H +#define __MACH_VF610_OCOTP_H + +#include + +#define VF610_OCOTP_CPU_BUS_FRQ OCOTP_WORD(0x430) | OCOTP_BIT(22) | OCOTP_WIDTH(1) +#define VF610_OCOTP_OVG_DISABLE OCOTP_WORD(0x430) | OCOTP_BIT(30) | OCOTP_WIDTH(1) +#define VF610_OCOTP_SEC_CONFIG_0 OCOTP_WORD(0x440) | OCOTP_BIT(1) | OCOTP_WIDTH(1) +#define VF610_OCOTP_SPEED_GRADING OCOTP_WORD(0x440) | OCOTP_BIT(18) | OCOTP_WIDTH(4) +#define VF610_OCOTP_MAC_ADDR0_31_0 OCOTP_MAC_ADDR_31_0 +#define VF610_OCOTP_MAC_ADDR0_47_32 OCOTP_MAC_ADDR_47_32 +#define VF610_OCOTP_MAC_ADDR1_31_0 (OCOTP_WORD(0x640) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define VF610_OCOTP_MAC_ADDR1_47_32 (OCOTP_WORD(0x650) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) + +#endif diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c index 68ff0ce..99b365a 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -69,12 +69,22 @@ /* Other definitions */ #define IMX6_OTP_DATA_ERROR_VAL 0xBADABADA #define DEF_RELAX 20 -#define MAC_OFFSET (0x22 * 4) +#define MAC_OFFSET_0 (0x22 * 4) +#define MAC_OFFSET_1 (0x24 * 4) +#define MAX_MAC_OFFSETS 2 #define MAC_BYTES 8 struct imx_ocotp_data { int num_regs; u32 (*addr_to_offset)(u32 addr); + u8 mac_offsets[MAX_MAC_OFFSETS]; + u8 mac_offsets_num; +}; + +struct ocotp_priv_ethaddr { + char value[MAC_BYTES]; + struct regmap *map; + u8 offset; }; struct ocotp_priv { @@ -84,9 +94,10 @@ struct device_d dev; int permanent_write_enable; int sense_enable; - char ethaddr[6]; + struct ocotp_priv_ethaddr ethaddr[MAX_MAC_OFFSETS]; struct regmap_config map_config; const struct imx_ocotp_data *data; + int mac_offset_idx; }; static struct ocotp_priv *imx_ocotp; @@ -348,6 +359,13 @@ return 0; } +bool imx_ocotp_sense_enable(bool enable) +{ + const bool old_value = imx_ocotp->sense_enable; + imx_ocotp->sense_enable = enable; + return old_value; +} + static uint32_t inc_offset(uint32_t offset) { if ((offset & 0x3) == 0x3) @@ -397,37 +415,39 @@ } } +static void memreverse(void *dest, const void *src, size_t n) +{ + char *destp = dest; + const char *srcp = src + n - 1; + + while(n--) + *destp++ = *srcp--; +} + static int imx_ocotp_get_mac(struct param_d *param, void *priv) { - struct ocotp_priv *ocotp_priv = priv; - char buf[8]; - int i, ret; + char buf[MAC_BYTES]; + int ret; + struct ocotp_priv_ethaddr *ethaddr = priv; - ret = regmap_bulk_read(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); + ret = regmap_bulk_read(ethaddr->map, ethaddr->offset, + buf, MAC_BYTES); if (ret < 0) return ret; - for (i = 0; i < 6; i++) - ocotp_priv->ethaddr[i] = buf[5 - i]; - + memreverse(ethaddr->value, buf, 6); return 0; } static int imx_ocotp_set_mac(struct param_d *param, void *priv) { - struct ocotp_priv *ocotp_priv = priv; - char buf[8]; - int i, ret; + char buf[MAC_BYTES]; + struct ocotp_priv_ethaddr *ethaddr = priv; - for (i = 0; i < 6; i++) - buf[5 - i] = ocotp_priv->ethaddr[i]; - buf[6] = 0; buf[7] = 0; + memreverse(buf, ethaddr->value, 6); - ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); - if (ret < 0) - return ret; - - return 0; + return regmap_bulk_write(ethaddr->map, ethaddr->offset, + buf, MAC_BYTES); } static struct regmap_bus imx_ocotp_regmap_bus = { @@ -486,9 +506,28 @@ NULL, NULL, &priv->permanent_write_enable, NULL); } - if (IS_ENABLED(CONFIG_NET)) - dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac, - imx_ocotp_get_mac, priv->ethaddr, priv); + if (IS_ENABLED(CONFIG_NET)) { + int i; + struct ocotp_priv_ethaddr *ethaddr; + + for (i = 0; i < priv->data->mac_offsets_num; i++) { + ethaddr = &priv->ethaddr[i]; + ethaddr->map = priv->map; + ethaddr->offset = priv->data->mac_offsets[i]; + + dev_add_param_mac(&priv->dev, xasprintf("mac_addr%d", i), + imx_ocotp_set_mac, imx_ocotp_get_mac, + ethaddr->value, ethaddr); + } + + /* + * Alias to mac_addr0 for backwards compatibility + */ + ethaddr = &priv->ethaddr[0]; + dev_add_param_mac(&priv->dev, "mac_addr", + imx_ocotp_set_mac, imx_ocotp_get_mac, + ethaddr->value, ethaddr); + } dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv); @@ -527,16 +566,22 @@ static struct imx_ocotp_data imx6q_ocotp_data = { .num_regs = 512, .addr_to_offset = imx6q_addr_to_offset, + .mac_offsets_num = 1, + .mac_offsets = { MAC_OFFSET_0 }, }; static struct imx_ocotp_data imx6sl_ocotp_data = { .num_regs = 256, .addr_to_offset = imx6sl_addr_to_offset, + .mac_offsets_num = 1, + .mac_offsets = { MAC_OFFSET_0 }, }; static struct imx_ocotp_data vf610_ocotp_data = { .num_regs = 512, .addr_to_offset = vf610_addr_to_offset, + .mac_offsets_num = 2, + .mac_offsets = { MAC_OFFSET_0, MAC_OFFSET_1 }, }; static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = { @@ -572,4 +617,4 @@ return 0; } -coredevice_initcall(imx_ocotp_init); +postcore_initcall(imx_ocotp_init); diff --git a/common/Kconfig b/common/Kconfig index c9fe2ce..f7ff046 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1074,6 +1074,13 @@ Say Y here if you want kernel low-level debugging support on i.MX6Q. +config DEBUG_IMX7D_UART + bool "i.MX7D Debug UART" + depends on ARCH_IMX7 + help + Say Y here if you want barebox low-level debugging support + on i.MX7D. + config DEBUG_VF610_UART bool "VF610 Debug UART" depends on ARCH_VF610 @@ -1122,6 +1129,7 @@ DEBUG_IMX53_UART || \ DEBUG_IMX6Q_UART || \ DEBUG_IMX6SL_UART || \ + DEBUG_IMX7D_UART || \ DEBUG_VF610_UART default 1 depends on ARCH_IMX diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index a4e4ed0..5811d28 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \ clk-mux.o clk-gate.o clk-composite.o \ - clk-fractional-divider.o clk-conf.o + clk-fractional-divider.o clk-conf.o \ + clk-gate-shared.o obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o obj-$(CONFIG_ARCH_MVEBU) += mvebu/ diff --git a/drivers/clk/clk-gate-shared.c b/drivers/clk/clk-gate-shared.c new file mode 100644 index 0000000..a95f940 --- /dev/null +++ b/drivers/clk/clk-gate-shared.c @@ -0,0 +1,123 @@ +/* + * clk-gate-shared.c - generic barebox clock support. Based on Linux clk support + * + * Copyright (c) 2017 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include + +struct clk_gate_shared { + struct clk clk; + const char *parent; + const char *companion_gate; + struct clk *companion_clk; +}; + +#define to_clk_gate_shared(_clk) container_of(_clk, struct clk_gate_shared, clk) + +static struct clk *lookup_companion(struct clk_gate_shared *g) +{ + if (IS_ERR(g->companion_clk)) + g->companion_clk = clk_lookup(g->companion_gate); + + if (IS_ERR(g->companion_clk)) + return NULL; + + return g->companion_clk; +} + +static int clk_gate_shared_enable(struct clk *clk) +{ + struct clk_gate_shared *g = to_clk_gate_shared(clk); + + return clk_enable(lookup_companion(g)); +} + +static void clk_gate_shared_disable(struct clk *clk) +{ + struct clk_gate_shared *g = to_clk_gate_shared(clk); + + clk_disable(lookup_companion(g)); +} + +static int clk_gate_shared_is_enabled(struct clk *clk) +{ + struct clk_gate_shared *g = to_clk_gate_shared(clk); + + return clk_is_enabled(lookup_companion(g)); +} + +static struct clk_ops clk_gate_shared_ops = { + .set_rate = clk_parent_set_rate, + .round_rate = clk_parent_round_rate, + .enable = clk_gate_shared_enable, + .disable = clk_gate_shared_disable, + .is_enabled = clk_gate_shared_is_enabled, +}; + +struct clk *clk_gate_shared_alloc(const char *name, const char *parent, const char *companion, + unsigned flags) +{ + struct clk_gate_shared *g = xzalloc(sizeof(*g)); + + g->parent = parent; + g->companion_gate = companion; + g->companion_clk = ERR_PTR(-EINVAL); + g->clk.ops = &clk_gate_shared_ops; + g->clk.name = name; + g->clk.flags = flags; + g->clk.parent_names = &g->parent; + g->clk.num_parents = 1; + + return &g->clk; +} + +void clk_gate_shared_free(struct clk *clk) +{ + struct clk_gate_shared *g = to_clk_gate_shared(clk); + + free(g); +} + +/* + * clk_gate_shared - register a gate controlled by another gate + * @name: The name of the new clock gate + * @parent: The parent name of the new clock + * companion: The hardware gate this clock is controlled by + * @flags: common CLK_* flags + * + * This gate clock is used when a single software control knob controls multiple + * gates in hardware. The first gate is then registered as the real hardware gate, + * the others are registered with this function. This gate has no hardware control + * itself, but only enables/disabled its companion hardware gate. + */ +struct clk *clk_gate_shared(const char *name, const char *parent, const char *companion, + unsigned flags) +{ + struct clk *clk; + int ret; + + clk = clk_gate_shared_alloc(name , parent, companion, flags); + + ret = clk_register(clk); + if (ret) { + clk_gate_shared_free(clk); + return ERR_PTR(ret); + } + + return clk; +} diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 1566bea..93e000c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -141,6 +141,7 @@ { struct clk *parent; unsigned long parent_rate = 0; + int ret; if (!clk) return 0; @@ -148,14 +149,26 @@ if (IS_ERR(clk)) return PTR_ERR(clk); + if (!clk->ops->set_rate) + return -ENOSYS; + parent = clk_get_parent(clk); - if (parent) + if (parent) { parent_rate = clk_get_rate(parent); - if (clk->ops->set_rate) - return clk->ops->set_rate(clk, rate, parent_rate); + if (clk->flags & CLK_OPS_PARENT_ENABLE) { + ret = clk_enable(parent); + if (ret) + return ret; + } + } - return -ENOSYS; + ret = clk->ops->set_rate(clk, rate, parent_rate); + + if (parent && clk->flags & CLK_OPS_PARENT_ENABLE) + clk_disable(parent); + + return ret; } struct clk *clk_lookup(const char *name) @@ -173,14 +186,15 @@ return ERR_PTR(-ENODEV); } -int clk_set_parent(struct clk *clk, struct clk *parent) +int clk_set_parent(struct clk *clk, struct clk *newparent) { - int i; + int i, ret; + struct clk *curparent = clk_get_parent(clk); if (IS_ERR(clk)) return PTR_ERR(clk); - if (IS_ERR(parent)) - return PTR_ERR(parent); + if (IS_ERR(newparent)) + return PTR_ERR(newparent); if (!clk->num_parents) return -EINVAL; @@ -192,14 +206,32 @@ clk->parents[i] = clk_lookup(clk->parent_names[i]); if (!IS_ERR_OR_NULL(clk->parents[i])) - if (clk->parents[i] == parent) + if (clk->parents[i] == newparent) break; } if (i == clk->num_parents) return -EINVAL; - return clk->ops->set_parent(clk, i); + if (clk->enable_count) + clk_enable(newparent); + + if (clk->flags & CLK_OPS_PARENT_ENABLE) { + clk_enable(curparent); + clk_enable(newparent); + } + + ret = clk->ops->set_parent(clk, i); + + if (clk->flags & CLK_OPS_PARENT_ENABLE) { + clk_disable(curparent); + clk_disable(newparent); + } + + if (clk->enable_count) + clk_disable(curparent); + + return ret; } struct clk *clk_get_parent(struct clk *clk) diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 65d7859..b864b4f 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -5,6 +5,7 @@ clk-pfd.o \ clk-gate2.o \ clk-gate-exclusive.o \ + clk-cpu.o \ clk.o obj-$(CONFIG_ARCH_IMX1) += clk-imx1.o @@ -18,5 +19,7 @@ obj-$(CONFIG_ARCH_IMX53) += clk-imx5.o obj-$(CONFIG_ARCH_IMX6) += clk-imx6.o obj-$(CONFIG_ARCH_IMX6SX) += clk-imx6sx.o +obj-$(CONFIG_ARCH_IMX6SL) += clk-imx6sl.o obj-$(CONFIG_ARCH_IMX6UL) += clk-imx6ul.o +obj-$(CONFIG_ARCH_IMX7) += clk-imx7.o obj-$(CONFIG_ARCH_VF610) += clk-vf610.o diff --git a/drivers/clk/imx/clk-cpu.c b/drivers/clk/imx/clk-cpu.c new file mode 100644 index 0000000..bd1749f --- /dev/null +++ b/drivers/clk/imx/clk-cpu.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014 Lucas Stach , Pengutronix + * + * 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. + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +struct clk_cpu { + struct clk clk; + struct clk *div; + struct clk *mux; + struct clk *pll; + struct clk *step; +}; + +static inline struct clk_cpu *to_clk_cpu(struct clk *clk) +{ + return container_of(clk, struct clk_cpu, clk); +} + +static unsigned long clk_cpu_recalc_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_cpu *cpu = to_clk_cpu(clk); + + return clk_get_rate(cpu->div); +} + +static long clk_cpu_round_rate(struct clk *clk, unsigned long rate, + unsigned long *prate) +{ + struct clk_cpu *cpu = to_clk_cpu(clk); + + return clk_round_rate(cpu->pll, rate); +} + +static int clk_cpu_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_cpu *cpu = to_clk_cpu(clk); + int ret; + + /* switch to PLL bypass clock */ + ret = clk_set_parent(cpu->mux, cpu->step); + if (ret) + return ret; + + /* reprogram PLL */ + ret = clk_set_rate(cpu->pll, rate); + if (ret) { + clk_set_parent(cpu->mux, cpu->pll); + return ret; + } + /* switch back to PLL clock */ + clk_set_parent(cpu->mux, cpu->pll); + + /* Ensure the divider is what we expect */ + clk_set_rate(cpu->div, rate); + + return 0; +} + +static const struct clk_ops clk_cpu_ops = { + .recalc_rate = clk_cpu_recalc_rate, + .round_rate = clk_cpu_round_rate, + .set_rate = clk_cpu_set_rate, +}; + +struct clk *imx_clk_cpu(const char *name, const char *parent_name, + struct clk *div, struct clk *mux, struct clk *pll, + struct clk *step) +{ + struct clk_cpu *cpu; + int ret; + + cpu = xzalloc(sizeof(*cpu)); + + cpu->div = div; + cpu->mux = mux; + cpu->pll = pll; + cpu->step = step; + + cpu->clk.name = name; + cpu->clk.ops = &clk_cpu_ops; + cpu->clk.flags = 0; + cpu->clk.parent_names = &parent_name; + cpu->clk.num_parents = 1; + + ret = clk_register(&cpu->clk); + if (ret) + free(cpu); + + return &cpu->clk; +} diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index f952f3e..e7dcd87 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -88,7 +88,8 @@ }; struct clk *clk_gate2_alloc(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 cgr_val) + void __iomem *reg, u8 shift, u8 cgr_val, + unsigned long flags) { struct clk_gate2 *g = xzalloc(sizeof(*g)); @@ -100,7 +101,7 @@ g->clk.name = name; g->clk.parent_names = &g->parent; g->clk.num_parents = 1; - g->clk.flags = CLK_SET_RATE_PARENT; + g->clk.flags = CLK_SET_RATE_PARENT | flags; return &g->clk; } @@ -113,12 +114,12 @@ } struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg, - u8 shift, u8 cgr_val) + u8 shift, u8 cgr_val, unsigned long flags) { struct clk *g; int ret; - g = clk_gate2_alloc(name , parent, reg, shift, cgr_val); + g = clk_gate2_alloc(name , parent, reg, shift, cgr_val, flags); ret = clk_register(g); if (ret) { @@ -135,7 +136,7 @@ struct clk *clk; struct clk_gate2 *g; - clk = clk_gate2(name, parent, reg, shift, 0x3); + clk = clk_gate2(name, parent, reg, shift, 0x3, 0); if (IS_ERR(clk)) return clk; diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c index 8d135c9..dbb5c15 100644 --- a/drivers/clk/imx/clk-imx31.c +++ b/drivers/clk/imx/clk-imx31.c @@ -63,14 +63,27 @@ mstick1_gate, mstick2_gate, csi_gate, rtc_gate, wdog_gate, pwm_gate, sim_gate, ect_gate, usb_gate, kpp_gate, ipu_gate, uart3_gate, uart4_gate, uart5_gate, owire_gate, ssi2_gate, cspi1_gate, cspi2_gate, - gacc_gate, emi_gate, rtic_gate, firi_gate, clk_max + gacc_gate, emi_gate, rtic_gate, firi_gate, fpm, pll_ref, mpll_byp, + clk_max }; static struct clk *clks[clk_max]; +static const char *pll_ref_sel[] = { + "dummy", + "fpm", + "ckih", + "dummy", +}; + +static const char *mpll_byp_sel[] = { + "mpll", + "pll_ref", +}; + static const char *mcu_main_sel[] = { "spll", - "mpll", + "mpll_byp", }; static const char *per_sel[] = { @@ -94,9 +107,14 @@ clks[ckih] = clk_fixed("ckih", 26000000); clks[ckil] = clk_fixed("ckil", 32768); - clks[mpll] = imx_clk_pllv1("mpll", "ckih", base + CCM_MPCTL); - clks[spll] = imx_clk_pllv1("spll", "ckih", base + CCM_SRPCTL); - clks[upll] = imx_clk_pllv1("upll", "ckih", base + CCM_UPCTL); + clks[fpm] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1); + clks[pll_ref] = imx_clk_mux("pll_ref", base + CCM_CCMR, 1, 2, + pll_ref_sel, ARRAY_SIZE(pll_ref_sel)); + clks[mpll] = imx_clk_pllv1("mpll", "pll_ref", base + CCM_MPCTL); + clks[spll] = imx_clk_pllv1("spll", "pll_ref", base + CCM_SRPCTL); + clks[upll] = imx_clk_pllv1("upll", "pll_ref", base + CCM_UPCTL); + clks[mpll_byp] = imx_clk_mux("mpll_byp", base + CCM_CCMR, 7, 1, + mpll_byp_sel, ARRAY_SIZE(mpll_byp_sel)); clks[mcu_main] = imx_clk_mux("mcu_main", base + CCM_PMCR0, 31, 1, mcu_main_sel, ARRAY_SIZE(mcu_main_sel)); clks[hsp] = imx_clk_divider("hsp", "mcu_main", base + CCM_PDR0, 11, 3); diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c new file mode 100644 index 0000000..89ede76 --- /dev/null +++ b/drivers/clk/imx/clk-imx6sl.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" +#include "common.h" + +static const char *step_sels[] = { "osc", "pll2_pfd2", }; +static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; +static const char *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", }; +static const char *ocram_sels[] = { "periph", "ocram_alt_sels", }; +static const char *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", }; +static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", }; +static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", }; +static const char *periph_sels[] = { "pre_periph_sel", "periph_clk2_podf", }; +static const char *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2_podf", }; +static const char *csi_sels[] = { "osc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", }; +static const char *lcdif_axi_sels[] = { "pll2_bus", "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", }; +static const char *usdhc_sels[] = { "pll2_pfd2", "pll2_pfd0", }; +static const char *perclk_sels[] = { "ipg", "osc", }; +static const char *pxp_axi_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd3", }; +static const char *epdc_axi_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd2", }; +static const char *gpu2d_ovg_sels[] = { "pll3_pfd1", "pll3_usb_otg", "pll2_bus", "pll2_pfd2", }; +static const char *gpu2d_sels[] = { "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", "pll2_bus", }; +static const char *lcdif_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll3_pfd0", "pll3_pfd1", }; +static const char *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", }; +static const char *ecspi_sels[] = { "pll3_60m", "osc", }; +static const char *uart_sels[] = { "pll3_80m", "osc", }; +static const char *lvds_sels[] = { + "pll1_sys", "pll2_bus", "pll2_pfd0", "pll2_pfd1", "pll2_pfd2", "dummy", "pll4_audio", "pll5_video", + "dummy", "enet_ref", "dummy", "dummy", "pll3_usb_otg", "pll7_usb_host", "pll3_pfd0", "pll3_pfd1", + "pll3_pfd2", "pll3_pfd3", "osc", "dummy", "dummy", "dummy", "dummy", "dummy", + "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", +}; +static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", }; +static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", }; +static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", }; +static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", }; +static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", }; +static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", }; +static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; +static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; + +static struct clk *clks[IMX6SL_CLK_END]; +static struct clk_onecell_data clk_data; + +static struct clk_div_table clk_enet_ref_table[] = { + { .val = 0, .div = 20, }, + { .val = 1, .div = 10, }, + { .val = 2, .div = 5, }, + { .val = 3, .div = 4, }, + { } +}; + +static struct clk_div_table post_div_table[] = { + { .val = 2, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 0, .div = 4, }, + { } +}; + +static struct clk_div_table video_div_table[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 2, .div = 1, }, + { .val = 3, .div = 4, }, + { } +}; + +static int imx6sl_ccm_probe(struct device_d *dev) +{ + struct resource *iores; + void __iomem *base, *anatop_base, *ccm_base; + struct device_node *ccm_node = dev->device_node; + + clks[IMX6SL_CLK_DUMMY] = clk_fixed("dummy", 0); + + anatop_base = (void *)MX6_ANATOP_BASE_ADDR; + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + ccm_base = IOMEM(iores->start); + + base = anatop_base; + + clks[IMX6SL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + + /* type name parent_name base div_mask */ + clks[IMX6SL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f); + clks[IMX6SL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1); + clks[IMX6SL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3); + clks[IMX6SL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f); + clks[IMX6SL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f); + clks[IMX6SL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3); + clks[IMX6SL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "osc", base + 0x20, 0x3); + + clks[IMX6SL_PLL1_BYPASS] = imx_clk_mux_p("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels)); + clks[IMX6SL_PLL2_BYPASS] = imx_clk_mux_p("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels)); + clks[IMX6SL_PLL3_BYPASS] = imx_clk_mux_p("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels)); + clks[IMX6SL_PLL4_BYPASS] = imx_clk_mux_p("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels)); + clks[IMX6SL_PLL5_BYPASS] = imx_clk_mux_p("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels)); + clks[IMX6SL_PLL6_BYPASS] = imx_clk_mux_p("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels)); + clks[IMX6SL_PLL7_BYPASS] = imx_clk_mux_p("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels)); + + /* Do not bypass PLLs initially */ + clk_set_parent(clks[IMX6SL_PLL1_BYPASS], clks[IMX6SL_CLK_PLL1]); + clk_set_parent(clks[IMX6SL_PLL2_BYPASS], clks[IMX6SL_CLK_PLL2]); + clk_set_parent(clks[IMX6SL_PLL3_BYPASS], clks[IMX6SL_CLK_PLL3]); + clk_set_parent(clks[IMX6SL_PLL4_BYPASS], clks[IMX6SL_CLK_PLL4]); + clk_set_parent(clks[IMX6SL_PLL5_BYPASS], clks[IMX6SL_CLK_PLL5]); + clk_set_parent(clks[IMX6SL_PLL6_BYPASS], clks[IMX6SL_CLK_PLL6]); + clk_set_parent(clks[IMX6SL_PLL7_BYPASS], clks[IMX6SL_CLK_PLL7]); + + clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", base + 0x00, 13); + clks[IMX6SL_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13); + clks[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13); + clks[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13); + clks[IMX6SL_CLK_PLL5_VIDEO] = imx_clk_gate("pll5_video", "pll5_bypass", base + 0xa0, 13); + clks[IMX6SL_CLK_PLL6_ENET] = imx_clk_gate("pll6_enet", "pll6_bypass", base + 0xe0, 13); + clks[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13); + + clks[IMX6SL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); + clks[IMX6SL_CLK_LVDS1_OUT] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x160, 10, BIT(12)); + clks[IMX6SL_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10)); + + /* + * usbphy1 and usbphy2 are implemented as dummy gates using reserve + * bit 20. They are used by phy driver to keep the refcount of + * parent PLL correct. usbphy1_gate and usbphy2_gate only needs to be + * turned on during boot, and software will not need to control it + * anymore after that. + */ + clks[IMX6SL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20); + clks[IMX6SL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20); + clks[IMX6SL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6); + clks[IMX6SL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6); + + /* dev name parent_name flags reg shift width div: flags, div_table lock */ + clks[IMX6SL_CLK_PLL4_POST_DIV] = imx_clk_divider_table("pll4_post_div", "pll4_audio", + base + 0x70, 19, 2, post_div_table); + clks[IMX6SL_CLK_PLL4_AUDIO_DIV] = imx_clk_divider("pll4_audio_div", "pll4_post_div", + base + 0x170, 15, 1); + clks[IMX6SL_CLK_PLL5_POST_DIV] = imx_clk_divider_table("pll5_post_div", "pll5_video", + base + 0xa0, 19, 2, post_div_table); + clks[IMX6SL_CLK_PLL5_VIDEO_DIV] = imx_clk_divider_table("pll5_video_div", "pll5_post_div", + base + 0x170, 30, 2, video_div_table); + clks[IMX6SL_CLK_ENET_REF] = imx_clk_divider_table("enet_ref", "pll6_enet", + base + 0xe0, 0, 2, clk_enet_ref_table); + + /* name parent_name reg idx */ + clks[IMX6SL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0", "pll2_bus", base + 0x100, 0); + clks[IMX6SL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_bus", base + 0x100, 1); + clks[IMX6SL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_bus", base + 0x100, 2); + clks[IMX6SL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0", "pll3_usb_otg", base + 0xf0, 0); + clks[IMX6SL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_usb_otg", base + 0xf0, 1); + clks[IMX6SL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", base + 0xf0, 2); + clks[IMX6SL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", base + 0xf0, 3); + + /* name parent_name mult div */ + clks[IMX6SL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2", 1, 2); + clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); + clks[IMX6SL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); + clks[IMX6SL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); + + base = ccm_base; + + /* name reg shift width parent_names num_parents */ + clks[IMX6SL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); + clks[IMX6SL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); + clks[IMX6SL_CLK_OCRAM_ALT_SEL] = imx_clk_mux("ocram_alt_sel", base + 0x14, 7, 1, ocram_alt_sels, ARRAY_SIZE(ocram_alt_sels)); + clks[IMX6SL_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 1, ocram_sels, ARRAY_SIZE(ocram_sels)); + clks[IMX6SL_CLK_PRE_PERIPH2_SEL] = imx_clk_mux("pre_periph2_sel", base + 0x18, 21, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); + clks[IMX6SL_CLK_PRE_PERIPH_SEL] = imx_clk_mux("pre_periph_sel", base + 0x18, 18, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); + clks[IMX6SL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); + clks[IMX6SL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); + clks[IMX6SL_CLK_CSI_SEL] = imx_clk_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels)); + clks[IMX6SL_CLK_LCDIF_AXI_SEL] = imx_clk_mux("lcdif_axi_sel", base + 0x3c, 14, 2, lcdif_axi_sels, ARRAY_SIZE(lcdif_axi_sels)); + clks[IMX6SL_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SL_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SL_CLK_USDHC3_SEL] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SL_CLK_USDHC4_SEL] = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SL_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels)); + clks[IMX6SL_CLK_PXP_AXI_SEL] = imx_clk_mux("pxp_axi_sel", base + 0x34, 6, 3, pxp_axi_sels, ARRAY_SIZE(pxp_axi_sels)); + clks[IMX6SL_CLK_EPDC_AXI_SEL] = imx_clk_mux("epdc_axi_sel", base + 0x34, 15, 3, epdc_axi_sels, ARRAY_SIZE(epdc_axi_sels)); + clks[IMX6SL_CLK_GPU2D_OVG_SEL] = imx_clk_mux("gpu2d_ovg_sel", base + 0x18, 4, 2, gpu2d_ovg_sels, ARRAY_SIZE(gpu2d_ovg_sels)); + clks[IMX6SL_CLK_GPU2D_SEL] = imx_clk_mux("gpu2d_sel", base + 0x18, 8, 2, gpu2d_sels, ARRAY_SIZE(gpu2d_sels)); + clks[IMX6SL_CLK_LCDIF_PIX_SEL] = imx_clk_mux("lcdif_pix_sel", base + 0x38, 6, 3, lcdif_pix_sels, ARRAY_SIZE(lcdif_pix_sels)); + clks[IMX6SL_CLK_EPDC_PIX_SEL] = imx_clk_mux("epdc_pix_sel", base + 0x38, 15, 3, epdc_pix_sels, ARRAY_SIZE(epdc_pix_sels)); + clks[IMX6SL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); + clks[IMX6SL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels)); + + /* name reg shift width busy: reg, shift parent_names num_parents */ + clks[IMX6SL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); + clks[IMX6SL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels)); + + /* name parent_name reg shift width */ + clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3); + clks[IMX6SL_CLK_PERIPH_CLK2_PODF] = imx_clk_divider("periph_clk2_podf", "periph_clk2_sel", base + 0x14, 27, 3); + clks[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_divider("periph2_clk2_podf", "periph2_clk2_sel", base + 0x14, 0, 3); + clks[IMX6SL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); + clks[IMX6SL_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3); + clks[IMX6SL_CLK_LCDIF_AXI_PODF] = imx_clk_divider("lcdif_axi_podf", "lcdif_axi_sel", base + 0x3c, 16, 3); + clks[IMX6SL_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3); + clks[IMX6SL_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3); + clks[IMX6SL_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3); + clks[IMX6SL_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); + clks[IMX6SL_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6); + clks[IMX6SL_CLK_PXP_AXI_PODF] = imx_clk_divider("pxp_axi_podf", "pxp_axi_sel", base + 0x34, 3, 3); + clks[IMX6SL_CLK_EPDC_AXI_PODF] = imx_clk_divider("epdc_axi_podf", "epdc_axi_sel", base + 0x34, 12, 3); + clks[IMX6SL_CLK_GPU2D_OVG_PODF] = imx_clk_divider("gpu2d_ovg_podf", "gpu2d_ovg_sel", base + 0x18, 26, 3); + clks[IMX6SL_CLK_GPU2D_PODF] = imx_clk_divider("gpu2d_podf", "gpu2d_sel", base + 0x18, 29, 3); + clks[IMX6SL_CLK_LCDIF_PIX_PRED] = imx_clk_divider("lcdif_pix_pred", "lcdif_pix_sel", base + 0x38, 3, 3); + clks[IMX6SL_CLK_EPDC_PIX_PRED] = imx_clk_divider("epdc_pix_pred", "epdc_pix_sel", base + 0x38, 12, 3); + clks[IMX6SL_CLK_LCDIF_PIX_PODF] = imx_clk_divider("lcdif_pix_podf", "lcdif_pix_pred", base + 0x1c, 20, 3); + clks[IMX6SL_CLK_EPDC_PIX_PODF] = imx_clk_divider("epdc_pix_podf", "epdc_pix_pred", base + 0x18, 23, 3); + clks[IMX6SL_CLK_ECSPI_ROOT] = imx_clk_divider("ecspi_root", "ecspi_sel", base + 0x38, 19, 6); + clks[IMX6SL_CLK_UART_ROOT] = imx_clk_divider("uart_root", "uart_sel", base + 0x24, 0, 6); + + /* name parent_name reg shift width busy: reg, shift */ + clks[IMX6SL_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1); + clks[IMX6SL_CLK_MMDC_ROOT] = imx_clk_busy_divider("mmdc", "periph2", base + 0x14, 3, 3, base + 0x48, 2); + clks[IMX6SL_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16); + + /* name parent_name reg shift */ + clks[IMX6SL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0); + clks[IMX6SL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2); + clks[IMX6SL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4); + clks[IMX6SL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6); + clks[IMX6SL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10); + clks[IMX6SL_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12); + clks[IMX6SL_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14); + clks[IMX6SL_CLK_GPT] = imx_clk_gate2("gpt", "perclk", base + 0x6c, 20); + clks[IMX6SL_CLK_GPT_SERIAL] = imx_clk_gate2("gpt_serial", "perclk", base + 0x6c, 22); + clks[IMX6SL_CLK_GPU2D_OVG] = imx_clk_gate2("gpu2d_ovg", "gpu2d_ovg_podf", base + 0x6c, 26); + clks[IMX6SL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6); + clks[IMX6SL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8); + clks[IMX6SL_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10); + clks[IMX6SL_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12); + clks[IMX6SL_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x74, 0); + clks[IMX6SL_CLK_PXP_AXI] = imx_clk_gate2("pxp_axi", "pxp_axi_podf", base + 0x74, 2); + clks[IMX6SL_CLK_EPDC_AXI] = imx_clk_gate2("epdc_axi", "epdc_axi_podf", base + 0x74, 4); + clks[IMX6SL_CLK_LCDIF_AXI] = imx_clk_gate2("lcdif_axi", "lcdif_axi_podf", base + 0x74, 6); + clks[IMX6SL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_pix_podf", base + 0x74, 8); + clks[IMX6SL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_pix_podf", base + 0x74, 10); + clks[IMX6SL_CLK_OCRAM] = imx_clk_gate2("ocram", "ocram_podf", base + 0x74, 28); + clks[IMX6SL_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16); + clks[IMX6SL_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18); + clks[IMX6SL_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20); + clks[IMX6SL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22); + clks[IMX6SL_CLK_SDMA] = imx_clk_gate2("sdma", "ipg", base + 0x7c, 6); + clks[IMX6SL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); + clks[IMX6SL_CLK_UART] = imx_clk_gate2("uart", "ipg", base + 0x7c, 24); + clks[IMX6SL_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_root", base + 0x7c, 26); + clks[IMX6SL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); + clks[IMX6SL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2); + clks[IMX6SL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); + clks[IMX6SL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); + clks[IMX6SL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data); + + if (IS_ENABLED(CONFIG_USB_IMX_PHY)) { + clk_enable(clks[IMX6SL_CLK_USBPHY1_GATE]); + clk_enable(clks[IMX6SL_CLK_USBPHY2_GATE]); + } + + return 0; +}; + +static int imx6sl_clocks_init(void) +{ + if (!of_machine_is_compatible("fsl,imx6sl")) + return 0; + + /* Ensure the AHB clk is at 132MHz. */ + clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000); + + return 0; +} +coredevice_initcall(imx6sl_clocks_init); + +static __maybe_unused struct of_device_id imx6sl_ccm_dt_ids[] = { + { + .compatible = "fsl,imx6sl-ccm", + }, { + /* sentinel */ + } +}; + +static struct driver_d imx6sl_ccm_driver = { + .probe = imx6sl_ccm_probe, + .name = "imx6-ccm", + .of_compatible = DRV_OF_COMPAT(imx6sl_ccm_dt_ids), +}; + +static int imx6sl_ccm_init(void) +{ + return platform_driver_register(&imx6sl_ccm_driver); +} +core_initcall(imx6sl_ccm_init); diff --git a/drivers/clk/imx/clk-imx7.c b/drivers/clk/imx/clk-imx7.c new file mode 100644 index 0000000..d3a036c --- /dev/null +++ b/drivers/clk/imx/clk-imx7.c @@ -0,0 +1,880 @@ +/* + * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +static struct clk *clks[IMX7D_CLK_END]; +static const char *arm_a7_sel[] = { "osc", "pll_arm_main", + "pll_enet_500m_clk", "pll_dram_main", + "pll_sys_main", "pll_sys_pfd0_392m_clk", "pll_audio_post_div", + "pll_usb_main_clk", }; + +static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_250m_clk", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main", + "pll_usb_main_clk", }; + +static const char *arm_m0_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_125m_clk", "pll_sys_pfd2_135m_clk", + "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main", + "pll_usb_main_clk", }; + +static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk", + "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk", + "pll_audio_post_div", "pll_video_main", "pll_sys_pfd7_clk", }; + +static const char *disp_axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk", + "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd6_clk", + "pll_sys_pfd7_clk", "pll_audio_post_div", "pll_video_main", }; + +static const char *enet_axi_sel[] = { "osc", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_enet_250m_clk", + "pll_sys_main_240m_clk", "pll_audio_post_div", "pll_video_main", + "pll_sys_pfd4_clk", }; + +static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_sys_main_240m_clk", + "pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk", + "pll_audio_post_div", }; + +static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", + "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_post_div", + "pll_video_main", }; + +static const char *dram_phym_sel[] = { "pll_dram_main", + "dram_phym_alt_clk", }; + +static const char *dram_sel[] = { "pll_dram_main", + "dram_alt_root_clk", }; + +static const char *dram_phym_alt_sel[] = { "osc", "pll_dram_533m_clk", + "pll_sys_main", "pll_enet_500m_clk", + "pll_usb_main_clk", "pll_sys_pfd7_clk", "pll_audio_post_div", + "pll_video_main", }; + +static const char *dram_alt_sel[] = { "osc", "pll_dram_533m_clk", + "pll_sys_main", "pll_enet_500m_clk", + "pll_enet_250m_clk", "pll_sys_pfd0_392m_clk", + "pll_audio_post_div", "pll_sys_pfd2_270m_clk", }; + +static const char *usb_hsic_sel[] = { "osc", "pll_sys_main", + "pll_usb_main_clk", "pll_sys_pfd3_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd5_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *pcie_ctrl_sel[] = { "osc", "pll_enet_250m_clk", + "pll_sys_main_240m_clk", "pll_sys_pfd2_270m_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", + "pll_sys_pfd1_332m_clk", "pll_sys_pfd6_clk", }; + +static const char *pcie_phy_sel[] = { "osc", "pll_enet_100m_clk", + "pll_enet_500m_clk", "ext_clk_1", "ext_clk_2", "ext_clk_3", + "ext_clk_4", "pll_sys_pfd0_392m_clk", }; + +static const char *epdc_pixel_sel[] = { "osc", "pll_sys_pfd1_332m_clk", + "pll_dram_533m_clk", "pll_sys_main", "pll_sys_pfd5_clk", + "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_main", }; + +static const char *lcdif_pixel_sel[] = { "osc", "pll_sys_pfd5_clk", + "pll_dram_533m_clk", "ext_clk_3", "pll_sys_pfd4_clk", + "pll_sys_pfd2_270m_clk", "pll_video_main", + "pll_usb_main_clk", }; + +static const char *mipi_dsi_sel[] = { "osc", "pll_sys_pfd5_clk", + "pll_sys_pfd3_clk", "pll_sys_main", "pll_sys_pfd0_196m_clk", + "pll_dram_533m_clk", "pll_video_main", "pll_audio_post_div", }; + +static const char *mipi_csi_sel[] = { "osc", "pll_sys_pfd4_clk", + "pll_sys_pfd3_clk", "pll_sys_main", "pll_sys_pfd0_196m_clk", + "pll_dram_533m_clk", "pll_video_main", "pll_audio_post_div", }; + +static const char *mipi_dphy_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_dram_533m_clk", "pll_sys_pfd5_clk", "ref_1m_clk", "ext_clk_2", + "pll_video_main", "ext_clk_3", }; + +static const char *sai1_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main", + "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", }; + +static const char *sai2_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main", + "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", }; + +static const char *sai3_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main", + "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_3", }; + +static const char *spdif_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main", + "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_3_clk", }; + +static const char *enet1_ref_sel[] = { "osc", "pll_enet_125m_clk", + "pll_enet_50m_clk", "pll_enet_25m_clk", + "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_main", + "ext_clk_4", }; + +static const char *enet1_time_sel[] = { "osc", "pll_enet_100m_clk", + "pll_audio_post_div", "ext_clk_1", "ext_clk_2", "ext_clk_3", + "ext_clk_4", "pll_video_main", }; + +static const char *enet2_ref_sel[] = { "osc", "pll_enet_125m_clk", + "pll_enet_50m_clk", "pll_enet_25m_clk", + "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_main", + "ext_clk_4", }; + +static const char *enet2_time_sel[] = { "osc", "pll_enet_100m_clk", + "pll_audio_post_div", "ext_clk_1", "ext_clk_2", "ext_clk_3", + "ext_clk_4", "pll_video_main", }; + +static const char *enet_phy_ref_sel[] = { "osc", "pll_enet_25m_clk", + "pll_enet_50m_clk", "pll_enet_125m_clk", + "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main", + "pll_sys_pfd3_clk", }; + +static const char *eim_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd3_clk", "pll_enet_125m_clk", + "pll_usb_main_clk", }; + +static const char *nand_sel[] = { "osc", "pll_sys_main", + "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd3_clk", + "pll_enet_500m_clk", "pll_enet_250m_clk", + "pll_video_main", }; + +static const char *qspi_sel[] = { "osc", "pll_sys_pfd4_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd3_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *usdhc1_sel[] = { "osc", "pll_sys_pfd0_392m_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *usdhc2_sel[] = { "osc", "pll_sys_pfd0_392m_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *usdhc3_sel[] = { "osc", "pll_sys_pfd0_392m_clk", + "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", }; + +static const char *can1_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_dram_533m_clk", "pll_sys_main", + "pll_enet_40m_clk", "pll_usb_main_clk", "ext_clk_1", + "ext_clk_4", }; + +static const char *can2_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_dram_533m_clk", "pll_sys_main", + "pll_enet_40m_clk", "pll_usb_main_clk", "ext_clk_1", + "ext_clk_3", }; + +static const char *i2c1_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_50m_clk", "pll_dram_533m_clk", + "pll_audio_post_div", "pll_video_main", "pll_usb_main_clk", + "pll_sys_pfd2_135m_clk", }; + +static const char *i2c2_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_50m_clk", "pll_dram_533m_clk", + "pll_audio_post_div", "pll_video_main", "pll_usb_main_clk", + "pll_sys_pfd2_135m_clk", }; + +static const char *i2c3_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_50m_clk", "pll_dram_533m_clk", + "pll_audio_post_div", "pll_video_main", "pll_usb_main_clk", + "pll_sys_pfd2_135m_clk", }; + +static const char *i2c4_sel[] = { "osc", "pll_sys_main_120m_clk", + "pll_enet_50m_clk", "pll_dram_533m_clk", + "pll_audio_post_div", "pll_video_main", "pll_usb_main_clk", + "pll_sys_pfd2_135m_clk", }; + +static const char *uart1_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main", "ext_clk_2", "ext_clk_4", + "pll_usb_main_clk", }; + +static const char *uart2_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main", "ext_clk_2", "ext_clk_3", + "pll_usb_main_clk", }; + +static const char *uart3_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main", "ext_clk_2", "ext_clk_4", + "pll_usb_main_clk", }; + +static const char *uart4_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main", "ext_clk_2", "ext_clk_3", + "pll_usb_main_clk", }; + +static const char *uart5_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main", "ext_clk_2", "ext_clk_4", + "pll_usb_main_clk", }; + +static const char *uart6_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main", "ext_clk_2", "ext_clk_3", + "pll_usb_main_clk", }; + +static const char *uart7_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_enet_100m_clk", + "pll_sys_main", "ext_clk_2", "ext_clk_4", + "pll_usb_main_clk", }; + +static const char *ecspi1_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_sys_main_120m_clk", + "pll_sys_main", "pll_sys_pfd4_clk", "pll_enet_250m_clk", + "pll_usb_main_clk", }; + +static const char *ecspi2_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_sys_main_120m_clk", + "pll_sys_main", "pll_sys_pfd4_clk", "pll_enet_250m_clk", + "pll_usb_main_clk", }; + +static const char *ecspi3_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_sys_main_120m_clk", + "pll_sys_main", "pll_sys_pfd4_clk", "pll_enet_250m_clk", + "pll_usb_main_clk", }; + +static const char *ecspi4_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_enet_40m_clk", "pll_sys_main_120m_clk", + "pll_sys_main", "pll_sys_pfd4_clk", "pll_enet_250m_clk", + "pll_usb_main_clk", }; + +static const char *pwm1_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div", + "ext_clk_1", "ref_1m_clk", "pll_video_main", }; + +static const char *pwm2_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div", + "ext_clk_1", "ref_1m_clk", "pll_video_main", }; + +static const char *pwm3_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div", + "ext_clk_2", "ref_1m_clk", "pll_video_main", }; + +static const char *pwm4_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div", + "ext_clk_2", "ref_1m_clk", "pll_video_main", }; + +static const char *flextimer1_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div", + "ext_clk_3", "ref_1m_clk", "pll_video_main", }; + +static const char *flextimer2_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div", + "ext_clk_3", "ref_1m_clk", "pll_video_main", }; + +static const char *sim1_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_usb_main_clk", "pll_audio_post_div", "pll_enet_125m_clk", + "pll_sys_pfd7_clk", }; + +static const char *sim2_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_usb_main_clk", "pll_video_main", "pll_enet_125m_clk", + "pll_sys_pfd7_clk", }; + +static const char *gpt1_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main", + "ref_1m_clk", "pll_audio_post_div", "ext_clk_1", }; + +static const char *gpt2_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main", + "ref_1m_clk", "pll_audio_post_div", "ext_clk_2", }; + +static const char *gpt3_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main", + "ref_1m_clk", "pll_audio_post_div", "ext_clk_3", }; + +static const char *gpt4_sel[] = { "osc", "pll_enet_100m_clk", + "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main", + "ref_1m_clk", "pll_audio_post_div", "ext_clk_4", }; + +static const char *trace_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_enet_125m_clk", "pll_usb_main_clk", "ext_clk_2", + "ext_clk_3", }; + +static const char *wdog_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_enet_125m_clk", "pll_usb_main_clk", "ref_1m_clk", + "pll_sys_pfd1_166m_clk", }; + +static const char *csi_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_main", + "pll_usb_main_clk", }; + +static const char *audio_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk", + "pll_sys_main_120m_clk", "pll_dram_533m_clk", + "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_main", + "pll_usb_main_clk", }; + +static const char *wrclk_sel[] = { "osc", "pll_enet_40m_clk", + "pll_dram_533m_clk", "pll_usb_main_clk", + "pll_sys_main_240m_clk", "pll_sys_pfd2_270m_clk", + "pll_enet_500m_clk", "pll_sys_pfd7_clk", }; + +static const char *clko1_sel[] = { "osc", "pll_sys_main", + "pll_sys_main_240m_clk", "pll_sys_pfd0_196m_clk", "pll_sys_pfd3_clk", + "pll_enet_500m_clk", "pll_dram_533m_clk", "ref_1m_clk", }; + +static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk", + "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk", + "pll_audio_post_div", "pll_video_main", "ckil", }; + +static const char *lvds1_sel[] = { "pll_arm_main", + "pll_sys_main", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk", + "pll_sys_pfd2_270m_clk", "pll_sys_pfd3_clk", "pll_sys_pfd4_clk", + "pll_sys_pfd5_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", + "pll_audio_post_div", "pll_video_main", "pll_enet_500m_clk", + "pll_enet_250m_clk", "pll_enet_125m_clk", "pll_enet_100m_clk", + "pll_enet_50m_clk", "pll_enet_40m_clk", "pll_enet_25m_clk", + "pll_dram_main", }; + +static int const clks_init_on[] __initconst = { + IMX7D_ARM_A7_ROOT_CLK, IMX7D_MAIN_AXI_ROOT_CLK, + IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK, + IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK, + IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK, + IMX7D_AHB_CHANNEL_ROOT_CLK, +}; + +static struct clk_onecell_data clk_data; + +static struct clk ** const uart_clks[] __initconst = { + &clks[IMX7D_UART1_ROOT_CLK], + &clks[IMX7D_UART2_ROOT_CLK], + &clks[IMX7D_UART3_ROOT_CLK], + &clks[IMX7D_UART4_ROOT_CLK], + &clks[IMX7D_UART5_ROOT_CLK], + &clks[IMX7D_UART6_ROOT_CLK], + &clks[IMX7D_UART7_ROOT_CLK], + NULL +}; + +static int imx7_clk_initialized; + +static int imx7_ccm_probe(struct device_d *dev) +{ + struct resource *iores; + void __iomem *base, *anatop_base, *ccm_base; + + anatop_base = IOMEM(MX7_ANATOP_BASE_ADDR); + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + ccm_base = IOMEM(iores->start); + + base = anatop_base; + + clks[IMX7D_PLL_ARM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "osc", base + 0x60, 0x7f); + clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_dram_main", "osc", base + 0x70, 0x7f); + clks[IMX7D_PLL_SYS_MAIN] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1); + clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0); + clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "osc", base + 0xf0, 0x7f); + clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "osc", base + 0x130, 0x7f); + + clks[IMX7D_PLL_SYS_PFD0_392M_CLK] = imx_clk_pfd("pll_sys_pfd0_392m_clk", "pll_sys_main", base + 0xc0, 0); + clks[IMX7D_PLL_SYS_PFD1_332M_CLK] = imx_clk_pfd("pll_sys_pfd1_332m_clk", "pll_sys_main", base + 0xc0, 1); + clks[IMX7D_PLL_SYS_PFD2_270M_CLK] = imx_clk_pfd("pll_sys_pfd2_270m_clk", "pll_sys_main", base + 0xc0, 2); + + clks[IMX7D_PLL_SYS_PFD3_CLK] = imx_clk_pfd("pll_sys_pfd3_clk", "pll_sys_main", base + 0xc0, 3); + clks[IMX7D_PLL_SYS_PFD4_CLK] = imx_clk_pfd("pll_sys_pfd4_clk", "pll_sys_main", base + 0xd0, 0); + clks[IMX7D_PLL_SYS_PFD5_CLK] = imx_clk_pfd("pll_sys_pfd5_clk", "pll_sys_main", base + 0xd0, 1); + clks[IMX7D_PLL_SYS_PFD6_CLK] = imx_clk_pfd("pll_sys_pfd6_clk", "pll_sys_main", base + 0xd0, 2); + clks[IMX7D_PLL_SYS_PFD7_CLK] = imx_clk_pfd("pll_sys_pfd7_clk", "pll_sys_main", base + 0xd0, 3); + + clks[IMX7D_PLL_SYS_MAIN_480M] = imx_clk_fixed_factor("pll_sys_main_480m", "pll_sys_main", 1, 1); + clks[IMX7D_PLL_SYS_MAIN_240M] = imx_clk_fixed_factor("pll_sys_main_240m", "pll_sys_main", 1, 2); + clks[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_fixed_factor("pll_sys_main_120m", "pll_sys_main", 1, 4); + clks[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_fixed_factor("pll_dram_533m", "pll_dram_main", 1, 2); + + clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4); + clks[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5); + clks[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6); + clks[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12); + + clks[IMX7D_PLL_SYS_PFD0_196M] = imx_clk_fixed_factor("pll_sys_pfd0_196m", "pll_sys_pfd0_392m_clk", 1, 2); + clks[IMX7D_PLL_SYS_PFD1_166M] = imx_clk_fixed_factor("pll_sys_pfd1_166m", "pll_sys_pfd1_332m_clk", 1, 2); + clks[IMX7D_PLL_SYS_PFD2_135M] = imx_clk_fixed_factor("pll_sys_pfd2_135m", "pll_sys_pfd2_270m_clk", 1, 2); + + clks[IMX7D_PLL_SYS_PFD0_196M_CLK] = imx_clk_gate_dis("pll_sys_pfd0_196m_clk", "pll_sys_pfd0_196m", base + 0xb0, 26); + clks[IMX7D_PLL_SYS_PFD1_166M_CLK] = imx_clk_gate_dis("pll_sys_pfd1_166m_clk", "pll_sys_pfd1_166m", base + 0xb0, 27); + clks[IMX7D_PLL_SYS_PFD2_135M_CLK] = imx_clk_gate_dis("pll_sys_pfd2_135m_clk", "pll_sys_pfd2_135m", base + 0xb0, 28); + + clks[IMX7D_PLL_ENET_MAIN_CLK] = imx_clk_fixed_factor("pll_enet_main_clk", "pll_enet_main", 1, 1); + clks[IMX7D_PLL_ENET_MAIN_500M] = imx_clk_fixed_factor("pll_enet_500m", "pll_enet_main_clk", 1, 2); + clks[IMX7D_PLL_ENET_MAIN_250M] = imx_clk_fixed_factor("pll_enet_250m", "pll_enet_main_clk", 1, 4); + clks[IMX7D_PLL_ENET_MAIN_125M] = imx_clk_fixed_factor("pll_enet_125m", "pll_enet_main_clk", 1, 8); + clks[IMX7D_PLL_ENET_MAIN_100M] = imx_clk_fixed_factor("pll_enet_100m", "pll_enet_main_clk", 1, 10); + clks[IMX7D_PLL_ENET_MAIN_50M] = imx_clk_fixed_factor("pll_enet_50m", "pll_enet_main_clk", 1, 20); + clks[IMX7D_PLL_ENET_MAIN_40M] = imx_clk_fixed_factor("pll_enet_40m", "pll_enet_main_clk", 1, 25); + clks[IMX7D_PLL_ENET_MAIN_25M] = imx_clk_fixed_factor("pll_enet_25m", "pll_enet_main_clk", 1, 40); + + clks[IMX7D_PLL_ENET_MAIN_500M_CLK] = imx_clk_gate("pll_enet_500m_clk", "pll_enet_500m", base + 0xe0, 12); + clks[IMX7D_PLL_ENET_MAIN_250M_CLK] = imx_clk_gate("pll_enet_250m_clk", "pll_enet_250m", base + 0xe0, 11); + clks[IMX7D_PLL_ENET_MAIN_125M_CLK] = imx_clk_gate("pll_enet_125m_clk", "pll_enet_125m", base + 0xe0, 10); + clks[IMX7D_PLL_ENET_MAIN_100M_CLK] = imx_clk_gate("pll_enet_100m_clk", "pll_enet_100m", base + 0xe0, 9); + clks[IMX7D_PLL_ENET_MAIN_50M_CLK] = imx_clk_gate("pll_enet_50m_clk", "pll_enet_50m", base + 0xe0, 8); + clks[IMX7D_PLL_ENET_MAIN_40M_CLK] = imx_clk_gate("pll_enet_40m_clk", "pll_enet_40m", base + 0xe0, 7); + clks[IMX7D_PLL_ENET_MAIN_25M_CLK] = imx_clk_gate("pll_enet_25m_clk", "pll_enet_25m", base + 0xe0, 6); + + clks[IMX7D_LVDS1_OUT_SEL] = imx_clk_mux("lvds1_sel", base + 0x170, 0, 5, lvds1_sel, ARRAY_SIZE(lvds1_sel)); + clks[IMX7D_LVDS1_OUT_CLK] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x170, 5, BIT(6)); + + base = ccm_base; + + clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel)); + clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel)); + clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux2("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel)); + clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel)); + clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel)); + clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel)); + clks[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_mux2("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel)); + clks[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_mux2("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel)); + clks[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_mux2("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel)); + clks[IMX7D_DRAM_ROOT_SRC] = imx_clk_mux2("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel)); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_mux2("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel)); + clks[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_mux2("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel)); + clks[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_mux2("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel)); + clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux2("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel)); + clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux2("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel)); + clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux2("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel)); + clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux2("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel)); + clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux2("mipi_dsi_src", base + 0xa380, 24, 3, mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel)); + clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux2("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel)); + clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux2("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel)); + clks[IMX7D_SAI1_ROOT_SRC] = imx_clk_mux2("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel)); + clks[IMX7D_SAI2_ROOT_SRC] = imx_clk_mux2("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel)); + clks[IMX7D_SAI3_ROOT_SRC] = imx_clk_mux2("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel)); + clks[IMX7D_SPDIF_ROOT_SRC] = imx_clk_mux2("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel)); + clks[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_mux2("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel)); + clks[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_mux2("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel)); + clks[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_mux2("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel)); + clks[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_mux2("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel)); + clks[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_mux2("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel)); + clks[IMX7D_EIM_ROOT_SRC] = imx_clk_mux2("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel)); + clks[IMX7D_NAND_ROOT_SRC] = imx_clk_mux2("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel)); + clks[IMX7D_QSPI_ROOT_SRC] = imx_clk_mux2("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel)); + clks[IMX7D_USDHC1_ROOT_SRC] = imx_clk_mux2("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel)); + clks[IMX7D_USDHC2_ROOT_SRC] = imx_clk_mux2("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel)); + clks[IMX7D_USDHC3_ROOT_SRC] = imx_clk_mux2("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel)); + clks[IMX7D_CAN1_ROOT_SRC] = imx_clk_mux2("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel)); + clks[IMX7D_CAN2_ROOT_SRC] = imx_clk_mux2("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel)); + clks[IMX7D_I2C1_ROOT_SRC] = imx_clk_mux2("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel)); + clks[IMX7D_I2C2_ROOT_SRC] = imx_clk_mux2("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel)); + clks[IMX7D_I2C3_ROOT_SRC] = imx_clk_mux2("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel)); + clks[IMX7D_I2C4_ROOT_SRC] = imx_clk_mux2("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel)); + clks[IMX7D_UART1_ROOT_SRC] = imx_clk_mux2("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel)); + clks[IMX7D_UART2_ROOT_SRC] = imx_clk_mux2("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel)); + clks[IMX7D_UART3_ROOT_SRC] = imx_clk_mux2("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel)); + clks[IMX7D_UART4_ROOT_SRC] = imx_clk_mux2("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel)); + clks[IMX7D_UART5_ROOT_SRC] = imx_clk_mux2("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel)); + clks[IMX7D_UART6_ROOT_SRC] = imx_clk_mux2("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel)); + clks[IMX7D_UART7_ROOT_SRC] = imx_clk_mux2("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel)); + clks[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_mux2("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel)); + clks[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_mux2("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel)); + clks[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_mux2("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel)); + clks[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_mux2("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel)); + clks[IMX7D_PWM1_ROOT_SRC] = imx_clk_mux2("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel)); + clks[IMX7D_PWM2_ROOT_SRC] = imx_clk_mux2("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel)); + clks[IMX7D_PWM3_ROOT_SRC] = imx_clk_mux2("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel)); + clks[IMX7D_PWM4_ROOT_SRC] = imx_clk_mux2("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel)); + clks[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_mux2("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel)); + clks[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_mux2("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel)); + clks[IMX7D_SIM1_ROOT_SRC] = imx_clk_mux2("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel)); + clks[IMX7D_SIM2_ROOT_SRC] = imx_clk_mux2("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel)); + clks[IMX7D_GPT1_ROOT_SRC] = imx_clk_mux2("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel)); + clks[IMX7D_GPT2_ROOT_SRC] = imx_clk_mux2("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel)); + clks[IMX7D_GPT3_ROOT_SRC] = imx_clk_mux2("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel)); + clks[IMX7D_GPT4_ROOT_SRC] = imx_clk_mux2("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel)); + clks[IMX7D_TRACE_ROOT_SRC] = imx_clk_mux2("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel)); + clks[IMX7D_WDOG_ROOT_SRC] = imx_clk_mux2("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel)); + clks[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_mux2("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel)); + clks[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_mux2("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel)); + clks[IMX7D_WRCLK_ROOT_SRC] = imx_clk_mux2("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel)); + clks[IMX7D_CLKO1_ROOT_SRC] = imx_clk_mux2("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel)); + clks[IMX7D_CLKO2_ROOT_SRC] = imx_clk_mux2("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel)); + + clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28); + clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); + clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate3("arm_m0_cg", "arm_m0_src", base + 0x8100, 28); + clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate3("axi_cg", "axi_src", base + 0x8800, 28); + clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28); + clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28); + clks[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_gate3("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28); + clks[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_gate3("ahb_cg", "ahb_src", base + 0x9000, 28); + clks[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_gate3("dram_phym_cg", "dram_phym_src", base + 0x9800, 28); + clks[IMX7D_DRAM_ROOT_CG] = imx_clk_gate3("dram_cg", "dram_src", base + 0x9880, 28); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_gate3("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28); + clks[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_gate3("dram_alt_cg", "dram_alt_src", base + 0xa080, 28); + clks[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_gate3("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28); + clks[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_gate3("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28); + clks[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_gate3("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28); + clks[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_gate3("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28); + clks[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_gate3("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28); + clks[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_gate3("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28); + clks[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_gate3("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28); + clks[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_gate3("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28); + clks[IMX7D_SAI1_ROOT_CG] = imx_clk_gate3("sai1_cg", "sai1_src", base + 0xa500, 28); + clks[IMX7D_SAI2_ROOT_CG] = imx_clk_gate3("sai2_cg", "sai2_src", base + 0xa580, 28); + clks[IMX7D_SAI3_ROOT_CG] = imx_clk_gate3("sai3_cg", "sai3_src", base + 0xa600, 28); + clks[IMX7D_SPDIF_ROOT_CG] = imx_clk_gate3("spdif_cg", "spdif_src", base + 0xa680, 28); + clks[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_gate3("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28); + clks[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_gate3("enet1_time_cg", "enet1_time_src", base + 0xa780, 28); + clks[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_gate3("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28); + clks[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_gate3("enet2_time_cg", "enet2_time_src", base + 0xa880, 28); + clks[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_gate3("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28); + clks[IMX7D_EIM_ROOT_CG] = imx_clk_gate3("eim_cg", "eim_src", base + 0xa980, 28); + clks[IMX7D_NAND_ROOT_CG] = imx_clk_gate3("nand_cg", "nand_src", base + 0xaa00, 28); + clks[IMX7D_QSPI_ROOT_CG] = imx_clk_gate3("qspi_cg", "qspi_src", base + 0xaa80, 28); + clks[IMX7D_USDHC1_ROOT_CG] = imx_clk_gate3("usdhc1_cg", "usdhc1_src", base + 0xab00, 28); + clks[IMX7D_USDHC2_ROOT_CG] = imx_clk_gate3("usdhc2_cg", "usdhc2_src", base + 0xab80, 28); + clks[IMX7D_USDHC3_ROOT_CG] = imx_clk_gate3("usdhc3_cg", "usdhc3_src", base + 0xac00, 28); + clks[IMX7D_CAN1_ROOT_CG] = imx_clk_gate3("can1_cg", "can1_src", base + 0xac80, 28); + clks[IMX7D_CAN2_ROOT_CG] = imx_clk_gate3("can2_cg", "can2_src", base + 0xad00, 28); + clks[IMX7D_I2C1_ROOT_CG] = imx_clk_gate3("i2c1_cg", "i2c1_src", base + 0xad80, 28); + clks[IMX7D_I2C2_ROOT_CG] = imx_clk_gate3("i2c2_cg", "i2c2_src", base + 0xae00, 28); + clks[IMX7D_I2C3_ROOT_CG] = imx_clk_gate3("i2c3_cg", "i2c3_src", base + 0xae80, 28); + clks[IMX7D_I2C4_ROOT_CG] = imx_clk_gate3("i2c4_cg", "i2c4_src", base + 0xaf00, 28); + clks[IMX7D_UART1_ROOT_CG] = imx_clk_gate3("uart1_cg", "uart1_src", base + 0xaf80, 28); + clks[IMX7D_UART2_ROOT_CG] = imx_clk_gate3("uart2_cg", "uart2_src", base + 0xb000, 28); + clks[IMX7D_UART3_ROOT_CG] = imx_clk_gate3("uart3_cg", "uart3_src", base + 0xb080, 28); + clks[IMX7D_UART4_ROOT_CG] = imx_clk_gate3("uart4_cg", "uart4_src", base + 0xb100, 28); + clks[IMX7D_UART5_ROOT_CG] = imx_clk_gate3("uart5_cg", "uart5_src", base + 0xb180, 28); + clks[IMX7D_UART6_ROOT_CG] = imx_clk_gate3("uart6_cg", "uart6_src", base + 0xb200, 28); + clks[IMX7D_UART7_ROOT_CG] = imx_clk_gate3("uart7_cg", "uart7_src", base + 0xb280, 28); + clks[IMX7D_ECSPI1_ROOT_CG] = imx_clk_gate3("ecspi1_cg", "ecspi1_src", base + 0xb300, 28); + clks[IMX7D_ECSPI2_ROOT_CG] = imx_clk_gate3("ecspi2_cg", "ecspi2_src", base + 0xb380, 28); + clks[IMX7D_ECSPI3_ROOT_CG] = imx_clk_gate3("ecspi3_cg", "ecspi3_src", base + 0xb400, 28); + clks[IMX7D_ECSPI4_ROOT_CG] = imx_clk_gate3("ecspi4_cg", "ecspi4_src", base + 0xb480, 28); + clks[IMX7D_PWM1_ROOT_CG] = imx_clk_gate3("pwm1_cg", "pwm1_src", base + 0xb500, 28); + clks[IMX7D_PWM2_ROOT_CG] = imx_clk_gate3("pwm2_cg", "pwm2_src", base + 0xb580, 28); + clks[IMX7D_PWM3_ROOT_CG] = imx_clk_gate3("pwm3_cg", "pwm3_src", base + 0xb600, 28); + clks[IMX7D_PWM4_ROOT_CG] = imx_clk_gate3("pwm4_cg", "pwm4_src", base + 0xb680, 28); + clks[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_gate3("flextimer1_cg", "flextimer1_src", base + 0xb700, 28); + clks[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_gate3("flextimer2_cg", "flextimer2_src", base + 0xb780, 28); + clks[IMX7D_SIM1_ROOT_CG] = imx_clk_gate3("sim1_cg", "sim1_src", base + 0xb800, 28); + clks[IMX7D_SIM2_ROOT_CG] = imx_clk_gate3("sim2_cg", "sim2_src", base + 0xb880, 28); + clks[IMX7D_GPT1_ROOT_CG] = imx_clk_gate3("gpt1_cg", "gpt1_src", base + 0xb900, 28); + clks[IMX7D_GPT2_ROOT_CG] = imx_clk_gate3("gpt2_cg", "gpt2_src", base + 0xb980, 28); + clks[IMX7D_GPT3_ROOT_CG] = imx_clk_gate3("gpt3_cg", "gpt3_src", base + 0xbA00, 28); + clks[IMX7D_GPT4_ROOT_CG] = imx_clk_gate3("gpt4_cg", "gpt4_src", base + 0xbA80, 28); + clks[IMX7D_TRACE_ROOT_CG] = imx_clk_gate3("trace_cg", "trace_src", base + 0xbb00, 28); + clks[IMX7D_WDOG_ROOT_CG] = imx_clk_gate3("wdog_cg", "wdog_src", base + 0xbb80, 28); + clks[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_gate3("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28); + clks[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_gate3("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28); + clks[IMX7D_WRCLK_ROOT_CG] = imx_clk_gate3("wrclk_cg", "wrclk_src", base + 0xbd00, 28); + clks[IMX7D_CLKO1_ROOT_CG] = imx_clk_gate3("clko1_cg", "clko1_src", base + 0xbd80, 28); + clks[IMX7D_CLKO2_ROOT_CG] = imx_clk_gate3("clko2_cg", "clko2_src", base + 0xbe00, 28); + + clks[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_divider2("axi_pre_div", "axi_cg", base + 0x8800, 16, 3); + clks[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_divider2("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3); + clks[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_divider2("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3); + clks[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_divider2("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3); + clks[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_divider2("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_divider2("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3); + clks[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_divider2("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3); + clks[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_divider2("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3); + clks[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_divider2("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3); + clks[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_divider2("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3); + clks[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_divider2("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3); + clks[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_divider2("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3); + clks[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_divider2("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3); + clks[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_divider2("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3); + clks[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_divider2("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3); + clks[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_divider2("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3); + clks[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_divider2("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3); + clks[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_divider2("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3); + clks[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_divider2("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3); + clks[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3); + clks[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_divider2("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3); + clks[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3); + clks[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_divider2("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3); + clks[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3); + clks[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_divider2("eim_pre_div", "eim_cg", base + 0xa980, 16, 3); + clks[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_divider2("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3); + clks[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_divider2("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3); + clks[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_divider2("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3); + clks[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_divider2("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3); + clks[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_divider2("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3); + clks[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_divider2("can1_pre_div", "can1_cg", base + 0xac80, 16, 3); + clks[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_divider2("can2_pre_div", "can2_cg", base + 0xad00, 16, 3); + clks[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_divider2("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3); + clks[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_divider2("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3); + clks[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_divider2("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3); + clks[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_divider2("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3); + clks[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_divider2("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3); + clks[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_divider2("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3); + clks[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_divider2("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3); + clks[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_divider2("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3); + clks[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_divider2("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3); + clks[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_divider2("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3); + clks[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_divider2("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3); + clks[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_divider2("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3); + clks[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_divider2("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3); + clks[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_divider2("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3); + clks[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_divider2("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3); + clks[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_divider2("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3); + clks[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_divider2("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3); + clks[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_divider2("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3); + clks[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_divider2("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3); + clks[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_divider2("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3); + clks[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_divider2("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3); + clks[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_divider2("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3); + clks[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_divider2("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3); + clks[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_divider2("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3); + clks[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_divider2("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3); + clks[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_divider2("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3); + clks[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_divider2("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3); + clks[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_divider2("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3); + clks[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_divider2("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3); + clks[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_divider2("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3); + clks[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_divider2("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3); + clks[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_divider2("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3); + clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider2("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3); + clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider2("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3); + + clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3); + clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); + clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider2("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3); + clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6); + clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6); + clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6); + clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider2("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6); + clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6); + clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3); + clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3); + clks[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_divider2("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6); + clks[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_divider2("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6); + clks[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_divider2("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6); + clks[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_divider2("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6); + clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider2("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6); + clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider2("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6); + clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider2("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6); + clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider2("mipi_dphy_post_div", "mipi_csi_dphy_div", base + 0xa480, 0, 6); + clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider2("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6); + clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider2("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6); + clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider2("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6); + clks[IMX7D_SPDIF_ROOT_DIV] = imx_clk_divider2("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6); + clks[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_divider2("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6); + clks[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_divider2("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6); + clks[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_divider2("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6); + clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider2("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6); + clks[IMX7D_ENET_PHY_REF_ROOT_DIV] = imx_clk_divider2("enet_phy_ref_post_div", "enet_phy_ref_pre_div", base + 0xa900, 0, 6); + clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider2("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6); + clks[IMX7D_NAND_ROOT_DIV] = imx_clk_divider2("nand_post_div", "nand_pre_div", base + 0xaa00, 0, 6); + clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider2("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6); + clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider2("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6); + clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider2("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6); + clks[IMX7D_USDHC3_ROOT_DIV] = imx_clk_divider2("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6); + clks[IMX7D_CAN1_ROOT_DIV] = imx_clk_divider2("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6); + clks[IMX7D_CAN2_ROOT_DIV] = imx_clk_divider2("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6); + clks[IMX7D_I2C1_ROOT_DIV] = imx_clk_divider2("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6); + clks[IMX7D_I2C2_ROOT_DIV] = imx_clk_divider2("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6); + clks[IMX7D_I2C3_ROOT_DIV] = imx_clk_divider2("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6); + clks[IMX7D_I2C4_ROOT_DIV] = imx_clk_divider2("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6); + clks[IMX7D_UART1_ROOT_DIV] = imx_clk_divider2("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6); + clks[IMX7D_UART2_ROOT_DIV] = imx_clk_divider2("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6); + clks[IMX7D_UART3_ROOT_DIV] = imx_clk_divider2("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6); + clks[IMX7D_UART4_ROOT_DIV] = imx_clk_divider2("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6); + clks[IMX7D_UART5_ROOT_DIV] = imx_clk_divider2("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6); + clks[IMX7D_UART6_ROOT_DIV] = imx_clk_divider2("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6); + clks[IMX7D_UART7_ROOT_DIV] = imx_clk_divider2("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6); + clks[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_divider2("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6); + clks[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_divider2("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6); + clks[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_divider2("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6); + clks[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_divider2("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6); + clks[IMX7D_PWM1_ROOT_DIV] = imx_clk_divider2("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6); + clks[IMX7D_PWM2_ROOT_DIV] = imx_clk_divider2("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6); + clks[IMX7D_PWM3_ROOT_DIV] = imx_clk_divider2("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6); + clks[IMX7D_PWM4_ROOT_DIV] = imx_clk_divider2("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6); + clks[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_divider2("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6); + clks[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_divider2("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6); + clks[IMX7D_SIM1_ROOT_DIV] = imx_clk_divider2("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6); + clks[IMX7D_SIM2_ROOT_DIV] = imx_clk_divider2("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6); + clks[IMX7D_GPT1_ROOT_DIV] = imx_clk_divider2("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6); + clks[IMX7D_GPT2_ROOT_DIV] = imx_clk_divider2("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6); + clks[IMX7D_GPT3_ROOT_DIV] = imx_clk_divider2("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6); + clks[IMX7D_GPT4_ROOT_DIV] = imx_clk_divider2("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6); + clks[IMX7D_TRACE_ROOT_DIV] = imx_clk_divider2("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6); + clks[IMX7D_WDOG_ROOT_DIV] = imx_clk_divider2("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6); + clks[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_divider2("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6); + clks[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_divider2("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6); + clks[IMX7D_WRCLK_ROOT_DIV] = imx_clk_divider2("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6); + clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6); + clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6); + + clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0); + clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0); + clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate4("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0); + clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); + clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); + clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); + clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0); + clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_post_div", base + 0x4120, 0); + clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate4("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0); + clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate4("ahb_root_clk", "ahb_post_div", base + 0x4200, 0); + clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0); + clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0); + clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0); + clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0); + clks[IMX7D_SDMA_CORE_CLK] = imx_clk_gate4("sdma_root_clk", "ahb_root_clk", base + 0x4480, 0); + clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0); + clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate4("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0); + clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate4("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0); + clks[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_gate4("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0); + + /* + * Linux code controls gates at 0x44e0, 0x44f0, 0x4500 and 0x4500. However, these do not seem to + * exist in hardware. According to the reference manual the ethernet clocks are controlled by + * gates at 0x4700 and 0x4710 + */ + clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate4("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x4700, 0); + clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate_shared("enet1_time_root_clk", "enet1_time_post_div", "enet1_ref_root_clk"); + clks[IMX7D_ENET2_REF_ROOT_CLK] = imx_clk_gate4("enet2_ref_root_clk", "enet2_ref_post_div", base + 0x4710, 0); + clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate_shared("enet2_time_root_clk", "enet2_time_post_div", "enet2_ref_root_clk"); + clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate4("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0); + + clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate4("eim_root_clk", "eim_post_div", base + 0x4160, 0); + clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate4("nand_root_clk", "nand_post_div", base + 0x4140, 0); + clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate4("qspi_root_clk", "qspi_post_div", base + 0x4150, 0); + clks[IMX7D_USB_CTRL_CLK] = imx_clk_gate4("usb_ctrl_clk", "osc", base + 0x4680, 0); + clks[IMX7D_USB_PHY1_CLK] = imx_clk_gate4("usbphy1_clk", "osc", base + 0x46a0, 0); + clks[IMX7D_USB_PHY2_CLK] = imx_clk_gate4("usbphy2_clk", "osc", base + 0x46b0, 0); + clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate4("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0); + clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate4("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0); + clks[IMX7D_USDHC3_ROOT_CLK] = imx_clk_gate4("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0); + clks[IMX7D_CAN1_ROOT_CLK] = imx_clk_gate4("can1_root_clk", "can1_post_div", base + 0x4740, 0); + clks[IMX7D_CAN2_ROOT_CLK] = imx_clk_gate4("can2_root_clk", "can2_post_div", base + 0x4750, 0); + clks[IMX7D_I2C1_ROOT_CLK] = imx_clk_gate4("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0); + clks[IMX7D_I2C2_ROOT_CLK] = imx_clk_gate4("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0); + clks[IMX7D_I2C3_ROOT_CLK] = imx_clk_gate4("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0); + clks[IMX7D_I2C4_ROOT_CLK] = imx_clk_gate4("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0); + clks[IMX7D_UART1_ROOT_CLK] = imx_clk_gate4("uart1_root_clk", "uart1_post_div", base + 0x4940, 0); + clks[IMX7D_UART2_ROOT_CLK] = imx_clk_gate4("uart2_root_clk", "uart2_post_div", base + 0x4950, 0); + clks[IMX7D_UART3_ROOT_CLK] = imx_clk_gate4("uart3_root_clk", "uart3_post_div", base + 0x4960, 0); + clks[IMX7D_UART4_ROOT_CLK] = imx_clk_gate4("uart4_root_clk", "uart4_post_div", base + 0x4970, 0); + clks[IMX7D_UART5_ROOT_CLK] = imx_clk_gate4("uart5_root_clk", "uart5_post_div", base + 0x4980, 0); + clks[IMX7D_UART6_ROOT_CLK] = imx_clk_gate4("uart6_root_clk", "uart6_post_div", base + 0x4990, 0); + clks[IMX7D_UART7_ROOT_CLK] = imx_clk_gate4("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0); + clks[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_gate4("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0); + clks[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_gate4("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0); + clks[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_gate4("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0); + clks[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_gate4("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0); + clks[IMX7D_PWM1_ROOT_CLK] = imx_clk_gate4("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0); + clks[IMX7D_PWM2_ROOT_CLK] = imx_clk_gate4("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0); + clks[IMX7D_PWM3_ROOT_CLK] = imx_clk_gate4("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0); + clks[IMX7D_PWM4_ROOT_CLK] = imx_clk_gate4("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0); + clks[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_gate4("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0); + clks[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_gate4("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0); + clks[IMX7D_SIM1_ROOT_CLK] = imx_clk_gate4("sim1_root_clk", "sim1_post_div", base + 0x4900, 0); + clks[IMX7D_SIM2_ROOT_CLK] = imx_clk_gate4("sim2_root_clk", "sim2_post_div", base + 0x4910, 0); + clks[IMX7D_GPT1_ROOT_CLK] = imx_clk_gate4("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0); + clks[IMX7D_GPT2_ROOT_CLK] = imx_clk_gate4("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0); + clks[IMX7D_GPT3_ROOT_CLK] = imx_clk_gate4("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0); + clks[IMX7D_GPT4_ROOT_CLK] = imx_clk_gate4("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0); + clks[IMX7D_TRACE_ROOT_CLK] = imx_clk_gate4("trace_root_clk", "trace_post_div", base + 0x4300, 0); + clks[IMX7D_WDOG1_ROOT_CLK] = imx_clk_gate4("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0); + clks[IMX7D_WDOG2_ROOT_CLK] = imx_clk_gate4("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0); + clks[IMX7D_WDOG3_ROOT_CLK] = imx_clk_gate4("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0); + clks[IMX7D_WDOG4_ROOT_CLK] = imx_clk_gate4("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0); + clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0); + clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0); + clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0); + clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate4("adc_root_clk", "ipg_root_clk", base + 0x4200, 0); + + clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); + + clks[IMX7D_CLK_ARM] = imx_clk_cpu("arm", "arm_a7_root_clk", + clks[IMX7D_ARM_A7_ROOT_CLK], + clks[IMX7D_ARM_A7_ROOT_SRC], + clks[IMX7D_PLL_ARM_MAIN_CLK], + clks[IMX7D_PLL_SYS_MAIN_CLK]); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data); + + imx7_clk_initialized = 1; + + return 0; +} + +static int imx7_clk_setup(void) +{ + int i; + + if (!imx7_clk_initialized) + return 0; + + clks[IMX7D_OSC_24M_CLK] = clk_lookup("osc"); + + for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) + clk_enable(clks[clks_init_on[i]]); + + /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */ + clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); + + /* set uart module clock's parent clock source that must be great then 80MHz */ + clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); + + clk_set_parent(clks[IMX7D_ENET1_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_125M_CLK]); + clk_set_parent(clks[IMX7D_ENET1_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]); + clk_set_parent(clks[IMX7D_ENET2_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_125M_CLK]); + clk_set_parent(clks[IMX7D_ENET2_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]); + + clk_set_rate(clks[IMX7D_PLL_SYS_PFD4_CLK], 392000000); + clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC], clks[IMX7D_PLL_SYS_PFD4_CLK]); + clk_set_rate(clks[IMX7D_ENET_AXI_ROOT_CLK], 197000000); + clk_set_rate(clks[IMX7D_ENET1_TIME_ROOT_CLK], 25000000); + clk_set_rate(clks[IMX7D_ENET2_TIME_ROOT_CLK], 25000000); + + return 0; +} +postcore_initcall(imx7_clk_setup); + +static __maybe_unused struct of_device_id imx7_ccm_dt_ids[] = { + { + .compatible = "fsl,imx7d-ccm", + }, { + /* sentinel */ + } +}; + +static struct driver_d imx7_ccm_driver = { + .probe = imx7_ccm_probe, + .name = "imx6-ccm", + .of_compatible = DRV_OF_COMPAT(imx7_ccm_dt_ids), +}; + +static int imx7_ccm_init(void) +{ + return platform_driver_register(&imx7_ccm_driver); +} +core_initcall(imx7_ccm_init); \ No newline at end of file diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 29c0f1c..6d4399b 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -26,10 +26,13 @@ #define PLL_NUM_OFFSET 0x10 #define PLL_DENOM_OFFSET 0x20 +#define SYS_VF610_PLL_OFFSET 0x10 + #define BM_PLL_POWER (0x1 << 12) #define BM_PLL_ENABLE (0x1 << 13) #define BM_PLL_BYPASS (0x1 << 16) #define BM_PLL_LOCK (0x1 << 31) +#define IMX7_ENET_PLL_POWER (0x1 << 5) struct clk_pllv3 { struct clk clk; @@ -38,6 +41,10 @@ u32 div_mask; u32 div_shift; const char *parent; + void __iomem *lock_reg; + u32 lock_mask; + u32 ref_clock; + u32 power_bit; }; #define to_clk_pllv3(_clk) container_of(_clk, struct clk_pllv3, clk) @@ -51,9 +58,9 @@ val = readl(pll->base); val &= ~BM_PLL_BYPASS; if (pll->powerup_set) - val |= BM_PLL_POWER; + val |= pll->power_bit; else - val &= ~BM_PLL_POWER; + val &= ~pll->power_bit; writel(val, pll->base); /* Wait for PLL to lock */ @@ -83,9 +90,9 @@ val |= BM_PLL_BYPASS; if (pll->powerup_set) - val &= ~BM_PLL_POWER; + val &= ~pll->power_bit; else - val |= BM_PLL_POWER; + val |= pll->power_bit; writel(val, pll->base); } @@ -265,7 +272,9 @@ static unsigned long clk_pllv3_enet_recalc_rate(struct clk *clk, unsigned long parent_rate) { - return 500000000; + struct clk_pllv3 *pll = to_clk_pllv3(clk); + + return pll->ref_clock; } static const struct clk_ops clk_pllv3_enet_ops = { @@ -279,6 +288,88 @@ .disable = clk_pllv3_disable, }; +static unsigned long clk_pllv3_sys_vf610_recalc_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_pllv3 *pll = to_clk_pllv3(clk); + + u32 mfn = readl(pll->base + SYS_VF610_PLL_OFFSET + PLL_NUM_OFFSET); + u32 mfd = readl(pll->base + SYS_VF610_PLL_OFFSET + PLL_DENOM_OFFSET); + u32 div = (readl(pll->base) & pll->div_mask) ? 22 : 20; + + return (parent_rate * div) + ((parent_rate / mfd) * mfn); +} + +static long clk_pllv3_sys_vf610_round_rate(struct clk *clk, unsigned long rate, + unsigned long *prate) +{ + unsigned long parent_rate = *prate; + unsigned long min_rate = parent_rate * 20; + unsigned long max_rate = 528000000; + u32 mfn, mfd = 1000000; + u64 temp64; + + if (rate >= max_rate) + return max_rate; + else if (rate < min_rate) + rate = min_rate; + + temp64 = (u64) (rate - 20 * parent_rate); + temp64 *= mfd; + do_div(temp64, parent_rate); + mfn = temp64; + + return parent_rate * 20 + parent_rate / mfd * mfn; +} + +static int clk_pllv3_sys_vf610_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_pllv3 *pll = to_clk_pllv3(clk); + unsigned long min_rate = parent_rate * 20; + unsigned long max_rate = 528000000; + u32 val; + u32 mfn, mfd = 1000000; + u64 temp64; + + if (rate < min_rate || rate > max_rate) + return -EINVAL; + + val = readl(pll->base); + + if (rate == max_rate) { + writel(0, pll->base + SYS_VF610_PLL_OFFSET + PLL_NUM_OFFSET); + val |= pll->div_mask; + writel(val, pll->base); + + return 0; + } else { + val &= ~pll->div_mask; + } + + temp64 = (u64) (rate - 20 * parent_rate); + temp64 *= mfd; + do_div(temp64, parent_rate); + mfn = temp64; + + writel(val, pll->base); + writel(mfn, pll->base + SYS_VF610_PLL_OFFSET + PLL_NUM_OFFSET); + writel(mfd, pll->base + SYS_VF610_PLL_OFFSET + PLL_DENOM_OFFSET); + + while (!(readl(pll->lock_reg) & pll->lock_mask)) + ; + + return 0; +} + +static const struct clk_ops clk_pllv3_sys_vf610_ops = { + .enable = clk_pllv3_enable, + .disable = clk_pllv3_disable, + .recalc_rate = clk_pllv3_sys_vf610_recalc_rate, + .round_rate = clk_pllv3_sys_vf610_round_rate, + .set_rate = clk_pllv3_sys_vf610_set_rate, +}; + struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, const char *parent, void __iomem *base, u32 div_mask) @@ -289,7 +380,12 @@ pll = xzalloc(sizeof(*pll)); + pll->power_bit = BM_PLL_POWER; + switch (type) { + case IMX_PLLV3_SYS_VF610: + ops = &clk_pllv3_sys_vf610_ops; + break; case IMX_PLLV3_SYS: ops = &clk_pllv3_sys_ops; break; @@ -302,7 +398,13 @@ case IMX_PLLV3_AV: ops = &clk_pllv3_av_ops; break; + case IMX_PLLV3_ENET_IMX7: + pll->power_bit = IMX7_ENET_PLL_POWER; + pll->ref_clock = 1000000000; + ops = &clk_pllv3_enet_ops; + break; case IMX_PLLV3_ENET: + pll->ref_clock = 500000000; ops = &clk_pllv3_enet_ops; break; case IMX_PLLV3_MLB: @@ -327,3 +429,22 @@ return &pll->clk; } + +struct clk *imx_clk_pllv3_locked(enum imx_pllv3_type type, const char *name, + const char *parent, void __iomem *base, + u32 div_mask, void __iomem *lock_reg, u32 lock_mask) +{ + struct clk *clk; + struct clk_pllv3 *pll; + + clk = imx_clk_pllv3(type, name, parent, base, div_mask); + if (IS_ERR(clk)) + return clk; + + pll = to_clk_pllv3(clk); + + pll->lock_reg = lock_reg; + pll->lock_mask = lock_mask; + + return clk; +} diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 9b9ac6c..41fa3e9 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -16,7 +16,10 @@ #include #include #include +#include #include +#include +#include #include "clk.h" @@ -76,6 +79,7 @@ #define PLL6_CTRL (anatop_base + 0xa0) #define PLL7_CTRL (anatop_base + 0x20) #define ANA_MISC1 (anatop_base + 0x160) +#define PLL_LOCK (anatop_base + 0x2c0) static void __iomem *anatop_base; static void __iomem *ccm_base; @@ -188,8 +192,9 @@ clk[VF610_CLK_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", PLL6_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); clk[VF610_CLK_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", PLL7_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); - clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1); - clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1); + clk[VF610_CLK_PLL1] = imx_clk_pllv3_locked(IMX_PLLV3_SYS_VF610, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1, PLL_LOCK, BIT(6)); + clk[VF610_CLK_PLL2] = imx_clk_pllv3_locked(IMX_PLLV3_SYS_VF610, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1, PLL_LOCK, BIT(5)); + clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2); clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f); clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3); @@ -444,3 +449,157 @@ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); } CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init); + +enum { + VF610_SPEED_500 = 0b1110, + VF610_SPEED_400 = 0b1001, + VF610_SPEED_266 = 0b0001, + + DDRMC_CR117 = 0x01d4, + DDRMC_CR117_AXI0_FITYPEREG_SYNC = 0b01 << 16, +}; + +static int vf610_switch_cpu_clock_to_500mhz(void) +{ + int ret; + + /* + * When switching A5 CPU to 500Mhz we expect DDRC to be + * clocked by PLL2_PFD2 and the system to be configured in + * asynchronous mode. + * + * We also can't just use default PFD1 output of PLL1 due to + * Errata e6235, so we have to re-clock the PLL itself and use + * its output to clock the CPU directly. + */ + + if (clk_get_parent(clk[VF610_CLK_DDR_SEL]) != clk[VF610_CLK_PLL2_PFD2]) { + pr_warn("DDRC is clocked by PLL1, can't switch CPU clock"); + return -EINVAL; + } + + ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL2_BUS]); + if (ret < 0) { + pr_crit("Unable to re-parent '%s'\n", + clk[VF610_CLK_SYS_SEL]->name); + return ret; + } + + ret = clk_set_rate(clk[VF610_CLK_PLL1], 500000000); + if (ret < 0) { + pr_crit("Unable to set %s to 500Mhz %d\n", + clk[VF610_CLK_PLL1]->name, ret); + return ret; + } + + ret = clk_set_parent(clk[VF610_CLK_PLL1_PFD_SEL], clk[VF610_CLK_PLL1_SYS]); + if (ret < 0) { + pr_crit("Unable to re-parent '%s'\n", + clk[VF610_CLK_PLL1_PFD_SEL]->name); + return ret; + } + + ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL1_PFD_SEL]); + if (ret < 0) { + pr_crit("Unable to re-parent '%s'\n", + clk[VF610_CLK_SYS_SEL]->name); + return ret; + } + + /* + * imx_clk_divider has no error path in its set_rate hook + */ + clk_set_rate(clk[VF610_CLK_SYS_BUS], clk_get_rate(clk[VF610_CLK_SYS_SEL])); + clk_set_rate(clk[VF610_CLK_PLATFORM_BUS], clk_get_rate(clk[VF610_CLK_SYS_BUS]) / 3); + + return ret; +} + +static int vf610_switch_cpu_clock_to_400mhz(void) +{ + int ret; + uint32_t cr117; + void * __iomem ddrmc = IOMEM(VF610_DDR_BASE_ADDR); + + if (clk_get_parent(clk[VF610_CLK_DDR_SEL]) != clk[VF610_CLK_PLL2_PFD2]) { + pr_warn("DDRC is clocked by PLL1, can't switch CPU clock"); + return -EINVAL; + } + + ret = clk_set_parent(clk[VF610_CLK_PLL2_PFD_SEL], clk[VF610_CLK_PLL2_PFD2]); + if (ret < 0) { + pr_crit("Unable to re-parent '%s'\n", + clk[VF610_CLK_PLL2_PFD_SEL]->name); + return ret; + } + + ret = clk_set_parent(clk[VF610_CLK_SYS_SEL], clk[VF610_CLK_PLL2_PFD_SEL]); + if (ret < 0) { + pr_crit("Unable to re-parent '%s'\n", + clk[VF610_CLK_SYS_SEL]->name); + return ret; + } + + /* + * imx_clk_divider has no error path in its set_rate hook + */ + clk_set_rate(clk[VF610_CLK_SYS_BUS], clk_get_rate(clk[VF610_CLK_SYS_SEL])); + clk_set_rate(clk[VF610_CLK_PLATFORM_BUS], clk_get_rate(clk[VF610_CLK_SYS_BUS]) / 3); + + /* + * Now that we are running off of the same clock as DDRMC we + * shouldn't need to use clock domain crossing FIFO and + * asynchronous mode and instead can swithch to sychronous + * mode for AXI0 accesses + */ + cr117 = readl(ddrmc + DDRMC_CR117); + cr117 |= DDRMC_CR117_AXI0_FITYPEREG_SYNC; + writel(cr117, ddrmc + DDRMC_CR117); + + return 0; +} + +static int vf610_switch_cpu_clock(void) +{ + int ret; + bool sense_enable; + uint32_t speed_grading; + + if (!of_machine_is_compatible("fsl,vf610")) + return 0; + + sense_enable = imx_ocotp_sense_enable(true); + ret = imx_ocotp_read_field(VF610_OCOTP_SPEED_GRADING, &speed_grading); + imx_ocotp_sense_enable(sense_enable); + if (ret < 0) + return ret; + + switch (speed_grading) { + default: + pr_err("Unknown CPU speed grading %x\n", speed_grading); + return -EINVAL; + + case VF610_SPEED_266: + return 0; + + case VF610_SPEED_500: + ret = vf610_switch_cpu_clock_to_500mhz(); + break; + + case VF610_SPEED_400: + ret = vf610_switch_cpu_clock_to_400mhz(); + break; + } + + clock_notifier_call_chain(); + return ret; +} +/* + * We can probably gain a bit of a boot speed if we switch CPU clock + * earlier, but if we do this we'd need to figure out a way how to + * re-adjust the baud rate settings of the UART for DEBUG_LL + * functionality, or, accept the fact that it will be unavailable + * after this hook is executed. Both are far from ideal, so a bit + * slower boot it is. + */ +postconsole_initcall(vf610_switch_cpu_clock); diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 970f65c..8da8064 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -2,7 +2,7 @@ #define __IMX_CLK_H struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg, - u8 shift, u8 cgr_val); + u8 shift, u8 cgr_val, unsigned long flags); static inline struct clk *imx_clk_divider(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width) @@ -16,6 +16,12 @@ return clk_divider(name, parent, reg, shift, width, 0); } +static inline struct clk *imx_clk_divider2(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width) +{ + return clk_divider(name, parent, reg, shift, width, CLK_OPS_PARENT_ENABLE); +} + static inline struct clk *imx_clk_divider_table(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width, const struct clk_div_table *table) @@ -44,6 +50,12 @@ return clk_mux(name, reg, shift, width, parents, num_parents, 0); } +static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg, + u8 shift, u8 width, const char **parents, u8 num_parents) +{ + return clk_mux(name, reg, shift, width, parents, num_parents, CLK_OPS_PARENT_ENABLE); +} + static inline struct clk *imx_clk_mux_p(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, u8 num_parents) { @@ -56,18 +68,41 @@ return clk_gate(name, parent, reg, shift, CLK_SET_RATE_PARENT, 0); } +static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_gate_inverted(name, parent, reg, shift, CLK_SET_RATE_PARENT); +} + static inline struct clk *imx_clk_gate2(const char *name, const char *parent, void __iomem *reg, u8 shift) { - return clk_gate2(name, parent, reg, shift, 0x3); + return clk_gate2(name, parent, reg, shift, 0x3, 0); } static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 cgr_val) { - return clk_gate2(name, parent, reg, shift, cgr_val); + return clk_gate2(name, parent, reg, shift, cgr_val, 0); } +static inline struct clk *imx_clk_gate3(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_gate(name, parent, reg, shift, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, 0); +} + +static inline struct clk *imx_clk_gate4(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_gate2(name, parent, reg, shift, 0x3, CLK_OPS_PARENT_ENABLE); +} + +static inline struct clk *imx_clk_gate_shared(const char *name, const char *parent, + const char *shared) +{ + return clk_gate_shared(name, parent, shared, CLK_SET_RATE_PARENT); +} struct clk *imx_clk_pllv1(const char *name, const char *parent, void __iomem *base); @@ -78,10 +113,12 @@ enum imx_pllv3_type { IMX_PLLV3_GENERIC, IMX_PLLV3_SYS, + IMX_PLLV3_SYS_VF610, IMX_PLLV3_USB, IMX_PLLV3_USB_VF610, IMX_PLLV3_AV, IMX_PLLV3_ENET, + IMX_PLLV3_ENET_IMX7, IMX_PLLV3_MLB, }; @@ -89,6 +126,10 @@ const char *parent, void __iomem *base, u32 div_mask); +struct clk *imx_clk_pllv3_locked(enum imx_pllv3_type type, const char *name, + const char *parent, void __iomem *base, + u32 div_mask, void __iomem *lock_reg, u32 lock_mask); + struct clk *imx_clk_pfd(const char *name, const char *parent, void __iomem *reg, u8 idx); @@ -119,5 +160,8 @@ void imx_check_clocks(struct clk *clks[], unsigned int count); +struct clk *imx_clk_cpu(const char *name, const char *parent_name, + struct clk *div, struct clk *mux, struct clk *pll, + struct clk *step); #endif /* __IMX_CLK_H */ diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 74f046d..5677443 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -673,6 +673,7 @@ ret = PTR_ERR(i2c_fsl->clk); goto fail; } + clk_enable(i2c_fsl->clk); #endif i2c_fsl->hwdata = of_device_get_match_data(pdev); diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 951ac45..b2961cc 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -218,13 +218,10 @@ u32 wml_value; if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) { - if (!(data->flags & MMC_DATA_READ)) { - if ((esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL) == 0) - goto err_locked; + if (!(data->flags & MMC_DATA_READ)) esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->src); - } else { + else esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->dest); - } } else { wml_value = data->blocksize/4; @@ -237,8 +234,6 @@ } else { if (wml_value > 0x80) wml_value = 0x80; - if ((esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL) == 0) - goto err_locked; esdhc_clrsetbits32(regs + IMX_SDHCI_WML, WML_WR_WML_MASK, wml_value << 16); @@ -249,11 +244,6 @@ esdhc_write32(regs + SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | data->blocksize); return 0; - -err_locked: - dev_err(host->dev, "Can not write to locked card.\n\n"); - - return -ETIMEDOUT; } static int esdhc_do_data(struct mci_host *mci, struct mci_data *data) @@ -630,6 +620,14 @@ host->clk = clk_get(dev, "per"); if (IS_ERR(host->clk)) return PTR_ERR(host->clk); + clk_enable(host->clk); + + ret = clk_enable(host->clk); + if (ret) { + dev_err(dev, "Failed to enable clock: %s\n", + strerror(ret)); + return ret; + } host->dev = dev; iores = dev_request_mem_resource(dev, 0); diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 4e176f7..055a5e2 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -436,6 +436,7 @@ part->blk.num_blocks = mci_calc_blk_cnt(size, part->blk.blockbits); part->area_type = area_type; part->part_cfg = part_cfg; + part->idx = idx; if (area_type == MMC_BLK_DATA_AREA_MAIN) part->blk.cdev.device_node = mci->host->hw_dev->device_node; @@ -1573,6 +1574,59 @@ "user", }; +static int mci_register_partition(struct mci_part *part) +{ + struct mci *mci = part->mci; + struct mci_host *host = mci->host; + const char *partnodename = NULL; + struct device_node *np; + int rc; + + /* + * An MMC/SD card acts like an ordinary disk. + * So, re-use the disk driver to gain access to this media + */ + part->blk.dev = &mci->dev; + part->blk.ops = &mci_ops; + + rc = blockdevice_register(&part->blk); + if (rc != 0) { + dev_err(&mci->dev, "Failed to register MCI/SD blockdevice\n"); + return rc; + } + dev_info(&mci->dev, "registered %s\n", part->blk.cdev.name); + + np = host->hw_dev->device_node; + + /* create partitions on demand */ + switch (part->area_type) { + case MMC_BLK_DATA_AREA_BOOT: + if (part->idx == 0) + partnodename = "boot0-partitions"; + else + partnodename = "boot1-partitions"; + + np = of_get_child_by_name(host->hw_dev->device_node, + partnodename); + break; + case MMC_BLK_DATA_AREA_MAIN: + break; + default: + return 0; + } + + rc = parse_partition_table(&part->blk); + if (rc != 0) { + dev_warn(&mci->dev, "No partition table found\n"); + rc = 0; /* it's not a failure */ + } + + if (np) + of_parse_partitions(&part->blk.cdev, np); + + return 0; +} + /** * Probe an MCI card at the given host interface * @param mci MCI device instance @@ -1647,29 +1701,7 @@ for (i = 0; i < mci->nr_parts; i++) { struct mci_part *part = &mci->part[i]; - /* - * An MMC/SD card acts like an ordinary disk. - * So, re-use the disk driver to gain access to this media - */ - part->blk.dev = &mci->dev; - part->blk.ops = &mci_ops; - - rc = blockdevice_register(&part->blk); - if (rc != 0) { - dev_err(&mci->dev, "Failed to register MCI/SD blockdevice\n"); - goto on_error; - } - dev_info(&mci->dev, "registered %s\n", part->blk.cdev.name); - - /* create partitions on demand */ - if (part->area_type == MMC_BLK_DATA_AREA_MAIN) { - rc = parse_partition_table(&part->blk); - if (rc != 0) { - dev_warn(&mci->dev, "No partition table found\n"); - rc = 0; /* it's not a failure */ - } - of_parse_partitions(&part->blk.cdev, host->hw_dev->device_node); - } + rc = mci_register_partition(part); if (IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) && part->area_type == MMC_BLK_DATA_AREA_BOOT && diff --git a/drivers/of/partition.c b/drivers/of/partition.c index bdf5945..8c2aef2 100644 --- a/drivers/of/partition.c +++ b/drivers/of/partition.c @@ -74,16 +74,16 @@ int of_parse_partitions(struct cdev *cdev, struct device_node *node) { - struct device_node *n; + struct device_node *n, *subnode; if (!node) return -EINVAL; - for_each_child_of_node(node, n) { - if (of_device_is_compatible(n, "fixed-partitions")) { - node = n; - break; - } + subnode = of_get_child_by_name(node, "partitions"); + if (subnode) { + if (!of_device_is_compatible(subnode, "fixed-partitions")) + return -EINVAL; + node = subnode; } for_each_child_of_node(node, n) { diff --git a/drivers/phy/usb-nop-xceiv.c b/drivers/phy/usb-nop-xceiv.c index 606e098..d403fe4 100644 --- a/drivers/phy/usb-nop-xceiv.c +++ b/drivers/phy/usb-nop-xceiv.c @@ -27,6 +27,7 @@ struct usb_phy usb_phy; struct phy *phy; struct phy_provider *provider; + struct clk *clk; }; static struct phy *nop_usbphy_xlate(struct device_d *dev, @@ -37,6 +38,13 @@ return nopphy->phy; } +static int nop_usbphy_init(struct phy *phy) +{ + struct nop_usbphy *nopphy = phy_get_drvdata(phy); + + return clk_enable(nopphy->clk); +} + static struct usb_phy *nop_usbphy_to_usbphy(struct phy *phy) { struct nop_usbphy *nopphy = phy_get_drvdata(phy); @@ -46,6 +54,7 @@ static const struct phy_ops nop_phy_ops = { .to_usbphy = nop_usbphy_to_usbphy, + .init = nop_usbphy_init, }; static int nop_usbphy_probe(struct device_d *dev) @@ -57,7 +66,10 @@ dev->priv = nopphy; - /* FIXME: Add clk support */ + nopphy->clk = clk_get(dev, "main_clk"); + if (IS_ERR(nopphy->clk)) + nopphy->clk = NULL; + /* FIXME: Add vbus regulator support */ /* FIXME: Add vbus-detect-gpio support */ @@ -97,8 +109,8 @@ .of_compatible = DRV_OF_COMPAT(nop_usbphy_dt_ids), }; -static int nop_usbphy_init(void) +static int nop_usbphy_driver_init(void) { return platform_driver_register(&nop_usbphy_driver); } -fs_initcall(nop_usbphy_init); +fs_initcall(nop_usbphy_driver_init); diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c index 4b3f033..50d7177 100644 --- a/drivers/pinctrl/imx-iomux-v3.c +++ b/drivers/pinctrl/imx-iomux-v3.c @@ -24,53 +24,29 @@ #include #include #include +#include struct imx_iomux_v3 { void __iomem *base; struct pinctrl_device pinctrl; + unsigned int flags; +}; + +struct imx_iomux_v3_data { + unsigned int flags; }; static void __iomem *iomuxv3_base; -static struct device_d *iomuxv3_dev; - -static void imx_iomuxv3_setup_single(void __iomem *base, struct device_d *dev, - u32 mux_reg, u32 conf_reg, u32 input_reg, - u32 mux_val, u32 conf_val, u32 input_val) -{ - dev_dbg(dev, - "mux: 0x%08x -> 0x%04x, conf: 0x%08x -> 0x%04x input: 0x%08x -> 0x%04x\n", - mux_val, mux_reg, conf_val, conf_reg, input_val, input_reg); - - if (mux_reg) - writel(mux_val, base + mux_reg); - if (conf_reg) - writel(conf_val, base + conf_reg); - if (input_reg) - writel(input_val, base + input_reg); -} /* * configures a single pad in the iomuxer */ int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad) { - u32 mux_reg = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT; - u32 mux_val = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT; - u32 input_reg = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT; - u32 input_val = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT; - u32 conf_reg = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT; - u32 conf_val = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT; - if (!iomuxv3_base) return -EINVAL; - if (conf_val & NO_PAD_CTRL) - conf_reg = 0; - - imx_iomuxv3_setup_single(iomuxv3_base, iomuxv3_dev, - mux_reg, conf_reg, input_reg, - mux_val, conf_val, input_val); - + imx_setup_pad(iomuxv3_base, pad); return 0; } EXPORT_SYMBOL(mxc_iomux_v3_setup_pad); @@ -140,9 +116,9 @@ if (conf_val & IMX_DT_NO_PAD_CTL) conf_reg = 0; - imx_iomuxv3_setup_single(iomux->base, iomux->pinctrl.dev, - mux_reg, conf_reg, input_reg, - mux_val, conf_val, input_val); + iomux_v3_setup_pad(iomux->base, iomux->flags, + mux_reg, conf_reg, input_reg, + mux_val, conf_val, input_val); } return 0; @@ -155,14 +131,18 @@ static int imx_pinctrl_dt(struct device_d *dev, void __iomem *base) { struct imx_iomux_v3 *iomux; + struct imx_iomux_v3_data *drvdata = NULL; int ret; + dev_get_drvdata(dev, (const void **)&drvdata); iomux = xzalloc(sizeof(*iomux)); iomux->base = base; iomux->pinctrl.dev = dev; iomux->pinctrl.ops = &imx_iomux_v3_ops; + if (drvdata) + iomux->flags = drvdata->flags; ret = pinctrl_register(&iomux->pinctrl); if (ret) @@ -173,24 +153,33 @@ static int imx_iomux_v3_probe(struct device_d *dev) { + void __iomem *base; struct resource *iores; int ret = 0; - if (iomuxv3_base) - return -EBUSY; - iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); - iomuxv3_base = IOMEM(iores->start); - iomuxv3_dev = dev; + base = IOMEM(iores->start); + + if (!iomuxv3_base) + /* + * Uh, this works only for the older controllers, not for + * i.MX7 which has two iomux controllers. i.MX7 based boards + * should not use mxc_iomux_v3_setup_pad anyway. + */ + iomuxv3_base = base; if (IS_ENABLED(CONFIG_PINCTRL) && dev->device_node) - ret = imx_pinctrl_dt(dev, iomuxv3_base); + ret = imx_pinctrl_dt(dev, base); return ret; } +static struct imx_iomux_v3_data imx_iomux_imx7_lpsr_data = { + .flags = ZERO_OFFSET_VALID | IMX7_PINMUX_LPSR, +}; + static __maybe_unused struct of_device_id imx_iomux_v3_dt_ids[] = { { .compatible = "fsl,imx25-iomuxc", @@ -202,13 +191,20 @@ .compatible = "fsl,imx53-iomuxc", }, { .compatible = "fsl,imx6q-iomuxc", - }, { + }, { .compatible = "fsl,imx6dl-iomuxc", }, { .compatible = "fsl,imx6sx-iomuxc", }, { .compatible = "fsl,imx6ul-iomuxc", }, { + .compatible = "fsl,imx6sl-iomuxc", + }, { + .compatible = "fsl,imx7d-iomuxc", + }, { + .compatible = "fsl,imx7d-iomuxc-lpsr", + .data = &imx_iomux_imx7_lpsr_data, + }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c index b479bf2..4234263 100644 --- a/drivers/pinctrl/pinctrl-vf610.c +++ b/drivers/pinctrl/pinctrl-vf610.c @@ -24,9 +24,10 @@ #include #include +#include + enum { PINCTRL_VF610_MUX_LINE_SIZE = 20, - PINCTRL_VF610_MUX_SHIFT = 20, PINCTRL_VF610_IBE = 1 << 0, PINCTRL_VF610_OBE = 1 << 1, @@ -60,17 +61,17 @@ npins = size / PINCTRL_VF610_MUX_LINE_SIZE; for (i = 0; i < npins; i++) { + iomux_v3_cfg_t pad; u32 mux_reg = be32_to_cpu(*list++); u32 input_reg = be32_to_cpu(*list++); u32 mux_val = be32_to_cpu(*list++); u32 input_val = be32_to_cpu(*list++); u32 conf_val = be32_to_cpu(*list++); - writel(mux_val << PINCTRL_VF610_MUX_SHIFT | conf_val, - iomux->base + mux_reg); + pad = IOMUX_PAD(mux_reg, mux_reg, mux_val, + input_reg, input_val, conf_val); - if (input_reg) - writel(input_val, iomux->base + input_reg); + vf610_setup_pad(iomux->base, pad); } return 0; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4b41252..6a6c6d2 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -16,4 +16,8 @@ depends on ARCH_BCM283X default y +config REGULATOR_PFUZE + bool "Freescale PFUZE100/200/3000 regulator driver" + depends on I2C + endif diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index a8dd9bd..ff5daf9 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_REGULATOR) += core.o obj-$(CONFIG_REGULATOR_FIXED) += fixed.o obj-$(CONFIG_REGULATOR_BCM283X) += bcm2835.o +obj-$(CONFIG_REGULATOR_PFUZE) += pfuze.o \ No newline at end of file diff --git a/drivers/regulator/pfuze.c b/drivers/regulator/pfuze.c new file mode 100644 index 0000000..2a5fb71 --- /dev/null +++ b/drivers/regulator/pfuze.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2017 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRIVERNAME "pfuze" + +#define MC13XXX_NUMREGS 0x3f + +struct pfuze { + struct device_d *dev; + struct regmap *map; + struct i2c_client *client; + int revision; +}; + +struct pfuze_devtype { + int (*revision)(struct pfuze*); +}; + +#define to_pfuze(a) container_of(a, struct pfuze, cdev) + +static struct pfuze *pfuze_dev; + +static void(*pfuze_init_callback)(struct regmap *map); + +int pfuze_register_init_callback(void(*callback)(struct regmap *map)) +{ + if (pfuze_init_callback) + return -EBUSY; + + pfuze_init_callback = callback; + + if (pfuze_dev) + pfuze_init_callback(pfuze_dev->map); + + return 0; +} + +static int pfuze_i2c_reg_read(void *ctx, unsigned int reg, unsigned int *val) +{ + struct pfuze *pfuze = ctx; + u8 buf[1]; + int ret; + + ret = i2c_read_reg(pfuze->client, reg, buf, 1); + *val = buf[0]; + + return ret == 1 ? 0 : ret; +} + +static int pfuze_i2c_reg_write(void *ctx, unsigned int reg, unsigned int val) +{ + struct pfuze *pfuze = ctx; + u8 buf[] = { + val & 0xff, + }; + int ret; + + ret = i2c_write_reg(pfuze->client, reg, buf, 1); + + return ret == 1 ? 0 : ret; +} + +static struct regmap_bus regmap_pfuze_i2c_bus = { + .reg_write = pfuze_i2c_reg_write, + .reg_read = pfuze_i2c_reg_read, +}; + +static const struct regmap_config pfuze_regmap_i2c_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 127, +}; + +static int __init pfuze_probe(struct device_d *dev) +{ + struct pfuze_devtype *devtype; + int ret; + + if (pfuze_dev) + return -EBUSY; + + ret = dev_get_drvdata(dev, (const void **)&devtype); + if (ret) + return ret; + + pfuze_dev = xzalloc(sizeof(*pfuze_dev)); + pfuze_dev->dev = dev; + + pfuze_dev->client = to_i2c_client(dev); + pfuze_dev->map = regmap_init(dev, ®map_pfuze_i2c_bus, + pfuze_dev, &pfuze_regmap_i2c_config); + + ret = regmap_register_cdev(pfuze_dev->map, NULL); + if (ret) + return ret; + + if (pfuze_init_callback) + pfuze_init_callback(pfuze_dev->map); + + return 0; +} + +static struct pfuze_devtype pfuze100_devtype = { +}; + +static struct pfuze_devtype pfuze200_devtype = { +}; + +static struct pfuze_devtype pfuze3000_devtype = { +}; + +static struct platform_device_id pfuze_ids[] = { + { .name = "pfuze100", .driver_data = (ulong)&pfuze100_devtype, }, + { .name = "pfuze200", .driver_data = (ulong)&pfuze200_devtype, }, + { .name = "pfuze3000", .driver_data = (ulong)&pfuze3000_devtype, }, + { } +}; + +static __maybe_unused struct of_device_id pfuze_dt_ids[] = { + { .compatible = "fsl,pfuze100", .data = &pfuze100_devtype, }, + { .compatible = "fsl,pfuze200", .data = &pfuze200_devtype, }, + { .compatible = "fsl,pfuze3000", .data = &pfuze3000_devtype, }, + { } +}; + +static struct driver_d pfuze_i2c_driver = { + .name = "pfuze-i2c", + .probe = pfuze_probe, + .id_table = pfuze_ids, + .of_compatible = DRV_OF_COMPAT(pfuze_dt_ids), +}; + +static int __init pfuze_init(void) +{ + int ret; + + ret = i2c_driver_register(&pfuze_i2c_driver); + if (ret) + return ret; + + return 0; + +} +late_initcall(pfuze_init); diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c index 2b1e5e0..e8c3836 100644 --- a/drivers/serial/serial_imx.c +++ b/drivers/serial/serial_imx.c @@ -228,6 +228,7 @@ ret = PTR_ERR(priv->clk); goto err_free; } + clk_enable(priv->clk); iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) @@ -289,6 +290,9 @@ }, { .compatible = "fsl,imx6ul-uart", .data = &imx21_data, + }, { + .compatible = "fsl,imx7d-uart", + .data = &imx21_data, }, { /* sentinel */ } diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig index b0c6a41..8e6f315 100644 --- a/drivers/usb/imx/Kconfig +++ b/drivers/usb/imx/Kconfig @@ -16,4 +16,4 @@ config USB_IMX_PHY bool - default y if ARCH_IMX6 && GENERIC_PHY + default y if (ARCH_IMX6 || ARCH_VF610) && GENERIC_PHY diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index ed00ff4..ccd5346 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -27,6 +27,7 @@ #include #include #include +#include #define MXC_EHCI_PORTSC_MASK ((0xf << 28) | (1 << 25)) @@ -37,12 +38,14 @@ unsigned long flags; uint32_t mode; int portno; + struct device_d *usbmisc; enum usb_phy_interface phymode; struct param_d *param_mode; int role_registered; struct regulator *vbus; struct phy *phy; struct usb_phy *usbphy; + struct clk *clk; }; static int imx_chipidea_port_init(void *drvdata) @@ -67,7 +70,7 @@ return ret; } - ret = imx_usbmisc_port_init(ci->portno, ci->flags); + ret = imx_usbmisc_port_init(ci->usbmisc, ci->portno, ci->flags); if (ret) dev_err(ci->dev, "misc init failed: %s\n", strerror(-ret)); @@ -79,7 +82,7 @@ struct imx_chipidea *ci = drvdata; int ret; - ret = imx_usbmisc_port_post_init(ci->portno, ci->flags); + ret = imx_usbmisc_port_post_init(ci->usbmisc, ci->portno, ci->flags); if (ret) dev_err(ci->dev, "post misc init failed: %s\n", strerror(-ret)); @@ -95,6 +98,10 @@ "#index-cells", 0, &out_args)) return -ENODEV; + ci->usbmisc = of_find_device_by_node(out_args.np); + if (!ci->usbmisc) + return -ENODEV; + ci->portno = out_args.args[0]; ci->flags = MXC_EHCI_MODE_UTMI_8BIT; @@ -263,6 +270,17 @@ if (IS_ERR(ci->vbus)) ci->vbus = NULL; + /* + * Some devices have more than one clock, in this case they are enabled + * by default in the clock driver. At least enable the main clock for + * devices which have only one. + */ + ci->clk = clk_get(dev, NULL); + if (IS_ERR(ci->clk)) + return PTR_ERR(ci->clk); + + clk_enable(ci->clk); + if (of_property_read_bool(dev->device_node, "fsl,usbphy")) { ci->phy = of_phy_get_by_phandle(dev, "fsl,usbphy", 0); if (IS_ERR(ci->phy)) { diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c index 7c18ca2..dc0de9e 100644 --- a/drivers/usb/imx/imx-usb-misc.c +++ b/drivers/usb/imx/imx-usb-misc.c @@ -43,6 +43,11 @@ int (*post_init)(void __iomem *base, int port, unsigned int flags); }; +struct imx_usb_misc_priv { + struct imx_usb_misc_data *data; + void __iomem *base; +}; + static __maybe_unused int mx25_initialize_usb_hw(void __iomem *base, int port, unsigned int flags) { unsigned int v; @@ -348,6 +353,7 @@ #define MX6_USB_CTRL(n) ((n) * 4) #define MX6_USB_CTRL_OVER_CUR_DIS (1 << 7) +#define MX6_USB_CTRL_OVER_CUR_ACT_HIGH (1 << 8) static void mx6_hsic_pullup(unsigned long reg, int on) { @@ -422,6 +428,68 @@ .post_init = mx6_post_init, }; +#define MX7D_USBNC_USB_CTRL2 0x4 +#define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK 0x3 +#define MX7D_USB_VBUS_WAKEUP_SOURCE(v) (v << 0) +#define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS MX7D_USB_VBUS_WAKEUP_SOURCE(0) +#define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1) +#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2) +#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3) + +static int usbmisc_imx7d_init(void __iomem *base, int port, + unsigned int flags) +{ + u32 reg; + + if (port >= 1) + return -EINVAL; + + reg = readl(base); + if (flags & MXC_EHCI_DISABLE_OVERCURRENT) { + reg |= MX6_USB_CTRL_OVER_CUR_DIS; + } else { + reg &= ~MX6_USB_CTRL_OVER_CUR_DIS; + if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) + reg &= ~MX6_USB_CTRL_OVER_CUR_ACT_HIGH; + else + reg |= MX6_USB_CTRL_OVER_CUR_ACT_HIGH; + } + writel(reg, base); + + reg = readl(base + MX7D_USBNC_USB_CTRL2); + reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; + writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, + base + MX7D_USBNC_USB_CTRL2); + + return 0; +} + +static __maybe_unused struct imx_usb_misc_data mx7_data = { + .init = usbmisc_imx7d_init, +}; + +#define VF610_OVER_CUR_DIS BIT(7) + +static __maybe_unused int vf610_initialize_usb_hw(void __iomem *base, int port, + unsigned int flags) +{ + u32 reg; + + if (port >= 1) + return -EINVAL; + + if (flags & MXC_EHCI_DISABLE_OVERCURRENT) { + reg = readl(base); + writel(reg | VF610_OVER_CUR_DIS, base); + } + + return 0; +} + +static __maybe_unused struct imx_usb_misc_data vf610_data = { + .init = vf610_initialize_usb_hw, +}; + static struct platform_device_id imx_usbmisc_ids[] = { #ifdef CONFIG_ARCH_IMX25 { @@ -471,6 +539,12 @@ .driver_data = (unsigned long)&mx6_data, }, #endif +#ifdef CONFIG_ARCH_IMX7 + { + .name = "imx7d-usb-misc", + .driver_data = (unsigned long)&mx7_data, + }, +#endif { /* sentinel */ }, @@ -519,40 +593,54 @@ .data = &mx6_data, }, #endif +#ifdef CONFIG_ARCH_IMX7 + { + .compatible = "fsl,imx7d-usbmisc", + .data = &mx7_data, + }, +#endif +#ifdef CONFIG_ARCH_VF610 + { + .compatible = "fsl,vf610-usbmisc", + .data = &vf610_data, + }, +#endif { /* sentinel */ }, }; -static struct imx_usb_misc_data *imxusbmisc_data; -static void __iomem *usbmisc_base; - -int imx_usbmisc_port_init(int port, unsigned flags) +int imx_usbmisc_port_init(struct device_d *dev, int port, unsigned flags) { - if (!imxusbmisc_data) + struct imx_usb_misc_priv *usbmisc = dev->priv; + + if (!usbmisc) return -ENODEV; - if (!imxusbmisc_data->init) + if (!usbmisc->data->init) return 0; - return imxusbmisc_data->init(usbmisc_base, port, flags); + return usbmisc->data->init(usbmisc->base, port, flags); } -int imx_usbmisc_port_post_init(int port, unsigned flags) +int imx_usbmisc_port_post_init(struct device_d *dev, int port, unsigned flags) { - if (!imxusbmisc_data) + struct imx_usb_misc_priv *usbmisc = dev->priv; + + if (!usbmisc) return -ENODEV; - if (!imxusbmisc_data->post_init) + if (!usbmisc->data->post_init) return 0; - return imxusbmisc_data->post_init(usbmisc_base, port, flags); + return usbmisc->data->post_init(usbmisc->base, port, flags); } static int imx_usbmisc_probe(struct device_d *dev) { struct resource *iores; struct imx_usb_misc_data *devtype; + struct imx_usb_misc_priv *usbmisc = dev->priv; int ret; ret = dev_get_drvdata(dev, (const void **)&devtype); @@ -562,9 +650,10 @@ iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); - usbmisc_base = IOMEM(iores->start); - imxusbmisc_data = devtype; + usbmisc = xzalloc(sizeof(*usbmisc)); + usbmisc->base = IOMEM(iores->start); + usbmisc->data = devtype; return 0; } diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c index 9f46f8d..274153b 100644 --- a/drivers/usb/imx/imx-usb-phy.c +++ b/drivers/usb/imx/imx-usb-phy.c @@ -168,6 +168,8 @@ { .compatible = "fsl,imx23-usbphy", }, { + .compatible = "fsl,vf610-usbphy", + }, { /* sentinel */ }, }; diff --git a/drivers/video/tc358767.c b/drivers/video/tc358767.c index 72f55f4..ab2e86e 100644 --- a/drivers/video/tc358767.c +++ b/drivers/video/tc358767.c @@ -6,6 +6,8 @@ * * Copyright (C) 2016 Pengutronix, Philipp Zabel * + * Copyright (C) 2016 Zodiac Inflight Innovations + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c index 03e116e..b920c72 100644 --- a/drivers/watchdog/imxwd.c +++ b/drivers/watchdog/imxwd.c @@ -25,7 +25,8 @@ struct imx_wd; struct imx_wd_ops { - int (*set_timeout)(struct imx_wd *, int); + int (*set_timeout)(struct imx_wd *, unsigned); + void (*soc_reset)(struct imx_wd *); int (*init)(struct imx_wd *); }; @@ -35,6 +36,7 @@ struct device_d *dev; const struct imx_wd_ops *ops; struct restart_handler restart; + bool ext_reset; }; #define to_imx_wd(h) container_of(h, struct imx_wd, wd) @@ -50,6 +52,7 @@ #define IMX21_WDOG_WSTR 0x04 /* Watchdog Status Register */ #define IMX21_WDOG_WMCR 0x08 /* Misc Register */ #define IMX21_WDOG_WCR_WDE (1 << 2) +#define IMX21_WDOG_WCR_WDT (1 << 3) #define IMX21_WDOG_WCR_SRS (1 << 4) #define IMX21_WDOG_WCR_WDA (1 << 5) @@ -62,7 +65,7 @@ /* valid for i.MX27, i.MX31, always '0' on i.MX25, i.MX35, i.MX51 */ #define WSTR_COLDSTART (1 << 4) -static int imx1_watchdog_set_timeout(struct imx_wd *priv, int timeout) +static int imx1_watchdog_set_timeout(struct imx_wd *priv, unsigned timeout) { u16 val; @@ -76,10 +79,7 @@ return 0; } - if (timeout > 0) - val = (timeout * 2 - 1) << 8; - else - val = 0; + val = (timeout * 2 - 1) << 8; writew(val, priv->base + IMX1_WDOG_WCR); writew(IMX1_WDOG_WCR_WDE | val, priv->base + IMX1_WDOG_WCR); @@ -91,25 +91,29 @@ return 0; } -static int imx21_watchdog_set_timeout(struct imx_wd *priv, int timeout) +static void imx1_soc_reset(struct imx_wd *priv) +{ + writew(IMX1_WDOG_WCR_WDE, priv->base + IMX1_WDOG_WCR); +} + +static int imx21_watchdog_set_timeout(struct imx_wd *priv, unsigned timeout) { u16 val; dev_dbg(priv->dev, "%s: %d\n", __func__, timeout); - if (timeout < -1 || timeout > 128) + if (timeout > 128) return -EINVAL; if (timeout == 0) /* bit 2 (WDE) cannot be set to 0 again */ return -ENOSYS; - if (timeout > 0) - val = ((timeout * 2 - 1) << 8) | IMX21_WDOG_WCR_SRS | - IMX21_WDOG_WCR_WDA; - else - val = 0; + val = ((timeout * 2 - 1) << 8) | IMX21_WDOG_WCR_SRS | + IMX21_WDOG_WCR_WDA; - writew(val, priv->base + IMX21_WDOG_WCR); + if (priv->ext_reset) + val |= IMX21_WDOG_WCR_WDT; + writew(IMX21_WDOG_WCR_WDE | val, priv->base + IMX21_WDOG_WCR); /* Write Service Sequence */ @@ -119,6 +123,19 @@ return 0; } +static void imx21_soc_reset(struct imx_wd *priv) +{ + u16 val = 0; + + /* Use internal reset or external - not both */ + if (priv->ext_reset) + val |= IMX21_WDOG_WCR_SRS; /* do not assert int reset */ + else + val |= IMX21_WDOG_WCR_WDA; /* do not assert ext-reset */ + + writew(val, priv->base + IMX21_WDOG_WCR); +} + static int imx_watchdog_set_timeout(struct watchdog *wd, unsigned timeout) { struct imx_wd *priv = (struct imx_wd *)to_imx_wd(wd); @@ -130,7 +147,7 @@ { struct imx_wd *priv = container_of(rst, struct imx_wd, restart); - priv->ops->set_timeout(priv, -1); + priv->ops->soc_reset(priv); mdelay(1000); @@ -194,6 +211,9 @@ priv->wd.dev = dev; priv->dev = dev; + priv->ext_reset = of_property_read_bool(dev->device_node, + "fsl,ext-reset-output"); + if (IS_ENABLED(CONFIG_WATCHDOG_IMX)) { ret = watchdog_register(&priv->wd); if (ret) @@ -227,11 +247,13 @@ static const struct imx_wd_ops imx21_wd_ops = { .set_timeout = imx21_watchdog_set_timeout, + .soc_reset = imx21_soc_reset, .init = imx21_wd_init, }; static const struct imx_wd_ops imx1_wd_ops = { .set_timeout = imx1_watchdog_set_timeout, + .soc_reset = imx1_soc_reset, }; static __maybe_unused struct of_device_id imx_wdt_dt_ids[] = { diff --git a/images/Makefile.imx b/images/Makefile.imx index 3b911ec..2563779 100644 --- a/images/Makefile.imx +++ b/images/Makefile.imx @@ -409,7 +409,27 @@ FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblx.imximg image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img +pblx-$(CONFIG_MACH_WARP7) += start_imx7s_element14_warp7 +CFG_start_imx7s_element14_warp7.pblx.imximg = $(board)/element14-warp7/flash-header-mx7-warp.imxcfg +FILE_barebox-element14-imx7s-warp7.img = start_imx7s_element14_warp7.pblx.imximg +image-$(CONFIG_MACH_WARP7) += barebox-element14-imx7s-warp7.img + pblx-$(CONFIG_MACH_VF610_TWR) += start_vf610_twr CFG_start_vf610_twr.pblx.imximg = $(board)/freescale-vf610-twr/flash-header-vf610-twr.imxcfg FILE_barebox-vf610-twr.img = start_vf610_twr.pblx.imximg image-$(CONFIG_MACH_VF610_TWR) += barebox-vf610-twr.img + +pblx-$(CONFIG_MACH_ZII_RDU2) += start_imx6q_zii_rdu2 +CFG_start_imx6q_zii_rdu2.pblx.imximg = $(board)/zii-imx6q-rdu2/flash-header-imx6q-rdu2.imxcfg +FILE_barebox-zii-imx6q-rdu2.img = start_imx6q_zii_rdu2.pblx.imximg +image-$(CONFIG_MACH_ZII_RDU2) += barebox-zii-imx6q-rdu2.img + +pblx-$(CONFIG_MACH_ZII_RDU2) += start_imx6qp_zii_rdu2 +CFG_start_imx6qp_zii_rdu2.pblx.imximg = $(board)/zii-imx6q-rdu2/flash-header-imx6qp-rdu2.imxcfg +FILE_barebox-zii-imx6qp-rdu2.img = start_imx6qp_zii_rdu2.pblx.imximg +image-$(CONFIG_MACH_ZII_RDU2) += barebox-zii-imx6qp-rdu2.img + +pblx-$(CONFIG_MACH_ZII_VF610_DEV) += start_zii_vf610_dev +CFG_start_zii_vf610_dev.pblx.imximg = $(board)/zii-vf610-dev/flash-header-zii-vf610-dev.imxcfg +FILE_barebox-zii-vf610-dev.img = start_zii_vf610_dev.pblx.imximg +image-$(CONFIG_MACH_ZII_VF610_DEV) += barebox-zii-vf610-dev.img diff --git a/include/linux/clk.h b/include/linux/clk.h index 8cb9731..7dd5238 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -198,6 +198,8 @@ #ifdef CONFIG_COMMON_CLK #define CLK_SET_RATE_PARENT (1 << 0) /* propagate rate change up one level */ +/* parents need enable during gate/ungate, set rate and re-parent */ +#define CLK_OPS_PARENT_ENABLE (1 << 12) #define CLK_GATE_INVERTED (1 << 0) #define CLK_GATE_HIWORD_MASK (1 << 1) @@ -294,6 +296,9 @@ u8 shift, unsigned flags, u8 clk_gate_flags); struct clk *clk_gate_inverted(const char *name, const char *parent, void __iomem *reg, u8 shift, unsigned flags); +struct clk *clk_gate_shared(const char *name, const char *parent, const char *shared, + unsigned flags); + int clk_is_enabled(struct clk *clk); int clk_is_enabled_always(struct clk *clk); diff --git a/include/mci.h b/include/mci.h index 0370547..cc4712c 100644 --- a/include/mci.h +++ b/include/mci.h @@ -433,6 +433,7 @@ uint64_t size; /* partition size (in bytes) */ unsigned int part_cfg; /* partition type */ char *name; + int idx; unsigned int area_type; #define MMC_BLK_DATA_AREA_MAIN (1<<0) #define MMC_BLK_DATA_AREA_BOOT (1<<1) diff --git a/include/mfd/pfuze.h b/include/mfd/pfuze.h new file mode 100644 index 0000000..6045cee --- /dev/null +++ b/include/mfd/pfuze.h @@ -0,0 +1,6 @@ +#ifndef __INCLUDE_PFUZE_H +#define __INCLUDE_PFUZE_H + +int pfuze_register_init_callback(void(*callback)(struct regmap *map)); + +#endif /* __INCLUDE_PFUZE_H */ diff --git a/include/serial/imx-uart.h b/include/serial/imx-uart.h index b40044e..9cab32f 100644 --- a/include/serial/imx-uart.h +++ b/include/serial/imx-uart.h @@ -175,6 +175,11 @@ imx_uart_setup(uartbase, 80000000); } +static inline void imx7_uart_setup(void __iomem *uartbase) +{ + imx_uart_setup(uartbase, 24000000); +} + static inline void imx_uart_putc(void *base, int c) { if (!(readl(base + UCR1) & UCR1_UARTEN)) diff --git a/include/usb/chipidea-imx.h b/include/usb/chipidea-imx.h index 64f086a..640ae06 100644 --- a/include/usb/chipidea-imx.h +++ b/include/usb/chipidea-imx.h @@ -48,7 +48,7 @@ enum imx_usb_mode mode; }; -int imx_usbmisc_port_init(int port, unsigned flags); -int imx_usbmisc_port_post_init(int port, unsigned flags); +int imx_usbmisc_port_init(struct device_d *dev, int port, unsigned flags); +int imx_usbmisc_port_post_init(struct device_d *dev, int port, unsigned flags); #endif /* __USB_CHIPIDEA_IMX_H */ diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index be0894f..9de7bb3 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -72,11 +72,11 @@ }; struct usb_id { - struct mach_id *mach_id; + const struct mach_id *mach_id; struct usb_work *work; }; -struct mach_id imx_ids[] = { +static const struct mach_id imx_ids[] = { { .vid = 0x066f, .pid = 0x3780, @@ -156,6 +156,13 @@ .header_type = HDR_MX53, .mode = MODE_HID, .max_transfer = 1024, + }, { + .vid = 0x15a2, + .pid = 0x0076, + .name = "i.MX7S", + .header_type = HDR_MX53, + .mode = MODE_HID, + .max_transfer = 1024, }, }; @@ -174,12 +181,12 @@ uint8_t rsvd; } __attribute__((packed)); -static struct mach_id *imx_device(unsigned short vid, unsigned short pid) +static const struct mach_id *imx_device(unsigned short vid, unsigned short pid) { int i; for (i = 0; i < ARRAY_SIZE(imx_ids); i++) { - struct mach_id *id = &imx_ids[i]; + const struct mach_id *id = &imx_ids[i]; if (id->vid == vid && id->pid == pid) { fprintf(stderr, "found %s USB device [%04x:%04x]\n", id->name, vid, pid); @@ -190,10 +197,10 @@ return NULL; } -static libusb_device *find_imx_dev(libusb_device **devs, struct mach_id **pp_id) +static libusb_device *find_imx_dev(libusb_device **devs, const struct mach_id **pp_id) { int i = 0; - struct mach_id *p; + const struct mach_id *p; for (;;) { struct libusb_device_descriptor desc; @@ -1288,7 +1295,7 @@ int main(int argc, char *argv[]) { - struct mach_id *mach; + const struct mach_id *mach; libusb_device **devs; libusb_device *dev; int r; diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c index bf3a42f..809d8a7 100644 --- a/scripts/imx/imx.c +++ b/scripts/imx/imx.c @@ -231,6 +231,7 @@ { .name = "imx51", .header_version = 1, .cpu_type = IMX_CPU_IMX51 }, { .name = "imx53", .header_version = 2, .cpu_type = IMX_CPU_IMX53 }, { .name = "imx6", .header_version = 2, .cpu_type = IMX_CPU_IMX6 }, + { .name = "imx7", .header_version = 2, .cpu_type = IMX_CPU_IMX7 }, { .name = "vf610", .header_version = 2, .cpu_type = IMX_CPU_VF610 }, };