diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-12-08 14:53:59 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-12-08 14:53:59 +0100 |
commit | 86916569a811a07eb1b5a4044fc4f04aeb75383c (patch) | |
tree | 18652b7fd46eb31c2887fae90a85fb793ec75569 /arch/arm | |
parent | 1e5b933b5d2538ea0ffeb86537c3996348ef9c64 (diff) | |
parent | d91a9642518806f9320e67f5b2c8be9347602c48 (diff) | |
download | barebox-86916569a811a07eb1b5a4044fc4f04aeb75383c.tar.gz barebox-86916569a811a07eb1b5a4044fc4f04aeb75383c.tar.xz |
Merge branch 'for-next/imx'
Diffstat (limited to 'arch/arm')
53 files changed, 1447 insertions, 129 deletions
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile index fb257fbfc7..9961ca8f11 100644 --- a/arch/arm/boards/Makefile +++ b/arch/arm/boards/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_MACH_REALQ7) += datamodul-edm-qmx6/ obj-$(CONFIG_MACH_RPI) += raspberry-pi/ obj-$(CONFIG_MACH_SABRELITE) += freescale-mx6-sabrelite/ obj-$(CONFIG_MACH_SABRESD) += freescale-mx6-sabresd/ +obj-$(CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB) += freescale-mx6sx-sabresdb/ obj-$(CONFIG_MACH_SAMA5D3XEK) += sama5d3xek/ obj-$(CONFIG_MACH_SAMA5D3_XPLAINED) += sama5d3_xplained/ obj-$(CONFIG_MACH_SAMA5D4_XPLAINED) += sama5d4_xplained/ diff --git a/arch/arm/boards/ccxmx51/lowlevel.c b/arch/arm/boards/ccxmx51/lowlevel.c index 3e67b314a7..2b3dc42e87 100644 --- a/arch/arm/boards/ccxmx51/lowlevel.c +++ b/arch/arm/boards/ccxmx51/lowlevel.c @@ -1,11 +1,12 @@ #include <common.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm.h> #include <asm/barebox-arm-head.h> #include <mach/imx51-regs.h> void __naked barebox_arm_reset_vector(void) { - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); barebox_arm_entry(MX51_CSD0_BASE_ADDR, SZ_128M, NULL); } diff --git a/arch/arm/boards/efika-mx-smartbook/Makefile b/arch/arm/boards/efika-mx-smartbook/Makefile index 0ac4693890..d00e0f6ed0 100644 --- a/arch/arm/boards/efika-mx-smartbook/Makefile +++ b/arch/arm/boards/efika-mx-smartbook/Makefile @@ -2,3 +2,4 @@ obj-y += board.o flash-header-imx51-genesi-efikasb.dcd.o lwl-y += lowlevel.o extra-y += flash-header-imx51-genesi-efikasb.dcd.S extra-y += flash-header-imx51-genesi-efikasb.dcd +bbenv-y += defaultenv-efikasb diff --git a/arch/arm/boards/efika-mx-smartbook/board.c b/arch/arm/boards/efika-mx-smartbook/board.c index 59410c1ec4..99efd666f9 100644 --- a/arch/arm/boards/efika-mx-smartbook/board.c +++ b/arch/arm/boards/efika-mx-smartbook/board.c @@ -17,6 +17,7 @@ #include <bootsource.h> #include <partition.h> #include <common.h> +#include <envfs.h> #include <fcntl.h> #include <gpio.h> #include <init.h> @@ -63,16 +64,9 @@ static inline int machine_is_efikasb(void) return 1; } -static int efikamx_power_init(void) +static void efikamx_power_init(struct mc13xxx *mc) { unsigned int val; - struct mc13xxx *mc; - - mc = mc13xxx_get(); - if (!mc) { - printf("could not get mc13892\n"); - return -ENODEV; - } /* Write needed to Power Gate 2 register */ mc13xxx_reg_read(mc, MC13892_REG_POWER_MISC, &val); @@ -177,8 +171,6 @@ static int efikamx_power_init(void) mc13xxx_reg_write(mc, MC13892_REG_POWER_CTL2, val); udelay(2500); - - return 0; } static int efikamx_usb_init(void) @@ -188,6 +180,8 @@ static int efikamx_usb_init(void) barebox_set_hostname("efikasb"); + mc13xxx_register_init_callback(efikamx_power_init); + gpio_direction_output(GPIO_BLUETOOTH, 0); gpio_direction_output(GPIO_WIFI_ENABLE, 1); gpio_direction_output(GPIO_WIFI_RESET, 0); @@ -245,7 +239,7 @@ static int efikamx_late_init(void) if (!of_machine_is_compatible("genesi,imx51-sb")) return 0; - efikamx_power_init(); + defaultenv_append_directory(defaultenv_efikasb); gpio_direction_output(GPIO_BACKLIGHT_POWER, 1); diff --git a/arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/bin/lvds_init index 692392cd6c..692392cd6c 100644 --- a/arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/bin/lvds_init diff --git a/arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/hd-internal index 2233f14269..2233f14269 100644 --- a/arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/hd-internal diff --git a/arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/mmc-left index da7bc0398a..da7bc0398a 100644 --- a/arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/mmc-left diff --git a/arch/arm/boards/efika-mx-smartbook/env/config b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/config index c63c6a1fa5..c63c6a1fa5 100644 --- a/arch/arm/boards/efika-mx-smartbook/env/config +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/config diff --git a/arch/arm/boards/efika-mx-smartbook/env/init/automount b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/automount index 8cb5eaf792..8cb5eaf792 100644 --- a/arch/arm/boards/efika-mx-smartbook/env/init/automount +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/automount diff --git a/arch/arm/boards/efika-mx-smartbook/env/init/bootsource b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/bootsource index 380e85589b..380e85589b 100644 --- a/arch/arm/boards/efika-mx-smartbook/env/init/bootsource +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/bootsource diff --git a/arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/network/eth0-discover index f8368a5ec6..f8368a5ec6 100644 --- a/arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/network/eth0-discover diff --git a/arch/arm/boards/efika-mx-smartbook/lowlevel.c b/arch/arm/boards/efika-mx-smartbook/lowlevel.c index 0d32eee860..52454c7d50 100644 --- a/arch/arm/boards/efika-mx-smartbook/lowlevel.c +++ b/arch/arm/boards/efika-mx-smartbook/lowlevel.c @@ -1,5 +1,6 @@ #include <common.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> #include <mach/imx5.h> @@ -10,7 +11,7 @@ ENTRY_FUNCTION(start_imx51_genesi_efikasb, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); arm_setup_stack(0x20000000 - 16); imx51_init_lowlevel(800); diff --git a/arch/arm/boards/eukrea_cpuimx51/lowlevel.c b/arch/arm/boards/eukrea_cpuimx51/lowlevel.c index c3f7b4acbb..7a85b489d2 100644 --- a/arch/arm/boards/eukrea_cpuimx51/lowlevel.c +++ b/arch/arm/boards/eukrea_cpuimx51/lowlevel.c @@ -1,9 +1,10 @@ #include <common.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm-head.h> void __naked barebox_arm_reset_vector(void) { - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); imx51_barebox_entry(NULL); } diff --git a/arch/arm/boards/freescale-mx51-babbage/lowlevel.c b/arch/arm/boards/freescale-mx51-babbage/lowlevel.c index 5a5a83c436..1b9ba16ef6 100644 --- a/arch/arm/boards/freescale-mx51-babbage/lowlevel.c +++ b/arch/arm/boards/freescale-mx51-babbage/lowlevel.c @@ -1,5 +1,6 @@ #include <common.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> @@ -9,7 +10,7 @@ ENTRY_FUNCTION(start_imx51_babbage, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); fdt = __dtb_imx51_babbage_start - get_runtime_offset(); diff --git a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c index 7d1c1d5b2a..aff6e3bc54 100644 --- a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c +++ b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c @@ -1,5 +1,6 @@ #include <common.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> #include <image-metadata.h> @@ -10,7 +11,7 @@ ENTRY_FUNCTION(start_imx53_loco, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); fdt = __dtb_imx53_qsb_start - get_runtime_offset(); @@ -23,7 +24,7 @@ ENTRY_FUNCTION(start_imx53_loco_r, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); fdt = __dtb_imx53_qsrb_start - get_runtime_offset(); diff --git a/arch/arm/boards/freescale-mx53-smd/lowlevel.c b/arch/arm/boards/freescale-mx53-smd/lowlevel.c index 1db07e2e2c..306db09acf 100644 --- a/arch/arm/boards/freescale-mx53-smd/lowlevel.c +++ b/arch/arm/boards/freescale-mx53-smd/lowlevel.c @@ -1,9 +1,10 @@ #include <common.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm-head.h> void __naked barebox_arm_reset_vector(void) { - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); imx53_barebox_entry(NULL); } diff --git a/arch/arm/boards/freescale-mx53-vmx53/lowlevel.c b/arch/arm/boards/freescale-mx53-vmx53/lowlevel.c index 4054fd51e2..487a9fd899 100644 --- a/arch/arm/boards/freescale-mx53-vmx53/lowlevel.c +++ b/arch/arm/boards/freescale-mx53-vmx53/lowlevel.c @@ -1,5 +1,6 @@ #include <common.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> @@ -9,7 +10,7 @@ ENTRY_FUNCTION(start_imx53_vmx53, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); fdt = __dtb_imx53_voipac_bsb_start - get_runtime_offset(); diff --git a/arch/arm/boards/freescale-mx6sx-sabresdb/Makefile b/arch/arm/boards/freescale-mx6sx-sabresdb/Makefile new file mode 100644 index 0000000000..cc4078f7b4 --- /dev/null +++ b/arch/arm/boards/freescale-mx6sx-sabresdb/Makefile @@ -0,0 +1,3 @@ +obj-y += board.o flash-header-mx6sx-sabresdb.dcd.o +extra-y += flash-header-mx6sx-sabresdb.dcd.S flash-header-mx6sx-sabresdb.dcd +lwl-y += lowlevel.o diff --git a/arch/arm/boards/freescale-mx6sx-sabresdb/board.c b/arch/arm/boards/freescale-mx6sx-sabresdb/board.c new file mode 100644 index 0000000000..c21b43dc56 --- /dev/null +++ b/arch/arm/boards/freescale-mx6sx-sabresdb/board.c @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2014 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. + */ +#define pr_fmt(fmt) "imx6sx-sdb: " fmt + +#include <environment.h> +#include <partition.h> +#include <common.h> +#include <sizes.h> +#include <gpio.h> +#include <init.h> +#include <io.h> +#include <mfd/imx6q-iomuxc-gpr.h> +#include <generated/mach-types.h> +#include <linux/clk.h> +#include <i2c/i2c.h> + +#include <asm/armlinux.h> + +#include <mach/devices-imx6.h> +#include <mach/imx6-regs.h> +#include <mach/iomux-mx6.h> +#include <mach/generic.h> +#include <mach/imx6.h> +#include <mach/bbu.h> + +#define PFUZE100_DEVICEID 0x0 +#define PFUZE100_REVID 0x3 +#define PFUZE100_FABID 0x4 + +#define PFUZE100_SW1ABVOL 0x20 +#define PFUZE100_SW1ABSTBY 0x21 +#define PFUZE100_SW1ABCONF 0x24 +#define PFUZE100_SW1CVOL 0x2e +#define PFUZE100_SW1CSTBY 0x2f +#define PFUZE100_SW1CCONF 0x32 +#define PFUZE100_SW1ABC_SETP(x) ((x - 3000) / 250) +#define PFUZE100_VGEN5CTL 0x70 + +/* set all switches APS in normal and PFM mode in standby */ +static int imx6sx_sdb_setup_pmic_mode(struct i2c_client *client, int chip) +{ + unsigned char offset, i, switch_num, value; + + if (!chip) { + /* pfuze100 */ + switch_num = 6; + offset = 0x31; + } else { + /* pfuze200 */ + switch_num = 4; + offset = 0x38; + } + + value = 0xc; + if (i2c_write_reg(client, 0x23, &value, 1) < 0) + return -EIO; + + for (i = 0; i < switch_num - 1; i++) + if (i2c_write_reg(client, offset + i * 7, &value, 1) < 0) + return -EIO; + + return 0; +} + +static int imx6sx_sdb_setup_pmic_voltages(void) +{ + unsigned char value, rev_id = 0; + struct i2c_adapter *adapter = NULL; + struct i2c_client client; + int addr = -1, bus = 0; + + if (!of_machine_is_compatible("fsl,imx6sx-sdb")) + return 0; + + /* I2C2 bus (2-1 = 1 in barebox numbering) */ + bus = 0; + + /* PFUZE100 device address is 0x08 */ + addr = 0x08; + + adapter = i2c_get_adapter(bus); + if (!adapter) + return -ENODEV; + + client.adapter = adapter; + client.addr = addr; + + if (i2c_read_reg(&client, PFUZE100_DEVICEID, &value, 1) < 0) + goto err_out; + if (i2c_read_reg(&client, PFUZE100_REVID, &rev_id, 1) < 0) + goto err_out; + + pr_info("Found PFUZE100! deviceid 0x%x, revid 0x%x\n", value, rev_id); + + if (imx6sx_sdb_setup_pmic_mode(&client, value & 0xf)) + goto err_out; + + /* set SW1AB standby volatage 0.975V */ + if (i2c_read_reg(&client, PFUZE100_SW1ABSTBY, &value, 1) < 0) + goto err_out; + + value &= ~0x3f; + value |= PFUZE100_SW1ABC_SETP(9750); + if (i2c_write_reg(&client, PFUZE100_SW1ABSTBY, &value, 1) < 0) + goto err_out; + + /* set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */ + if (i2c_read_reg(&client, PFUZE100_SW1ABCONF, &value, 1) < 0) + goto err_out; + + value &= ~0xc0; + value |= 0x40; + if (i2c_write_reg(&client, PFUZE100_SW1ABCONF, &value, 1) < 0) + goto err_out; + + + /* set SW1C standby volatage 0.975V */ + if (i2c_read_reg(&client, PFUZE100_SW1CSTBY, &value, 1) < 0) + goto err_out; + + value &= ~0x3f; + value |= PFUZE100_SW1ABC_SETP(9750); + if (i2c_write_reg(&client, PFUZE100_SW1CSTBY, &value, 1) < 0) + goto err_out; + + + /* set SW1C/VDDSOC step ramp up time to from 16us to 4us/25mV */ + if (i2c_read_reg(&client, PFUZE100_SW1CCONF, &value, 1) < 0) + goto err_out; + + value &= ~0xc0; + value |= 0x40; + if (i2c_write_reg(&client, PFUZE100_SW1CCONF, &value, 1) < 0) + goto err_out; + + /* Enable power of VGEN5 3V3, needed for SD3 */ + if (i2c_read_reg(&client, PFUZE100_VGEN5CTL, &value, 1) < 0) + goto err_out; + + value &= ~0x1F; + value |= 0x1F; + if (i2c_write_reg(&client, PFUZE100_VGEN5CTL, &value, 1) < 0) + goto err_out; + + return 0; + +err_out: + pr_err("Setting up PMIC failed\n"); + + return -EIO; +} +fs_initcall(imx6sx_sdb_setup_pmic_voltages); + +int ar8031_phy_fixup(struct phy_device *phydev) +{ + /* + * Enable 1.8V(SEL_1P5_1P8_POS_REG) on + * Phy control debug reg 0 + */ + phy_write(phydev, 0x1d, 0x1f); + phy_write(phydev, 0x1e, 0x8); + + /* rgmii tx clock delay enable */ + phy_write(phydev, 0x1d, 0x05); + phy_write(phydev, 0x1e, 0x100); + + return 0; +} + +#define PHY_ID_AR8031 0x004dd074 +#define AR_PHY_ID_MASK 0xffffffff + +static int imx6sx_sdb_setup_fec(void) +{ + void __iomem *gprbase = (void *)MX6_IOMUXC_BASE_ADDR + 0x4000; + uint32_t val; + struct clk *clk; + + phy_register_fixup_for_uid(PHY_ID_AR8031, AR_PHY_ID_MASK, + ar8031_phy_fixup); + + /* Active high for ncp692 */ + gpio_direction_output(IMX_GPIO_NR(4, 16), 1); + + clk = clk_lookup("enet_ptp_25m"); + if (IS_ERR(clk)) + goto err; + + clk_enable(clk); + + clk = clk_lookup("enet_ref"); + if (IS_ERR(clk)) + goto err; + clk_enable(clk); + + clk = clk_lookup("enet2_ref_125m"); + if (IS_ERR(clk)) + goto err; + + clk_enable(clk); + + val = readl(gprbase + IOMUXC_GPR1); + /* Use 125M anatop loopback REF_CLK1 for ENET1, clear gpr1[13], gpr1[17]*/ + val &= ~(1 << 13); + val &= ~(1 << 17); + /* Use 125M anatop loopback REF_CLK1 for ENET2, clear gpr1[14], gpr1[18]*/ + val &= ~(1 << 14); + val &= ~(1 << 18); + writel(val, gprbase + IOMUXC_GPR1); + + /* Enable the ENET power, active low */ + gpio_direction_output(IMX_GPIO_NR(2, 6), 0); + + /* Reset AR8031 PHY */ + gpio_direction_output(IMX_GPIO_NR(2, 7), 0); + udelay(500); + gpio_set_value(IMX_GPIO_NR(2, 7), 1); + + return 0; +err: + pr_err("Setting up DFEC\n"); + + return -EIO; +} + +static int imx6sx_sdb_coredevices_init(void) +{ + if (!of_machine_is_compatible("fsl,imx6sx-sdb")) + return 0; + + imx6sx_sdb_setup_fec(); + + imx6_bbu_internal_mmc_register_handler("sd", "/dev/mmc3", + BBU_HANDLER_FLAG_DEFAULT); + + return 0; +} +console_initcall(imx6sx_sdb_coredevices_init); diff --git a/arch/arm/boards/freescale-mx6sx-sabresdb/flash-header-mx6sx-sabresdb.imxcfg b/arch/arm/boards/freescale-mx6sx-sabresdb/flash-header-mx6sx-sabresdb.imxcfg new file mode 100644 index 0000000000..a96b3e7154 --- /dev/null +++ b/arch/arm/boards/freescale-mx6sx-sabresdb/flash-header-mx6sx-sabresdb.imxcfg @@ -0,0 +1,75 @@ +loadaddr 0x80000000 +soc imx6 +dcdofs 0x400 + +wm 32 0x020c4068 0xffffffff +wm 32 0x020c406c 0xffffffff +wm 32 0x020c4070 0xffffffff +wm 32 0x020c4074 0xffffffff +wm 32 0x020c4078 0xffffffff +wm 32 0x020c407c 0xffffffff +wm 32 0x020c4080 0xffffffff +wm 32 0x020c4084 0xffffffff + +wm 32 0x020e0618 0x000c0000 +wm 32 0x020e05fc 0x00000000 +wm 32 0x020e032c 0x00000030 + +wm 32 0x020e0300 0x00000030 +wm 32 0x020e02fc 0x00000030 +wm 32 0x020e05f4 0x00000030 +wm 32 0x020e0340 0x00000030 + +wm 32 0x020e0320 0x00000000 +wm 32 0x020e0310 0x00000030 +wm 32 0x020e0314 0x00000030 +wm 32 0x020e0614 0x00000030 +wm 32 0x020e05f8 0x00020000 +wm 32 0x020e0330 0x00000030 +wm 32 0x020e0334 0x00000030 +wm 32 0x020e0338 0x00000030 +wm 32 0x020e033c 0x00000030 +wm 32 0x020e0608 0x00020000 +wm 32 0x020e060c 0x00000030 +wm 32 0x020e0610 0x00000030 +wm 32 0x020e061c 0x00000030 +wm 32 0x020e0620 0x00000030 +wm 32 0x020e02ec 0x00000030 +wm 32 0x020e02f0 0x00000030 +wm 32 0x020e02f4 0x00000030 +wm 32 0x020e02f8 0x00000030 +wm 32 0x021b0800 0xa1390003 +wm 32 0x021b080c 0x00270025 +wm 32 0x021b0810 0x001b001e +wm 32 0x021b083c 0x4144013c +wm 32 0x021b0840 0x01300128 +wm 32 0x021b0848 0x4044464a +wm 32 0x021b0850 0x3a383c34 +wm 32 0x021b081c 0x33333333 +wm 32 0x021b0820 0x33333333 +wm 32 0x021b0824 0x33333333 +wm 32 0x021b0828 0x33333333 +wm 32 0x021b08b8 0x00000800 +wm 32 0x021b0004 0x0002002d +wm 32 0x021b0008 0x00333030 +wm 32 0x021b000c 0x676b52f3 +wm 32 0x021b0010 0xb66d8b63 +wm 32 0x021b0014 0x01ff00db +wm 32 0x021b0018 0x00011740 +wm 32 0x021b001c 0x00008000 +wm 32 0x021b002c 0x000026d2 +wm 32 0x021b0030 0x006b1023 +wm 32 0x021b0040 0x0000005f +wm 32 0x021b0000 0x84190000 +wm 32 0x021b001c 0x04008032 +wm 32 0x021b001c 0x00008033 +wm 32 0x021b001c 0x00068031 +wm 32 0x021b001c 0x05208030 +wm 32 0x021b001c 0x04008040 +wm 32 0x021b0020 0x00000800 +wm 32 0x021b0818 0x00011117 +wm 32 0x021b001c 0x00000000 +wm 32 0x021b083c 0x41400138 +wm 32 0x021b0840 0x012c011c +wm 32 0x021b0848 0x3c3c4044 +wm 32 0x021b0850 0x34343638 diff --git a/arch/arm/boards/freescale-mx6sx-sabresdb/lowlevel.c b/arch/arm/boards/freescale-mx6sx-sabresdb/lowlevel.c new file mode 100644 index 0000000000..33f3700288 --- /dev/null +++ b/arch/arm/boards/freescale-mx6sx-sabresdb/lowlevel.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2014 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 <debug_ll.h> +#include <common.h> +#include <sizes.h> +#include <mach/generic.h> +#include <asm/barebox-arm-head.h> +#include <asm/barebox-arm.h> + +static inline void setup_uart(void) +{ + void __iomem *ccmbase = (void *)MX6_CCM_BASE_ADDR; + void __iomem *uartbase = (void *)MX6_UART1_BASE_ADDR; + void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR; + + writel(0xffffffff, ccmbase + 0x68); + writel(0xffffffff, ccmbase + 0x6c); + writel(0xffffffff, ccmbase + 0x70); + writel(0xffffffff, ccmbase + 0x74); + writel(0xffffffff, ccmbase + 0x78); + writel(0xffffffff, ccmbase + 0x7c); + writel(0xffffffff, ccmbase + 0x80); + + writel(0x0, iomuxbase + 0x24); + writel(0x1b0b1, iomuxbase + 0x036C); + writel(0x0, iomuxbase + 0x28); + writel(0x1b0b1, iomuxbase + 0x0370); + + writel(0x00000000, uartbase + 0x80); + writel(0x00004027, uartbase + 0x84); + writel(0x00000784, uartbase + 0x88); + writel(0x00000a81, uartbase + 0x90); + writel(0x0000002b, uartbase + 0x9c); + writel(0x0001b0b0, uartbase + 0xb0); + writel(0x0000047f, uartbase + 0xa4); + writel(0x0000c34f, uartbase + 0xa8); + writel(0x00000001, uartbase + 0x80); + + putc_ll('>'); +} + +extern char __dtb_imx6sx_sdb_start[]; + +ENTRY_FUNCTION(start_imx6sx_sabresdb, r0, r1, r2) +{ + void *fdt; + + imx6_cpu_lowlevel_init(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) + setup_uart(); + + fdt = __dtb_imx6sx_sdb_start - get_runtime_offset(); + + barebox_arm_entry(0x80000000, SZ_1G, fdt); +} diff --git a/arch/arm/boards/guf-vincell/lowlevel.c b/arch/arm/boards/guf-vincell/lowlevel.c index 186c0d9dd0..00e34fba39 100644 --- a/arch/arm/boards/guf-vincell/lowlevel.c +++ b/arch/arm/boards/guf-vincell/lowlevel.c @@ -6,6 +6,7 @@ #include <mach/iomux-v3.h> #include <mach/esdctl-v4.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm.h> #include <asm/barebox-arm-head.h> #include <io.h> @@ -127,7 +128,7 @@ void __bare_init __naked barebox_arm_reset_vector(void) { u32 r; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); /* Skip SDRAM initialization if we run from RAM */ r = get_pc(); diff --git a/arch/arm/boards/karo-tx51/lowlevel.c b/arch/arm/boards/karo-tx51/lowlevel.c index c3f7b4acbb..7a85b489d2 100644 --- a/arch/arm/boards/karo-tx51/lowlevel.c +++ b/arch/arm/boards/karo-tx51/lowlevel.c @@ -1,9 +1,10 @@ #include <common.h> #include <mach/esdctl.h> +#include <mach/generic.h> #include <asm/barebox-arm-head.h> void __naked barebox_arm_reset_vector(void) { - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); imx51_barebox_entry(NULL); } diff --git a/arch/arm/boards/karo-tx53/lowlevel.c b/arch/arm/boards/karo-tx53/lowlevel.c index d82e6669b0..8adbd8d666 100644 --- a/arch/arm/boards/karo-tx53/lowlevel.c +++ b/arch/arm/boards/karo-tx53/lowlevel.c @@ -3,10 +3,11 @@ #include <asm/barebox-arm.h> #include <mach/imx5.h> #include <mach/esdctl.h> +#include <mach/generic.h> void __naked barebox_arm_reset_vector(void) { - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); /* * For the TX53 rev 8030 the SDRAM setup is not stable without diff --git a/arch/arm/boards/phytec-phyflex-imx6/board.c b/arch/arm/boards/phytec-phyflex-imx6/board.c index 09a5c79a9a..1551460393 100644 --- a/arch/arm/boards/phytec-phyflex-imx6/board.c +++ b/arch/arm/boards/phytec-phyflex-imx6/board.c @@ -63,13 +63,6 @@ static void phyflex_err006282_workaround(void) gpio_direction_input(MX6_PHYFLEX_ERR006282); } -static int ksz9031rn_phy_fixup(struct phy_device *dev) -{ - phy_write_mmd_indirect(dev, 8, 2, 0x039F); - - return 0; -} - static int phytec_pfla02_init(void) { if (!of_machine_is_compatible("phytec,imx6q-pfla02") && @@ -79,9 +72,6 @@ static int phytec_pfla02_init(void) phyflex_err006282_workaround(); - phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK, - ksz9031rn_phy_fixup); - imx6_bbu_nand_register_handler("nand", BBU_HANDLER_FLAG_DEFAULT); switch (bootsource_get()) { diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c index 84014d772a..ce168b2cca 100644 --- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c +++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c @@ -54,16 +54,16 @@ static inline void setup_uart(void) putc_ll('>'); } -extern char __dtb_imx6q_phytec_pbab01_start[]; -extern char __dtb_imx6dl_phytec_pbab01_start[]; -extern char __dtb_imx6s_phytec_pbab01_start[]; +#define SZ_4G 0xEFFFFFF8 -BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_512M, IMD_TYPE_PARAMETER, "memsize=512", 0); -BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0); -BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_2G, IMD_TYPE_PARAMETER, "memsize=2048", 0); -BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_4G, IMD_TYPE_PARAMETER, "memsize=4096", 0); +BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_SZ_512M, IMD_TYPE_PARAMETER, "memsize=512", 0); +BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_SZ_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0); +BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_SZ_2G, IMD_TYPE_PARAMETER, "memsize=2048", 0); +BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_SZ_4G, IMD_TYPE_PARAMETER, "memsize=4096", 0); -static void __noreturn start_imx6q_phytec_pbab01_common(uint32_t size) +static void __noreturn start_imx6_phytec_common(uint32_t size, + bool do_early_uart_config, + void *fdt_blob_fixed_offset) { void *fdt; @@ -71,67 +71,28 @@ static void __noreturn start_imx6q_phytec_pbab01_common(uint32_t size) arm_setup_stack(0x00920000 - 8); - if (IS_ENABLED(CONFIG_DEBUG_LL)) + if (do_early_uart_config && IS_ENABLED(CONFIG_DEBUG_LL)) setup_uart(); - fdt = __dtb_imx6q_phytec_pbab01_start - get_runtime_offset(); - - barebox_arm_entry(0x10000000, size, fdt); -} - - -static void __noreturn start_imx6dl_phytec_pbab01_common(uint32_t size) -{ - void *fdt; - - imx6_cpu_lowlevel_init(); - - arm_setup_stack(0x00920000 - 8); - - fdt = __dtb_imx6dl_phytec_pbab01_start - get_runtime_offset(); - + fdt = fdt_blob_fixed_offset - get_runtime_offset(); barebox_arm_entry(0x10000000, size, fdt); } -ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2) -{ - IMD_USED(phyflex_mx6_memsize_1G); - - start_imx6q_phytec_pbab01_common(SZ_1G); -} - -ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2) -{ - IMD_USED(phyflex_mx6_memsize_2G); - - start_imx6q_phytec_pbab01_common(SZ_2G); -} - -ENTRY_FUNCTION(start_phytec_pbab01_4gib, r0, r1, r2) -{ - IMD_USED(phyflex_mx6_memsize_4G); - - start_imx6q_phytec_pbab01_common(0xEFFFFFF8); -} - -ENTRY_FUNCTION(start_phytec_pbab01dl_1gib, r0, r1, r2) -{ - IMD_USED(phyflex_mx6_memsize_1G); - - start_imx6dl_phytec_pbab01_common(SZ_1G); -} - -ENTRY_FUNCTION(start_phytec_pbab01s_512mb, r0, r1, r2) -{ - void *fdt; - - imx6_cpu_lowlevel_init(); - - arm_setup_stack(0x00920000 - 8); - - IMD_USED(phyflex_mx6_memsize_512M); - - fdt = __dtb_imx6s_phytec_pbab01_start - get_runtime_offset(); - - barebox_arm_entry(0x10000000, SZ_512M, fdt); -} +#define PHYTEC_ENTRY(name, fdt_name, memory_size, do_early_uart_config) \ + ENTRY_FUNCTION(name, r0, r1, r2) \ + { \ + extern char __dtb_##fdt_name##_start[]; \ + \ + IMD_USED(phyflex_mx6_memsize_##memory_size); \ + \ + start_imx6_phytec_common(memory_size, do_early_uart_config, \ + __dtb_##fdt_name##_start); \ + } + +PHYTEC_ENTRY(start_phytec_pbab01_1gib, imx6q_phytec_pbab01, SZ_1G, true); +PHYTEC_ENTRY(start_phytec_pbab01_2gib, imx6q_phytec_pbab01, SZ_2G, true); +PHYTEC_ENTRY(start_phytec_pbab01_4gib, imx6q_phytec_pbab01, SZ_4G, true); +PHYTEC_ENTRY(start_phytec_pbab01dl_1gib, imx6dl_phytec_pbab01, SZ_1G, false); +PHYTEC_ENTRY(start_phytec_pbab01s_512mb, imx6s_phytec_pbab01, SZ_512M, false); +PHYTEC_ENTRY(start_phytec_phyboard_alcor_1gib, imx6q_phytec_phyboard_alcor, SZ_1G, false); +PHYTEC_ENTRY(start_phytec_phyboard_subra_512mb, imx6dl_phytec_phyboard_subra, SZ_512M, false); diff --git a/arch/arm/boards/tqma53/lowlevel.c b/arch/arm/boards/tqma53/lowlevel.c index cd87212555..4e129e49f6 100644 --- a/arch/arm/boards/tqma53/lowlevel.c +++ b/arch/arm/boards/tqma53/lowlevel.c @@ -5,6 +5,7 @@ #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> #include <mach/imx5.h> +#include <mach/generic.h> #include <image-metadata.h> extern char __dtb_imx53_mba53_start[]; @@ -41,7 +42,7 @@ ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); arm_setup_stack(0xf8020000 - 8); @@ -60,7 +61,7 @@ ENTRY_FUNCTION(start_imx53_mba53_1gib, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); arm_setup_stack(0xf8020000 - 8); diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig index 2c8eb856cf..755217f062 100644 --- a/arch/arm/configs/imx_v7_defconfig +++ b/arch/arm/configs/imx_v7_defconfig @@ -13,8 +13,10 @@ CONFIG_MACH_GUF_SANTARO=y CONFIG_MACH_REALQ7=y CONFIG_MACH_GK802=y CONFIG_MACH_TQMA6X=y +CONFIG_MACH_TX6X=y CONFIG_MACH_SABRELITE=y CONFIG_MACH_SABRESD=y +CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB=y CONFIG_MACH_NITROGEN6X=y CONFIG_MACH_SOLIDRUN_MICROSOM=y CONFIG_MACH_EMBEST_RIOTBOARD=y @@ -42,10 +44,13 @@ CONFIG_CONSOLE_ACTIVATE_NONE=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_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y CONFIG_CMD_BOOTM_INITRD=y @@ -56,6 +61,7 @@ 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 @@ -94,6 +100,7 @@ CONFIG_CMD_I2C=y CONFIG_CMD_LED=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 @@ -107,12 +114,11 @@ CONFIG_OFDEVICE=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_I2C=y -CONFIG_I2C_IMX=y CONFIG_MTD=y CONFIG_MTD_RAW_DEVICE=y CONFIG_MTD_DATAFLASH=y @@ -136,6 +142,8 @@ 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 @@ -161,6 +169,8 @@ CONFIG_PWM=y CONFIG_PWM_IMX=y CONFIG_MXS_APBH_DMA=y CONFIG_GPIO_STMPE=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED=y CONFIG_FS_EXT4=y CONFIG_FS_TFTP=y CONFIG_FS_NFS=y diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index d8160feb3b..9981073c40 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -28,13 +28,14 @@ pbl-dtb-$(CONFIG_MACH_PCAAXL3) += imx6q-phytec-pbaa03.dtb.o pbl-dtb-$(CONFIG_MACH_PCM038) += imx27-phytec-phycore-rdk.dtb.o pbl-dtb-$(CONFIG_MACH_PCM051) += am335x-phytec-phycore-som.dtb.o am335x-phytec-phycore-som-no-spi.dtb.o am335x-phytec-phycore-som-mlo.dtb.o pbl-dtb-$(CONFIG_MACH_PFLA03) += am335x-phytec-phyflex.dtb.o -pbl-dtb-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o +pbl-dtb-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o imx6q-phytec-phyboard-alcor.dtb.o imx6dl-phytec-phyboard-subra.dtb.o pbl-dtb-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3) += armada-xp-openblocks-ax3-4-bb.dtb.o pbl-dtb-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_A6) += kirkwood-openblocks_a6-bb.dtb.o pbl-dtb-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o pbl-dtb-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o pbl-dtb-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o pbl-dtb-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o +pbl-dtb-$(CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB) += imx6sx-sdb.dtb.o pbl-dtb-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += socfpga_cyclone5_socrates.dtb.o pbl-dtb-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += socfpga_cyclone5_sockit.dtb.o pbl-dtb-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o diff --git a/arch/arm/dts/imx51-genesi-efika-sb.dts b/arch/arm/dts/imx51-genesi-efika-sb.dts index 6d6ab81603..26829d14c0 100644 --- a/arch/arm/dts/imx51-genesi-efika-sb.dts +++ b/arch/arm/dts/imx51-genesi-efika-sb.dts @@ -10,6 +10,7 @@ */ /dts-v1/; +#include "imx51.dtsi" #include <arm/imx51.dtsi> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/interrupt-controller/irq.h> diff --git a/arch/arm/dts/imx51.dtsi b/arch/arm/dts/imx51.dtsi new file mode 100644 index 0000000000..828a6c2e1b --- /dev/null +++ b/arch/arm/dts/imx51.dtsi @@ -0,0 +1,6 @@ +/{ + aliases { + pwm0 = &pwm1; + pwm1 = &pwm2; + }; +}; diff --git a/arch/arm/dts/imx6dl-phytec-phyboard-subra.dts b/arch/arm/dts/imx6dl-phytec-phyboard-subra.dts new file mode 100644 index 0000000000..34e414413c --- /dev/null +++ b/arch/arm/dts/imx6dl-phytec-phyboard-subra.dts @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Christian Hemp <c.hemp@phytec.de>, PHYTEC Messtechnik GmbH + * + * 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 + */ + +/dts-v1/; +#include "imx6s-phytec-pfla02.dtsi" + +/ { + model = "Phytec phyBOARD SUBRA"; + compatible = "phytec,imx6dl-pbab05", "phytec,imx6s-pfla02", "fsl,imx6dl"; + + chosen { + stdout-path = &uart4; + }; +}; + +&fec { + status = "okay"; +}; + +&uart4 { + status = "okay"; +}; + +&usdhc3 { + status = "okay"; +}; diff --git a/arch/arm/dts/imx6q-guf-santaro.dts b/arch/arm/dts/imx6q-guf-santaro.dts index db93a4881a..e4dc856bc2 100644 --- a/arch/arm/dts/imx6q-guf-santaro.dts +++ b/arch/arm/dts/imx6q-guf-santaro.dts @@ -28,7 +28,7 @@ environment-emmc { compatible = "barebox,environment"; - device-path = &usdhc2, "partname:barebox-environment"; + device-path = &usdhc4, "partname:boot1"; }; }; @@ -41,7 +41,7 @@ enable-active-high; }; - backlight { + backlight: backlight { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_backlight>; compatible = "pwm-backlight"; @@ -51,6 +51,24 @@ power-supply = <®_backlight>; status = "okay"; }; + + phyclk: phyclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + panel { + compatible = "unknown,the-display-on-the-garz-fricke-santaro"; + backlight = <&backlight>; + enable-gpios = <&gpio5 21 GPIO_ACTIVE_LOW>; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; }; &fec { @@ -58,6 +76,9 @@ pinctrl-0 = <&pinctrl_enet>; phy-mode = "rmii"; status = "okay"; + clocks = <&clks IMX6QDL_CLK_ENET>, + <&clks IMX6QDL_CLK_ENET>, + <&phyclk>; }; &i2c1 { @@ -195,7 +216,7 @@ status = "okay"; polytouch: edt-ft5x06@38 { - compatible = "edt,edt-ft5x06"; + compatible = "edt,edt-ft5206"; reg = <0x38>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_touch>; @@ -510,6 +531,13 @@ vsync-active = <1>; }; }; + + port@4 { + reg = <4>; + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; }; }; @@ -549,8 +577,8 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; bus-width = <4>; - cd-gpios = <&gpio2 2 0>; - wp-gpios = <&gpio2 3 0>; + cd-gpios = <&gpio1 4 0>; + wp-gpios = <&gpio1 2 0>; status = "okay"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/dts/imx6q-phytec-phyboard-alcor.dts b/arch/arm/dts/imx6q-phytec-phyboard-alcor.dts new file mode 100644 index 0000000000..a60fc186e2 --- /dev/null +++ b/arch/arm/dts/imx6q-phytec-phyboard-alcor.dts @@ -0,0 +1,38 @@ +/* + * Copyright 2014 Christian Hemp <c.hemp@phytec.de>, PHYTEC Messtechnik GmbH + * + * 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 + */ + +/dts-v1/; +#include "imx6q-phytec-pfla02.dtsi" + +/ { + model = "Phytec phyBOARD ALCOR"; + compatible = "phytec,imx6q-pbab02", "phytec,imx6q-pfla02", "fsl,imx6q"; + + chosen { + stdout-path = &uart4; + }; +}; + +ðphy { + max-speed = <100>; +}; + +&fec { + status = "okay"; +}; + +&uart4 { + status = "okay"; +}; + +&usdhc3 { + status = "okay"; +}; diff --git a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi index 5c7bcee7f7..32ce088fee 100644 --- a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi +++ b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi @@ -62,9 +62,22 @@ &fec { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet>; + phy-handle = <ðphy>; phy-mode = "rgmii"; phy-reset-gpios = <&gpio3 23 0>; status = "disabled"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy: ethernet-phy@3 { + reg = <3>; + + txc-skew-ps = <1680>; + rxc-skew-ps = <1860>; + }; + }; }; &gpmi { diff --git a/arch/arm/dts/imx6sx-sdb.dts b/arch/arm/dts/imx6sx-sdb.dts new file mode 100644 index 0000000000..fbf098bbe6 --- /dev/null +++ b/arch/arm/dts/imx6sx-sdb.dts @@ -0,0 +1,92 @@ +/* + * 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/imx6sx-sdb.dts> +#include "imx6sx.dtsi" + +/ { + chosen { + environment@0 { + compatible = "barebox,environment"; + device-path = &usdhc4, "partname:barebox-environment"; + }; + }; +}; + +&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>; +}; + +&usdhc4 { + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox-environment"; + reg = <0x80000 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/dts/imx6sx.dtsi b/arch/arm/dts/imx6sx.dtsi new file mode 100644 index 0000000000..5a8ee46446 --- /dev/null +++ b/arch/arm/dts/imx6sx.dtsi @@ -0,0 +1,12 @@ +/ { + aliases { + pwm0 = &pwm1; + pwm1 = &pwm2; + pwm2 = &pwm3; + pwm3 = &pwm4; + pwm4 = &pwm5; + pwm5 = &pwm6; + pwm6 = &pwm7; + pwm7 = &pwm8; + }; +}; diff --git a/arch/arm/include/asm/errata.h b/arch/arm/include/asm/errata.h index e2ffd87360..9525823e4c 100644 --- a/arch/arm/include/asm/errata.h +++ b/arch/arm/include/asm/errata.h @@ -12,6 +12,18 @@ * GNU General Public License for more details. */ +static inline void enable_arm_errata_709718_war(void) +{ + __asm__ __volatile__ ( + "mrc p15, 0, r0, c10, c2, 0\n" + "bic r0, #3 << 16\n" + "mcr p15, 0, r0, c10, c2, 0\n" + "mrc p15, 0, r0, c1, c0, 0\n" + "orr r0, r0, #1 << 28\n" + "mcr p15, 0, r0, c1, c0, 0\n" + ); +} + static inline void enable_arm_errata_716044_war(void) { __asm__ __volatile__ ( diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 53d91bc070..a931de921e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -102,11 +102,13 @@ endchoice config ARCH_IMX_EXTERNAL_BOOT_NAND bool + depends on MTD depends on ARCH_IMX25 || ARCH_IMX27 || ARCH_IMX31 || ARCH_IMX35 prompt "Support Starting barebox from NAND in external bootmode" config BAREBOX_UPDATE_IMX_EXTERNAL_NAND bool + depends on MTD depends on ARCH_IMX_EXTERNAL_BOOT_NAND depends on BAREBOX_UPDATE depends on MTD @@ -115,6 +117,7 @@ config BAREBOX_UPDATE_IMX_EXTERNAL_NAND config BAREBOX_UPDATE_IMX6_NAND bool + depends on MTD depends on ARCH_IMX6 depends on BAREBOX_UPDATE depends on MTD @@ -174,6 +177,11 @@ config ARCH_IMX6 select CPU_V7 select PINCTRL_IMX_IOMUX_V3 +config ARCH_IMX6SX + bool + select ARCH_IMX6 + select COMMON_CLK_OF_PROVIDER + config IMX_MULTI_BOARDS bool "Allow multiple boards to be selected" select HAVE_DEFAULT_ENVIRONMENT_NEW @@ -293,6 +301,12 @@ config MACH_SABRESD bool "Freescale i.MX6 SabreSD" select ARCH_IMX6 +config MACH_FREESCALE_IMX6SX_SABRESDB + bool "Freescale i.MX6sx SabreSDB" + select ARCH_IMX6SX + select I2C + select I2C_IMX + config MACH_NITROGEN6X bool "BoundaryDevices Nitrogen6x" select ARCH_IMX6 diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 1d311a4177..048cac5fb0 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -11,11 +11,12 @@ obj-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o clk-imx5.o esdctl-v4.o pbl-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o clk-imx6.o lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o +obj-$(CONFIG_ARCH_IMX6SX) += clk-imx6sx.o obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_IMX_OCOTP) += ocotp.o obj-$(CONFIG_NAND_IMX) += nand.o lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o -obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-pfd.o +obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-pfd.o clk-gate2.o obj-y += devices.o imx.o esdctl.o obj-y += boot.o obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c new file mode 100644 index 0000000000..344c2fb1e6 --- /dev/null +++ b/arch/arm/mach-imx/clk-gate2.c @@ -0,0 +1,142 @@ +/* + * clk-gate2.c - barebox 2-bit clock support. Based on Linux clk support + * + * 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 <common.h> +#include <io.h> +#include <malloc.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include "clk.h" + + +struct clk_gate2 { + struct clk clk; + void __iomem *reg; + int shift; + const char *parent; +#define CLK_GATE_INVERTED (1 << 0) + unsigned flags; +}; + +#define to_clk_gate2(_clk) container_of(_clk, struct clk_gate2, clk) + +static int clk_gate2_enable(struct clk *clk) +{ + struct clk_gate2 *g = to_clk_gate2(clk); + u32 val; + + val = readl(g->reg); + + if (g->flags & CLK_GATE_INVERTED) + val &= ~(3 << g->shift); + else + val |= 3 << g->shift; + + writel(val, g->reg); + + return 0; +} + +static void clk_gate2_disable(struct clk *clk) +{ + struct clk_gate2 *g = to_clk_gate2(clk); + u32 val; + + val = readl(g->reg); + + if (g->flags & CLK_GATE_INVERTED) + val |= 3 << g->shift; + else + val &= ~(3 << g->shift); + + writel(val, g->reg); +} + +static int clk_gate2_is_enabled(struct clk *clk) +{ + struct clk_gate2 *g = to_clk_gate2(clk); + u32 val; + + val = readl(g->reg); + + if (val & (1 << g->shift)) + return g->flags & CLK_GATE_INVERTED ? 0 : 1; + else + return g->flags & CLK_GATE_INVERTED ? 1 : 0; +} + +static struct clk_ops clk_gate2_ops = { + .enable = clk_gate2_enable, + .disable = clk_gate2_disable, + .is_enabled = clk_gate2_is_enabled, +}; + +struct clk *clk_gate2_alloc(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + struct clk_gate2 *g = xzalloc(sizeof(*g)); + + g->parent = parent; + g->reg = reg; + g->shift = shift; + g->clk.ops = &clk_gate2_ops; + g->clk.name = name; + g->clk.parent_names = &g->parent; + g->clk.num_parents = 1; + + return &g->clk; +} + +void clk_gate2_free(struct clk *clk) +{ + struct clk_gate2 *g = to_clk_gate2(clk); + + free(g); +} + +struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg, + u8 shift) +{ + struct clk *g; + int ret; + + g = clk_gate2_alloc(name , parent, reg, shift); + + ret = clk_register(g); + if (ret) { + free(to_clk_gate2(g)); + return ERR_PTR(ret); + } + + 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); + if (IS_ERR(clk)) + return clk; + + g = to_clk_gate2(clk); + + g->flags = CLK_GATE_INVERTED; + + return clk; +} diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c index c0518768fc..3bc59497a8 100644 --- a/arch/arm/mach-imx/clk-imx6.c +++ b/arch/arm/mach-imx/clk-imx6.c @@ -89,7 +89,7 @@ enum mx6q_clks { sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div, - lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, clk_max + lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, enfc_gate, clk_max, }; static struct clk *clks[clk_max]; @@ -398,6 +398,8 @@ static int imx6_ccm_probe(struct device_d *dev) clks[periph] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); clks[periph2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels)); + clks[enfc_gate] = imx_clk_gate2("enfc_gate", "enfc_sel", base + 0x70, 14); + /* name parent_name reg shift width */ clks[periph_clk2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3); clks[periph2_clk2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3); @@ -410,7 +412,7 @@ static int imx6_ccm_probe(struct device_d *dev) clks[usdhc2_podf] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3); clks[usdhc3_podf] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3); clks[usdhc4_podf] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); - clks[enfc_pred] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3); + clks[enfc_pred] = imx_clk_divider("enfc_pred", "enfc_gate", base + 0x2c, 18, 3); clks[enfc_podf] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6); clks[emi_podf] = imx_clk_divider("emi_podf", "emi_sel", base + 0x1c, 20, 3); clks[emi_slow_podf] = imx_clk_divider("emi_slow_podf", "emi_slow_sel", base + 0x1c, 23, 3); @@ -469,6 +471,7 @@ static int imx6_ccm_probe(struct device_d *dev) clk_enable(clks[pll6_enet]); clk_enable(clks[sata_ref_100m]); + clk_enable(clks[enfc_podf]); return 0; } diff --git a/arch/arm/mach-imx/clk-imx6sx.c b/arch/arm/mach-imx/clk-imx6sx.c new file mode 100644 index 0000000000..e88e240202 --- /dev/null +++ b/arch/arm/mach-imx/clk-imx6sx.c @@ -0,0 +1,481 @@ +/* + * 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 <dt-bindings/clock/imx6sx-clock.h> +#include <common.h> +#include <init.h> +#include <driver.h> +#include <linux/clk.h> +#include <io.h> +#include <of.h> +#include <linux/clkdev.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <mach/imx6-regs.h> +#include <mach/revision.h> +#include <mach/imx6.h> + +#include "clk.h" +#include "common.h" + +#define CCDR 0x4 +#define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16) + +static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; +static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; +static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; +static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", }; +static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", }; +static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", }; +static const char *periph_sels[] = { "periph_pre", "periph_clk2", }; +static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", }; +static const char *ocram_sels[] = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", }; +static const char *gpu_axi_sels[] = { "pll2_pfd2_396m", "pll3_pfd0_720m", "pll3_pfd1_540m", "pll2_bus", }; +static const char *gpu_core_sels[] = { "pll3_pfd1_540m", "pll3_pfd0_720m", "pll2_bus", "pll2_pfd2_396m", }; +static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", }; +static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", }; +static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", }; +static const char *ldb_di1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", }; +static const char *pcie_axi_sels[] = { "axi", "ahb", }; +static const char *qspi1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", }; +static const char *perclk_sels[] = { "ipg", "osc", }; +static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; +static const char *vid_sels[] = { "pll3_pfd1_540m", "pll3_usb_otg", "pll3_pfd3_454m", "pll4_audio_div", "pll5_video_div", }; +static const char *uart_sels[] = { "pll3_80m", "osc", }; +static const char *qspi2_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd3_454m", "dummy", "dummy", "dummy", }; +static const char *enet_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", }; +static const char *enet_sels[] = { "enet_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; +static const char *m4_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "osc", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd3_454m", }; +static const char *m4_sels[] = { "m4_pre_sel", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; +static const char *eim_slow_sels[] = { "ocram", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", }; +static const char *ecspi_sels[] = { "pll3_60m", "osc", }; +static const char *lcdif1_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", }; +static const char *lcdif1_sels[] = { "lcdif1_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; +static const char *lcdif2_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd3_594m", "pll3_pfd1_540m", }; +static const char *lcdif2_sels[] = { "lcdif2_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; +static const char *display_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll3_usb_otg", "pll3_pfd1_540m", }; +static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; +static const char *cko1_sels[] = { + "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div", + "dummy", "ocram", "dummy", "pxp_axi", "epdc_axi", "lcdif_pix", + "epdc_pix", "ahb", "ipg", "perclk", "ckil", "pll4_audio_div", +}; +static const char *cko2_sels[] = { + "dummy", "mmdc_p0_fast", "usdhc4", "usdhc1", "dummy", "wrck", + "ecspi_root", "dummy", "usdhc3", "pcie", "arm", "csi_core", + "lcdif_axi", "dummy", "osc", "dummy", "gpu2d_ovg_core", + "usdhc2", "ssi1", "ssi2", "ssi3", "gpu2d_core", "dummy", + "dummy", "dummy", "dummy", "esai_extal", "eim_slow", "uart_serial", + "spdif", "asrc", "dummy", +}; +static const char *cko_sels[] = { "cko1", "cko2", }; +static const char *lvds_sels[] = { + "arm", "pll1_sys", "dummy", "dummy", "dummy", "dummy", "dummy", "pll5_video_div", + "dummy", "dummy", "pcie_ref_125m", "dummy", "usbphy1", "usbphy2", +}; +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[IMX6SX_CLK_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 imx6sx_ccm_probe(struct device_d *dev) +{ + void __iomem *base, *anatop_base, *ccm_base; + struct device_node *ccm_node = dev->device_node; + + clks[IMX6SX_CLK_DUMMY] = clk_fixed("dummy", 0); + + anatop_base = (void *)MX6_ANATOP_BASE_ADDR; + ccm_base = dev_request_mem_region(dev, 0); + if (IS_ERR(ccm_base)) + return PTR_ERR(ccm_base); + + base = anatop_base; + + clks[IMX6SX_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SX_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SX_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SX_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SX_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SX_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); + clks[IMX6SX_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[IMX6SX_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f); + clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1); + clks[IMX6SX_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3); + clks[IMX6SX_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f); + clks[IMX6SX_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f); + clks[IMX6SX_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3); + clks[IMX6SX_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3); + + clks[IMX6SX_PLL1_BYPASS] = imx_clk_mux_p("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels)); + clks[IMX6SX_PLL2_BYPASS] = imx_clk_mux_p("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels)); + clks[IMX6SX_PLL3_BYPASS] = imx_clk_mux_p("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels)); + clks[IMX6SX_PLL4_BYPASS] = imx_clk_mux_p("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels)); + clks[IMX6SX_PLL5_BYPASS] = imx_clk_mux_p("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels)); + clks[IMX6SX_PLL6_BYPASS] = imx_clk_mux_p("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels)); + clks[IMX6SX_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[IMX6SX_PLL1_BYPASS], clks[IMX6SX_CLK_PLL1]); + clk_set_parent(clks[IMX6SX_PLL2_BYPASS], clks[IMX6SX_CLK_PLL2]); + clk_set_parent(clks[IMX6SX_PLL3_BYPASS], clks[IMX6SX_CLK_PLL3]); + clk_set_parent(clks[IMX6SX_PLL4_BYPASS], clks[IMX6SX_CLK_PLL4]); + clk_set_parent(clks[IMX6SX_PLL5_BYPASS], clks[IMX6SX_CLK_PLL5]); + clk_set_parent(clks[IMX6SX_PLL6_BYPASS], clks[IMX6SX_CLK_PLL6]); + clk_set_parent(clks[IMX6SX_PLL7_BYPASS], clks[IMX6SX_CLK_PLL7]); + + clks[IMX6SX_CLK_PLL1_SYS] = imx_clk_gate("pll1_sys", "pll1_bypass", base + 0x00, 13); + clks[IMX6SX_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13); + clks[IMX6SX_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13); + clks[IMX6SX_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13); + clks[IMX6SX_CLK_PLL5_VIDEO] = imx_clk_gate("pll5_video", "pll5_bypass", base + 0xa0, 13); + clks[IMX6SX_CLK_PLL6_ENET] = imx_clk_gate("pll6_enet", "pll6_bypass", base + 0xe0, 13); + clks[IMX6SX_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13); + + /* + * Bit 20 is the reserved and read-only bit, we do this only for: + * - Do nothing for usbphy clk_enable/disable + * - Keep refcount when do usbphy clk_enable/disable, in that case, + * the clk framework may need to enable/disable usbphy's parent + */ + clks[IMX6SX_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20); + clks[IMX6SX_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20); + + /* + * usbphy*_gate needs to be on after system boots up, and software + * never needs to control it anymore. + */ + clks[IMX6SX_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6); + clks[IMX6SX_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6); + + /* FIXME 100Mhz is used for pcie ref for all imx6 pcie, excepted imx6q */ + clks[IMX6SX_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 5); + clks[IMX6SX_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19); + + clks[IMX6SX_CLK_ENET_REF] = imx_clk_divider_table("enet_ref", "pll6_enet", + base + 0xe0, 0, 2, clk_enet_ref_table); + clks[IMX6SX_CLK_ENET2_REF] = imx_clk_divider_table("enet2_ref", "pll6_enet", + base + 0xe0, 2, 2, clk_enet_ref_table); + clks[IMX6SX_CLK_ENET2_REF_125M] = imx_clk_gate("enet2_ref_125m", "enet2_ref", base + 0xe0, 20); + + clks[IMX6SX_CLK_ENET_PTP_REF] = imx_clk_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20); + clks[IMX6SX_CLK_ENET_PTP] = imx_clk_gate("enet_ptp_25m", "enet_ptp_ref", base + 0xe0, 21); + + /* name parent_name reg idx */ + clks[IMX6SX_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0); + clks[IMX6SX_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1); + clks[IMX6SX_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2); + clks[IMX6SX_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus", base + 0x100, 3); + clks[IMX6SX_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0); + clks[IMX6SX_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1); + clks[IMX6SX_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2); + clks[IMX6SX_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3); + + /* name parent_name mult div */ + clks[IMX6SX_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2); + clks[IMX6SX_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); + clks[IMX6SX_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); + clks[IMX6SX_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); + clks[IMX6SX_CLK_TWD] = imx_clk_fixed_factor("twd", "arm", 1, 2); + clks[IMX6SX_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); + + clks[IMX6SX_CLK_PLL4_POST_DIV] = imx_clk_divider_table("pll4_post_div", "pll4_audio", + base + 0x70, 19, 2, post_div_table); + clks[IMX6SX_CLK_PLL4_AUDIO_DIV] = imx_clk_divider("pll4_audio_div", "pll4_post_div", + base + 0x170, 15, 1); + clks[IMX6SX_CLK_PLL5_POST_DIV] = imx_clk_divider_table("pll5_post_div", "pll5_video", + base + 0xa0, 19, 2, post_div_table); + clks[IMX6SX_CLK_PLL5_VIDEO_DIV] = imx_clk_divider_table("pll5_video_div", "pll5_post_div", + base + 0x170, 30, 2, video_div_table); + + /* name reg shift width parent_names num_parents */ + clks[IMX6SX_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); + + base = ccm_base; + + /* name reg shift width parent_names num_parents */ + clks[IMX6SX_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); + clks[IMX6SX_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); + clks[IMX6SX_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 2, ocram_sels, ARRAY_SIZE(ocram_sels)); + clks[IMX6SX_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels)); + clks[IMX6SX_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels)); + clks[IMX6SX_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); + clks[IMX6SX_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); + clks[IMX6SX_CLK_PCIE_AXI_SEL] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels)); + clks[IMX6SX_CLK_GPU_AXI_SEL] = imx_clk_mux("gpu_axi_sel", base + 0x18, 8, 2, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels)); + clks[IMX6SX_CLK_GPU_CORE_SEL] = imx_clk_mux("gpu_core_sel", base + 0x18, 4, 2, gpu_core_sels, ARRAY_SIZE(gpu_core_sels)); + clks[IMX6SX_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels)); + clks[IMX6SX_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SX_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SX_CLK_USDHC3_SEL] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SX_CLK_USDHC4_SEL] = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SX_CLK_QSPI1_SEL] = imx_clk_mux_p("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels)); + clks[IMX6SX_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels)); + clks[IMX6SX_CLK_VID_SEL] = imx_clk_mux("vid_sel", base + 0x20, 21, 3, vid_sels, ARRAY_SIZE(vid_sels)); + clks[IMX6SX_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels)); + clks[IMX6SX_CLK_QSPI2_SEL] = imx_clk_mux_p("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels)); + clks[IMX6SX_CLK_ENET_PRE_SEL] = imx_clk_mux("enet_pre_sel", base + 0x34, 15, 3, enet_pre_sels, ARRAY_SIZE(enet_pre_sels)); + clks[IMX6SX_CLK_ENET_SEL] = imx_clk_mux("enet_sel", base + 0x34, 9, 3, enet_sels, ARRAY_SIZE(enet_sels)); + clks[IMX6SX_CLK_M4_PRE_SEL] = imx_clk_mux("m4_pre_sel", base + 0x34, 6, 3, m4_pre_sels, ARRAY_SIZE(m4_pre_sels)); + clks[IMX6SX_CLK_M4_SEL] = imx_clk_mux("m4_sel", base + 0x34, 0, 3, m4_sels, ARRAY_SIZE(m4_sels)); + clks[IMX6SX_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); + clks[IMX6SX_CLK_LCDIF2_PRE_SEL] = imx_clk_mux("lcdif2_pre_sel", base + 0x38, 6, 3, lcdif2_pre_sels, ARRAY_SIZE(lcdif2_pre_sels)); + clks[IMX6SX_CLK_LCDIF2_SEL] = imx_clk_mux("lcdif2_sel", base + 0x38, 0, 3, lcdif2_sels, ARRAY_SIZE(lcdif2_sels)); + clks[IMX6SX_CLK_DISPLAY_SEL] = imx_clk_mux("display_sel", base + 0x3c, 14, 2, display_sels, ARRAY_SIZE(display_sels)); + clks[IMX6SX_CLK_CSI_SEL] = imx_clk_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels)); + clks[IMX6SX_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels)); + clks[IMX6SX_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels)); + clks[IMX6SX_CLK_CKO] = imx_clk_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels)); + + clks[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux_p("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels)); + clks[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux_p("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels)); + clks[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_mux_p("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels)); + clks[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_mux_p("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels)); + clks[IMX6SX_CLK_LCDIF1_PRE_SEL] = imx_clk_mux_p("lcdif1_pre_sel", base + 0x38, 15, 3, lcdif1_pre_sels, ARRAY_SIZE(lcdif1_pre_sels)); + clks[IMX6SX_CLK_LCDIF1_SEL] = imx_clk_mux_p("lcdif1_sel", base + 0x38, 9, 3, lcdif1_sels, ARRAY_SIZE(lcdif1_sels)); + + /* name parent_name reg shift width */ + clks[IMX6SX_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3); + clks[IMX6SX_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3); + clks[IMX6SX_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); + clks[IMX6SX_CLK_GPU_CORE_PODF] = imx_clk_divider("gpu_core_podf", "gpu_core_sel", base + 0x18, 29, 3); + clks[IMX6SX_CLK_GPU_AXI_PODF] = imx_clk_divider("gpu_axi_podf", "gpu_axi_sel", base + 0x18, 26, 3); + clks[IMX6SX_CLK_LCDIF1_PODF] = imx_clk_divider("lcdif1_podf", "lcdif1_pred", base + 0x18, 23, 3); + clks[IMX6SX_CLK_QSPI1_PODF] = imx_clk_divider("qspi1_podf", "qspi1_sel", base + 0x1c, 26, 3); + clks[IMX6SX_CLK_EIM_SLOW_PODF] = imx_clk_divider("eim_slow_podf", "eim_slow_sel", base + 0x1c, 23, 3); + clks[IMX6SX_CLK_LCDIF2_PODF] = imx_clk_divider("lcdif2_podf", "lcdif2_pred", base + 0x1c, 20, 3); + clks[IMX6SX_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6); + clks[IMX6SX_CLK_VID_PODF] = imx_clk_divider("vid_podf", "vid_sel", base + 0x20, 24, 2); + clks[IMX6SX_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); + clks[IMX6SX_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3); + clks[IMX6SX_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3); + clks[IMX6SX_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3); + clks[IMX6SX_CLK_UART_PODF] = imx_clk_divider("uart_podf", "uart_sel", base + 0x24, 0, 6); + clks[IMX6SX_CLK_QSPI2_PRED] = imx_clk_divider("qspi2_pred", "qspi2_sel", base + 0x2c, 18, 3); + clks[IMX6SX_CLK_QSPI2_PODF] = imx_clk_divider("qspi2_podf", "qspi2_pred", base + 0x2c, 21, 6); + clks[IMX6SX_CLK_ENET_PODF] = imx_clk_divider("enet_podf", "enet_pre_sel", base + 0x34, 12, 3); + clks[IMX6SX_CLK_M4_PODF] = imx_clk_divider("m4_podf", "m4_sel", base + 0x34, 3, 3); + clks[IMX6SX_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel", base + 0x38, 19, 6); + clks[IMX6SX_CLK_LCDIF1_PRED] = imx_clk_divider("lcdif1_pred", "lcdif1_pre_sel", base + 0x38, 12, 3); + clks[IMX6SX_CLK_LCDIF2_PRED] = imx_clk_divider("lcdif2_pred", "lcdif2_pre_sel", base + 0x38, 3, 3); + clks[IMX6SX_CLK_DISPLAY_PODF] = imx_clk_divider("display_podf", "display_sel", base + 0x3c, 16, 3); + clks[IMX6SX_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3); + clks[IMX6SX_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3); + clks[IMX6SX_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3); + + clks[IMX6SX_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); + clks[IMX6SX_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7); + clks[IMX6SX_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); + clks[IMX6SX_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7); + + /* name reg shift width busy: reg, shift parent_names num_parents */ + clks[IMX6SX_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); + clks[IMX6SX_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 busy: reg, shift */ + clks[IMX6SX_CLK_OCRAM_PODF] = imx_clk_busy_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3, base + 0x48, 0); + clks[IMX6SX_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1); + clks[IMX6SX_CLK_MMDC_PODF] = imx_clk_busy_divider("mmdc_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2); + clks[IMX6SX_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16); + + /* name parent_name reg shift */ + /* CCGR0 */ + clks[IMX6SX_CLK_AIPS_TZ1] = imx_clk_gate2("aips_tz1", "ahb", base + 0x68, 0); + clks[IMX6SX_CLK_AIPS_TZ2] = imx_clk_gate2("aips_tz2", "ahb", base + 0x68, 2); + clks[IMX6SX_CLK_APBH_DMA] = imx_clk_gate2("apbh_dma", "usdhc3", base + 0x68, 4); + clks[IMX6SX_CLK_CAAM_MEM] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8); + clks[IMX6SX_CLK_CAAM_ACLK] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10); + clks[IMX6SX_CLK_CAAM_IPG] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12); + clks[IMX6SX_CLK_DCIC1] = imx_clk_gate2("dcic1", "display_podf", base + 0x68, 24); + clks[IMX6SX_CLK_DCIC2] = imx_clk_gate2("dcic2", "display_podf", base + 0x68, 26); + clks[IMX6SX_CLK_AIPS_TZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30); + + /* CCGR1 */ + clks[IMX6SX_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_podf", base + 0x6c, 0); + clks[IMX6SX_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_podf", base + 0x6c, 2); + clks[IMX6SX_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_podf", base + 0x6c, 4); + clks[IMX6SX_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_podf", base + 0x6c, 6); + clks[IMX6SX_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_podf", base + 0x6c, 8); + clks[IMX6SX_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12); + clks[IMX6SX_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14); + clks[IMX6SX_CLK_WAKEUP] = imx_clk_gate2("wakeup", "ipg", base + 0x6c, 18); + clks[IMX6SX_CLK_GPT_BUS] = imx_clk_gate2("gpt_bus", "perclk", base + 0x6c, 20); + clks[IMX6SX_CLK_GPT_SERIAL] = imx_clk_gate2("gpt_serial", "perclk", base + 0x6c, 22); + clks[IMX6SX_CLK_GPU] = imx_clk_gate2("gpu", "gpu_core_podf", base + 0x6c, 26); + + /* CCGR2 */ + clks[IMX6SX_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x70, 2); + clks[IMX6SX_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6); + clks[IMX6SX_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8); + clks[IMX6SX_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10); + clks[IMX6SX_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12); + clks[IMX6SX_CLK_IOMUXC] = imx_clk_gate2("iomuxc", "lcdif1_podf", base + 0x70, 14); + clks[IMX6SX_CLK_IPMUX1] = imx_clk_gate2("ipmux1", "ahb", base + 0x70, 16); + clks[IMX6SX_CLK_IPMUX2] = imx_clk_gate2("ipmux2", "ahb", base + 0x70, 18); + clks[IMX6SX_CLK_IPMUX3] = imx_clk_gate2("ipmux3", "ahb", base + 0x70, 20); + clks[IMX6SX_CLK_TZASC1] = imx_clk_gate2("tzasc1", "mmdc_podf", base + 0x70, 22); + clks[IMX6SX_CLK_LCDIF_APB] = imx_clk_gate2("lcdif_apb", "display_podf", base + 0x70, 28); + clks[IMX6SX_CLK_PXP_AXI] = imx_clk_gate2("pxp_axi", "display_podf", base + 0x70, 30); + + /* CCGR3 */ + clks[IMX6SX_CLK_M4] = imx_clk_gate2("m4", "m4_podf", base + 0x74, 2); + clks[IMX6SX_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x74, 4); + clks[IMX6SX_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "enet_sel", base + 0x74, 4); + clks[IMX6SX_CLK_DISPLAY_AXI] = imx_clk_gate2("display_axi", "display_podf", base + 0x74, 6); + clks[IMX6SX_CLK_LCDIF2_PIX] = imx_clk_gate2("lcdif2_pix", "lcdif2_sel", base + 0x74, 8); + clks[IMX6SX_CLK_LCDIF1_PIX] = imx_clk_gate2("lcdif1_pix", "lcdif1_sel", base + 0x74, 10); + clks[IMX6SX_CLK_LDB_DI0] = imx_clk_gate2("ldb_di0", "ldb_di0_div_sel", base + 0x74, 12); + clks[IMX6SX_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_podf", base + 0x74, 14); + clks[IMX6SX_CLK_MLB] = imx_clk_gate2("mlb", "ahb", base + 0x74, 18); + clks[IMX6SX_CLK_MMDC_P0_FAST] = imx_clk_gate2("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20); + clks[IMX6SX_CLK_MMDC_P0_IPG] = imx_clk_gate2("mmdc_p0_ipg", "ipg", base + 0x74, 24); + clks[IMX6SX_CLK_OCRAM] = imx_clk_gate2("ocram", "ocram_podf", base + 0x74, 28); + + /* CCGR4 */ + clks[IMX6SX_CLK_PCIE_AXI] = imx_clk_gate2("pcie_axi", "display_podf", base + 0x78, 0); + clks[IMX6SX_CLK_QSPI2] = imx_clk_gate2("qspi2", "qspi2_podf", base + 0x78, 10); + clks[IMX6SX_CLK_PER1_BCH] = imx_clk_gate2("per1_bch", "usdhc3", base + 0x78, 12); + clks[IMX6SX_CLK_PER2_MAIN] = imx_clk_gate2("per2_main", "ahb", base + 0x78, 14); + clks[IMX6SX_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16); + clks[IMX6SX_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18); + clks[IMX6SX_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20); + clks[IMX6SX_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22); + clks[IMX6SX_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb", "usdhc3", base + 0x78, 24); + clks[IMX6SX_CLK_GPMI_BCH] = imx_clk_gate2("gpmi_bch", "usdhc4", base + 0x78, 26); + clks[IMX6SX_CLK_GPMI_IO] = imx_clk_gate2("gpmi_io", "qspi2_podf", base + 0x78, 28); + clks[IMX6SX_CLK_GPMI_APB] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); + + /* CCGR5 */ + clks[IMX6SX_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); + clks[IMX6SX_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); + clks[IMX6SX_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); + clks[IMX6SX_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24); + clks[IMX6SX_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_podf", base + 0x7c, 26); + clks[IMX6SX_CLK_SAI1_IPG] = imx_clk_gate2("sai1_ipg", "ipg", base + 0x7c, 28); + clks[IMX6SX_CLK_SAI2_IPG] = imx_clk_gate2("sai2_ipg", "ipg", base + 0x7c, 30); + + /* CCGR6 */ + clks[IMX6SX_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); + clks[IMX6SX_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2); + clks[IMX6SX_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); + clks[IMX6SX_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); + clks[IMX6SX_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); + clks[IMX6SX_CLK_EIM_SLOW] = imx_clk_gate2("eim_slow", "eim_slow_podf", base + 0x80, 10); + clks[IMX6SX_CLK_PWM8] = imx_clk_gate2("pwm8", "perclk", base + 0x80, 16); + clks[IMX6SX_CLK_VADC] = imx_clk_gate2("vadc", "vid_podf", base + 0x80, 20); + clks[IMX6SX_CLK_GIS] = imx_clk_gate2("gis", "display_podf", base + 0x80, 22); + clks[IMX6SX_CLK_I2C4] = imx_clk_gate2("i2c4", "perclk", base + 0x80, 24); + clks[IMX6SX_CLK_PWM5] = imx_clk_gate2("pwm5", "perclk", base + 0x80, 26); + clks[IMX6SX_CLK_PWM6] = imx_clk_gate2("pwm6", "perclk", base + 0x80, 28); + clks[IMX6SX_CLK_PWM7] = imx_clk_gate2("pwm7", "perclk", base + 0x80, 30); + + clks[IMX6SX_CLK_CKO1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7); + clks[IMX6SX_CLK_CKO2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24); + + /* mask handshake of mmdc */ + writel(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR); + + 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[IMX6SX_CLK_USBPHY1_GATE]); + clk_enable(clks[IMX6SX_CLK_USBPHY2_GATE]); + } + + return 0; +}; + +static int imx6sx_clocks_init(void) +{ + if (!of_machine_is_compatible("fsl,imx6sx")) + return 0; + + /* Set the default 132MHz for EIM module */ + clk_set_parent(clks[IMX6SX_CLK_EIM_SLOW_SEL], clks[IMX6SX_CLK_PLL2_PFD2]); + clk_set_rate(clks[IMX6SX_CLK_EIM_SLOW], 132000000); + + /* set parent clock for LCDIF1 pixel clock */ + clk_set_parent(clks[IMX6SX_CLK_LCDIF1_PRE_SEL], clks[IMX6SX_CLK_PLL5_VIDEO_DIV]); + clk_set_parent(clks[IMX6SX_CLK_LCDIF1_SEL], clks[IMX6SX_CLK_LCDIF1_PODF]); + + /* + * Init enet system AHB clock, set to 200Mhz + * pll2_pfd2_396m-> ENET_PODF-> ENET_AHB + */ + clk_set_parent(clks[IMX6SX_CLK_ENET_PRE_SEL], clks[IMX6SX_CLK_PLL2_PFD2]); + clk_set_parent(clks[IMX6SX_CLK_ENET_SEL], clks[IMX6SX_CLK_ENET_PODF]); + clk_set_rate(clks[IMX6SX_CLK_ENET_PODF], 200000000); + clk_set_rate(clks[IMX6SX_CLK_ENET_REF], 125000000); + clk_set_rate(clks[IMX6SX_CLK_ENET2_REF], 125000000); + + /* Set parent clock for vadc */ + clk_set_parent(clks[IMX6SX_CLK_VID_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]); + + /* Update gpu clock from default 528M to 720M */ + clk_set_parent(clks[IMX6SX_CLK_GPU_CORE_SEL], clks[IMX6SX_CLK_PLL3_PFD0]); + clk_set_parent(clks[IMX6SX_CLK_GPU_AXI_SEL], clks[IMX6SX_CLK_PLL3_PFD0]); + + return 0; +} +coredevice_initcall(imx6sx_clocks_init); + +static __maybe_unused struct of_device_id imx6sx_ccm_dt_ids[] = { + { + .compatible = "fsl,imx6sx-ccm", + }, { + /* sentinel */ + } +}; + +static struct driver_d imx6sx_ccm_driver = { + .probe = imx6sx_ccm_probe, + .name = "imx6-ccm", + .of_compatible = DRV_OF_COMPAT(imx6sx_ccm_dt_ids), +}; + +static int imx6sx_ccm_init(void) +{ + return platform_driver_register(&imx6sx_ccm_driver); +} +core_initcall(imx6sx_ccm_init); diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index e2f4143879..8ec3eb5430 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -1,6 +1,9 @@ #ifndef __IMX_CLK_H #define __IMX_CLK_H +struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg, + u8 shift); + static inline struct clk *imx_clk_divider(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width) { @@ -39,6 +42,12 @@ static inline struct clk *imx_clk_gate(const char *name, const char *parent, return clk_gate(name, parent, reg, shift, CLK_SET_RATE_PARENT, 0); } +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); +} + struct clk *imx_clk_pllv1(const char *name, const char *parent, void __iomem *base); diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c index 68eacf7a60..8b10e63ade 100644 --- a/arch/arm/mach-imx/cpu_init.c +++ b/arch/arm/mach-imx/cpu_init.c @@ -15,6 +15,13 @@ #include <asm/barebox-arm-head.h> #include <asm/errata.h> +void imx5_cpu_lowlevel_init(void) +{ + arm_cpu_lowlevel_init(); + + enable_arm_errata_709718_war(); +} + void imx6_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 f0d2b5b166..433cfac1d5 100644 --- a/arch/arm/mach-imx/esdctl.c +++ b/arch/arm/mach-imx/esdctl.c @@ -280,11 +280,30 @@ static void imx_esdctl_v4_add_mem(void *esdctlbase, struct imx_esdctl_data *data data->base1, imx_v4_sdram_size(esdctlbase, 1)); } +/* + * On i.MX6 the adress space reserved for SDRAM is 0x10000000 to 0xFFFFFFFF + * which makes the maximum supported RAM size 0xF0000000. + */ +#define IMX6_MAX_SDRAM_SIZE 0xF0000000 + static void imx6_mmdc_add_mem(void *mmdcbase, struct imx_esdctl_data *data) { + /* + * It is possible to have a configuration in which both chip + * selects of the memory controller have 2GB of memory. To + * account for this case we need to use 64-bit arithmetic and + * also make sure we do not report more than + * IMX6_MAX_SDRAM_SIZE bytes of memory available. + */ + + u64 size_cs0 = imx6_mmdc_sdram_size(mmdcbase, 0); + u64 size_cs1 = imx6_mmdc_sdram_size(mmdcbase, 1); + u64 total = size_cs0 + size_cs1; + + resource_size_t size = min(total, (u64)IMX6_MAX_SDRAM_SIZE); + arm_add_mem_device("ram0", data->base0, - imx6_mmdc_sdram_size(mmdcbase, 0) + - imx6_mmdc_sdram_size(mmdcbase, 1)); + size); } static int imx_esdctl_probe(struct device_d *dev) diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c index 07d7ba1be7..374ee35df1 100644 --- a/arch/arm/mach-imx/imx.c +++ b/arch/arm/mach-imx/imx.c @@ -28,7 +28,7 @@ void imx_set_silicon_revision(const char *soc, int revision) { __imx_silicon_revision = revision; - printf("detected %s revision %d.%d\n", soc, + pr_info("detected %s revision %d.%d\n", soc, (revision >> 4) & 0xf, revision & 0xf); } @@ -57,6 +57,8 @@ static int imx_soc_from_dt(void) return IMX_CPU_IMX6; if (of_machine_is_compatible("fsl,imx6dl")) return IMX_CPU_IMX6; + if (of_machine_is_compatible("fsl,imx6sx")) + return IMX_CPU_IMX6; return 0; } diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c index a0b627f6aa..cef302b350 100644 --- a/arch/arm/mach-imx/imx51.c +++ b/arch/arm/mach-imx/imx51.c @@ -41,11 +41,26 @@ static int imx51_silicon_revision(void) return 0; } +static void imx51_ipu_mipi_setup(void) +{ + void __iomem *hsc_addr = (void __iomem *)MX51_MIPI_HSC_BASE_ADDR; + u32 val; + + /* setup MIPI module to legacy mode */ + writel(0xf00, hsc_addr); + + /* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */ + val = readl(hsc_addr + 0x800); + val |= 0x30ff; + writel(val, hsc_addr + 0x800); +} + int imx51_init(void) { imx_set_silicon_revision("i.MX51", imx51_silicon_revision()); imx51_boot_save_loc((void *)MX51_SRC_BASE_ADDR); add_generic_device("imx51-esdctl", 0, NULL, MX51_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + imx51_ipu_mipi_setup(); return 0; } diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index ec5e1416f3..c5cae6e238 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -161,6 +161,9 @@ int imx6_init(void) case IMX6_CPUTYPE_IMX6S: cputypestr = "i.MX6 Solo"; break; + case IMX6_CPUTYPE_IMX6SX: + cputypestr = "i.MX6 SoloX"; + break; default: cputypestr = "unknown i.MX6"; break; diff --git a/arch/arm/mach-imx/include/mach/bbu.h b/arch/arm/mach-imx/include/mach/bbu.h index 74c334a075..5eb9a47363 100644 --- a/arch/arm/mach-imx/include/mach/bbu.h +++ b/arch/arm/mach-imx/include/mach/bbu.h @@ -27,8 +27,6 @@ int imx6_bbu_internal_mmc_register_handler(const char *name, char *devicefile, int imx6_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, unsigned long flags); -int imx6_bbu_nand_register_handler(const char *name, unsigned long flags); - int imx_bbu_external_nor_register_handler(const char *name, char *devicefile, unsigned long flags); @@ -70,13 +68,17 @@ static inline int imx6_bbu_internal_spi_i2c_register_handler(const char *name, c return -ENOSYS; } -static inline int imx6_bbu_nand_register_handler(const char *name, unsigned long flags) +static inline int imx_bbu_external_nor_register_handler(const char *name, char *devicefile, + unsigned long flags) { return -ENOSYS; } +#endif -static inline int imx_bbu_external_nor_register_handler(const char *name, char *devicefile, - unsigned long flags) +#if defined(CONFIG_BAREBOX_UPDATE_IMX6_NAND) +int imx6_bbu_nand_register_handler(const char *name, unsigned long flags); +#else +static inline int imx6_bbu_nand_register_handler(const char *name, unsigned long flags) { return -ENOSYS; } diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h index 505a54268d..d4b6a1f7b4 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -33,6 +33,7 @@ int imx51_devices_init(void); int imx53_devices_init(void); int imx6_devices_init(void); +void imx5_cpu_lowlevel_init(void); void imx6_cpu_lowlevel_init(void); /* There's a off-by-one betweem the gpio bank number and the gpiochip */ diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h index 1898d8150b..3b7542169e 100644 --- a/arch/arm/mach-imx/include/mach/imx6.h +++ b/arch/arm/mach-imx/include/mach/imx6.h @@ -11,6 +11,7 @@ void imx6_init_lowlevel(void); #define IMX6_CPUTYPE_IMX6S 0x161 #define IMX6_CPUTYPE_IMX6DL 0x261 +#define IMX6_CPUTYPE_IMX6SX 0x462 #define IMX6_CPUTYPE_IMX6D 0x263 #define IMX6_CPUTYPE_IMX6Q 0x463 @@ -67,4 +68,9 @@ static inline int cpu_is_mx6q(void) return imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q; } +static inline int cpu_is_mx6sx(void) +{ + return imx6_cpu_type() == IMX6_CPUTYPE_IMX6SX; +} + #endif /* __MACH_IMX6_H */ diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c index 5912d75866..b58aafa6d0 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -320,6 +320,14 @@ static struct file_operations imx6_ocotp_ops = { .lseek = dev_lseek_default, }; +static uint32_t inc_offset(uint32_t offset) +{ + if ((offset & 0x3) == 0x3) + return offset + 0xd; + else + return offset + 1; +} + static void imx_ocotp_init_dt(struct device_d *dev, void __iomem *base) { char mac[6]; @@ -336,21 +344,24 @@ static void imx_ocotp_init_dt(struct device_d *dev, void __iomem *base) while (len >= MAC_ADDRESS_PROPLEN) { struct device_node *rnode; - uint32_t phandle, offset, value; + uint32_t phandle, offset; phandle = be32_to_cpup(prop++); rnode = of_find_node_by_phandle(phandle); offset = be32_to_cpup(prop++); - value = readl(base + offset + 0x10); - mac[0] = (value >> 8); - mac[1] = value; - value = readl(base + offset); - mac[2] = value >> 24; - mac[3] = value >> 16; - mac[4] = value >> 8; - mac[5] = value; + mac[5] = readb(base + offset); + offset = inc_offset(offset); + mac[4] = readb(base + offset); + offset = inc_offset(offset); + mac[3] = readb(base + offset); + offset = inc_offset(offset); + mac[2] = readb(base + offset); + offset = inc_offset(offset); + mac[1] = readb(base + offset); + offset = inc_offset(offset); + mac[0] = readb(base + offset); of_eth_register_ethaddr(rnode, mac); @@ -445,6 +456,8 @@ static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = { { .compatible = "fsl,imx6q-ocotp", }, { + .compatible = "fsl,imx6sx-ocotp", + }, { /* sentinel */ } }; |