diff --git a/Documentation/boards/garz-fricke.rst b/Documentation/boards/garz-fricke.rst new file mode 100644 index 0000000..33d0dd3 --- /dev/null +++ b/Documentation/boards/garz-fricke.rst @@ -0,0 +1,33 @@ +Garz & Fricke based boards +========================== + +Garz & Fricke have a variety of Freescale i.MX based boards. Most boards are +shipped with the redboot bootloader, newer boards are shipped with a combination +of a shim (U-Boot based) non interactive loader and a Linux based rescue system +called 'Flash-N-Go'. + +Santaro (i.MX6) +--------------- + +This board comes with Flash-N-Go. It boots from the internal eMMC boot0 partition. +To put barebox on this board boot the system up in the Flash-N-Go system by holding +the user button pressed during startup. The barebox image can be transferred via +network or any other medium the Santaro supports. You can backup the original bootloader +with: + +.. code-block:: sh + cat /dev/mmcblk0boot0 > /mnt/mmcblk0boot0.backup + cat /dev/mmcblk0boot1 > /mnt/mmcblk0boot1.backup + +The original bootloader can be restored by copying the backup files back to the +device. + +To install barebox on the board do: + +.. code-block:: sh + echo 0 > /sys/block/mmcblk0boot0/force_ro + cat barebox-guf-santaro.img > /dev/mmcblk0boot0 + +The board will come up with barebox after restart. Should you end up with a nonworking +barebox or otherwise brick your board this way write a mail to s.hauer@pengutronix.de. +There's a way to put the board into SD/USB boot mode, but this requires opening the case. diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile index fb257fb..9961ca8 100644 --- a/arch/arm/boards/Makefile +++ b/arch/arm/boards/Makefile @@ -93,6 +93,7 @@ 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 3e67b31..2b3dc42 100644 --- a/arch/arm/boards/ccxmx51/lowlevel.c +++ b/arch/arm/boards/ccxmx51/lowlevel.c @@ -1,11 +1,12 @@ #include #include +#include #include #include #include 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 0ac4693..d00e0f6 100644 --- a/arch/arm/boards/efika-mx-smartbook/Makefile +++ b/arch/arm/boards/efika-mx-smartbook/Makefile @@ -2,3 +2,4 @@ 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 59410c1..99efd66 100644 --- a/arch/arm/boards/efika-mx-smartbook/board.c +++ b/arch/arm/boards/efika-mx-smartbook/board.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -63,16 +64,9 @@ 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 @@ mc13xxx_reg_write(mc, MC13892_REG_POWER_CTL2, val); udelay(2500); - - return 0; } static int efikamx_usb_init(void) @@ -188,6 +180,8 @@ 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 @@ 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/defaultenv-efikasb/bin/lvds_init b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/bin/lvds_init new file mode 100644 index 0000000..692392c --- /dev/null +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/bin/lvds_init @@ -0,0 +1,22 @@ +#!/bin/sh + +# Initialize lvds and backlight in case your Kernel does not handle this... + +GPIO_BACKLIGHT_POWER=108 +GPIO_BACKLIGHT_PWM=2 +GPIO_LVDS_POWER=71 +GPIO_LVDS_RESET=69 +GPIO_LVDS_ENABLE=76 +GPIO_LCD_ENABLE=77 + +gpio_direction_output $GPIO_BACKLIGHT_PWM 0 +gpio_direction_output $GPIO_LVDS_RESET 1 +gpio_direction_output $GPIO_LVDS_POWER 1 +msleep 5 +gpio_direction_output $GPIO_LVDS_RESET 0 +msleep 5 +gpio_direction_output $GPIO_LVDS_ENABLE 1 +gpio_direction_output $GPIO_BACKLIGHT_POWER 0 +gpio_direction_output $GPIO_LCD_ENABLE 1 +msleep 300 +gpio_direction_output $GPIO_BACKLIGHT_PWM 1 diff --git a/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/hd-internal b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/hd-internal new file mode 100644 index 0000000..2233f14 --- /dev/null +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/hd-internal @@ -0,0 +1,12 @@ +#!/bin/sh + +path="/mnt/internal-hd0.0" + +global.bootm.image="${path}/linuximage" + +oftree=${path}/oftree +if [ -f $oftree ]; then + global.bootm.oftree="$oftree" +fi + +global.linux.bootargs.dyn.root="root=/dev/sda2" diff --git a/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/mmc-left b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/mmc-left new file mode 100644 index 0000000..da7bc03 --- /dev/null +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/boot/mmc-left @@ -0,0 +1,14 @@ +#!/bin/sh + +path="/mnt/mmc-left.0" + +global.bootm.image="${path}/linuximage" + +oftree=${path}/oftree +if [ -f $oftree ]; then + global.bootm.oftree="$oftree" +fi + +# The rootdevice may actually be mmcblk1p2 if a card +# is inserted to the back MMC slot +global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2" diff --git a/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/config b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/config new file mode 100644 index 0000000..c63c6a1 --- /dev/null +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/config @@ -0,0 +1,29 @@ +#!/bin/sh + +# change network settings in /env/network/eth0 +# change mtd partition settings and automountpoints in /env/init/* + +#global.hostname= + +# set to false if you do not want to have colors +global.allow_color=true + +# user (used for network filenames) +global.user=none + +# timeout in seconds before the default boot entry is started +global.autoboot_timeout=1 + +# default boot entry (one of /env/boot/*) +# (if not overwritten here, the bootdevice barebox comes from +# is used) +#global.boot.default=net + +# base bootargs +global.linux.bootargs.base="console=tty1" + +# suitable for 800MHz +global linux.bootargs.lpj="lpj=3997696" + +# speed up booting by being more quiet +global linux.bootargs.quiet="quiet" diff --git a/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/automount b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/automount new file mode 100644 index 0000000..8cb5eaf --- /dev/null +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/automount @@ -0,0 +1,29 @@ +#!/bin/sh + +if [ "$1" = menu ]; then + init-menu-add-entry "$0" "Automountpoints" + exit +fi + +# automount tftp server based on $eth0.serverip + +mkdir -p /mnt/tftp +automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp' + +# automount nfs server example + +# internal harddisk /boot partition +mkdir -p /mnt/internal-hd0.0 +automount -d /mnt/internal-hd0.0 'mount /dev/ata0.0 /mnt/internal-hd0.0' + +# internal harddisk rootfs +mkdir -p /mnt/internal-hd0.1 +automount -d /mnt/internal-hd0.1 'mount /dev/ata0.1 /mnt/internal-hd0.1' + +# left SD card slot, first partition +mkdir -p /mnt/mmc-left.0 +automount -d /mnt/mmc-left.0 'mount /dev/mmc_left.0 /mnt/mmc-left.0' + +# back SD card slot, first partition +mkdir -p /mnt/mmc-back.0 +automount -d /mnt/mmc-back.0 'mount /dev/mmc_back.0 /mnt/mmc-back.0' diff --git a/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/bootsource b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/bootsource new file mode 100644 index 0000000..380e855 --- /dev/null +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/init/bootsource @@ -0,0 +1,10 @@ +#!/bin/sh + +# by default pick kernel from MMC card if booting from +# it, otherwise default to boot from internal harddisk + +if [ $bootsource = mmc ]; then + global.boot.default=mmc-left +else + global.boot.default=hd-internal +fi diff --git a/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/network/eth0-discover b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/network/eth0-discover new file mode 100644 index 0000000..f8368a5 --- /dev/null +++ b/arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/network/eth0-discover @@ -0,0 +1,4 @@ +#!/bin/sh + +usb +sleep 3 diff --git a/arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init b/arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init deleted file mode 100644 index 692392c..0000000 --- a/arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# Initialize lvds and backlight in case your Kernel does not handle this... - -GPIO_BACKLIGHT_POWER=108 -GPIO_BACKLIGHT_PWM=2 -GPIO_LVDS_POWER=71 -GPIO_LVDS_RESET=69 -GPIO_LVDS_ENABLE=76 -GPIO_LCD_ENABLE=77 - -gpio_direction_output $GPIO_BACKLIGHT_PWM 0 -gpio_direction_output $GPIO_LVDS_RESET 1 -gpio_direction_output $GPIO_LVDS_POWER 1 -msleep 5 -gpio_direction_output $GPIO_LVDS_RESET 0 -msleep 5 -gpio_direction_output $GPIO_LVDS_ENABLE 1 -gpio_direction_output $GPIO_BACKLIGHT_POWER 0 -gpio_direction_output $GPIO_LCD_ENABLE 1 -msleep 300 -gpio_direction_output $GPIO_BACKLIGHT_PWM 1 diff --git a/arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal b/arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal deleted file mode 100644 index 2233f14..0000000 --- a/arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -path="/mnt/internal-hd0.0" - -global.bootm.image="${path}/linuximage" - -oftree=${path}/oftree -if [ -f $oftree ]; then - global.bootm.oftree="$oftree" -fi - -global.linux.bootargs.dyn.root="root=/dev/sda2" diff --git a/arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left b/arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left deleted file mode 100644 index da7bc03..0000000 --- a/arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -path="/mnt/mmc-left.0" - -global.bootm.image="${path}/linuximage" - -oftree=${path}/oftree -if [ -f $oftree ]; then - global.bootm.oftree="$oftree" -fi - -# The rootdevice may actually be mmcblk1p2 if a card -# is inserted to the back MMC slot -global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2" diff --git a/arch/arm/boards/efika-mx-smartbook/env/config b/arch/arm/boards/efika-mx-smartbook/env/config deleted file mode 100644 index c63c6a1..0000000 --- a/arch/arm/boards/efika-mx-smartbook/env/config +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -# change network settings in /env/network/eth0 -# change mtd partition settings and automountpoints in /env/init/* - -#global.hostname= - -# set to false if you do not want to have colors -global.allow_color=true - -# user (used for network filenames) -global.user=none - -# timeout in seconds before the default boot entry is started -global.autoboot_timeout=1 - -# default boot entry (one of /env/boot/*) -# (if not overwritten here, the bootdevice barebox comes from -# is used) -#global.boot.default=net - -# base bootargs -global.linux.bootargs.base="console=tty1" - -# suitable for 800MHz -global linux.bootargs.lpj="lpj=3997696" - -# speed up booting by being more quiet -global linux.bootargs.quiet="quiet" diff --git a/arch/arm/boards/efika-mx-smartbook/env/init/automount b/arch/arm/boards/efika-mx-smartbook/env/init/automount deleted file mode 100644 index 8cb5eaf..0000000 --- a/arch/arm/boards/efika-mx-smartbook/env/init/automount +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -if [ "$1" = menu ]; then - init-menu-add-entry "$0" "Automountpoints" - exit -fi - -# automount tftp server based on $eth0.serverip - -mkdir -p /mnt/tftp -automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp' - -# automount nfs server example - -# internal harddisk /boot partition -mkdir -p /mnt/internal-hd0.0 -automount -d /mnt/internal-hd0.0 'mount /dev/ata0.0 /mnt/internal-hd0.0' - -# internal harddisk rootfs -mkdir -p /mnt/internal-hd0.1 -automount -d /mnt/internal-hd0.1 'mount /dev/ata0.1 /mnt/internal-hd0.1' - -# left SD card slot, first partition -mkdir -p /mnt/mmc-left.0 -automount -d /mnt/mmc-left.0 'mount /dev/mmc_left.0 /mnt/mmc-left.0' - -# back SD card slot, first partition -mkdir -p /mnt/mmc-back.0 -automount -d /mnt/mmc-back.0 'mount /dev/mmc_back.0 /mnt/mmc-back.0' diff --git a/arch/arm/boards/efika-mx-smartbook/env/init/bootsource b/arch/arm/boards/efika-mx-smartbook/env/init/bootsource deleted file mode 100644 index 380e855..0000000 --- a/arch/arm/boards/efika-mx-smartbook/env/init/bootsource +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -# by default pick kernel from MMC card if booting from -# it, otherwise default to boot from internal harddisk - -if [ $bootsource = mmc ]; then - global.boot.default=mmc-left -else - global.boot.default=hd-internal -fi diff --git a/arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover b/arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover deleted file mode 100644 index f8368a5..0000000 --- a/arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -usb -sleep 3 diff --git a/arch/arm/boards/efika-mx-smartbook/lowlevel.c b/arch/arm/boards/efika-mx-smartbook/lowlevel.c index 0d32eee..52454c7 100644 --- a/arch/arm/boards/efika-mx-smartbook/lowlevel.c +++ b/arch/arm/boards/efika-mx-smartbook/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -10,7 +11,7 @@ { 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 c3f7b4a..7a85b48 100644 --- a/arch/arm/boards/eukrea_cpuimx51/lowlevel.c +++ b/arch/arm/boards/eukrea_cpuimx51/lowlevel.c @@ -1,9 +1,10 @@ #include #include +#include #include 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 5a5a83c..1b9ba16 100644 --- a/arch/arm/boards/freescale-mx51-babbage/lowlevel.c +++ b/arch/arm/boards/freescale-mx51-babbage/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,7 +10,7 @@ { 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 7d1c1d5..aff6e3b 100644 --- a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c +++ b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -10,7 +11,7 @@ { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); fdt = __dtb_imx53_qsb_start - get_runtime_offset(); @@ -23,7 +24,7 @@ { 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 1db07e2..306db09 100644 --- a/arch/arm/boards/freescale-mx53-smd/lowlevel.c +++ b/arch/arm/boards/freescale-mx53-smd/lowlevel.c @@ -1,9 +1,10 @@ #include #include +#include #include 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 4054fd5..487a9fd 100644 --- a/arch/arm/boards/freescale-mx53-vmx53/lowlevel.c +++ b/arch/arm/boards/freescale-mx53-vmx53/lowlevel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -9,7 +10,7 @@ { 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 0000000..cc4078f --- /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 0000000..c21b43d --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#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 0000000..a96b3e7 --- /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 0000000..33f3700 --- /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 +#include +#include +#include +#include +#include + +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 186c0d9..00e34fb 100644 --- a/arch/arm/boards/guf-vincell/lowlevel.c +++ b/arch/arm/boards/guf-vincell/lowlevel.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -127,7 +128,7 @@ { 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 c3f7b4a..7a85b48 100644 --- a/arch/arm/boards/karo-tx51/lowlevel.c +++ b/arch/arm/boards/karo-tx51/lowlevel.c @@ -1,9 +1,10 @@ #include #include +#include #include 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 d82e666..8adbd8d 100644 --- a/arch/arm/boards/karo-tx53/lowlevel.c +++ b/arch/arm/boards/karo-tx53/lowlevel.c @@ -3,10 +3,11 @@ #include #include #include +#include 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 09a5c79..1551460 100644 --- a/arch/arm/boards/phytec-phyflex-imx6/board.c +++ b/arch/arm/boards/phytec-phyflex-imx6/board.c @@ -63,13 +63,6 @@ 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 @@ 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 84014d7..ce168b2 100644 --- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c +++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c @@ -54,16 +54,16 @@ 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 @@ 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(); - + fdt = fdt_blob_fixed_offset - get_runtime_offset(); barebox_arm_entry(0x10000000, size, 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); \ + } -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(); - - 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); -} +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 cd87212..4e129e4 100644 --- a/arch/arm/boards/tqma53/lowlevel.c +++ b/arch/arm/boards/tqma53/lowlevel.c @@ -5,6 +5,7 @@ #include #include #include +#include #include extern char __dtb_imx53_mba53_start[]; @@ -41,7 +42,7 @@ { void *fdt; - arm_cpu_lowlevel_init(); + imx5_cpu_lowlevel_init(); arm_setup_stack(0xf8020000 - 8); @@ -60,7 +61,7 @@ { 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 2c8eb85..755217f 100644 --- a/arch/arm/configs/imx_v7_defconfig +++ b/arch/arm/configs/imx_v7_defconfig @@ -13,8 +13,10 @@ 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_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_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_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_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_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_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 d8160fe..9981073 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -28,13 +28,14 @@ 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 6d6ab81..26829d1 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 #include #include diff --git a/arch/arm/dts/imx51.dtsi b/arch/arm/dts/imx51.dtsi new file mode 100644 index 0000000..828a6c2 --- /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 0000000..34e4144 --- /dev/null +++ b/arch/arm/dts/imx6dl-phytec-phyboard-subra.dts @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Christian Hemp , 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 db93a48..e4dc856 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 0000000..a60fc18 --- /dev/null +++ b/arch/arm/dts/imx6q-phytec-phyboard-alcor.dts @@ -0,0 +1,38 @@ +/* + * Copyright 2014 Christian Hemp , 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 5c7bcee..32ce088 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 0000000..fbf098b --- /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 +#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 0000000..5a8ee46 --- /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 e2ffd87..9525823 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 53d91bc..a931de9 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -102,11 +102,13 @@ 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_IMX6_NAND bool + depends on MTD depends on ARCH_IMX6 depends on BAREBOX_UPDATE depends on MTD @@ -174,6 +177,11 @@ 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 @@ 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 1d311a4..048cac5 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -11,11 +11,12 @@ 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 0000000..344c2fb --- /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 +#include +#include +#include +#include + +#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 c051876..3bc5949 100644 --- a/arch/arm/mach-imx/clk-imx6.c +++ b/arch/arm/mach-imx/clk-imx6.c @@ -89,7 +89,7 @@ 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 @@ 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 @@ 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 @@ 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 0000000..e88e240 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 e2f4143..8ec3eb5 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 @@ 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 68eacf7..8b10e63 100644 --- a/arch/arm/mach-imx/cpu_init.c +++ b/arch/arm/mach-imx/cpu_init.c @@ -15,6 +15,13 @@ #include #include +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 f0d2b5b..433cfac 100644 --- a/arch/arm/mach-imx/esdctl.c +++ b/arch/arm/mach-imx/esdctl.c @@ -280,11 +280,30 @@ 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 07d7ba1..374ee35 100644 --- a/arch/arm/mach-imx/imx.c +++ b/arch/arm/mach-imx/imx.c @@ -28,7 +28,7 @@ { __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 @@ 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 a0b627f..cef302b 100644 --- a/arch/arm/mach-imx/imx51.c +++ b/arch/arm/mach-imx/imx51.c @@ -41,11 +41,26 @@ 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 ec5e141..c5cae6e 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -161,6 +161,9 @@ 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 74c334a..5eb9a47 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_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 @@ 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 505a542..d4b6a1f 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -33,6 +33,7 @@ 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 1898d81..3b75421 100644 --- a/arch/arm/mach-imx/include/mach/imx6.h +++ b/arch/arm/mach-imx/include/mach/imx6.h @@ -11,6 +11,7 @@ #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 @@ 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 5912d75..b58aafa 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -320,6 +320,14 @@ .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 @@ 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 @@ { .compatible = "fsl,imx6q-ocotp", }, { + .compatible = "fsl,imx6sx-ocotp", + }, { /* sentinel */ } }; diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 487cd41..239cd37 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -474,8 +474,9 @@ /* Set the initial clock speed */ set_sysctl(mci, 400000); - /* Disable the BRR and BWR bits in IRQSTAT */ - esdhc_clrbits32(regs + SDHCI_INT_ENABLE, IRQSTATEN_BRR | IRQSTATEN_BWR); + writel(IRQSTATEN_CC | IRQSTATEN_TC | IRQSTATEN_CINT | IRQSTATEN_CTOE | + IRQSTATEN_CCE | IRQSTATEN_CEBE | IRQSTATEN_CIE | IRQSTATEN_DTOE | + IRQSTATEN_DCE | IRQSTATEN_DEBE | IRQSTATEN_DINT, regs + SDHCI_INT_ENABLE); /* Put the PROCTL reg back to the default */ esdhc_write32(regs + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, @@ -606,6 +607,8 @@ }, { .compatible = "fsl,imx6q-usdhc", }, { + .compatible = "fsl,imx6sl-usdhc", + }, { /* sentinel */ } }; diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c index 8989de0..94101a3 100644 --- a/drivers/mtd/nand/nand_mxs.c +++ b/drivers/mtd/nand/nand_mxs.c @@ -1266,6 +1266,7 @@ return PTR_ERR(nand_info->clk); if (mxs_nand_is_imx6(nand_info)) { + clk_disable(nand_info->clk); clk_set_rate(nand_info->clk, 96000000); clk_enable(nand_info->clk); nand_info->dma_channel_base = 0; diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 4ed5e8e..a2852ed 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -772,6 +772,9 @@ }, { .compatible = "fsl,imx6q-fec", .data = FEC_TYPE_IMX6, + }, { + .compatible = "fsl,imx6sx-fec", + .data = FEC_TYPE_IMX6, }, { /* sentinel */ } diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c index 5dfcde6..62a352b 100644 --- a/drivers/pinctrl/imx-iomux-v3.c +++ b/drivers/pinctrl/imx-iomux-v3.c @@ -199,6 +199,8 @@ }, { .compatible = "fsl,imx6dl-iomuxc", }, { + .compatible = "fsl,imx6sx-iomuxc", + }, { /* sentinel */ } }; diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c index e379f29..21189cb 100644 --- a/drivers/serial/serial_imx.c +++ b/drivers/serial/serial_imx.c @@ -324,7 +324,7 @@ cdev = &priv->cdev; dev->priv = priv; - priv->clk = clk_get(dev, NULL); + priv->clk = clk_get(dev, "per"); if (IS_ERR(priv->clk)) { ret = PTR_ERR(priv->clk); goto err_free; diff --git a/images/Makefile.imx b/images/Makefile.imx index 23a3d66..fd7f725 100644 --- a/images/Makefile.imx +++ b/images/Makefile.imx @@ -115,6 +115,16 @@ FILE_barebox-phytec-pbab01s-512mb.img = start_phytec_pbab01s_512mb.pblx.imximg image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01s-512mb.img +pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_phyboard_alcor_1gib +CFG_start_phytec_phyboard_alcor_1gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg +FILE_barebox-phytec-phyboard-alcor-1gib.img = start_phytec_phyboard_alcor_1gib.pblx.imximg +image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-phyboard-alcor-1gib.img + +pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_phyboard_subra_512mb +CFG_start_phytec_phyboard_subra_512mb.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg +FILE_barebox-phytec-phyboard-subra-512mb.img = start_phytec_phyboard_subra_512mb.pblx.imximg +image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-phyboard-subra-512mb.img + pblx-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6dl_dfi_fs700_m60_6s CFG_start_imx6dl_dfi_fs700_m60_6s.pblx.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6s.imxcfg FILE_barebox-dfi-fs700-m60-6s.img = start_imx6dl_dfi_fs700_m60_6s.pblx.imximg @@ -145,6 +155,11 @@ FILE_barebox-freescale-imx6q-sabresd.img = start_imx6q_sabresd.pblx.imximg image-$(CONFIG_MACH_SABRESD) += barebox-freescale-imx6q-sabresd.img +pblx-$(CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB) += start_imx6sx_sabresdb +CFG_start_imx6sx_sabresdb.pblx.imximg = $(board)/freescale-mx6sx-sabresdb/flash-header-mx6sx-sabresdb.imxcfg +FILE_barebox-freescale-imx6sx-sabresdb.img = start_imx6sx_sabresdb.pblx.imximg +image-$(CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB) += barebox-freescale-imx6sx-sabresdb.img + pblx-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_imx6dl_hummingboard CFG_start_imx6dl_hummingboard.pblx.imximg = $(board)/solidrun-microsom/flash-header-solidrun-hummingboard.imxcfg FILE_barebox-solidrun-imx6dl-hummingboard.img = start_imx6dl_hummingboard.pblx.imximg diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index c86260c..94b3763 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -103,6 +103,13 @@ .header_type = HDR_MX53, .mode = MODE_HID, .max_transfer = 1024, + }, { + .vid = 0x15a2, + .pid = 0x0071, + .name = "i.MX6 SoloX", + .header_type = HDR_MX53, + .mode = MODE_HID, + .max_transfer = 1024, }, { .vid = 0x15a2, .pid = 0x0041,