diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2018-07-09 08:21:06 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2018-07-09 08:21:06 +0200 |
commit | 47d229d5c0fc626707101f0ad6c653ee68a65616 (patch) | |
tree | f893f4b10972f0886d94bea547ed20fc2523246f | |
parent | 0d0e894257392e6d7fbcc03991ee16b334d2f1ed (diff) | |
parent | 8470a9eeca22e3d169375241424306be9c5e5838 (diff) | |
download | barebox-47d229d5c0fc626707101f0ad6c653ee68a65616.tar.gz barebox-47d229d5c0fc626707101f0ad6c653ee68a65616.tar.xz |
Merge branch 'for-next/imx'
45 files changed, 1260 insertions, 423 deletions
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile index b2fea4a40f..e5d217f52c 100644 --- a/arch/arm/boards/Makefile +++ b/arch/arm/boards/Makefile @@ -43,7 +43,7 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += eukrea_cpuimx51/ obj-$(CONFIG_MACH_ELTEC_HIPERCAM) += eltec-hipercam/ obj-$(CONFIG_MACH_FREESCALE_MX25_3STACK) += freescale-mx25-3ds/ obj-$(CONFIG_MACH_FREESCALE_MX35_3STACK) += freescale-mx35-3ds/ -obj-$(CONFIG_MACH_FREESCALE_MX51_PDK) += freescale-mx51-babbage/ +obj-y += freescale-mx51-babbage/ obj-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += freescale-mx53-qsb/ obj-$(CONFIG_MACH_FREESCALE_MX53_SMD) += freescale-mx53-smd/ obj-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += freescale-mx53-vmx53/ @@ -150,5 +150,6 @@ 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_RDU1) += zii-imx51-rdu1/ obj-$(CONFIG_MACH_ZII_RDU2) += zii-imx6q-rdu2/ obj-$(CONFIG_MACH_ZII_VF610_DEV) += zii-vf610-dev/ diff --git a/arch/arm/boards/freescale-mx51-babbage/Makefile b/arch/arm/boards/freescale-mx51-babbage/Makefile index 01c7a259e9..b6e085818f 100644 --- a/arch/arm/boards/freescale-mx51-babbage/Makefile +++ b/arch/arm/boards/freescale-mx51-babbage/Makefile @@ -1,2 +1,3 @@ -obj-y += board.o -lwl-y += lowlevel.o +obj-$(CONFIG_MACH_FREESCALE_MX51_PDK_POWER) += power.o +obj-$(CONFIG_MACH_FREESCALE_MX51_PDK) += board.o +lwl-$(CONFIG_MACH_FREESCALE_MX51_PDK) += lowlevel.o diff --git a/arch/arm/boards/freescale-mx51-babbage/board.c b/arch/arm/boards/freescale-mx51-babbage/board.c index 915748528d..74ad7fa51f 100644 --- a/arch/arm/boards/freescale-mx51-babbage/board.c +++ b/arch/arm/boards/freescale-mx51-babbage/board.c @@ -31,7 +31,6 @@ #include <nand.h> #include <notifier.h> #include <spi/spi.h> -#include <mfd/mc13xxx.h> #include <io.h> #include <asm/mmu.h> #include <mach/imx5.h> @@ -44,120 +43,14 @@ #define MX51_CCM_CACRR 0x10 -static void babbage_power_init(struct mc13xxx *mc13xxx) -{ - u32 val; - - /* Write needed to Power Gate 2 register */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_POWER_MISC, &val); - val &= ~0x10000; - mc13xxx_reg_write(mc13xxx, MC13892_REG_POWER_MISC, val); - - /* Write needed to update Charger 0 */ - mc13xxx_reg_write(mc13xxx, MC13892_REG_CHARGE, 0x0023807F); - - /* power up the system first */ - mc13xxx_reg_write(mc13xxx, MC13892_REG_POWER_MISC, 0x00200000); - - if (imx_silicon_revision() < IMX_CHIP_REV_3_0) { - /* Set core voltage to 1.1V */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_0, &val); - val &= ~0x1f; - val |= 0x14; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_0, val); - - /* Setup VCC (SW2) to 1.25 */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_1, &val); - val &= ~0x1f; - val |= 0x1a; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_1, val); - - /* Setup 1V2_DIG1 (SW3) to 1.25 */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_2, &val); - val &= ~0x1f; - val |= 0x1a; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_2, val); - } else { - /* Setup VCC (SW2) to 1.225 */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_1, &val); - val &= ~0x1f; - val |= 0x19; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_1, val); - - /* Setup 1V2_DIG1 (SW3) to 1.2 */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_2, &val); - val &= ~0x1f; - val |= 0x18; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_2, val); - } - - if (mc13xxx_revision(mc13xxx) < MC13892_REVISION_2_0) { - /* Set switchers in PWM mode for Atlas 2.0 and lower */ - /* Setup the switcher mode for SW1 & SW2*/ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_4, &val); - val &= ~0x3c0f; - val |= 0x1405; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_4, val); - - /* Setup the switcher mode for SW3 & SW4 */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_5, &val); - val &= ~0xf0f; - val |= 0x505; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_5, val); - } else { - /* Set switchers in Auto in NORMAL mode & STANDBY mode for Atlas 2.0a */ - /* Setup the switcher mode for SW1 & SW2*/ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_4, &val); - val &= ~0x3c0f; - val |= 0x2008; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_4, val); - - /* Setup the switcher mode for SW3 & SW4 */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_5, &val); - val &= ~0xf0f; - val |= 0x808; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_5, val); - } - - /* Set VDIG to 1.65V, VGEN3 to 1.8V, VCAM to 2.5V */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SETTING_0, &val); - val &= ~0x34030; - val |= 0x10020; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SETTING_0, val); - - /* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */ - mc13xxx_reg_read(mc13xxx, MC13892_REG_SETTING_1, &val); - val &= ~0x1FC; - val |= 0x1F4; - mc13xxx_reg_write(mc13xxx, MC13892_REG_SETTING_1, val); - - /* Configure VGEN3 and VCAM regulators to use external PNP */ - val = 0x208; - mc13xxx_reg_write(mc13xxx, MC13892_REG_MODE_1, val); - - udelay(200); - - /* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */ - val = 0x49249; - mc13xxx_reg_write(mc13xxx, MC13892_REG_MODE_1, val); - - udelay(200); - - pr_info("initialized PMIC\n"); - - console_flush(); - imx51_init_lowlevel(800); - clock_notifier_call_chain(); -} - static int imx51_babbage_init(void) { if (!of_machine_is_compatible("fsl,imx51-babbage")) return 0; - barebox_set_hostname("babbage"); + imx51_babbage_power_init(); - mc13xxx_register_init_callback(babbage_power_init); + barebox_set_hostname("babbage"); armlinux_set_architecture(MACH_TYPE_MX51_BABBAGE); diff --git a/arch/arm/boards/freescale-mx51-babbage/lowlevel.c b/arch/arm/boards/freescale-mx51-babbage/lowlevel.c index 1c20b6a7ae..216576ca27 100644 --- a/arch/arm/boards/freescale-mx51-babbage/lowlevel.c +++ b/arch/arm/boards/freescale-mx51-babbage/lowlevel.c @@ -1,5 +1,6 @@ #include <debug_ll.h> #include <mach/clock-imx51_53.h> +#include <mach/iomux-mx51.h> #include <common.h> #include <mach/esdctl.h> #include <mach/generic.h> @@ -22,15 +23,7 @@ static inline void setup_uart(void) writel(MX5_CCM_CSCMR1_RESET_VALUE, ccmbase + MX5_CCM_CSCMR1); writel(MX5_CCM_CSCDR1_RESET_VALUE, ccmbase + MX5_CCM_CSCDR1); - /* - * The code below should be more or less a "moral equivalent" - * of: - * MX51_PAD_UART1_TXD__UART1_TXD 0x1c5 - * - * in device tree - */ - writel(0x00000000, iomuxbase + 0x022c); - writel(0x000001c5, iomuxbase + 0x061c); + imx_setup_pad(iomuxbase, MX51_PAD_UART1_TXD__UART1_TXD); imx51_uart_setup_ll(); diff --git a/arch/arm/boards/freescale-mx51-babbage/power.c b/arch/arm/boards/freescale-mx51-babbage/power.c new file mode 100644 index 0000000000..6edc672a5a --- /dev/null +++ b/arch/arm/boards/freescale-mx51-babbage/power.c @@ -0,0 +1,120 @@ +#define pr_fmt(fmt) "babbage-power: " fmt + +#include <common.h> +#include <init.h> +#include <notifier.h> +#include <mach/revision.h> +#include <mach/imx5.h> +#include <mfd/mc13xxx.h> + +static void babbage_power_init(struct mc13xxx *mc13xxx) +{ + u32 val; + + /* Write needed to Power Gate 2 register */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_POWER_MISC, &val); + val &= ~0x10000; + mc13xxx_reg_write(mc13xxx, MC13892_REG_POWER_MISC, val); + + /* Write needed to update Charger 0 */ + mc13xxx_reg_write(mc13xxx, MC13892_REG_CHARGE, 0x0023807F); + + /* power up the system first */ + mc13xxx_reg_write(mc13xxx, MC13892_REG_POWER_MISC, 0x00200000); + + if (imx_silicon_revision() < IMX_CHIP_REV_3_0) { + /* Set core voltage to 1.1V */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_0, &val); + val &= ~0x1f; + val |= 0x14; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_0, val); + + /* Setup VCC (SW2) to 1.25 */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_1, &val); + val &= ~0x1f; + val |= 0x1a; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_1, val); + + /* Setup 1V2_DIG1 (SW3) to 1.25 */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_2, &val); + val &= ~0x1f; + val |= 0x1a; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_2, val); + } else { + /* Setup VCC (SW2) to 1.225 */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_1, &val); + val &= ~0x1f; + val |= 0x19; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_1, val); + + /* Setup 1V2_DIG1 (SW3) to 1.2 */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_2, &val); + val &= ~0x1f; + val |= 0x18; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_2, val); + } + + if (mc13xxx_revision(mc13xxx) < MC13892_REVISION_2_0) { + /* Set switchers in PWM mode for Atlas 2.0 and lower */ + /* Setup the switcher mode for SW1 & SW2*/ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_4, &val); + val &= ~0x3c0f; + val |= 0x1405; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_4, val); + + /* Setup the switcher mode for SW3 & SW4 */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_5, &val); + val &= ~0xf0f; + val |= 0x505; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_5, val); + } else { + /* Set switchers in Auto in NORMAL mode & STANDBY mode + * for Atlas 2.0a */ + /* Setup the switcher mode for SW1 & SW2*/ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_4, &val); + val &= ~0x3c0f; + val |= 0x2008; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_4, val); + + /* Setup the switcher mode for SW3 & SW4 */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_5, &val); + val &= ~0xf0f; + val |= 0x808; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_5, val); + } + + /* Set VDIG to 1.65V, VGEN3 to 1.8V, VCAM to 2.5V */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SETTING_0, &val); + val &= ~0x34030; + val |= 0x10020; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SETTING_0, val); + + /* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */ + mc13xxx_reg_read(mc13xxx, MC13892_REG_SETTING_1, &val); + val &= ~0x1FC; + val |= 0x1F4; + mc13xxx_reg_write(mc13xxx, MC13892_REG_SETTING_1, val); + + /* Configure VGEN3 and VCAM regulators to use external PNP */ + val = 0x208; + mc13xxx_reg_write(mc13xxx, MC13892_REG_MODE_1, val); + + udelay(200); + + /* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */ + val = 0x49249; + mc13xxx_reg_write(mc13xxx, MC13892_REG_MODE_1, val); + + udelay(200); + + pr_info("initialized PMIC\n"); + + console_flush(); + imx51_init_lowlevel(800); + clock_notifier_call_chain(); +} + +void imx51_babbage_power_init(void) +{ + mc13xxx_register_init_callback(babbage_power_init); +} diff --git a/arch/arm/boards/zii-imx51-rdu1/Makefile b/arch/arm/boards/zii-imx51-rdu1/Makefile new file mode 100644 index 0000000000..01c7a259e9 --- /dev/null +++ b/arch/arm/boards/zii-imx51-rdu1/Makefile @@ -0,0 +1,2 @@ +obj-y += board.o +lwl-y += lowlevel.o diff --git a/arch/arm/boards/zii-imx51-rdu1/board.c b/arch/arm/boards/zii-imx51-rdu1/board.c new file mode 100644 index 0000000000..ac5232e17b --- /dev/null +++ b/arch/arm/boards/zii-imx51-rdu1/board.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright (C) 2017 Zodiac Inflight Innovation + * + * Author: Andrey Smirnov <andrew.smirnov@gmail.com> + * + * based on previous iterations of this code + * + * Copyright (C) 2015 Nikita Yushchenko, CogentEmbedded, Inc + * Copyright (C) 2015 Andrey Gusakov, CogentEmbedded, Inc + * + * based on similar i.MX51 EVK (Babbage) board support code + * + * Copyright (C) 2007 Sascha Hauer, Pengutronix + */ + +#include <common.h> +#include <init.h> +#include <mach/bbu.h> +#include <libfile.h> +#include <mach/imx5.h> + +static int zii_rdu1_init(void) +{ + if (!of_machine_is_compatible("zii,imx51-rdu1")) + return 0; + + imx51_babbage_power_init(); + + barebox_set_hostname("rdu1"); + + imx51_bbu_internal_mmc_register_handler("mmc", "/dev/mmc0", 0); + imx51_bbu_internal_spi_i2c_register_handler("spi", + "/dev/dataflash0.barebox", + BBU_HANDLER_FLAG_DEFAULT | + IMX_BBU_FLAG_PARTITION_STARTS_AT_HEADER); + + return 0; +} +coredevice_initcall(zii_rdu1_init); diff --git a/arch/arm/boards/zii-imx51-rdu1/flash-header-imx51-zii-rdu1.imxcfg b/arch/arm/boards/zii-imx51-rdu1/flash-header-imx51-zii-rdu1.imxcfg new file mode 100644 index 0000000000..76f4c6b59b --- /dev/null +++ b/arch/arm/boards/zii-imx51-rdu1/flash-header-imx51-zii-rdu1.imxcfg @@ -0,0 +1,60 @@ +soc imx51 +loadaddr 0x90000000 +dcdofs 0x400 + +wm 32 0x73fa88a0 0x00000200 +wm 32 0x73fa850c 0x000020c5 +wm 32 0x73fa8510 0x000020c5 +wm 32 0x73fa883c 0x00000002 +wm 32 0x73fa8848 0x00000002 +wm 32 0x73fa84b8 0x000000e7 +wm 32 0x73fa84bc 0x00000045 +wm 32 0x73fa84c0 0x00000045 +wm 32 0x73fa84c4 0x00000045 +wm 32 0x73fa84c8 0x00000045 +wm 32 0x73fa8820 0x00000000 +wm 32 0x73fa84a4 0x00000003 +wm 32 0x73fa84a8 0x00000003 +wm 32 0x73fa84ac 0x000000e3 +wm 32 0x73fa84b0 0x000000e3 +wm 32 0x73fa84b4 0x000000e3 +wm 32 0x73fa84cc 0x000000e3 +wm 32 0x73fa84d0 0x000000e2 +wm 32 0x73fa882c 0x00000004 +wm 32 0x73fa88a4 0x00000004 +wm 32 0x73fa88ac 0x00000004 +wm 32 0x73fa88b8 0x00000004 +wm 32 0x83fd9000 0x82a20000 +wm 32 0x83fd9008 0x82a20000 +wm 32 0x83fd9010 0x000ad0d0 +wm 32 0x83fd9004 0x3f3584ab +wm 32 0x83fd900c 0x3f3584ab +wm 32 0x83fd9014 0x04008008 +wm 32 0x83fd9014 0x0000801a +wm 32 0x83fd9014 0x0000801b +wm 32 0x83fd9014 0x00448019 +wm 32 0x83fd9014 0x07328018 +wm 32 0x83fd9014 0x04008008 +wm 32 0x83fd9014 0x00008010 +wm 32 0x83fd9014 0x00008010 +wm 32 0x83fd9014 0x06328018 +wm 32 0x83fd9014 0x03808019 +wm 32 0x83fd9014 0x00408019 +wm 32 0x83fd9014 0x00008000 +wm 32 0x83fd9014 0x0400800c +wm 32 0x83fd9014 0x0000801e +wm 32 0x83fd9014 0x0000801f +wm 32 0x83fd9014 0x0000801d +wm 32 0x83fd9014 0x0732801c +wm 32 0x83fd9014 0x0400800c +wm 32 0x83fd9014 0x00008014 +wm 32 0x83fd9014 0x00008014 +wm 32 0x83fd9014 0x0632801c +wm 32 0x83fd9014 0x0380801d +wm 32 0x83fd9014 0x0040801d +wm 32 0x83fd9014 0x00008004 +wm 32 0x83fd9000 0xb2a20000 +wm 32 0x83fd9008 0xb2a20000 +wm 32 0x83fd9010 0x000ad6d0 +wm 32 0x83fd9034 0x90000000 +wm 32 0x83fd9014 0x00000000 diff --git a/arch/arm/boards/zii-imx51-rdu1/lowlevel.c b/arch/arm/boards/zii-imx51-rdu1/lowlevel.c new file mode 100644 index 0000000000..cca331a9cb --- /dev/null +++ b/arch/arm/boards/zii-imx51-rdu1/lowlevel.c @@ -0,0 +1,46 @@ +#include <debug_ll.h> +#include <mach/clock-imx51_53.h> +#include <mach/iomux-mx51.h> +#include <common.h> +#include <mach/esdctl.h> +#include <mach/generic.h> +#include <asm/barebox-arm-head.h> +#include <asm/barebox-arm.h> + +static inline void setup_uart(void) +{ + void __iomem *iomuxbase = IOMEM(MX51_IOMUXC_BASE_ADDR); + void __iomem *ccmbase = IOMEM(MX51_CCM_BASE_ADDR); + + /* + * Restore CCM values that might be changed by the Mask ROM + * code. + * + * Source: RealView debug scripts provided by Freescale + */ + writel(MX5_CCM_CBCDR_RESET_VALUE, ccmbase + MX5_CCM_CBCDR); + writel(MX5_CCM_CSCMR1_RESET_VALUE, ccmbase + MX5_CCM_CSCMR1); + writel(MX5_CCM_CSCDR1_RESET_VALUE, ccmbase + MX5_CCM_CSCDR1); + + imx_setup_pad(iomuxbase, MX51_PAD_UART1_TXD__UART1_TXD); + + imx51_uart_setup_ll(); + + putc_ll('>'); +} + +extern char __dtb_imx51_zii_rdu1_start[]; + +ENTRY_FUNCTION(start_imx51_zii_rdu1, r0, r1, r2) +{ + void *fdt; + + imx5_cpu_lowlevel_init(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) + setup_uart(); + + fdt = __dtb_imx51_zii_rdu1_start + get_runtime_offset(); + + imx51_barebox_entry(fdt); +} diff --git a/arch/arm/boards/zii-imx6q-rdu2/board.c b/arch/arm/boards/zii-imx6q-rdu2/board.c index 265f97e2f4..f6c908c9f1 100644 --- a/arch/arm/boards/zii-imx6q-rdu2/board.c +++ b/arch/arm/boards/zii-imx6q-rdu2/board.c @@ -19,6 +19,8 @@ #include <init.h> #include <mach/bbu.h> #include <mach/imx6.h> +#include <net.h> +#include <linux/nvmem-consumer.h> #define RDU2_DAC1_RESET IMX_GPIO_NR(1, 0) #define RDU2_DAC2_RESET IMX_GPIO_NR(1, 2) @@ -151,3 +153,58 @@ static int rdu2_devices_init(void) return 0; } device_initcall(rdu2_devices_init); + +static int rdu2_eth_register_ethaddr(struct device_node *np) +{ + u8 mac[ETH_ALEN]; + u8 *data; + int i; + + data = nvmem_cell_get_and_read(np, "mac-address", ETH_ALEN); + if (IS_ERR(data)) + return PTR_ERR(data); + /* + * EEPROM stores MAC address in reverse (to what we expect it + * to be) byte order. + */ + for (i = 0; i < ETH_ALEN; i++) + mac[i] = data[ETH_ALEN - i - 1]; + + free(data); + + of_eth_register_ethaddr(np, mac); + + return 0; +} + +static int rdu2_ethernet_init(void) +{ + const char *aliases[] = { "ethernet0", "ethernet1" }; + struct device_node *np, *root; + int i, ret; + + if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") && + !of_machine_is_compatible("zii,imx6qp-zii-rdu2")) + return 0; + + root = of_get_root_node(); + + for (i = 0; i < ARRAY_SIZE(aliases); i++) { + const char *alias = aliases[i]; + + np = of_find_node_by_alias(root, alias); + if (!np) { + pr_warn("Failed to find %s\n", alias); + continue; + } + + ret = rdu2_eth_register_ethaddr(np); + if (ret) { + pr_warn("Failed to register MAC for %s\n", alias); + continue; + } + } + + return 0; +} +late_initcall(rdu2_ethernet_init); diff --git a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c index 6b9c719c6d..a5ac6f64c2 100644 --- a/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c +++ b/arch/arm/boards/zii-imx6q-rdu2/lowlevel.c @@ -19,6 +19,7 @@ #include <mach/generic.h> #include <mach/imx6.h> #include <mach/xload.h> +#include <mach/iomux-mx6.h> #include <asm/barebox-arm.h> struct reginit { @@ -255,12 +256,7 @@ static inline void setup_uart(void) { void __iomem *iomuxbase = IOMEM(MX6_IOMUXC_BASE_ADDR); - 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); imx6_uart_setup_ll(); @@ -278,7 +274,7 @@ static noinline void rdu2_sram_setup(void) imx6_ungate_all_peripherals(); if (IS_ENABLED(CONFIG_DEBUG_LL)) - setup_uart(); + setup_uart(); arm_setup_stack(0x00920000 - 8); relocate_to_current_adr(); diff --git a/arch/arm/boards/zii-vf610-dev/board.c b/arch/arm/boards/zii-vf610-dev/board.c index 6fd49df549..c90644b048 100644 --- a/arch/arm/boards/zii-vf610-dev/board.c +++ b/arch/arm/boards/zii-vf610-dev/board.c @@ -20,6 +20,7 @@ #include <linux/clk.h> #include <dt-bindings/clock/vf610-clock.h> #include <envfs.h> +#include <mach/bbu.h> static int expose_signals(const struct gpio *signals, @@ -147,3 +148,20 @@ static int zii_vf610_dev_set_hostname(void) return 0; } late_initcall(zii_vf610_dev_set_hostname); + +static int zii_vf610_spu3_register_bbu(void) +{ + int ret; + if (!of_machine_is_compatible("zii,vf610spu3-a")) + return 0; + + ret = vf610_bbu_internal_mmc_register_handler("eMMC", "/dev/disk0", + BBU_HANDLER_FLAG_DEFAULT); + if (ret) { + pr_err("Failed to register eMMC BBU handler\n"); + return ret; + } + + return 0; +} +late_initcall(zii_vf610_spu3_register_bbu);
\ No newline at end of file diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig index 8aef9d6ef6..0fc3c9c502 100644 --- a/arch/arm/configs/imx_v7_defconfig +++ b/arch/arm/configs/imx_v7_defconfig @@ -35,6 +35,7 @@ CONFIG_MACH_CM_FX6=y CONFIG_MACH_ADVANTECH_ROM_742X=y CONFIG_MACH_WARP7=y CONFIG_MACH_VF610_TWR=y +CONFIG_MACH_ZII_RDU1=y CONFIG_MACH_ZII_RDU2=y CONFIG_MACH_ZII_VF610_DEV=y CONFIG_MACH_PHYTEC_PHYCORE_IMX7=y diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index b69592e64e..1c94193d12 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -102,6 +102,7 @@ pbl-dtb-$(CONFIG_MACH_VEXPRESS) += vexpress-v2p-ca15.dtb.o pbl-dtb-$(CONFIG_MACH_VSCOM_BALTOS) += am335x-baltos-minimal.dtb.o pbl-dtb-$(CONFIG_MACH_WARP7) += imx7s-warp.dtb.o pbl-dtb-$(CONFIG_MACH_VF610_TWR) += vf610-twr.dtb.o +pbl-dtb-$(CONFIG_MACH_ZII_RDU1) += imx51-zii-rdu1.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 \ diff --git a/arch/arm/dts/imx51-zii-rdu1.dts b/arch/arm/dts/imx51-zii-rdu1.dts new file mode 100644 index 0000000000..979c4c9de6 --- /dev/null +++ b/arch/arm/dts/imx51-zii-rdu1.dts @@ -0,0 +1,88 @@ +/* + * Copyright 2018 CogentEmbedded, Inc. + * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * 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 <arm/imx51-zii-rdu1.dts> + +/ { + compatible = "zii,imx51-rdu1", "fsl,imx51-babbage-power", "fsl,imx51"; + + chosen { + stdout-path = &uart1; + + environment-spi { + compatible = "barebox,environment"; + device-path = &spinor, "partname:barebox-environment"; + }; + }; +}; + +&ecspi1 { + spinor: flash@1 { + partition@0 { + /* + * Do not change the size of this + * partition. RDU1's BBU code relies on + * "barebox" partition starting at 1024 byte + * mark to function properly + */ + label = "config"; + reg = <0x0 0x400>; + }; + + partition@400 { + label = "barebox"; + reg = <0x400 0xdfc00>; + }; + + partition@e0000 { + label = "barebox-environment"; + reg = <0xe0000 0x20000>; + }; + }; +}; + +&uart3 { + rave-sp { + #address-cells = <1>; + #size-cells = <1>; + + watchdog { + nvmem-cells = <&boot_source>; + nvmem-cell-names = "boot-source"; + }; + + eeprom@a3 { + compatible = "zii,rave-sp-eeprom"; + reg = <0xa3 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + zii,eeprom-name = "dds-eeprom"; + }; + + eeprom@a4 { + compatible = "zii,rave-sp-eeprom"; + reg = <0xa4 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + zii,eeprom-name = "main-eeprom"; + + boot_source: boot-source@83 { + reg = <0x83 1>; + }; + }; + + backlight { + compatible = "zii,rave-sp-backlight"; + }; + }; +}; diff --git a/arch/arm/dts/imx6dl-advantech-rom-7421.dts b/arch/arm/dts/imx6dl-advantech-rom-7421.dts index 1d5fd89264..cdf378114a 100755 --- a/arch/arm/dts/imx6dl-advantech-rom-7421.dts +++ b/arch/arm/dts/imx6dl-advantech-rom-7421.dts @@ -79,6 +79,13 @@ status = "okay"; }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + clock-frequency = <100000>; + status = "okay"; +}; + &uart1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; @@ -144,6 +151,17 @@ &iomuxc { pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + pinctrl_hog: hoggrp { + fsl,pins = < + /* custom watchdog controls disabled */ + MX6QDL_PAD_NANDF_RB0__GPIO6_IO10 0x130b0 + MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x130b0 + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x130b0 + + >; + }; pinctrl_ecspi1: ecspi1grp { fsl,pins = < @@ -175,6 +193,13 @@ >; }; + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1 + MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1 + >; + }; + pinctrl_uart1: uart1grp { fsl,pins = < MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 diff --git a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi index 7ab569b789..a74fb47831 100644 --- a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi +++ b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi @@ -55,69 +55,45 @@ }; }; + &uart4 { - pic { - compatible = "zii,pic-rdu2"; - current-speed = <1000000>; - status = "okay"; + rave-sp { + #address-cells = <1>; + #size-cells = <1>; + + watchdog { + nvmem-cells = <&boot_source>; + nvmem-cell-names = "boot-source"; + }; - main_eeprom { - compatible = "zii,pic-main-eeprom"; + eeprom@a3 { + compatible = "zii,rave-sp-eeprom"; + reg = <0xa3 0x4000>; + zii,eeprom-name = "dds-eeprom"; + }; + + eeprom@a4 { + compatible = "zii,rave-sp-eeprom"; + reg = <0xa4 0x4000>; #address-cells = <1>; #size-cells = <1>; - status = "okay"; + zii,eeprom-name = "main-eeprom"; boot_source: boot-source@83 { reg = <0x83 1>; }; - max_failed_boots: max-failed-boots@8E { - reg = <0x8E 2>; - }; - }; - - dds_eeprom { - compatible = "zii,pic-dds-eeprom"; - #address-cells = <1>; - #size-cells = <1>; - status = "okay"; - }; - watchdog { - compatible = "zii,pic-watchdog"; - status = "okay"; - }; + mac_address_0: mac-address@180 { + reg = <0x180 6>; + }; - hwmon { - compatible = "zii,pic-hwmon"; - sensors = "RMB_3V3_PMIC", - "RMB_3V3_MCU", - "RMB_5V_MAIN", - "RMB_12V_MAIN", - "RMB_28V_FIL", - "RMB_28V_HOTSWAP", - "DEB_1V8", - "DEB_3V3", - "DEB_28V_DEB", - "DEB_28V_RDU", - "TEMPERATURE", - "TEMPERATURE_2", - "RMB_28V_CURRENT"; - status = "okay"; + mac_address_1: mac-address@190 { + reg = <0x190 6>; + }; }; backlight { - compatible = "zii,pic-backlight"; - status = "okay"; - }; - - leds { - compatible = "zii,pic-leds"; - status = "okay"; - }; - - pwrbutton { - compatible = "zii,pic-pwrbutton"; - status = "okay"; + compatible = "zii,rave-sp-backlight"; }; }; }; @@ -139,6 +115,11 @@ }; }; +&fec { + nvmem-cells = <&mac_address_0>; + nvmem-cell-names = "mac-address"; +}; + &i2c2 { temp-sense@48 { barebox,sensor-name = "Temp Sensor 1"; @@ -154,6 +135,8 @@ i210: i210@0 { reg = <0 0 0 0 0>; + nvmem-cells = <&mac_address_1>; + nvmem-cell-names = "mac-address"; }; }; }; diff --git a/arch/arm/dts/imx6sx-sdb.dts b/arch/arm/dts/imx6sx-sdb.dts index 88832840b2..18d873ccf2 100644 --- a/arch/arm/dts/imx6sx-sdb.dts +++ b/arch/arm/dts/imx6sx-sdb.dts @@ -19,31 +19,6 @@ }; }; -&fec1 { - phy-handle = <&phy1>; - - mdio { - #address-cells = <1>; - #size-cells = <0>; - - phy1: phy@1 { - reg = <1>; - }; - - phy2: phy@2 { - reg = <2>; - }; - }; -}; - -&fec2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_enet2>; - phy-mode = "rgmii"; - status = "okay"; - phy-handle = <&phy2>; -}; - &ocotp { barebox,provide-mac-address = <&fec1 0x620 &fec2 0x632>; }; @@ -57,36 +32,3 @@ reg = <0xe0000 0x20000>; }; }; - -&iomuxc { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hog>; - - imx6x-sdb { - pinctrl_hog: hoggrp { - fsl,pins = < - MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x17059 /* PERI_3V3 */ - MX6SX_PAD_ENET2_COL__GPIO2_IO_6 0x17059 /* ENET PHY Power */ - MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 0x17059 /* AR8031 PHY Reset. */ - MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x17059 /* Phy 25M Clock */ - >; - }; - - pinctrl_enet2: enet2grp { - fsl,pins = < - MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b1 - MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1 - MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1 - MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1 - MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1 - MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1 - MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081 - MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081 - MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081 - MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081 - MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081 - MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081 - >; - }; - }; -}; diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index dec5e387e1..83d32f30c5 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -85,6 +85,15 @@ config RESET_IMX_SRC def_bool y depends on ARCH_IMX6 || ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53 +# +# PMIC configuration found on i.MX51 Babbadge board +# +config MACH_FREESCALE_MX51_PDK_POWER + bool + select SPI + select DRIVER_SPI_IMX + select MFD_MC13XXX + comment "Freescale i.MX System-on-Chip" config ARCH_IMX1 @@ -256,9 +265,7 @@ config MACH_EMBEDSKY_E9 config MACH_FREESCALE_MX51_PDK bool "Freescale i.MX51 PDK" select ARCH_IMX51 - select SPI - select DRIVER_SPI_IMX - select MFD_MC13XXX + select MACH_FREESCALE_MX51_PDK_POWER config MACH_CCMX53 bool "Digi ConnectCore i.MX53" @@ -416,6 +423,11 @@ config MACH_VF610_TWR bool "Freescale VF610 Tower Board" select ARCH_VF610 +config MACH_ZII_RDU1 + bool "ZII i.MX51 RDU1" + select ARCH_IMX51 + select MACH_FREESCALE_MX51_PDK_POWER + config MACH_ZII_RDU2 bool "ZII i.MX6Q(+) RDU2" select ARCH_IMX6 diff --git a/arch/arm/mach-imx/imx-bbu-internal.c b/arch/arm/mach-imx/imx-bbu-internal.c index c7375ff52a..55e344cff2 100644 --- a/arch/arm/mach-imx/imx-bbu-internal.c +++ b/arch/arm/mach-imx/imx-bbu-internal.c @@ -34,15 +34,13 @@ #define FLASH_HEADER_OFFSET_MMC 0x400 -#define IMX_INTERNAL_FLAG_NAND (1 << 0) -#define IMX_INTERNAL_FLAG_KEEP_DOSPART (1 << 1) -#define IMX_INTERNAL_FLAG_ERASE (1 << 2) +#define IMX_INTERNAL_FLAG_NAND BIT(31) +#define IMX_INTERNAL_FLAG_ERASE BIT(30) struct imx_internal_bbu_handler { struct bbu_handler handler; unsigned long flash_header_offset; size_t device_size; - unsigned long flags; }; /* @@ -53,72 +51,51 @@ static int imx_bbu_write_device(struct imx_internal_bbu_handler *imx_handler, const char *devicefile, struct bbu_data *data, const void *buf, int image_len) { - int fd, ret; - int written = 0; + int fd, ret, offset = 0; fd = open(devicefile, O_RDWR | O_CREAT); if (fd < 0) return fd; - if (imx_handler->flags & IMX_INTERNAL_FLAG_ERASE) { - debug("%s: unprotecting %s from 0 to 0x%08x\n", __func__, - devicefile, image_len); - ret = protect(fd, image_len, 0, 0); - if (ret && ret != -ENOSYS) { - printf("unprotecting %s failed with %s\n", devicefile, - strerror(-ret)); - goto err_close; - } - - debug("%s: erasing %s from 0 to 0x%08x\n", __func__, - devicefile, image_len); - ret = erase(fd, image_len, 0); - if (ret) { - printf("erasing %s failed with %s\n", devicefile, - strerror(-ret)); - goto err_close; - } + if (imx_handler->handler.flags & (IMX_BBU_FLAG_KEEP_HEAD | + IMX_BBU_FLAG_PARTITION_STARTS_AT_HEADER)) { + image_len -= imx_handler->flash_header_offset; + buf += imx_handler->flash_header_offset; } - if (imx_handler->flags & IMX_INTERNAL_FLAG_KEEP_DOSPART) { - void *mbr = xzalloc(512); + if (imx_handler->handler.flags & IMX_BBU_FLAG_KEEP_HEAD) + offset += imx_handler->flash_header_offset; - debug("%s: reading DOS partition table in order to keep it\n", __func__); - - ret = read(fd, mbr, 512); - if (ret < 0) { - free(mbr); + if (imx_handler->handler.flags & IMX_INTERNAL_FLAG_ERASE) { + pr_debug("%s: unprotecting %s from 0x%08x to 0x%08x\n", __func__, + devicefile, offset, image_len); + ret = protect(fd, image_len, offset, 0); + if (ret && ret != -ENOSYS) { + pr_err("unprotecting %s failed with %s\n", devicefile, + strerror(-ret)); goto err_close; } - memcpy(mbr, buf, 0x1b8); - - ret = lseek(fd, 0, SEEK_SET); + pr_debug("%s: erasing %s from 0x%08x to 0x%08x\n", __func__, + devicefile, offset, image_len); + ret = erase(fd, image_len, offset); if (ret) { - free(mbr); + pr_err("erasing %s failed with %s\n", devicefile, + strerror(-ret)); goto err_close; } - - ret = write(fd, mbr, 512); - - free(mbr); - - if (ret < 0) - goto err_close; - - written = 512; } - ret = write(fd, buf + written, image_len - written); + ret = pwrite(fd, buf, image_len, offset); if (ret < 0) goto err_close; - if (imx_handler->flags & IMX_INTERNAL_FLAG_ERASE) { - debug("%s: protecting %s from 0 to 0x%08x\n", __func__, - devicefile, image_len); - ret = protect(fd, image_len, 0, 1); + if (imx_handler->handler.flags & IMX_INTERNAL_FLAG_ERASE) { + pr_debug("%s: protecting %s from 0x%08x to 0x%08x\n", __func__, + devicefile, offset, image_len); + ret = protect(fd, image_len, offset, 1); if (ret && ret != -ENOSYS) { - printf("protecting %s failed with %s\n", devicefile, + pr_err("protecting %s failed with %s\n", devicefile, strerror(-ret)); } } @@ -166,7 +143,7 @@ static int imx_bbu_internal_v1_update(struct bbu_handler *handler, struct bbu_da if (ret) return ret; - printf("updating to %s\n", data->devicefile); + pr_info("updating to %s\n", data->devicefile); ret = imx_bbu_write_device(imx_handler, data->devicefile, data, data->image, data->len); @@ -257,7 +234,7 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * if (ret) { if (!offset) { - printf("1st block is bad. This is not supported\n"); + pr_err("1st block is bad. This is not supported\n"); ret = -EINVAL; goto out; } @@ -266,7 +243,7 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * *num_bb += 1; if (*num_bb == 425) { /* Maximum number of bad blocks the ROM supports */ - printf("maximum number of bad blocks reached\n"); + pr_err("maximum number of bad blocks reached\n"); ret = -ENOSPC; goto out; } @@ -281,7 +258,7 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * block++; if (size_available < 0) { - printf("device is too small"); + pr_err("device is too small"); ret = -ENOSPC; goto out; } @@ -292,7 +269,7 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * data->len + pre_image_size + *num_bb * blocksize); if (data->len + pre_image_size + *num_bb * blocksize > imx_handler->device_size) { - printf("needed space (0x%08zx) exceeds partition space (0x%08zx)\n", + pr_err("needed space (0x%08zx) exceeds partition space (0x%08zx)\n", data->len + pre_image_size + *num_bb * blocksize, imx_handler->device_size); ret = -ENOSPC; @@ -320,7 +297,7 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * continue; } - debug("writing %d bytes at 0x%08llx\n", now, offset); + pr_debug("writing %d bytes at 0x%08llx\n", now, offset); ret = erase(fd, blocksize, offset); if (ret) @@ -367,11 +344,11 @@ static int imx_bbu_internal_v2_update(struct bbu_handler *handler, struct bbu_da barker = data->image + imx_handler->flash_header_offset; if (*barker != IVT_BARKER) { - printf("Board does not provide DCD data and this image is no imximage\n"); + pr_err("Board does not provide DCD data and this image is no imximage\n"); return -EINVAL; } - if (imx_handler->flags & IMX_INTERNAL_FLAG_NAND) + if (imx_handler->handler.flags & IMX_INTERNAL_FLAG_NAND) ret = imx_bbu_internal_v2_write_nand_dbbt(imx_handler, data); else ret = imx_bbu_write_device(imx_handler, data->devicefile, data, @@ -394,7 +371,7 @@ static int imx_bbu_internal_v2_mmcboot_update(struct bbu_handler *handler, barker = data->image + imx_handler->flash_header_offset; if (*barker != IVT_BARKER) { - printf("Board does not provide DCD data and this image is no imximage\n"); + pr_err("Board does not provide DCD data and this image is no imximage\n"); return -EINVAL; } @@ -473,19 +450,17 @@ static int __register_handler(struct imx_internal_bbu_handler *imx_handler) return ret; } -/* - * Register an i.MX51 internal boot update handler for MMC/SD - */ -int imx51_bbu_internal_mmc_register_handler(const char *name, char *devicefile, - unsigned long flags) +static int +imx_bbu_internal_mmc_register_handler(const char *name, char *devicefile, + unsigned long flags, void *handler) { struct imx_internal_bbu_handler *imx_handler; - imx_handler = __init_handler(name, devicefile, flags); + imx_handler = __init_handler(name, devicefile, flags | + IMX_BBU_FLAG_KEEP_HEAD); imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; - imx_handler->flags = IMX_INTERNAL_FLAG_KEEP_DOSPART; - imx_handler->handler.handler = imx_bbu_internal_v1_update; + imx_handler->handler.handler = handler; return __register_handler(imx_handler); } @@ -495,30 +470,34 @@ int imx51_bbu_internal_spi_i2c_register_handler(const char *name, { struct imx_internal_bbu_handler *imx_handler; - imx_handler = __init_handler(name, devicefile, flags); + imx_handler = __init_handler(name, devicefile, flags | + IMX_INTERNAL_FLAG_ERASE); imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; - imx_handler->flags = IMX_INTERNAL_FLAG_ERASE; imx_handler->handler.handler = imx_bbu_internal_v1_update; return __register_handler(imx_handler); } /* - * Register an i.MX53 internal boot update handler for MMC/SD + * Register an i.MX51 internal boot update handler for MMC/SD */ -int imx53_bbu_internal_mmc_register_handler(const char *name, char *devicefile, +int imx51_bbu_internal_mmc_register_handler(const char *name, char *devicefile, unsigned long flags) { - struct imx_internal_bbu_handler *imx_handler; - - imx_handler = __init_handler(name, devicefile, flags); - imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; - imx_handler->flags = IMX_INTERNAL_FLAG_KEEP_DOSPART; - imx_handler->handler.handler = imx_bbu_internal_v2_update; + return imx_bbu_internal_mmc_register_handler(name, devicefile, flags, + imx_bbu_internal_v1_update); +} - return __register_handler(imx_handler); +/* + * Register an i.MX53 internal boot update handler for MMC/SD + */ +int imx53_bbu_internal_mmc_register_handler(const char *name, char *devicefile, + unsigned long flags) +{ + return imx_bbu_internal_mmc_register_handler(name, devicefile, flags, + imx_bbu_internal_v2_update); } /* @@ -531,10 +510,10 @@ int imx53_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefi { struct imx_internal_bbu_handler *imx_handler; - imx_handler = __init_handler(name, devicefile, flags); + imx_handler = __init_handler(name, devicefile, flags | + IMX_INTERNAL_FLAG_ERASE); imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; - imx_handler->flags = IMX_INTERNAL_FLAG_ERASE; imx_handler->handler.handler = imx_bbu_internal_v2_update; return __register_handler(imx_handler); @@ -548,11 +527,11 @@ int imx53_bbu_internal_nand_register_handler(const char *name, { struct imx_internal_bbu_handler *imx_handler; - imx_handler = __init_handler(name, NULL, flags); - imx_handler->flash_header_offset = 0x400; + imx_handler = __init_handler(name, NULL, flags | + IMX_INTERNAL_FLAG_NAND); + imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; imx_handler->handler.handler = imx_bbu_internal_v2_update; - imx_handler->flags = IMX_INTERNAL_FLAG_NAND; imx_handler->handler.devicefile = "/dev/nand0"; imx_handler->device_size = partition_size; @@ -563,18 +542,15 @@ int imx53_bbu_internal_nand_register_handler(const char *name, * Register an i.MX6 internal boot update handler for MMC/SD */ int imx6_bbu_internal_mmc_register_handler(const char *name, char *devicefile, - unsigned long flags) -{ - struct imx_internal_bbu_handler *imx_handler; - - imx_handler = __init_handler(name, devicefile, flags); - imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; - - imx_handler->flags = IMX_INTERNAL_FLAG_KEEP_DOSPART; - imx_handler->handler.handler = imx_bbu_internal_v2_update; + unsigned long flags) + __alias(imx53_bbu_internal_mmc_register_handler); - return __register_handler(imx_handler); -} +/* + * Register an VF610 internal boot update handler for MMC/SD + */ +int vf610_bbu_internal_mmc_register_handler(const char *name, char *devicefile, + unsigned long flags) + __alias(imx6_bbu_internal_mmc_register_handler); /* * Register a handler that writes to the non-active boot partition of an mmc @@ -603,27 +579,18 @@ int imx6_bbu_internal_mmcboot_register_handler(const char *name, char *devicefil * EEPROMs / flashes. Nearly the same as MMC/SD, but we do not need to * keep a partition table. We have to erase the device beforehand though. */ -int imx6_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, - unsigned long flags) -{ - struct imx_internal_bbu_handler *imx_handler; - - imx_handler = __init_handler(name, devicefile, flags); - imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; - - imx_handler->flags = IMX_INTERNAL_FLAG_ERASE; - imx_handler->handler.handler = imx_bbu_internal_v2_update; - - return __register_handler(imx_handler); -} +int imx6_bbu_internal_spi_i2c_register_handler(const char *name, + char *devicefile, + unsigned long flags) + __alias(imx53_bbu_internal_spi_i2c_register_handler); int imx_bbu_external_nor_register_handler(const char *name, char *devicefile, unsigned long flags) { struct imx_internal_bbu_handler *imx_handler; - imx_handler = __init_handler(name, devicefile, flags); - imx_handler->flags = IMX_INTERNAL_FLAG_ERASE; + imx_handler = __init_handler(name, devicefile, flags | + IMX_INTERNAL_FLAG_ERASE); imx_handler->handler.handler = imx_bbu_external_update; return __register_handler(imx_handler); diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c index 56f1bda75e..b22929f749 100644 --- a/arch/arm/mach-imx/imx53.c +++ b/arch/arm/mach-imx/imx53.c @@ -86,7 +86,7 @@ int imx53_devices_init(void) void imx53_init_lowlevel_early(unsigned int cpufreq_mhz) { void __iomem *ccm = (void __iomem *)MX53_CCM_BASE_ADDR; - u32 r; + u32 r, cbcdr, cbcmr; imx5_init_lowlevel(); @@ -122,8 +122,16 @@ void imx53_init_lowlevel_early(unsigned int cpufreq_mhz) imx5_setup_pll_400((void __iomem *)MX53_PLL3_BASE_ADDR); /* Switch peripheral to PLL3 */ - writel(0x00015154, ccm + MX5_CCM_CBCMR); - writel(0x02888945 | (1<<16), ccm + MX5_CCM_CBCDR); + cbcmr = readl(ccm + MX5_CCM_CBCMR); + cbcmr &= ~(3 << 12); + cbcmr |= (1 << 12); + writel(cbcmr, ccm + MX5_CCM_CBCMR); + + cbcdr = readl(ccm + MX5_CCM_CBCDR); + cbcdr |= (1 << 25); + cbcdr &= ~(7 << 16); + cbcdr |= (1 << 16); + writel(cbcdr, ccm + MX5_CCM_CBCDR); /* make sure change is effective */ while (readl(ccm + MX5_CCM_CDHIPR)); @@ -131,14 +139,13 @@ void imx53_init_lowlevel_early(unsigned int cpufreq_mhz) imx5_setup_pll_400((void __iomem *)MX53_PLL2_BASE_ADDR); /* Switch peripheral to PLL2 */ - r = 0x00808145 | - (2 << 10) | - (0 << 16) | - (1 << 19); - - writel(r, ccm + MX5_CCM_CBCDR); + cbcdr &= ~(1 << 25); + cbcdr &= ~(7 << 16); + writel(cbcdr, ccm + MX5_CCM_CBCDR); - writel(0x00016154, ccm + MX5_CCM_CBCMR); + cbcmr &= ~(3 << 12); + cbcmr |= (2 << 12); + writel(cbcmr, ccm + MX5_CCM_CBCMR); r = readl(ccm + MX5_CCM_CSCMR1); diff --git a/arch/arm/mach-imx/include/mach/bbu.h b/arch/arm/mach-imx/include/mach/bbu.h index bde3e02d27..7df9d668bb 100644 --- a/arch/arm/mach-imx/include/mach/bbu.h +++ b/arch/arm/mach-imx/include/mach/bbu.h @@ -7,6 +7,29 @@ struct imx_dcd_entry; struct imx_dcd_v2_entry; +/* + * The ROM code reads images from a certain offset of the boot device + * (usually 0x400), whereas the update images start from offset 0x0. + * Set this flag to skip the offset on both the update image and the + * device so that the initial boot device portion is preserved. This + * is useful if a partition table or other data is in this area. + */ +#define IMX_BBU_FLAG_KEEP_HEAD BIT(16) + +/* + * Set this flag when the partition the update image is written to + * actually starts at the offset where the i.MX flash header is expected + * (usually 0x400). This means for the update code that it has to skip + * the first 0x400 bytes of the image. + */ +#define IMX_BBU_FLAG_PARTITION_STARTS_AT_HEADER (1 << 17) + +/* + * The upper 16 bit of the flags passes to the below functions are reserved + * for i.MX specific flags + */ +#define IMX_BBU_FLAG_MASK 0xffff0000 + #ifdef CONFIG_BAREBOX_UPDATE int imx51_bbu_internal_mmc_register_handler(const char *name, char *devicefile, @@ -33,6 +56,9 @@ int imx6_bbu_internal_mmcboot_register_handler(const char *name, char *devicefil int imx6_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, unsigned long flags); +int vf610_bbu_internal_mmc_register_handler(const char *name, char *devicefile, + unsigned long flags); + int imx_bbu_external_nor_register_handler(const char *name, char *devicefile, unsigned long flags); @@ -87,6 +113,12 @@ static inline int imx6_bbu_internal_spi_i2c_register_handler(const char *name, c return -ENOSYS; } +int vf610_bbu_internal_mmc_register_handler(const char *name, char *devicefile, + unsigned long flags) +{ + return -ENOSYS; +} + static inline int imx_bbu_external_nor_register_handler(const char *name, char *devicefile, unsigned long flags) { diff --git a/arch/arm/mach-imx/include/mach/imx5.h b/arch/arm/mach-imx/include/mach/imx5.h index 5957141298..dd5cfe99cf 100644 --- a/arch/arm/mach-imx/include/mach/imx5.h +++ b/arch/arm/mach-imx/include/mach/imx5.h @@ -18,4 +18,6 @@ void imx5_setup_pll(void __iomem *base, int freq, u32 op, u32 mfd, u32 mfn); #define imx5_setup_pll_400(base) imx5_setup_pll((base), 400, (( 8 << 4) + ((2 - 1) << 0)), (3 - 1), 1) #define imx5_setup_pll_216(base) imx5_setup_pll((base), 216, (( 6 << 4) + ((3 - 1) << 0)), (4 - 1), 3) +void imx51_babbage_power_init(void); + #endif /* __MACH_MX53_H */ diff --git a/common/clock.c b/common/clock.c index f98176dd52..904bee0b46 100644 --- a/common/clock.c +++ b/common/clock.c @@ -181,10 +181,12 @@ EXPORT_SYMBOL(is_timeout_non_interruptible); int is_timeout(uint64_t start_ns, uint64_t time_offset_ns) { + int ret = is_timeout_non_interruptible(start_ns, time_offset_ns); + if (time_offset_ns >= 100 * USECOND) poller_call(); - return is_timeout_non_interruptible(start_ns, time_offset_ns); + return ret; } EXPORT_SYMBOL(is_timeout); diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index e7dcd87a7e..f2e704cdb2 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -129,20 +129,3 @@ struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg, return g; } - -struct clk *clk_gate2_inverted(const char *name, const char *parent, - void __iomem *reg, u8 shift) -{ - struct clk *clk; - struct clk_gate2 *g; - - clk = clk_gate2(name, parent, reg, shift, 0x3, 0); - if (IS_ERR(clk)) - return clk; - - g = to_clk_gate2(clk); - - g->flags = CLK_GATE_INVERTED; - - return clk; -} diff --git a/drivers/clk/imx/clk-imx6.c b/drivers/clk/imx/clk-imx6.c index 8c3bb46a48..35b995dae2 100644 --- a/drivers/clk/imx/clk-imx6.c +++ b/drivers/clk/imx/clk-imx6.c @@ -527,7 +527,6 @@ static int imx6_ccm_probe(struct device_d *dev) clk_enable(clks[IMX6QDL_CLK_MMDC_CH0_AXI_PODF]); clk_enable(clks[IMX6QDL_CLK_PLL6_ENET]); clk_enable(clks[IMX6QDL_CLK_SATA_REF_100M]); - clk_enable(clks[IMX6QDL_CLK_ENFC_PODF]); clk_set_parent(clks[IMX6QDL_CLK_LVDS1_SEL], clks[IMX6QDL_CLK_SATA_REF_100M]); diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 4b8eaec057..7980a91e19 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -246,9 +246,6 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, command = priv->command; - dev_dbg(&priv->spi->dev, "READ: (%x) %x %x %x\n", - command[0], command[1], command[2], command[3]); - spi_message_init(&msg); memset(&x[0], 0, sizeof(struct spi_transfer) * 2); @@ -271,6 +268,9 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, command[3] = (u8)(addr >> 0); /* plus 4 "don't care" bytes */ + dev_dbg(&priv->spi->dev, "READ: (%x) %x %x %x\n", + command[0], command[1], command[2], command[3]); + status = spi_sync(priv->spi, &msg); if (status >= 0) { diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c index 337748af48..0e0f5e68b2 100644 --- a/drivers/mtd/nand/nand_mxs.c +++ b/drivers/mtd/nand/nand_mxs.c @@ -2051,7 +2051,9 @@ static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info) nand->select_chip(mtd, -1); /* [3] set the main IO clock, 100MHz for mode 5, 80MHz for mode 4. */ + clk_disable(info->clk); clk_set_rate(info->clk, (mode == 5) ? 100000000 : 80000000); + clk_enable(info->clk); dev_dbg(info->dev, "using asynchronous EDO mode %d\n", mode); @@ -2147,6 +2149,8 @@ static int mxs_nand_probe(struct device_d *dev) if (IS_ERR(nand_info->clk)) return PTR_ERR(nand_info->clk); + clk_enable(nand_info->clk); + if (mxs_nand_is_imx6(nand_info)) { clk_disable(nand_info->clk); clk_set_rate(nand_info->clk, 22000000); @@ -2154,7 +2158,6 @@ static int mxs_nand_probe(struct device_d *dev) nand_info->dma_channel_base = 0; } else { nand_info->dma_channel_base = MXS_DMA_CHANNEL_AHB_APBH_GPMI0; - clk_enable(nand_info->clk); } err = mxs_nand_alloc_buffers(nand_info); diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index a3797b4aac..38b6f42419 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -36,4 +36,11 @@ config IMX_OCOTP_WRITE the value of the address by 4. mw -l -d /dev/imx-ocotp 0x8C 0x00001234 mw -l -d /dev/imx-ocotp 0x88 0x56789ABC + +config RAVE_SP_EEPROM + tristate "Rave SP EEPROM Support" + depends on RAVE_SP_CORE + help + Say y here to enable Rave SP EEPROM support. + endif diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index 998a9c4b9a..716e5dbe87 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -10,4 +10,7 @@ obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o nvmem_snvs_lpgpr-y := snvs_lpgpr.o obj-$(CONFIG_IMX_OCOTP) += nvmem_ocotp.o -nvmem_ocotp-y := ocotp.o
\ No newline at end of file +nvmem_ocotp-y := ocotp.o + +obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o +nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
\ No newline at end of file diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 53b934bb33..c0f61f453a 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -750,3 +750,26 @@ int nvmem_device_write(struct nvmem_device *nvmem, return bytes; } EXPORT_SYMBOL_GPL(nvmem_device_write); + +void *nvmem_cell_get_and_read(struct device_node *np, const char *cell_name, + size_t bytes) +{ + struct nvmem_cell *cell; + void *value; + size_t len; + + cell = of_nvmem_cell_get(np, cell_name); + if (IS_ERR(cell)) + return cell; + + value = nvmem_cell_read(cell, &len); + if (!IS_ERR(value) && len != bytes) { + kfree(value); + value = ERR_PTR(-EINVAL); + } + + nvmem_cell_put(cell); + + return value; +} +EXPORT_SYMBOL_GPL(nvmem_cell_get_and_read); diff --git a/drivers/nvmem/rave-sp-eeprom.c b/drivers/nvmem/rave-sp-eeprom.c new file mode 100644 index 0000000000..6c6ed17f18 --- /dev/null +++ b/drivers/nvmem/rave-sp-eeprom.c @@ -0,0 +1,370 @@ +/* + * EEPROM driver for RAVE SP + * + * Copyright (C) 2017 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 (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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <io.h> +#include <of.h> +#include <of_device.h> +#include <malloc.h> +#include <linux/sizes.h> +#include <linux/mfd/rave-sp.h> +#include <linux/nvmem-provider.h> + +/** + * enum rave_sp_eeprom_access_type - Supported types of EEPROM access + * + * @RAVE_SP_EEPROM_WRITE: EEPROM write + * @RAVE_SP_EEPROM_READ: EEPROM read + * + * Note that values of both constant are chose so that they'd match + * similar values from RAVE SP ICD. + */ +enum rave_sp_eeprom_access_type { + RAVE_SP_EEPROM_WRITE = 0, + RAVE_SP_EEPROM_READ = 1, +}; + +/** + * enum rave_sp_eeprom_header_size - EEPROM command header sizes + * + * @RAVE_SP_EEPROM_HEADER_SMALL: EEPROM header size for "small" devices (< 8K) + * @RAVE_SP_EEPROM_HEADER_BIG: EEPROM header size for "big" devices (> 8K, < 2M) + * + * Note that values of both constant are chose so that they'd match + * similar values from RAVE SP ICD. + */ +enum rave_sp_eeprom_header_size { + RAVE_SP_EEPROM_HEADER_SMALL = 4U, + RAVE_SP_EEPROM_HEADER_BIG = 5U, +}; +#define RAVE_SP_EEPROM_HEADER_MAX RAVE_SP_EEPROM_HEADER_BIG + +#define RAVE_SP_EEPROM_PAGE_SIZE 32U + +/** + * struct rave_sp_eeprom_page - RAVE SP EEPROM page + * + * @type: Access type (see enum rave_sp_eeprom_access_type) + * @success: Success flag (Success = 1, Failure = 0) + * @data: Read data + * + * Note that the layout of this structure is made to follow the layout + * of RSP_*_EEPROM from device's ICD (only the data portion of it due + * to how rave_sp_exec() returns data) + */ +struct rave_sp_eeprom_page { + u8 type; + u8 success; + u8 data[RAVE_SP_EEPROM_PAGE_SIZE]; +} __packed; + +/** + * struct rave_sp_eeprom - RAVE SP EEPROM device + * + * @sp: Pointer to parent RAVE SP device + * @mutex: Lock protecting access to EEPROM + * @address: EEPROM device address (first byte of the command to access it) + * @header_size: Size of EEPROM command header for this device + */ +struct rave_sp_eeprom { + struct rave_sp *sp; + u8 address; + unsigned int header_size; +}; + +/** + * rave_sp_eeprom_io - Low-level part of EEPROM page access + * + * @eeprom: EEPROM device to write to + * @type: EEPROM access type (read or write) + * @idx: number of the EEPROM page + * @page: Data to write or buffer to store result (via page->data) + * + * This function does all of the low-lever work required to perform a + * EEPROM access. This includes formatting corredct command payload, + * sending it and checking received results. + * + * Returns zero in case of success or negative error code in + * case of failure. + */ +static int rave_sp_eeprom_io(struct rave_sp_eeprom *eeprom, + enum rave_sp_eeprom_access_type type, + u16 idx, + struct rave_sp_eeprom_page *page) +{ + const bool is_write = type == RAVE_SP_EEPROM_WRITE; + const unsigned int data_size = is_write ? sizeof(page->data) : 0; + const unsigned int cmd_size = eeprom->header_size + data_size; + const unsigned int rsp_size = + is_write ? sizeof(*page) - sizeof(page->data) : sizeof(*page); + unsigned int offset = 0; + u8 cmd[RAVE_SP_EEPROM_HEADER_MAX + sizeof(page->data)]; + int ret; + + if (WARN_ON(cmd_size > sizeof(cmd))) + return -EINVAL; + + cmd[offset++] = eeprom->address; + cmd[offset++] = 0; + cmd[offset++] = type; + cmd[offset++] = idx; + + if (offset < eeprom->header_size) + cmd[offset++] = idx >> 8; + /* + * Copy our data to write to command buffer first. In case of + * a read data_size should be zero and memcpy would become a + * no-op + */ + memcpy(&cmd[offset], page->data, data_size); + + ret = rave_sp_exec(eeprom->sp, cmd, cmd_size, page, rsp_size); + if (ret) + return ret; + + if (page->type != type) + return -EPROTO; + + if (!page->success) + return -EIO; + + return 0; +} + +/** + * rave_sp_eeprom_page_access - Access single EEPROM page + * + * @eeprom: EEPROM device to access + * @type: Access type to perform (read or write) + * @offset: Offset within EEPROM to access + * @data: Data buffer + * @data_len: Size of the data buffer + * + * This function performs a generic access to a single page or a + * portion thereof. Requested access MUST NOT cross the EEPROM page + * boundary. + * + * Returns zero in case of success or negative error code in + * case of failure. + */ +static int +rave_sp_eeprom_page_access(struct rave_sp_eeprom *eeprom, + enum rave_sp_eeprom_access_type type, + unsigned int offset, u8 *data, + size_t data_len) +{ + const unsigned int page_offset = offset % RAVE_SP_EEPROM_PAGE_SIZE; + const unsigned int page_nr = offset / RAVE_SP_EEPROM_PAGE_SIZE; + struct rave_sp_eeprom_page page; + int ret; + + /* + * This function will not work if data access we've been asked + * to do is crossing EEPROM page boundary. Normally this + * should never happen and getting here would indicate a bug + * in the code. + */ + if (WARN_ON(data_len > sizeof(page.data) - page_offset)) + return -EINVAL; + + if (type == RAVE_SP_EEPROM_WRITE) { + /* + * If doing a partial write we need to do a read first + * to fill the rest of the page with correct data. + */ + if (data_len < RAVE_SP_EEPROM_PAGE_SIZE) { + ret = rave_sp_eeprom_io(eeprom, RAVE_SP_EEPROM_READ, + page_nr, &page); + if (ret) + return ret; + } + + memcpy(&page.data[page_offset], data, data_len); + } + + ret = rave_sp_eeprom_io(eeprom, type, page_nr, &page); + if (ret) + return ret; + + /* + * Since we receive the result of the read via 'page.data' + * buffer we need to copy that to 'data' + */ + if (type == RAVE_SP_EEPROM_READ) + memcpy(data, &page.data[page_offset], data_len); + + return 0; +} + +/** + * rave_sp_eeprom_access - Access EEPROM data + * + * @eeprom: EEPROM device to access + * @type: Access type to perform (read or write) + * @offset: Offset within EEPROM to access + * @data: Data buffer + * @data_len: Size of the data buffer + * + * This function performs a generic access (either read or write) at + * arbitrary offset (not necessary page aligned) of arbitrary length + * (is not constrained by EEPROM page size). + * + * Returns zero in case of success or negative error code in case of + * failure. + */ +static int rave_sp_eeprom_access(struct rave_sp_eeprom *eeprom, + enum rave_sp_eeprom_access_type type, + unsigned int offset, u8 *data, + unsigned int data_len) +{ + unsigned int residue; + unsigned int chunk; + unsigned int head; + int ret; + + head = offset % RAVE_SP_EEPROM_PAGE_SIZE; + residue = data_len; + + do { + /* + * First iteration, if we are doing an access that is + * not 32-byte aligned, we need to access only data up + * to a page boundary to avoid corssing it in + * rave_sp_eeprom_page_access() + */ + if (head) { + chunk = RAVE_SP_EEPROM_PAGE_SIZE - head; + /* + * This can only happen once per + * rave_sp_eeprom_access() call, so we set + * head to zero to process all the other + * iterations normally. + */ + head = 0; + } else { + chunk = RAVE_SP_EEPROM_PAGE_SIZE; + } + + /* + * We should never read more that 'residue' bytes + */ + chunk = min(chunk, residue); + ret = rave_sp_eeprom_page_access(eeprom, type, offset, + data, chunk); + if (ret) + return ret; + + residue -= chunk; + offset += chunk; + data += chunk; + } while (residue); + + return 0; +} + +static int rave_sp_eeprom_read(struct device_d *dev, const int offset, + void *val, int bytes) +{ + return rave_sp_eeprom_access(dev->parent->priv, + RAVE_SP_EEPROM_READ, + offset, val, bytes); +} + +static int rave_sp_eeprom_write(struct device_d *dev, const int offset, + const void *val, int bytes) +{ + return rave_sp_eeprom_access(dev->parent->priv, + RAVE_SP_EEPROM_WRITE, + offset, (void *)val, bytes); +} + +static const struct nvmem_bus rave_sp_eeprom_nvmem_bus = { + .write = rave_sp_eeprom_write, + .read = rave_sp_eeprom_read, +}; + +static int rave_sp_eeprom_probe(struct device_d *dev) +{ + struct rave_sp *sp = dev->parent->priv; + struct nvmem_config config = { 0 }; + struct rave_sp_eeprom *eeprom; + struct nvmem_device *nvmem; + u32 reg[2], size; + + if (of_property_read_u32_array(dev->device_node, + "reg", reg, ARRAY_SIZE(reg))) { + dev_err(dev, "Failed to parse \"reg\" property\n"); + return -EINVAL; + } + + size = reg[1]; + /* + * Per ICD, we have no more than 2 bytes to specify EEPROM + * page. + */ + if (size > U16_MAX * RAVE_SP_EEPROM_PAGE_SIZE) { + dev_err(dev, "Specified size is too big\n"); + return -EINVAL; + } + + eeprom = xzalloc(sizeof(*eeprom)); + eeprom->address = reg[0]; + eeprom->sp = sp; + + dev->priv = eeprom; + + if (size > SZ_8K) + eeprom->header_size = RAVE_SP_EEPROM_HEADER_BIG; + else + eeprom->header_size = RAVE_SP_EEPROM_HEADER_SMALL; + + config.name = dev_name(dev); + /* + * If a name is specified via DT, override the above with it. + */ + of_property_read_string(dev->device_node, "zii,eeprom-name", + &config.name); + config.dev = dev; + config.word_size = 1; + config.stride = 1; + config.size = reg[1]; + config.bus = &rave_sp_eeprom_nvmem_bus; + + nvmem = nvmem_register(&config); + if (IS_ERR(nvmem)) { + free(eeprom); + return PTR_ERR(nvmem); + } + + return 0; +} + +static __maybe_unused const struct of_device_id rave_sp_eeprom_of_match[] = { + { .compatible = "zii,rave-sp-eeprom" }, + {} +}; + +static struct driver_d rave_sp_eeprom_driver = { + .name = "rave-sp-eeprom", + .probe = rave_sp_eeprom_probe, + .of_compatible = DRV_OF_COMPAT(rave_sp_eeprom_of_match), +}; +console_platform_driver(rave_sp_eeprom_driver); diff --git a/drivers/usb/core/common.c b/drivers/usb/core/common.c index 690d5a39ea..bcbe3a155d 100644 --- a/drivers/usb/core/common.c +++ b/drivers/usb/core/common.c @@ -17,3 +17,15 @@ const char *usb_speed_string(enum usb_device_speed speed) return speed_names[speed]; } EXPORT_SYMBOL_GPL(usb_speed_string); + +enum usb_device_speed usb_speed_by_string(const char *string) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(speed_names); i++) + if (!strcmp(string, speed_names[i])) + return i; + + return USB_SPEED_UNKNOWN; +} +EXPORT_SYMBOL_GPL(usb_speed_by_string); diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c index fd20368424..979088ef4e 100644 --- a/drivers/usb/core/of.c +++ b/drivers/usb/core/of.c @@ -90,3 +90,27 @@ enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np, return USBPHY_INTERFACE_MODE_UNKNOWN; } EXPORT_SYMBOL_GPL(of_usb_get_phy_mode); + +/** + * of_usb_get_maximum_speed - Get maximum speed for given device_node + * @np: Pointer to the given device_node + * + * The function gets maximum speed string from property 'maximum-speed', + * and returns the correspondig enum usb_device_speed + */ +enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np, + const char *propname) +{ + const char *maximum_speed; + int err; + + if (!propname) + propname = "maximum-speed"; + + err = of_property_read_string(np, propname, &maximum_speed); + if (err < 0) + return USB_SPEED_UNKNOWN; + + return usb_speed_by_string(maximum_speed); +} +EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed); diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 505f5eb35d..3e3e6a365f 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -51,6 +51,7 @@ struct imx_chipidea { static int imx_chipidea_port_init(void *drvdata) { struct imx_chipidea *ci = drvdata; + uint32_t portsc; int ret; if ((ci->flags & MXC_EHCI_PORTSC_MASK) == MXC_EHCI_MODE_ULPI) { @@ -74,6 +75,14 @@ static int imx_chipidea_port_init(void *drvdata) if (ret) dev_err(ci->dev, "misc init failed: %s\n", strerror(-ret)); + /* PFSC bit is reset by ehci_reset(), thus have to set it not in + * probe but here, after ehci_reset() is already called */ + if (ci->flags & MXC_EHCI_PFSC) { + portsc = readl(ci->base + 0x184); + portsc |= MXC_EHCI_PFSC; + writel(portsc, ci->base + 0x184); + } + return ret; } @@ -159,6 +168,10 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci) "over-current-active-high", NULL)) ci->flags |= MXC_EHCI_OC_PIN_ACTIVE_LOW; + if (of_usb_get_maximum_speed(ci->dev->device_node, NULL) == + USB_SPEED_FULL) + ci->flags |= MXC_EHCI_PFSC; + return 0; } diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 1dcae48f80..79de32cf8e 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -124,6 +124,13 @@ config DRIVER_VIDEO_BACKLIGHT_PWM help Enable this to get support for backlight devices driven by a PWM. +config BACKLIGHT_RAVE_SP + tristate "RAVE SP Backlight driver" + depends on RAVE_SP_CORE + depends on DRIVER_VIDEO_BACKLIGHT + help + Support for backlight control on RAVE SP device. + comment "Video encoder chips" config DRIVER_VIDEO_MTL017 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 081e4463d8..01fabe8809 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -23,3 +23,5 @@ obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB) += simplefb.o obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += imx-ipu-v3/ obj-$(CONFIG_DRIVER_VIDEO_EFI_GOP) += efi_gop.o obj-$(CONFIG_DRIVER_VIDEO_FB_SSD1307) += ssd1307fb.o +obj-$(CONFIG_BACKLIGHT_RAVE_SP) += rave-sp-backlight.o + diff --git a/drivers/video/rave-sp-backlight.c b/drivers/video/rave-sp-backlight.c new file mode 100644 index 0000000000..88ec86e730 --- /dev/null +++ b/drivers/video/rave-sp-backlight.c @@ -0,0 +1,72 @@ +/* + * LCD Backlight driver for RAVE SP + * + * Copyright (C) 2018 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 (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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <malloc.h> +#include <init.h> +#include <video/backlight.h> +#include <linux/mfd/rave-sp.h> + +#define RAVE_SP_BACKLIGHT_LCD_EN BIT(7) + +static int rave_sp_backlight_set(struct backlight_device *bd, int brightness) +{ + struct rave_sp *sp = bd->dev.priv; + u8 cmd[] = { + [0] = RAVE_SP_CMD_SET_BACKLIGHT, + [1] = 0, + [2] = brightness ? RAVE_SP_BACKLIGHT_LCD_EN | brightness : 0, + [3] = 0, + [4] = 0, + }; + + return rave_sp_exec(sp, cmd, sizeof(cmd), NULL, 0); +} + +static int rave_sp_backlight_probe(struct device_d *dev) +{ + struct backlight_device *bd; + int ret; + + bd = xzalloc(sizeof(*bd)); + bd->dev.priv = dev->parent->priv; + bd->brightness_default = 50; + bd->brightness_max = 100; + bd->brightness_set = rave_sp_backlight_set; + + ret = backlight_register(bd); + if (ret) { + free(bd); + return ret; + } + + return 0; +} + +static const struct of_device_id rave_sp_backlight_of_match[] = { + { .compatible = "zii,rave-sp-backlight" }, + {} +}; + +static struct driver_d rave_sp_backlight_driver = { + .name = "rave-sp-backlight", + .probe = rave_sp_backlight_probe, + .of_compatible = DRV_OF_COMPAT(rave_sp_backlight_of_match), +}; +device_platform_driver(rave_sp_backlight_driver); diff --git a/drivers/watchdog/rave-sp-wdt.c b/drivers/watchdog/rave-sp-wdt.c index 1643167851..dc673ee35f 100644 --- a/drivers/watchdog/rave-sp-wdt.c +++ b/drivers/watchdog/rave-sp-wdt.c @@ -37,9 +37,6 @@ enum { RAVE_SP_RESET_REASON_CP_REQUEST = 13, RAVE_SP_RESET_DELAY_MS = 500, - - RAVE_SP_BOOT_SOURCE_GET = 0, - RAVE_SP_BOOT_SOURCE_SET = 1, }; /** @@ -75,7 +72,7 @@ struct rave_sp_wdt { struct restart_handler restart; unsigned int timeout; unsigned int boot_source; - struct device_d dev; + struct nvmem_cell *boot_source_cell; }; static struct rave_sp_wdt *to_rave_sp_wdt(struct watchdog *wdd) @@ -90,26 +87,6 @@ static int rave_sp_wdt_exec(struct watchdog *wdd, void *data, data, data_size, NULL, 0); } - -static int rave_sp_wdt_access_boot_source(struct rave_sp_wdt *sp_wd, u8 set_get) -{ - u8 cmd[] = { - [0] = RAVE_SP_CMD_BOOT_SOURCE, - [1] = 0, - [2] = set_get, - [3] = sp_wd->boot_source, - }; - u8 response; - int ret; - - ret = rave_sp_exec(sp_wd->sp, cmd, sizeof(cmd), &response, - sizeof(response)); - if (ret) - return ret; - - return response; -} - static int __rave_sp_wdt_rdu_reset_reason(struct watchdog *wdd, uint8_t response[], size_t response_len) @@ -278,9 +255,12 @@ static const struct of_device_id rave_sp_wdt_of_match[] = { static int rave_sp_wdt_set_boot_source(struct param_d *param, void *priv) { + struct rave_sp_wdt *sp_wd = priv; + u8 boot_source = sp_wd->boot_source; int ret; - ret = rave_sp_wdt_access_boot_source(priv, RAVE_SP_BOOT_SOURCE_SET); + ret = nvmem_cell_write(sp_wd->boot_source_cell, &boot_source, + sizeof(boot_source)); if (ret < 0) return ret; @@ -290,13 +270,38 @@ static int rave_sp_wdt_set_boot_source(struct param_d *param, void *priv) static int rave_sp_wdt_get_boot_source(struct param_d *param, void *priv) { struct rave_sp_wdt *sp_wd = priv; - int ret; + u8 *boot_source; + size_t len; - ret = rave_sp_wdt_access_boot_source(sp_wd, RAVE_SP_BOOT_SOURCE_GET); - if (ret < 0) - return ret; + boot_source = nvmem_cell_read(sp_wd->boot_source_cell, &len); + if (IS_ERR(boot_source)) + return PTR_ERR(boot_source); + + sp_wd->boot_source = *boot_source; + kfree(boot_source); + + return 0; +} + +static int rave_sp_wdt_add_params(struct rave_sp_wdt *sp_wd) +{ + struct watchdog *wdd = &sp_wd->wdd; + struct device_node *np = wdd->hwdev->device_node; + struct param_d *p; + + sp_wd->boot_source_cell = of_nvmem_cell_get(np, "boot-source"); + if (IS_ERR(sp_wd->boot_source_cell)) { + dev_warn(wdd->hwdev, "No bootsource info availible\n"); + return 0; + } + + p = dev_add_param_int(&wdd->dev, "boot_source", + rave_sp_wdt_set_boot_source, + rave_sp_wdt_get_boot_source, + &sp_wd->boot_source, "%u", sp_wd); + if (IS_ERR(p)) + return PTR_ERR(p); - sp_wd->boot_source = ret; return 0; } @@ -307,7 +312,6 @@ static int rave_sp_wdt_probe(struct device_d *dev) struct nvmem_cell *cell; struct watchdog *wdd; __le16 timeout = 60; - struct param_d *p; int ret; sp_wd = xzalloc(sizeof(*sp_wd)); @@ -344,6 +348,12 @@ static int rave_sp_wdt_probe(struct device_d *dev) return ret; } + ret = rave_sp_wdt_add_params(sp_wd); + if (ret) { + dev_err(dev, "Failed to register device parameters"); + return ret; + } + sp_wd->restart.name = "rave-sp-wdt"; sp_wd->restart.restart = rave_sp_wdt_restart_handler; sp_wd->restart.priority = 200; @@ -352,16 +362,6 @@ static int rave_sp_wdt_probe(struct device_d *dev) if (ret) dev_warn(dev, "Cannot register restart handler\n"); - - p = dev_add_param_int(&wdd->dev, "boot_source", - rave_sp_wdt_set_boot_source, - rave_sp_wdt_get_boot_source, - &sp_wd->boot_source, "%u", sp_wd); - if (IS_ERR(p)) { - unregister_device(&sp_wd->dev); - return PTR_ERR(p); - } - ret = sp_wd->variant->reset_reason(wdd); if (ret < 0) { dev_warn(dev, "Failed to query reset reason\n"); diff --git a/images/Makefile.imx b/images/Makefile.imx index 43505b1ff9..e3f3b2c8cb 100644 --- a/images/Makefile.imx +++ b/images/Makefile.imx @@ -76,6 +76,11 @@ CFG_start_imx51_babbage_xload.pblx.imximg = $(board)/freescale-mx51-babbage/flas FILE_barebox-freescale-imx51-babbage-xload.img = start_imx51_babbage_xload.pblx.imximg imx-xload-$(CONFIG_MACH_FREESCALE_MX51_PDK) += barebox-freescale-imx51-babbage-xload.img +pblx-$(CONFIG_MACH_ZII_RDU1) += start_imx51_zii_rdu1 +CFG_start_imx51_zii_rdu1.pblx.imximg = $(board)/zii-imx51-rdu1/flash-header-imx51-zii-rdu1.imxcfg +FILE_barebox-zii-imx51-rdu1.img = start_imx51_zii_rdu1.pblx.imximg +imx-barebox-$(CONFIG_MACH_ZII_RDU1) += barebox-zii-imx51-rdu1.img + ifdef CONFIG_ARCH_IMX_XLOAD image-y += $(imx-xload-y) else diff --git a/include/bbu.h b/include/bbu.h index def568e498..d1ab9f5638 100644 --- a/include/bbu.h +++ b/include/bbu.h @@ -25,6 +25,10 @@ struct bbu_handler { struct list_head list; #define BBU_HANDLER_FLAG_DEFAULT (1 << 0) #define BBU_HANDLER_CAN_REFRESH (1 << 1) + /* + * The lower 16bit are generic flags, the upper 16bit are reserved + * for handler specific flags. + */ unsigned long flags; /* default device file, can be overwritten on the command line */ diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h index 606cadb498..0ec2f05b97 100644 --- a/include/linux/nvmem-consumer.h +++ b/include/linux/nvmem-consumer.h @@ -32,6 +32,9 @@ struct nvmem_cell_info { struct nvmem_cell *nvmem_cell_get(struct device_d *dev, const char *name); void nvmem_cell_put(struct nvmem_cell *cell); void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len); +void *nvmem_cell_get_and_read(struct device_node *np, const char *cell_name, + size_t bytes); + int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len); /* direct nvmem device read/write interface */ @@ -55,6 +58,13 @@ static inline char *nvmem_cell_read(struct nvmem_cell *cell, size_t *len) return ERR_PTR(-ENOSYS); } +static inline void *nvmem_cell_get_and_read(struct device_node *np, + const char *cell_name, + size_t bytes) +{ + return ERR_PTR(-ENOSYS); +} + static inline int nvmem_cell_write(struct nvmem_cell *cell, const char *buf, size_t len) { diff --git a/include/usb/ch9.h b/include/usb/ch9.h index ab5d531925..b44d41e85f 100644 --- a/include/usb/ch9.h +++ b/include/usb/ch9.h @@ -1004,6 +1004,12 @@ struct usb_set_sel_req { */ const char *usb_speed_string(enum usb_device_speed speed); +/** + * usb_speed_by_string() - Get speed from human readable name. + * @string: The human readable name for the speed. If it is not one of known + * names, USB_SPEED_UNKNOWN will be returned. + */ +enum usb_device_speed usb_speed_by_string(const char *string); /** * usb_state_string - Returns human readable name for the state. diff --git a/include/usb/chipidea-imx.h b/include/usb/chipidea-imx.h index 640ae06944..973aee6a0e 100644 --- a/include/usb/chipidea-imx.h +++ b/include/usb/chipidea-imx.h @@ -13,6 +13,7 @@ #define MXC_EHCI_MODE_ULPI (2 << 30) #define MXC_EHCI_MODE_HSIC (1 << 25) #define MXC_EHCI_MODE_SERIAL (3 << 30) +#define MXC_EHCI_PFSC (1 << 24) /* * USB misc flags diff --git a/include/usb/usb.h b/include/usb/usb.h index 93308cec00..9aab06c87c 100644 --- a/include/usb/usb.h +++ b/include/usb/usb.h @@ -438,6 +438,9 @@ enum usb_dr_mode { enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np, const char *propname); +enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np, + const char *propname); + extern struct list_head usb_device_list; #endif /*_USB_H_ */ |