From 6f9d41403a054cf2ce5cd7484a72ee81eeaac34a Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Fri, 20 Nov 2020 21:18:53 +0530 Subject: [PATCH 01/42] board: ti: am65x: Set SERDES0 mux to PCIe to use USB 2.0 interface It has been observed that setting SERDES0 lane mux to USB prevents USB 2.0 operation on USB0. Setting SERDES0 lane mux to non-USB when USB0 is used in USB 2.0 only mode solves this issue. However, for USB3.0+2.0 operation this issue is not present. Implement this workaround by writing 1 to LANE_FUNC_SEL field in CTRLMMR_SERDES0_CTRL register. Signed-off-by: Aswath Govindraju --- board/ti/am65x/evm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c index 36063b1138..4438f14e4f 100644 --- a/board/ti/am65x/evm.c +++ b/board/ti/am65x/evm.c @@ -38,6 +38,10 @@ enum { /* Max number of MAC addresses that are parsed/processed per daughter card */ #define DAUGHTER_CARD_NO_OF_MAC_ADDR 8 +/* Regiter that controls the SERDES0 lane and clock assignment */ +#define CTRLMMR_SERDES0_CTRL 0x00104080 +#define PCIE_LANE0 0x1 + DECLARE_GLOBAL_DATA_PTR; int board_init(void) @@ -312,6 +316,18 @@ static int probe_daughtercards(void) (uchar *)mac_addr[j]); } + /* + * It has been observed that setting SERDES0 lane mux to USB prevents USB + * 2.0 operation on USB0. Setting SERDES0 lane mux to non-USB when USB0 is + * used in USB 2.0 only mode solves this issue. For USB3.0+2.0 operation + * this issue is not present. + * + * Implement this workaround by writing 1 to LANE_FUNC_SEL field in + * CTRLMMR_SERDES0_CTRL register. + */ + if (!strncmp(ep.name, "SER-PCIE2LEVM", sizeof(ep.name))) + writel(PCIE_LANE0, CTRLMMR_SERDES0_CTRL); + /* Skip if no overlays are to be added */ if (!strlen(cards[i].dtbo_name)) continue; From d3af9e37727efd505e53e00fe1180ba628febf83 Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Fri, 20 Nov 2020 21:18:54 +0530 Subject: [PATCH 02/42] arm: dts: am654-base-board-uboot: Set USB0 dr_mode to host USB3SS0 controller is to be used as a host in U-boot. Fix it by changing the dr_mode to host. Signed-off-by: Aswath Govindraju --- arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi index d75d1b1c28..bd2f334c2b 100644 --- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -270,7 +270,7 @@ &usb0 { pinctrl-names = "default"; pinctrl-0 = <&usb0_pins_default>; - dr_mode = "peripheral"; + dr_mode = "host"; u-boot,dm-spl; }; From 62be2367f5f8f2e83cedbe2189263b73d5f57834 Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Fri, 20 Nov 2020 21:18:55 +0530 Subject: [PATCH 03/42] arm: dts: am654-base-board-uboot: Add aliases for USB subsystems The sequence number assigned for USB subsystem in a uclass is dependent on the order of occurrence in the device tree. If the dr_mode of USB3SS0 controller is varied then the sequence number of USB3SS1 controller also changes. If aliases are added then sequence numbers are assigned using the alias number. This makes the sequence number of USB3SS1 controller independent of USB3SS0 controller's dr_mode. Therefore, add aliases to fix the sequence number assigned to the USB subsystems. Signed-off-by: Aswath Govindraju --- arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi index bd2f334c2b..727bc3e8a0 100644 --- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -14,6 +14,8 @@ aliases { serial2 = &main_uart0; ethernet0 = &cpsw_port1; + usb0 = &usb0; + usb1 = &usb1; }; }; From ba904727690532b21b4be886831cb259a34f27ca Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Tue, 24 Nov 2020 15:59:34 +0530 Subject: [PATCH 04/42] configs: am65x_evm: Define the maximum file size for DFU In include/dfu.h, if CONFIG_SYS_DFU_MAX_FILE_SIZE is not defined then it is defined as CONFIG_SYS_DFU_DATA_BUF_SIZE. This is 128 KiB for a53 core and 20 KiB for r5 core. If a larger file is transferred using dfu then it fails. CONFIG_SYS_DFU_DATA_BUF_SIZE can not be increased as there is not enough heap memory to be allocated for the buffer in case of R5 spl. Fix this by defining CONFIG_SYS_DFU_MAX_FILE_SIZE as the default CONFIG_SYS_DFU_DATA_BUF_SIZE value. Signed-off-by: Aswath Govindraju --- include/configs/am65x_evm.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h index 9eed0ea203..b39a5b4ca4 100644 --- a/include/configs/am65x_evm.h +++ b/include/configs/am65x_evm.h @@ -56,6 +56,12 @@ #define CONFIG_SKIP_LOWLEVEL_INIT #endif +/* + * If the maximum size is not declared then it is defined as + * CONFIG_SYS_DFU_DATA_BUF_SIZE. + */ +#define CONFIG_SYS_DFU_MAX_FILE_SIZE (1024 * 1024 * 8) /* 8 MiB */ + #define CONFIG_SPL_MAX_SIZE CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE #define CONFIG_SYS_BOOTM_LEN SZ_64M From 49b4c54bc969aae9a79e598266feec3d74275635 Mon Sep 17 00:00:00 2001 From: Tomas Novotny Date: Wed, 25 Nov 2020 18:42:16 +0100 Subject: [PATCH 05/42] gpio: tca642x: fix input subcommand for gpio banks > 0 The value of input pin for bank > 0 is always 0 for input subcommand. The reason is that gpio_bank variable is computed only for invert and output subcommands (it depends on number of arguments). The default value of zero causes to shift the mask away for banks > 0. Please note that info subcommand works as expected, because the input pin values are accessed differently. Fixes: 61c1775f16ed ("gpio: tca642x: Add the tca642x gpio expander driver") Cc: Dan Murphy Signed-off-by: Tomas Novotny --- drivers/gpio/tca642x.c | 49 ++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/tca642x.c b/drivers/gpio/tca642x.c index 463cfe879a..7007c7a002 100644 --- a/drivers/gpio/tca642x.c +++ b/drivers/gpio/tca642x.c @@ -213,6 +213,24 @@ static int tca642x_info(uchar chip) return 0; } +static int tca642x_get_bank(int pin) +{ + int gpio_bank; + + if (pin <= 7) { + gpio_bank = 0; + } else if ((pin >= 10) && (pin <= 17)) { + gpio_bank = 1; + } else if ((pin >= 20) && (pin <= 27)) { + gpio_bank = 2; + } else { + printf("Requested pin is not available\n"); + gpio_bank = -1; + } + + return gpio_bank; +} + static struct cmd_tbl cmd_tca642x[] = { U_BOOT_CMD_MKENT(device, 3, 0, (void *)TCA642X_CMD_DEVICE, "", ""), U_BOOT_CMD_MKENT(output, 4, 0, (void *)TCA642X_CMD_OUTPUT, "", ""), @@ -226,7 +244,7 @@ static int do_tca642x(struct cmd_tbl *cmdtp, int flag, int argc, { static uchar chip = CONFIG_SYS_I2C_TCA642X_ADDR; int ret = CMD_RET_USAGE, val; - uint8_t gpio_bank = 0; + int gpio_bank = 0; uint8_t bank_shift; ulong ul_arg2 = 0; ulong ul_arg3 = 0; @@ -247,20 +265,8 @@ static int do_tca642x(struct cmd_tbl *cmdtp, int flag, int argc, ul_arg2 = simple_strtoul(argv[2], NULL, 10); /* arg3 used as pin or invert value */ - if (argc > 3) { + if (argc > 3) ul_arg3 = simple_strtoul(argv[3], NULL, 10) & 0x1; - if (ul_arg2 <= 7) { - gpio_bank = 0; - } else if ((ul_arg2 >= 10) && (ul_arg2 <= 17)) { - gpio_bank = 1; - } else if ((ul_arg2 >= 20) && (ul_arg2 <= 27)) { - gpio_bank = 2; - } else { - printf("Requested pin is not available\n"); - ret = CMD_RET_FAILURE; - goto error; - } - } switch ((int)c->cmd) { case TCA642X_CMD_INFO: @@ -277,6 +283,11 @@ static int do_tca642x(struct cmd_tbl *cmdtp, int flag, int argc, break; case TCA642X_CMD_INPUT: + gpio_bank = tca642x_get_bank(ul_arg2); + if (gpio_bank < 0) { + ret = CMD_RET_FAILURE; + goto error; + } bank_shift = ul_arg2 - (gpio_bank * 10); ret = tca642x_set_dir(chip, gpio_bank, (1 << bank_shift), TCA642X_DIR_IN << bank_shift); @@ -291,6 +302,11 @@ static int do_tca642x(struct cmd_tbl *cmdtp, int flag, int argc, break; case TCA642X_CMD_OUTPUT: + gpio_bank = tca642x_get_bank(ul_arg2); + if (gpio_bank < 0) { + ret = CMD_RET_FAILURE; + goto error; + } bank_shift = ul_arg2 - (gpio_bank * 10); ret = tca642x_set_dir(chip, gpio_bank, (1 << bank_shift), (TCA642X_DIR_OUT << bank_shift)); @@ -303,6 +319,11 @@ static int do_tca642x(struct cmd_tbl *cmdtp, int flag, int argc, break; case TCA642X_CMD_INVERT: + gpio_bank = tca642x_get_bank(ul_arg2); + if (gpio_bank < 0) { + ret = CMD_RET_FAILURE; + goto error; + } bank_shift = ul_arg2 - (gpio_bank * 10); ret = tca642x_set_pol(chip, gpio_bank, (1 << bank_shift), (ul_arg3 << bank_shift)); From 705082d4b1a2040c9f1ff2a7d5c4f2fccafde4bc Mon Sep 17 00:00:00 2001 From: Ovidiu Panait Date: Sat, 28 Nov 2020 10:11:28 +0200 Subject: [PATCH 06/42] spi: ti_qspi: Fix "spi-max-frequency" error path in ti_qspi_ofdata_to_platdata struct ti_qspi_priv->max_hz is declared as unsigned int, so the following error path check will always be false, even when "spi-max-frequency" property is invalid/missing: priv->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", -1); if (priv->max_hz < 0) { ... } Replace the fdtdec call with dev_read_u32_default() and use 0 as the default value. Error out if max_hz is zero. Signed-off-by: Ovidiu Panait --- drivers/spi/ti_qspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c index 7c3b1f7b88..76bc480f43 100644 --- a/drivers/spi/ti_qspi.c +++ b/drivers/spi/ti_qspi.c @@ -467,8 +467,8 @@ static int ti_qspi_of_to_plat(struct udevice *bus) priv->memory_map = map_physmem(mmap_addr, mmap_size, MAP_NOCACHE); priv->mmap_size = mmap_size; - priv->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", -1); - if (priv->max_hz < 0) { + priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 0); + if (!priv->max_hz) { debug("Error: Max frequency missing\n"); return -ENODEV; } From f3f83ad4caf4f4fb2394d70585a20ce56b552c5e Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Sun, 29 Nov 2020 12:53:05 +0530 Subject: [PATCH 07/42] spi: omap3_spi: Fix speed and mode selection McSPI IP provides per CS specific speed and mode selection. Therefore it is possible to apply these settings only after CS is known. But set_speed and set_mode can be called without bus being claimed, this would lead driver to set up wrong CS (or previously used CS). Fix this by apply set_speed and set_mode only if bus is already claimed. Signed-off-by: Vignesh Raghavendra Tested-by: Miquel Raynal --- drivers/spi/omap3_spi.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 78e2a25cdb..74931768c0 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -37,6 +37,8 @@ struct omap3_spi_priv { unsigned int mode; unsigned int wordlen; unsigned int pin_dir:1; + + bool bus_claimed; }; static void omap3_spi_write_chconf(struct omap3_spi_priv *priv, int val) @@ -372,6 +374,8 @@ static void _omap3_spi_claim_bus(struct omap3_spi_priv *priv) conf |= OMAP3_MCSPI_MODULCTRL_SINGLE; writel(conf, &priv->regs->modulctrl); + + priv->bus_claimed = true; } static int omap3_spi_claim_bus(struct udevice *dev) @@ -381,9 +385,12 @@ static int omap3_spi_claim_bus(struct udevice *dev) struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); priv->cs = slave_plat->cs; - priv->freq = slave_plat->max_hz; + if (!priv->freq) + priv->freq = slave_plat->max_hz; _omap3_spi_claim_bus(priv); + _omap3_spi_set_speed(priv); + _omap3_spi_set_mode(priv); return 0; } @@ -395,6 +402,8 @@ static int omap3_spi_release_bus(struct udevice *dev) writel(OMAP3_MCSPI_MODULCTRL_MS, &priv->regs->modulctrl); + priv->bus_claimed = false; + return 0; } @@ -440,7 +449,8 @@ static int omap3_spi_set_speed(struct udevice *dev, unsigned int speed) struct omap3_spi_priv *priv = dev_get_priv(dev); priv->freq = speed; - _omap3_spi_set_speed(priv); + if (priv->bus_claimed) + _omap3_spi_set_speed(priv); return 0; } @@ -451,7 +461,8 @@ static int omap3_spi_set_mode(struct udevice *dev, uint mode) priv->mode = mode; - _omap3_spi_set_mode(priv); + if (priv->bus_claimed) + _omap3_spi_set_mode(priv); return 0; } From 9c789fec10672be122cfc41977f7d2bc2a6b0d5b Mon Sep 17 00:00:00 2001 From: Praneeth Bajjuri Date: Thu, 3 Dec 2020 17:43:47 -0600 Subject: [PATCH 08/42] arm: dts: k3-j721e: ddr: Update to 0.5.0 version of DDR config tool Update the ddr settings to use the DDR reg config tool rev 0.5.0. This enables 4266MTs DDR configuration. Signed-off-by: Praneeth Bajjuri Signed-off-by: Kevin Scholz --- ...33.dtsi => k3-j721e-ddr-evm-lp4-4266.dtsi} | 436 +++++++++--------- .../arm/dts/k3-j721e-r5-common-proc-board.dts | 2 +- 2 files changed, 219 insertions(+), 219 deletions(-) rename arch/arm/dts/{k3-j721e-ddr-evm-lp4-3733.dtsi => k3-j721e-ddr-evm-lp4-4266.dtsi} (90%) diff --git a/arch/arm/dts/k3-j721e-ddr-evm-lp4-3733.dtsi b/arch/arm/dts/k3-j721e-ddr-evm-lp4-4266.dtsi similarity index 90% rename from arch/arm/dts/k3-j721e-ddr-evm-lp4-3733.dtsi rename to arch/arm/dts/k3-j721e-ddr-evm-lp4-4266.dtsi index 5ac32a0ffa..ca05e06e93 100644 --- a/arch/arm/dts/k3-j721e-ddr-evm-lp4-3733.dtsi +++ b/arch/arm/dts/k3-j721e-ddr-evm-lp4-4266.dtsi @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ - * This file was generated by the AM752x_DRA82x_TDA4x_DDRSS_RegConfigTool, Revision: 0.2.0 - * This file was generated on 10/09/2019 + * This file was generated by the Jacinto7_DDRSS_RegConfigTool, Revision: 0.5.0 + * This file was generated on 09/25/2020 */ #define DDRSS_PLL_FHS_CNT 10 -#define DDRSS_PLL_FREQUENCY_1 933000000 -#define DDRSS_PLL_FREQUENCY_2 933000000 +#define DDRSS_PLL_FREQUENCY_1 1066500000 +#define DDRSS_PLL_FREQUENCY_2 1066500000 #define DDRSS_CTL_00_DATA 0x00000B00 #define DDRSS_CTL_01_DATA 0x00000000 @@ -20,14 +20,14 @@ #define DDRSS_CTL_08_DATA 0x000186A0 #define DDRSS_CTL_09_DATA 0x00000005 #define DDRSS_CTL_10_DATA 0x00000064 -#define DDRSS_CTL_11_DATA 0x0005B18F -#define DDRSS_CTL_12_DATA 0x0038EF90 +#define DDRSS_CTL_11_DATA 0x000681C8 +#define DDRSS_CTL_12_DATA 0x004111C9 #define DDRSS_CTL_13_DATA 0x00000005 -#define DDRSS_CTL_14_DATA 0x00000E94 -#define DDRSS_CTL_15_DATA 0x0005B18F -#define DDRSS_CTL_16_DATA 0x0038EF90 +#define DDRSS_CTL_14_DATA 0x000010A9 +#define DDRSS_CTL_15_DATA 0x000681C8 +#define DDRSS_CTL_16_DATA 0x004111C9 #define DDRSS_CTL_17_DATA 0x00000005 -#define DDRSS_CTL_18_DATA 0x00000E94 +#define DDRSS_CTL_18_DATA 0x000010A9 #define DDRSS_CTL_19_DATA 0x01010000 #define DDRSS_CTL_20_DATA 0x02011001 #define DDRSS_CTL_21_DATA 0x02010000 @@ -37,66 +37,66 @@ #define DDRSS_CTL_25_DATA 0x00000000 #define DDRSS_CTL_26_DATA 0x00000000 #define DDRSS_CTL_27_DATA 0x02020200 -#define DDRSS_CTL_28_DATA 0x00004B4B +#define DDRSS_CTL_28_DATA 0x00005656 #define DDRSS_CTL_29_DATA 0x00100000 #define DDRSS_CTL_30_DATA 0x00000000 #define DDRSS_CTL_31_DATA 0x00000000 #define DDRSS_CTL_32_DATA 0x00000000 #define DDRSS_CTL_33_DATA 0x00000000 #define DDRSS_CTL_34_DATA 0x040C0000 -#define DDRSS_CTL_35_DATA 0x10401040 +#define DDRSS_CTL_35_DATA 0x12481248 #define DDRSS_CTL_36_DATA 0x00050804 #define DDRSS_CTL_37_DATA 0x09040008 -#define DDRSS_CTL_38_DATA 0x12000204 -#define DDRSS_CTL_39_DATA 0x1854007A -#define DDRSS_CTL_40_DATA 0x12003A26 -#define DDRSS_CTL_41_DATA 0x1854007A -#define DDRSS_CTL_42_DATA 0x20003A26 +#define DDRSS_CTL_38_DATA 0x15000204 +#define DDRSS_CTL_39_DATA 0x1B60008B +#define DDRSS_CTL_40_DATA 0x1500422B +#define DDRSS_CTL_41_DATA 0x1B60008B +#define DDRSS_CTL_42_DATA 0x2000422B #define DDRSS_CTL_43_DATA 0x000A0A09 #define DDRSS_CTL_44_DATA 0x040006DB -#define DDRSS_CTL_45_DATA 0x1B130F04 -#define DDRSS_CTL_46_DATA 0x0E00FFCD -#define DDRSS_CTL_47_DATA 0x1B130F0E -#define DDRSS_CTL_48_DATA 0x0E00FFCD -#define DDRSS_CTL_49_DATA 0x0203040E -#define DDRSS_CTL_50_DATA 0x26040500 -#define DDRSS_CTL_51_DATA 0x08282628 +#define DDRSS_CTL_45_DATA 0x1E161104 +#define DDRSS_CTL_46_DATA 0x10012458 +#define DDRSS_CTL_47_DATA 0x1E161110 +#define DDRSS_CTL_48_DATA 0x10012458 +#define DDRSS_CTL_49_DATA 0x02030410 +#define DDRSS_CTL_50_DATA 0x2C040500 +#define DDRSS_CTL_51_DATA 0x082D2C2D #define DDRSS_CTL_52_DATA 0x14000D0A -#define DDRSS_CTL_53_DATA 0x03010A0A -#define DDRSS_CTL_54_DATA 0x01010003 -#define DDRSS_CTL_55_DATA 0x044E4E08 -#define DDRSS_CTL_56_DATA 0x042B2B04 -#define DDRSS_CTL_57_DATA 0x00002B2B +#define DDRSS_CTL_53_DATA 0x04010A0A +#define DDRSS_CTL_54_DATA 0x01010004 +#define DDRSS_CTL_55_DATA 0x04585808 +#define DDRSS_CTL_56_DATA 0x04313104 +#define DDRSS_CTL_57_DATA 0x00003131 #define DDRSS_CTL_58_DATA 0x00010100 #define DDRSS_CTL_59_DATA 0x03010000 #define DDRSS_CTL_60_DATA 0x00000E08 #define DDRSS_CTL_61_DATA 0x000000BB -#define DDRSS_CTL_62_DATA 0x0000020B -#define DDRSS_CTL_63_DATA 0x00001C64 -#define DDRSS_CTL_64_DATA 0x0000020B -#define DDRSS_CTL_65_DATA 0x00001C64 +#define DDRSS_CTL_62_DATA 0x00000256 +#define DDRSS_CTL_63_DATA 0x00002073 +#define DDRSS_CTL_64_DATA 0x00000256 +#define DDRSS_CTL_65_DATA 0x00002073 #define DDRSS_CTL_66_DATA 0x00000005 #define DDRSS_CTL_67_DATA 0x00030000 -#define DDRSS_CTL_68_DATA 0x00830010 -#define DDRSS_CTL_69_DATA 0x00830386 -#define DDRSS_CTL_70_DATA 0x00400386 +#define DDRSS_CTL_68_DATA 0x00950010 +#define DDRSS_CTL_69_DATA 0x00950408 +#define DDRSS_CTL_70_DATA 0x00400408 #define DDRSS_CTL_71_DATA 0x00120103 -#define DDRSS_CTL_72_DATA 0x000E0005 -#define DDRSS_CTL_73_DATA 0x2908000E -#define DDRSS_CTL_74_DATA 0x05050129 +#define DDRSS_CTL_72_DATA 0x00100005 +#define DDRSS_CTL_73_DATA 0x2F080010 +#define DDRSS_CTL_74_DATA 0x0505012F #define DDRSS_CTL_75_DATA 0x0401030A -#define DDRSS_CTL_76_DATA 0x041B0E0A -#define DDRSS_CTL_77_DATA 0x0E0A0401 -#define DDRSS_CTL_78_DATA 0x0001041B +#define DDRSS_CTL_76_DATA 0x041E100B +#define DDRSS_CTL_77_DATA 0x100B0401 +#define DDRSS_CTL_78_DATA 0x0001041E #define DDRSS_CTL_79_DATA 0x000F000F -#define DDRSS_CTL_80_DATA 0x02190219 -#define DDRSS_CTL_81_DATA 0x02190219 +#define DDRSS_CTL_80_DATA 0x02660266 +#define DDRSS_CTL_81_DATA 0x02660266 #define DDRSS_CTL_82_DATA 0x03050505 #define DDRSS_CTL_83_DATA 0x03010303 -#define DDRSS_CTL_84_DATA 0x1C0A0E0A -#define DDRSS_CTL_85_DATA 0x04040E04 -#define DDRSS_CTL_86_DATA 0x1C0A0E0A -#define DDRSS_CTL_87_DATA 0x04040E04 +#define DDRSS_CTL_84_DATA 0x200B100B +#define DDRSS_CTL_85_DATA 0x04041004 +#define DDRSS_CTL_86_DATA 0x200B100B +#define DDRSS_CTL_87_DATA 0x04041004 #define DDRSS_CTL_88_DATA 0x03010000 #define DDRSS_CTL_89_DATA 0x00010000 #define DDRSS_CTL_90_DATA 0x00000000 @@ -118,20 +118,20 @@ #define DDRSS_CTL_106_DATA 0x00002EC0 #define DDRSS_CTL_107_DATA 0x00000000 #define DDRSS_CTL_108_DATA 0x0000051D -#define DDRSS_CTL_109_DATA 0x00071900 -#define DDRSS_CTL_110_DATA 0x00071900 -#define DDRSS_CTL_111_DATA 0x00071900 -#define DDRSS_CTL_112_DATA 0x00071900 -#define DDRSS_CTL_113_DATA 0x00071900 +#define DDRSS_CTL_109_DATA 0x00081CC0 +#define DDRSS_CTL_110_DATA 0x00081CC0 +#define DDRSS_CTL_111_DATA 0x00081CC0 +#define DDRSS_CTL_112_DATA 0x00081CC0 +#define DDRSS_CTL_113_DATA 0x00081CC0 #define DDRSS_CTL_114_DATA 0x00000000 -#define DDRSS_CTL_115_DATA 0x0000C6BC -#define DDRSS_CTL_116_DATA 0x00071900 -#define DDRSS_CTL_117_DATA 0x00071900 -#define DDRSS_CTL_118_DATA 0x00071900 -#define DDRSS_CTL_119_DATA 0x00071900 -#define DDRSS_CTL_120_DATA 0x00071900 +#define DDRSS_CTL_115_DATA 0x0000E325 +#define DDRSS_CTL_116_DATA 0x00081CC0 +#define DDRSS_CTL_117_DATA 0x00081CC0 +#define DDRSS_CTL_118_DATA 0x00081CC0 +#define DDRSS_CTL_119_DATA 0x00081CC0 +#define DDRSS_CTL_120_DATA 0x00081CC0 #define DDRSS_CTL_121_DATA 0x00000000 -#define DDRSS_CTL_122_DATA 0x0000C6BC +#define DDRSS_CTL_122_DATA 0x0000E325 #define DDRSS_CTL_123_DATA 0x00000000 #define DDRSS_CTL_124_DATA 0x00000000 #define DDRSS_CTL_125_DATA 0x00000000 @@ -140,8 +140,8 @@ #define DDRSS_CTL_128_DATA 0x00000000 #define DDRSS_CTL_129_DATA 0x00000000 #define DDRSS_CTL_130_DATA 0x00000000 -#define DDRSS_CTL_131_DATA 0x0A030500 -#define DDRSS_CTL_132_DATA 0x00040A04 +#define DDRSS_CTL_131_DATA 0x0B030500 +#define DDRSS_CTL_132_DATA 0x00040B04 #define DDRSS_CTL_133_DATA 0x0A090000 #define DDRSS_CTL_134_DATA 0x0A090701 #define DDRSS_CTL_135_DATA 0x0900000E @@ -176,23 +176,23 @@ #define DDRSS_CTL_164_DATA 0x000A0000 #define DDRSS_CTL_165_DATA 0x000D0005 #define DDRSS_CTL_166_DATA 0x000D0404 -#define DDRSS_CTL_167_DATA 0x00BB0176 -#define DDRSS_CTL_168_DATA 0x0E0E01D3 -#define DDRSS_CTL_169_DATA 0x017601D3 -#define DDRSS_CTL_170_DATA 0x01D300BB -#define DDRSS_CTL_171_DATA 0x01D30E0E +#define DDRSS_CTL_167_DATA 0x00D601AB +#define DDRSS_CTL_168_DATA 0x10100216 +#define DDRSS_CTL_169_DATA 0x01AB0216 +#define DDRSS_CTL_170_DATA 0x021600D6 +#define DDRSS_CTL_171_DATA 0x02161010 #define DDRSS_CTL_172_DATA 0x00000000 #define DDRSS_CTL_173_DATA 0x00000000 #define DDRSS_CTL_174_DATA 0x00000000 -#define DDRSS_CTL_175_DATA 0x36E40084 -#define DDRSS_CTL_176_DATA 0x330036E4 +#define DDRSS_CTL_175_DATA 0x3FF40084 +#define DDRSS_CTL_176_DATA 0x33003FF4 #define DDRSS_CTL_177_DATA 0x00003333 #define DDRSS_CTL_178_DATA 0x56000000 #define DDRSS_CTL_179_DATA 0x27270056 #define DDRSS_CTL_180_DATA 0x0F0F0000 #define DDRSS_CTL_181_DATA 0x00000000 #define DDRSS_CTL_182_DATA 0x00840606 -#define DDRSS_CTL_183_DATA 0x36E436E4 +#define DDRSS_CTL_183_DATA 0x3FF43FF4 #define DDRSS_CTL_184_DATA 0x33333300 #define DDRSS_CTL_185_DATA 0x00000000 #define DDRSS_CTL_186_DATA 0x00565600 @@ -270,12 +270,12 @@ #define DDRSS_CTL_258_DATA 0x00320040 #define DDRSS_CTL_259_DATA 0x00020008 #define DDRSS_CTL_260_DATA 0x00400100 -#define DDRSS_CTL_261_DATA 0x0038074A +#define DDRSS_CTL_261_DATA 0x00400855 #define DDRSS_CTL_262_DATA 0x01000200 -#define DDRSS_CTL_263_DATA 0x074A0040 -#define DDRSS_CTL_264_DATA 0x00000038 -#define DDRSS_CTL_265_DATA 0x005E0003 -#define DDRSS_CTL_266_DATA 0x0100005E +#define DDRSS_CTL_263_DATA 0x08550040 +#define DDRSS_CTL_264_DATA 0x00000040 +#define DDRSS_CTL_265_DATA 0x006B0003 +#define DDRSS_CTL_266_DATA 0x0100006B #define DDRSS_CTL_267_DATA 0x00000000 #define DDRSS_CTL_268_DATA 0x01010000 #define DDRSS_CTL_269_DATA 0x00000202 @@ -327,15 +327,15 @@ #define DDRSS_CTL_315_DATA 0x01000101 #define DDRSS_CTL_316_DATA 0x01010001 #define DDRSS_CTL_317_DATA 0x00010101 -#define DDRSS_CTL_318_DATA 0x05090903 -#define DDRSS_CTL_319_DATA 0x0E081B1B -#define DDRSS_CTL_320_DATA 0x0009030E -#define DDRSS_CTL_321_DATA 0x0A0D030F -#define DDRSS_CTL_322_DATA 0x0A0D0306 -#define DDRSS_CTL_323_DATA 0x0D090006 -#define DDRSS_CTL_324_DATA 0x0100000D -#define DDRSS_CTL_325_DATA 0x07030701 -#define DDRSS_CTL_326_DATA 0x00000003 +#define DDRSS_CTL_318_DATA 0x050A0A03 +#define DDRSS_CTL_319_DATA 0x10081F1F +#define DDRSS_CTL_320_DATA 0x00090310 +#define DDRSS_CTL_321_DATA 0x0B0C030F +#define DDRSS_CTL_322_DATA 0x0B0C0306 +#define DDRSS_CTL_323_DATA 0x0C090006 +#define DDRSS_CTL_324_DATA 0x0100000C +#define DDRSS_CTL_325_DATA 0x08040801 +#define DDRSS_CTL_326_DATA 0x00000004 #define DDRSS_CTL_327_DATA 0x00000000 #define DDRSS_CTL_328_DATA 0x00010000 #define DDRSS_CTL_329_DATA 0x00280D00 @@ -396,7 +396,7 @@ #define DDRSS_CTL_384_DATA 0x00000000 #define DDRSS_CTL_385_DATA 0x00000000 #define DDRSS_CTL_386_DATA 0x00000000 -#define DDRSS_CTL_387_DATA 0x37371B00 +#define DDRSS_CTL_387_DATA 0x3A3A1B00 #define DDRSS_CTL_388_DATA 0x000A0000 #define DDRSS_CTL_389_DATA 0x00000176 #define DDRSS_CTL_390_DATA 0x00000200 @@ -406,22 +406,22 @@ #define DDRSS_CTL_394_DATA 0x00000462 #define DDRSS_CTL_395_DATA 0x00000E9C #define DDRSS_CTL_396_DATA 0x00000204 -#define DDRSS_CTL_397_DATA 0x000038C8 +#define DDRSS_CTL_397_DATA 0x000040E6 #define DDRSS_CTL_398_DATA 0x00000200 #define DDRSS_CTL_399_DATA 0x00000200 #define DDRSS_CTL_400_DATA 0x00000200 #define DDRSS_CTL_401_DATA 0x00000200 -#define DDRSS_CTL_402_DATA 0x0000AA58 -#define DDRSS_CTL_403_DATA 0x000237D0 -#define DDRSS_CTL_404_DATA 0x00000C12 -#define DDRSS_CTL_405_DATA 0x000038C8 +#define DDRSS_CTL_402_DATA 0x0000C2B2 +#define DDRSS_CTL_403_DATA 0x000288FC +#define DDRSS_CTL_404_DATA 0x00000E15 +#define DDRSS_CTL_405_DATA 0x000040E6 #define DDRSS_CTL_406_DATA 0x00000200 #define DDRSS_CTL_407_DATA 0x00000200 #define DDRSS_CTL_408_DATA 0x00000200 #define DDRSS_CTL_409_DATA 0x00000200 -#define DDRSS_CTL_410_DATA 0x0000AA58 -#define DDRSS_CTL_411_DATA 0x000237D0 -#define DDRSS_CTL_412_DATA 0x02020C12 +#define DDRSS_CTL_410_DATA 0x0000C2B2 +#define DDRSS_CTL_411_DATA 0x000288FC +#define DDRSS_CTL_412_DATA 0x02020E15 #define DDRSS_CTL_413_DATA 0x03030202 #define DDRSS_CTL_414_DATA 0x00000022 #define DDRSS_CTL_415_DATA 0x00000000 @@ -432,13 +432,13 @@ #define DDRSS_CTL_420_DATA 0x00000000 #define DDRSS_CTL_421_DATA 0x00030000 #define DDRSS_CTL_422_DATA 0x0006001E -#define DDRSS_CTL_423_DATA 0x00190031 -#define DDRSS_CTL_424_DATA 0x00190031 +#define DDRSS_CTL_423_DATA 0x001B0033 +#define DDRSS_CTL_424_DATA 0x001B0033 #define DDRSS_CTL_425_DATA 0x00000000 #define DDRSS_CTL_426_DATA 0x00000000 #define DDRSS_CTL_427_DATA 0x02000000 #define DDRSS_CTL_428_DATA 0x01000404 -#define DDRSS_CTL_429_DATA 0x091A091A +#define DDRSS_CTL_429_DATA 0x0B1E0B1E #define DDRSS_CTL_430_DATA 0x00000105 #define DDRSS_CTL_431_DATA 0x00010101 #define DDRSS_CTL_432_DATA 0x00010101 @@ -447,8 +447,8 @@ #define DDRSS_CTL_435_DATA 0x02000201 #define DDRSS_CTL_436_DATA 0x02010000 #define DDRSS_CTL_437_DATA 0x00000200 -#define DDRSS_CTL_438_DATA 0x22060000 -#define DDRSS_CTL_439_DATA 0x00000122 +#define DDRSS_CTL_438_DATA 0x28060000 +#define DDRSS_CTL_439_DATA 0x00000128 #define DDRSS_CTL_440_DATA 0xFFFFFFFF #define DDRSS_CTL_441_DATA 0xFFFFFFFF #define DDRSS_CTL_442_DATA 0x00000000 @@ -515,7 +515,7 @@ #define DDRSS_PI_43_DATA 0x00000000 #define DDRSS_PI_44_DATA 0x00000000 #define DDRSS_PI_45_DATA 0x000F0F00 -#define DDRSS_PI_46_DATA 0x00000019 +#define DDRSS_PI_46_DATA 0x0000001B #define DDRSS_PI_47_DATA 0x000007D0 #define DDRSS_PI_48_DATA 0x00000300 #define DDRSS_PI_49_DATA 0x00000000 @@ -535,13 +535,13 @@ #define DDRSS_PI_63_DATA 0x01000404 #define DDRSS_PI_64_DATA 0x00000000 #define DDRSS_PI_65_DATA 0x00000000 -#define DDRSS_PI_66_DATA 0x00000101 +#define DDRSS_PI_66_DATA 0x00000100 #define DDRSS_PI_67_DATA 0x0001010F #define DDRSS_PI_68_DATA 0x00340000 #define DDRSS_PI_69_DATA 0x00000000 #define DDRSS_PI_70_DATA 0x00000000 -#define DDRSS_PI_71_DATA 0x00000000 -#define DDRSS_PI_72_DATA 0x01000000 +#define DDRSS_PI_71_DATA 0x0000FFFF +#define DDRSS_PI_72_DATA 0x00000000 #define DDRSS_PI_73_DATA 0x00080100 #define DDRSS_PI_74_DATA 0x02000200 #define DDRSS_PI_75_DATA 0x01000100 @@ -632,18 +632,18 @@ #define DDRSS_PI_160_DATA 0x00000000 #define DDRSS_PI_161_DATA 0x00010000 #define DDRSS_PI_162_DATA 0x00000000 -#define DDRSS_PI_163_DATA 0x26260100 +#define DDRSS_PI_163_DATA 0x2B2B0100 #define DDRSS_PI_164_DATA 0x00000034 -#define DDRSS_PI_165_DATA 0x0000005E -#define DDRSS_PI_166_DATA 0x0002005E +#define DDRSS_PI_165_DATA 0x00000064 +#define DDRSS_PI_166_DATA 0x00020064 #define DDRSS_PI_167_DATA 0x02000200 -#define DDRSS_PI_168_DATA 0x40100C04 -#define DDRSS_PI_169_DATA 0x000E4010 +#define DDRSS_PI_168_DATA 0x48120C04 +#define DDRSS_PI_169_DATA 0x000E4812 #define DDRSS_PI_170_DATA 0x000000BB -#define DDRSS_PI_171_DATA 0x0000020B -#define DDRSS_PI_172_DATA 0x00001C64 -#define DDRSS_PI_173_DATA 0x0000020B -#define DDRSS_PI_174_DATA 0x04001C64 +#define DDRSS_PI_171_DATA 0x00000256 +#define DDRSS_PI_172_DATA 0x00002073 +#define DDRSS_PI_173_DATA 0x00000256 +#define DDRSS_PI_174_DATA 0x04002073 #define DDRSS_PI_175_DATA 0x01010404 #define DDRSS_PI_176_DATA 0x00001501 #define DDRSS_PI_177_DATA 0x00150015 @@ -654,80 +654,80 @@ #define DDRSS_PI_182_DATA 0x00000101 #define DDRSS_PI_183_DATA 0x00000000 #define DDRSS_PI_184_DATA 0x00000000 -#define DDRSS_PI_185_DATA 0x12040000 -#define DDRSS_PI_186_DATA 0x0C0C0212 +#define DDRSS_PI_185_DATA 0x15040000 +#define DDRSS_PI_186_DATA 0x0E0E0215 #define DDRSS_PI_187_DATA 0x00040402 #define DDRSS_PI_188_DATA 0x000C8034 -#define DDRSS_PI_189_DATA 0x001F0047 -#define DDRSS_PI_190_DATA 0x001F0047 +#define DDRSS_PI_189_DATA 0x00218049 +#define DDRSS_PI_190_DATA 0x00218049 #define DDRSS_PI_191_DATA 0x01010101 -#define DDRSS_PI_192_DATA 0x0003000D -#define DDRSS_PI_193_DATA 0x000301D3 -#define DDRSS_PI_194_DATA 0x010001D3 +#define DDRSS_PI_192_DATA 0x0004000D +#define DDRSS_PI_193_DATA 0x00040216 +#define DDRSS_PI_194_DATA 0x01000216 #define DDRSS_PI_195_DATA 0x000E000E -#define DDRSS_PI_196_DATA 0x01D40100 -#define DDRSS_PI_197_DATA 0x010001D4 -#define DDRSS_PI_198_DATA 0x01D401D4 +#define DDRSS_PI_196_DATA 0x02170100 +#define DDRSS_PI_197_DATA 0x01000217 +#define DDRSS_PI_198_DATA 0x02170217 #define DDRSS_PI_199_DATA 0x32103200 #define DDRSS_PI_200_DATA 0x01013210 #define DDRSS_PI_201_DATA 0x0A070601 -#define DDRSS_PI_202_DATA 0x1C11090D -#define DDRSS_PI_203_DATA 0x1C110913 -#define DDRSS_PI_204_DATA 0x0000C013 +#define DDRSS_PI_202_DATA 0x1F130A0D +#define DDRSS_PI_203_DATA 0x1F130A14 +#define DDRSS_PI_204_DATA 0x0000C014 #define DDRSS_PI_205_DATA 0x00C01000 #define DDRSS_PI_206_DATA 0x00C01000 #define DDRSS_PI_207_DATA 0x00021000 -#define DDRSS_PI_208_DATA 0x0021000D -#define DDRSS_PI_209_DATA 0x002101D3 -#define DDRSS_PI_210_DATA 0x001101D3 +#define DDRSS_PI_208_DATA 0x0024000D +#define DDRSS_PI_209_DATA 0x00240216 +#define DDRSS_PI_210_DATA 0x00110216 #define DDRSS_PI_211_DATA 0x32000056 -#define DDRSS_PI_212_DATA 0x00000101 -#define DDRSS_PI_213_DATA 0x005A0035 -#define DDRSS_PI_214_DATA 0x01013212 -#define DDRSS_PI_215_DATA 0x00003500 -#define DDRSS_PI_216_DATA 0x3212005A -#define DDRSS_PI_217_DATA 0x09000101 +#define DDRSS_PI_212_DATA 0x00000301 +#define DDRSS_PI_213_DATA 0x005B003A +#define DDRSS_PI_214_DATA 0x03013212 +#define DDRSS_PI_215_DATA 0x00003A00 +#define DDRSS_PI_216_DATA 0x3212005B +#define DDRSS_PI_217_DATA 0x09000301 #define DDRSS_PI_218_DATA 0x04010504 #define DDRSS_PI_219_DATA 0x0400062B #define DDRSS_PI_220_DATA 0x0A032001 -#define DDRSS_PI_221_DATA 0x262B0F0A -#define DDRSS_PI_222_DATA 0x00002819 -#define DDRSS_PI_223_DATA 0x5400E638 -#define DDRSS_PI_224_DATA 0x1B1C2007 -#define DDRSS_PI_225_DATA 0x262B0F13 -#define DDRSS_PI_226_DATA 0x00002819 -#define DDRSS_PI_227_DATA 0x5400E638 -#define DDRSS_PI_228_DATA 0x1B1C2007 -#define DDRSS_PI_229_DATA 0x00017613 +#define DDRSS_PI_221_DATA 0x2C31110A +#define DDRSS_PI_222_DATA 0x00002D1C +#define DDRSS_PI_223_DATA 0x6001071C +#define DDRSS_PI_224_DATA 0x1E202008 +#define DDRSS_PI_225_DATA 0x2C311116 +#define DDRSS_PI_226_DATA 0x00002D1C +#define DDRSS_PI_227_DATA 0x6001071C +#define DDRSS_PI_228_DATA 0x1E202008 +#define DDRSS_PI_229_DATA 0x00017616 #define DDRSS_PI_230_DATA 0x00000E9C -#define DDRSS_PI_231_DATA 0x000038C8 -#define DDRSS_PI_232_DATA 0x000237D0 -#define DDRSS_PI_233_DATA 0x000038C8 -#define DDRSS_PI_234_DATA 0x000237D0 -#define DDRSS_PI_235_DATA 0x0219000F -#define DDRSS_PI_236_DATA 0x03030219 +#define DDRSS_PI_231_DATA 0x000040E6 +#define DDRSS_PI_232_DATA 0x000288FC +#define DDRSS_PI_233_DATA 0x000040E6 +#define DDRSS_PI_234_DATA 0x000288FC +#define DDRSS_PI_235_DATA 0x0266000F +#define DDRSS_PI_236_DATA 0x03030266 #define DDRSS_PI_237_DATA 0x00271003 #define DDRSS_PI_238_DATA 0x000186A0 #define DDRSS_PI_239_DATA 0x00000005 #define DDRSS_PI_240_DATA 0x00000064 #define DDRSS_PI_241_DATA 0x0000000F -#define DDRSS_PI_242_DATA 0x0005B18F +#define DDRSS_PI_242_DATA 0x000681C8 #define DDRSS_PI_243_DATA 0x000186A0 #define DDRSS_PI_244_DATA 0x00000005 -#define DDRSS_PI_245_DATA 0x00000E94 -#define DDRSS_PI_246_DATA 0x00000219 -#define DDRSS_PI_247_DATA 0x0005B18F +#define DDRSS_PI_245_DATA 0x000010A9 +#define DDRSS_PI_246_DATA 0x00000266 +#define DDRSS_PI_247_DATA 0x000681C8 #define DDRSS_PI_248_DATA 0x000186A0 #define DDRSS_PI_249_DATA 0x00000005 -#define DDRSS_PI_250_DATA 0x00000E94 -#define DDRSS_PI_251_DATA 0x01000219 +#define DDRSS_PI_250_DATA 0x000010A9 +#define DDRSS_PI_251_DATA 0x01000266 #define DDRSS_PI_252_DATA 0x00320040 #define DDRSS_PI_253_DATA 0x00010008 -#define DDRSS_PI_254_DATA 0x074A0040 -#define DDRSS_PI_255_DATA 0x00010038 -#define DDRSS_PI_256_DATA 0x074A0040 -#define DDRSS_PI_257_DATA 0x00000338 -#define DDRSS_PI_258_DATA 0x005E005E +#define DDRSS_PI_254_DATA 0x08550040 +#define DDRSS_PI_255_DATA 0x00010040 +#define DDRSS_PI_256_DATA 0x08550040 +#define DDRSS_PI_257_DATA 0x00000340 +#define DDRSS_PI_258_DATA 0x006B006B #define DDRSS_PI_259_DATA 0x00040404 #define DDRSS_PI_260_DATA 0x00000055 #define DDRSS_PI_261_DATA 0x55003C5A @@ -746,27 +746,27 @@ #define DDRSS_PI_274_DATA 0x00000000 #define DDRSS_PI_275_DATA 0x00330084 #define DDRSS_PI_276_DATA 0x00160000 -#define DDRSS_PI_277_DATA 0x563336E4 +#define DDRSS_PI_277_DATA 0x56333FF4 #define DDRSS_PI_278_DATA 0x00160F27 -#define DDRSS_PI_279_DATA 0x563336E4 +#define DDRSS_PI_279_DATA 0x56333FF4 #define DDRSS_PI_280_DATA 0x00160F27 #define DDRSS_PI_281_DATA 0x00330084 #define DDRSS_PI_282_DATA 0x00160000 -#define DDRSS_PI_283_DATA 0x563336E4 +#define DDRSS_PI_283_DATA 0x56333FF4 #define DDRSS_PI_284_DATA 0x00160F27 -#define DDRSS_PI_285_DATA 0x563336E4 +#define DDRSS_PI_285_DATA 0x56333FF4 #define DDRSS_PI_286_DATA 0x00160F27 #define DDRSS_PI_287_DATA 0x00330084 #define DDRSS_PI_288_DATA 0x00160000 -#define DDRSS_PI_289_DATA 0x563336E4 +#define DDRSS_PI_289_DATA 0x56333FF4 #define DDRSS_PI_290_DATA 0x00160F27 -#define DDRSS_PI_291_DATA 0x563336E4 +#define DDRSS_PI_291_DATA 0x56333FF4 #define DDRSS_PI_292_DATA 0x00160F27 #define DDRSS_PI_293_DATA 0x00330084 #define DDRSS_PI_294_DATA 0x00160000 -#define DDRSS_PI_295_DATA 0x563336E4 +#define DDRSS_PI_295_DATA 0x56333FF4 #define DDRSS_PI_296_DATA 0x00160F27 -#define DDRSS_PI_297_DATA 0x563336E4 +#define DDRSS_PI_297_DATA 0x56333FF4 #define DDRSS_PI_298_DATA 0x00160F27 #define DDRSS_PI_299_DATA 0x00000000 @@ -787,7 +787,7 @@ #define DDRSS_PHY_14_DATA 0x060100CC #define DDRSS_PHY_15_DATA 0x00030066 #define DDRSS_PHY_16_DATA 0x00000000 -#define DDRSS_PHY_17_DATA 0x00000001 +#define DDRSS_PHY_17_DATA 0x00000301 #define DDRSS_PHY_18_DATA 0x0000AAAA #define DDRSS_PHY_19_DATA 0x00005555 #define DDRSS_PHY_20_DATA 0x0000B5B5 @@ -803,7 +803,7 @@ #define DDRSS_PHY_30_DATA 0x0F000000 #define DDRSS_PHY_31_DATA 0x00000F0F #define DDRSS_PHY_32_DATA 0x10200000 -#define DDRSS_PHY_33_DATA 0x0C002004 +#define DDRSS_PHY_33_DATA 0x0C002007 #define DDRSS_PHY_34_DATA 0x00000000 #define DDRSS_PHY_35_DATA 0x00000000 #define DDRSS_PHY_36_DATA 0x55555555 @@ -855,35 +855,35 @@ #define DDRSS_PHY_82_DATA 0x00000000 #define DDRSS_PHY_83_DATA 0x00000100 #define DDRSS_PHY_84_DATA 0x01CC0C01 -#define DDRSS_PHY_85_DATA 0x0003CC0C +#define DDRSS_PHY_85_DATA 0x1003CC0C #define DDRSS_PHY_86_DATA 0x20000140 #define DDRSS_PHY_87_DATA 0x07FF0200 #define DDRSS_PHY_88_DATA 0x0000DD01 #define DDRSS_PHY_89_DATA 0x10100303 #define DDRSS_PHY_90_DATA 0x10101010 #define DDRSS_PHY_91_DATA 0x10101010 -#define DDRSS_PHY_92_DATA 0x00041010 +#define DDRSS_PHY_92_DATA 0x00021010 #define DDRSS_PHY_93_DATA 0x00100010 #define DDRSS_PHY_94_DATA 0x00100010 #define DDRSS_PHY_95_DATA 0x00100010 #define DDRSS_PHY_96_DATA 0x00100010 #define DDRSS_PHY_97_DATA 0x00050010 #define DDRSS_PHY_98_DATA 0x51517041 -#define DDRSS_PHY_99_DATA 0x31C06000 +#define DDRSS_PHY_99_DATA 0x31C06001 #define DDRSS_PHY_100_DATA 0x07AB0340 #define DDRSS_PHY_101_DATA 0x00C0C001 -#define DDRSS_PHY_102_DATA 0x0D0C0001 +#define DDRSS_PHY_102_DATA 0x0E0D0001 #define DDRSS_PHY_103_DATA 0x10001000 -#define DDRSS_PHY_104_DATA 0x0C063E42 -#define DDRSS_PHY_105_DATA 0x0F0C3201 +#define DDRSS_PHY_104_DATA 0x0C083E42 +#define DDRSS_PHY_105_DATA 0x0F0C3701 #define DDRSS_PHY_106_DATA 0x01000140 #define DDRSS_PHY_107_DATA 0x0C000420 -#define DDRSS_PHY_108_DATA 0x000002DD +#define DDRSS_PHY_108_DATA 0x00000322 #define DDRSS_PHY_109_DATA 0x0A0000D0 #define DDRSS_PHY_110_DATA 0x00030200 #define DDRSS_PHY_111_DATA 0x02800000 #define DDRSS_PHY_112_DATA 0x80800000 -#define DDRSS_PHY_113_DATA 0x000D2010 +#define DDRSS_PHY_113_DATA 0x000E2010 #define DDRSS_PHY_114_DATA 0x76543210 #define DDRSS_PHY_115_DATA 0x00000008 #define DDRSS_PHY_116_DATA 0x02800280 @@ -900,13 +900,13 @@ #define DDRSS_PHY_127_DATA 0x00A000A0 #define DDRSS_PHY_128_DATA 0x00A000A0 #define DDRSS_PHY_129_DATA 0x00A000A0 -#define DDRSS_PHY_130_DATA 0x006D00A0 +#define DDRSS_PHY_130_DATA 0x01C200A0 #define DDRSS_PHY_131_DATA 0x01A00005 #define DDRSS_PHY_132_DATA 0x00000000 #define DDRSS_PHY_133_DATA 0x00000000 #define DDRSS_PHY_134_DATA 0x00080200 #define DDRSS_PHY_135_DATA 0x00000000 -#define DDRSS_PHY_136_DATA 0x20202020 +#define DDRSS_PHY_136_DATA 0x20202000 #define DDRSS_PHY_137_DATA 0x20202020 #define DDRSS_PHY_138_DATA 0xF0F02020 #define DDRSS_PHY_139_DATA 0x00000000 @@ -1043,7 +1043,7 @@ #define DDRSS_PHY_270_DATA 0x060100CC #define DDRSS_PHY_271_DATA 0x00030066 #define DDRSS_PHY_272_DATA 0x00000000 -#define DDRSS_PHY_273_DATA 0x00000001 +#define DDRSS_PHY_273_DATA 0x00000301 #define DDRSS_PHY_274_DATA 0x0000AAAA #define DDRSS_PHY_275_DATA 0x00005555 #define DDRSS_PHY_276_DATA 0x0000B5B5 @@ -1059,7 +1059,7 @@ #define DDRSS_PHY_286_DATA 0x0F000000 #define DDRSS_PHY_287_DATA 0x00000F0F #define DDRSS_PHY_288_DATA 0x10200000 -#define DDRSS_PHY_289_DATA 0x0C002004 +#define DDRSS_PHY_289_DATA 0x0C002007 #define DDRSS_PHY_290_DATA 0x00000000 #define DDRSS_PHY_291_DATA 0x00000000 #define DDRSS_PHY_292_DATA 0x55555555 @@ -1111,35 +1111,35 @@ #define DDRSS_PHY_338_DATA 0x00000000 #define DDRSS_PHY_339_DATA 0x00000100 #define DDRSS_PHY_340_DATA 0x01CC0C01 -#define DDRSS_PHY_341_DATA 0x0003CC0C +#define DDRSS_PHY_341_DATA 0x1003CC0C #define DDRSS_PHY_342_DATA 0x20000140 #define DDRSS_PHY_343_DATA 0x07FF0200 #define DDRSS_PHY_344_DATA 0x0000DD01 #define DDRSS_PHY_345_DATA 0x10100303 #define DDRSS_PHY_346_DATA 0x10101010 #define DDRSS_PHY_347_DATA 0x10101010 -#define DDRSS_PHY_348_DATA 0x00041010 +#define DDRSS_PHY_348_DATA 0x00021010 #define DDRSS_PHY_349_DATA 0x00100010 #define DDRSS_PHY_350_DATA 0x00100010 #define DDRSS_PHY_351_DATA 0x00100010 #define DDRSS_PHY_352_DATA 0x00100010 #define DDRSS_PHY_353_DATA 0x00050010 #define DDRSS_PHY_354_DATA 0x51517041 -#define DDRSS_PHY_355_DATA 0x31C06000 +#define DDRSS_PHY_355_DATA 0x31C06001 #define DDRSS_PHY_356_DATA 0x07AB0340 #define DDRSS_PHY_357_DATA 0x00C0C001 -#define DDRSS_PHY_358_DATA 0x0D0C0001 +#define DDRSS_PHY_358_DATA 0x0E0D0001 #define DDRSS_PHY_359_DATA 0x10001000 -#define DDRSS_PHY_360_DATA 0x0C063E42 -#define DDRSS_PHY_361_DATA 0x0F0C3201 +#define DDRSS_PHY_360_DATA 0x0C083E42 +#define DDRSS_PHY_361_DATA 0x0F0C3701 #define DDRSS_PHY_362_DATA 0x01000140 #define DDRSS_PHY_363_DATA 0x0C000420 -#define DDRSS_PHY_364_DATA 0x000002DD +#define DDRSS_PHY_364_DATA 0x00000322 #define DDRSS_PHY_365_DATA 0x0A0000D0 #define DDRSS_PHY_366_DATA 0x00030200 #define DDRSS_PHY_367_DATA 0x02800000 #define DDRSS_PHY_368_DATA 0x80800000 -#define DDRSS_PHY_369_DATA 0x000D2010 +#define DDRSS_PHY_369_DATA 0x000E2010 #define DDRSS_PHY_370_DATA 0x76543210 #define DDRSS_PHY_371_DATA 0x00000008 #define DDRSS_PHY_372_DATA 0x02800280 @@ -1156,13 +1156,13 @@ #define DDRSS_PHY_383_DATA 0x00A000A0 #define DDRSS_PHY_384_DATA 0x00A000A0 #define DDRSS_PHY_385_DATA 0x00A000A0 -#define DDRSS_PHY_386_DATA 0x006D00A0 +#define DDRSS_PHY_386_DATA 0x01C200A0 #define DDRSS_PHY_387_DATA 0x01A00005 #define DDRSS_PHY_388_DATA 0x00000000 #define DDRSS_PHY_389_DATA 0x00000000 #define DDRSS_PHY_390_DATA 0x00080200 #define DDRSS_PHY_391_DATA 0x00000000 -#define DDRSS_PHY_392_DATA 0x20202020 +#define DDRSS_PHY_392_DATA 0x20202000 #define DDRSS_PHY_393_DATA 0x20202020 #define DDRSS_PHY_394_DATA 0xF0F02020 #define DDRSS_PHY_395_DATA 0x00000000 @@ -1299,7 +1299,7 @@ #define DDRSS_PHY_526_DATA 0x060100CC #define DDRSS_PHY_527_DATA 0x00030066 #define DDRSS_PHY_528_DATA 0x00000000 -#define DDRSS_PHY_529_DATA 0x00000001 +#define DDRSS_PHY_529_DATA 0x00000301 #define DDRSS_PHY_530_DATA 0x0000AAAA #define DDRSS_PHY_531_DATA 0x00005555 #define DDRSS_PHY_532_DATA 0x0000B5B5 @@ -1315,7 +1315,7 @@ #define DDRSS_PHY_542_DATA 0x0F000000 #define DDRSS_PHY_543_DATA 0x00000F0F #define DDRSS_PHY_544_DATA 0x10200000 -#define DDRSS_PHY_545_DATA 0x0C002004 +#define DDRSS_PHY_545_DATA 0x0C002007 #define DDRSS_PHY_546_DATA 0x00000000 #define DDRSS_PHY_547_DATA 0x00000000 #define DDRSS_PHY_548_DATA 0x55555555 @@ -1367,35 +1367,35 @@ #define DDRSS_PHY_594_DATA 0x00000000 #define DDRSS_PHY_595_DATA 0x00000100 #define DDRSS_PHY_596_DATA 0x01CC0C01 -#define DDRSS_PHY_597_DATA 0x0003CC0C +#define DDRSS_PHY_597_DATA 0x1003CC0C #define DDRSS_PHY_598_DATA 0x20000140 #define DDRSS_PHY_599_DATA 0x07FF0200 #define DDRSS_PHY_600_DATA 0x0000DD01 #define DDRSS_PHY_601_DATA 0x10100303 #define DDRSS_PHY_602_DATA 0x10101010 #define DDRSS_PHY_603_DATA 0x10101010 -#define DDRSS_PHY_604_DATA 0x00041010 +#define DDRSS_PHY_604_DATA 0x00021010 #define DDRSS_PHY_605_DATA 0x00100010 #define DDRSS_PHY_606_DATA 0x00100010 #define DDRSS_PHY_607_DATA 0x00100010 #define DDRSS_PHY_608_DATA 0x00100010 #define DDRSS_PHY_609_DATA 0x00050010 #define DDRSS_PHY_610_DATA 0x51517041 -#define DDRSS_PHY_611_DATA 0x31C06000 +#define DDRSS_PHY_611_DATA 0x31C06001 #define DDRSS_PHY_612_DATA 0x07AB0340 #define DDRSS_PHY_613_DATA 0x00C0C001 -#define DDRSS_PHY_614_DATA 0x0D0C0001 +#define DDRSS_PHY_614_DATA 0x0E0D0001 #define DDRSS_PHY_615_DATA 0x10001000 -#define DDRSS_PHY_616_DATA 0x0C063E42 -#define DDRSS_PHY_617_DATA 0x0F0C3201 +#define DDRSS_PHY_616_DATA 0x0C083E42 +#define DDRSS_PHY_617_DATA 0x0F0C3701 #define DDRSS_PHY_618_DATA 0x01000140 #define DDRSS_PHY_619_DATA 0x0C000420 -#define DDRSS_PHY_620_DATA 0x000002DD +#define DDRSS_PHY_620_DATA 0x00000322 #define DDRSS_PHY_621_DATA 0x0A0000D0 #define DDRSS_PHY_622_DATA 0x00030200 #define DDRSS_PHY_623_DATA 0x02800000 #define DDRSS_PHY_624_DATA 0x80800000 -#define DDRSS_PHY_625_DATA 0x000D2010 +#define DDRSS_PHY_625_DATA 0x000E2010 #define DDRSS_PHY_626_DATA 0x76543210 #define DDRSS_PHY_627_DATA 0x00000008 #define DDRSS_PHY_628_DATA 0x02800280 @@ -1412,13 +1412,13 @@ #define DDRSS_PHY_639_DATA 0x00A000A0 #define DDRSS_PHY_640_DATA 0x00A000A0 #define DDRSS_PHY_641_DATA 0x00A000A0 -#define DDRSS_PHY_642_DATA 0x006D00A0 +#define DDRSS_PHY_642_DATA 0x01C200A0 #define DDRSS_PHY_643_DATA 0x01A00005 #define DDRSS_PHY_644_DATA 0x00000000 #define DDRSS_PHY_645_DATA 0x00000000 #define DDRSS_PHY_646_DATA 0x00080200 #define DDRSS_PHY_647_DATA 0x00000000 -#define DDRSS_PHY_648_DATA 0x20202020 +#define DDRSS_PHY_648_DATA 0x20202000 #define DDRSS_PHY_649_DATA 0x20202020 #define DDRSS_PHY_650_DATA 0xF0F02020 #define DDRSS_PHY_651_DATA 0x00000000 @@ -1555,7 +1555,7 @@ #define DDRSS_PHY_782_DATA 0x060100CC #define DDRSS_PHY_783_DATA 0x00030066 #define DDRSS_PHY_784_DATA 0x00000000 -#define DDRSS_PHY_785_DATA 0x00000001 +#define DDRSS_PHY_785_DATA 0x00000301 #define DDRSS_PHY_786_DATA 0x0000AAAA #define DDRSS_PHY_787_DATA 0x00005555 #define DDRSS_PHY_788_DATA 0x0000B5B5 @@ -1571,7 +1571,7 @@ #define DDRSS_PHY_798_DATA 0x0F000000 #define DDRSS_PHY_799_DATA 0x00000F0F #define DDRSS_PHY_800_DATA 0x10200000 -#define DDRSS_PHY_801_DATA 0x0C002004 +#define DDRSS_PHY_801_DATA 0x0C002007 #define DDRSS_PHY_802_DATA 0x00000000 #define DDRSS_PHY_803_DATA 0x00000000 #define DDRSS_PHY_804_DATA 0x55555555 @@ -1623,35 +1623,35 @@ #define DDRSS_PHY_850_DATA 0x00000000 #define DDRSS_PHY_851_DATA 0x00000100 #define DDRSS_PHY_852_DATA 0x01CC0C01 -#define DDRSS_PHY_853_DATA 0x0003CC0C +#define DDRSS_PHY_853_DATA 0x1003CC0C #define DDRSS_PHY_854_DATA 0x20000140 #define DDRSS_PHY_855_DATA 0x07FF0200 #define DDRSS_PHY_856_DATA 0x0000DD01 #define DDRSS_PHY_857_DATA 0x10100303 #define DDRSS_PHY_858_DATA 0x10101010 #define DDRSS_PHY_859_DATA 0x10101010 -#define DDRSS_PHY_860_DATA 0x00041010 +#define DDRSS_PHY_860_DATA 0x00021010 #define DDRSS_PHY_861_DATA 0x00100010 #define DDRSS_PHY_862_DATA 0x00100010 #define DDRSS_PHY_863_DATA 0x00100010 #define DDRSS_PHY_864_DATA 0x00100010 #define DDRSS_PHY_865_DATA 0x00050010 #define DDRSS_PHY_866_DATA 0x51517041 -#define DDRSS_PHY_867_DATA 0x31C06000 +#define DDRSS_PHY_867_DATA 0x31C06001 #define DDRSS_PHY_868_DATA 0x07AB0340 #define DDRSS_PHY_869_DATA 0x00C0C001 -#define DDRSS_PHY_870_DATA 0x0D0C0001 +#define DDRSS_PHY_870_DATA 0x0E0D0001 #define DDRSS_PHY_871_DATA 0x10001000 -#define DDRSS_PHY_872_DATA 0x0C063E42 -#define DDRSS_PHY_873_DATA 0x0F0C3201 +#define DDRSS_PHY_872_DATA 0x0C083E42 +#define DDRSS_PHY_873_DATA 0x0F0C3701 #define DDRSS_PHY_874_DATA 0x01000140 #define DDRSS_PHY_875_DATA 0x0C000420 -#define DDRSS_PHY_876_DATA 0x000002DD +#define DDRSS_PHY_876_DATA 0x00000322 #define DDRSS_PHY_877_DATA 0x0A0000D0 #define DDRSS_PHY_878_DATA 0x00030200 #define DDRSS_PHY_879_DATA 0x02800000 #define DDRSS_PHY_880_DATA 0x80800000 -#define DDRSS_PHY_881_DATA 0x000D2010 +#define DDRSS_PHY_881_DATA 0x000E2010 #define DDRSS_PHY_882_DATA 0x76543210 #define DDRSS_PHY_883_DATA 0x00000008 #define DDRSS_PHY_884_DATA 0x02800280 @@ -1668,13 +1668,13 @@ #define DDRSS_PHY_895_DATA 0x00A000A0 #define DDRSS_PHY_896_DATA 0x00A000A0 #define DDRSS_PHY_897_DATA 0x00A000A0 -#define DDRSS_PHY_898_DATA 0x006D00A0 +#define DDRSS_PHY_898_DATA 0x01C200A0 #define DDRSS_PHY_899_DATA 0x01A00005 #define DDRSS_PHY_900_DATA 0x00000000 #define DDRSS_PHY_901_DATA 0x00000000 #define DDRSS_PHY_902_DATA 0x00080200 #define DDRSS_PHY_903_DATA 0x00000000 -#define DDRSS_PHY_904_DATA 0x20202020 +#define DDRSS_PHY_904_DATA 0x20202000 #define DDRSS_PHY_905_DATA 0x20202020 #define DDRSS_PHY_906_DATA 0xF0F02020 #define DDRSS_PHY_907_DATA 0x00000000 @@ -1834,7 +1834,7 @@ #define DDRSS_PHY_1061_DATA 0x00000000 #define DDRSS_PHY_1062_DATA 0x00000000 #define DDRSS_PHY_1063_DATA 0x00000000 -#define DDRSS_PHY_1064_DATA 0x000505FF +#define DDRSS_PHY_1064_DATA 0x000305FF #define DDRSS_PHY_1065_DATA 0x00030000 #define DDRSS_PHY_1066_DATA 0x00000300 #define DDRSS_PHY_1067_DATA 0x00000300 @@ -2163,8 +2163,8 @@ #define DDRSS_PHY_1390_DATA 0x00000000 #define DDRSS_PHY_1391_DATA 0x00000000 #define DDRSS_PHY_1392_DATA 0x00000000 -#define DDRSS_PHY_1393_DATA 0x0001F7C5 -#define DDRSS_PHY_1394_DATA 0x00000005 +#define DDRSS_PHY_1393_DATA 0x0001F7C0 +#define DDRSS_PHY_1394_DATA 0x00000003 #define DDRSS_PHY_1395_DATA 0x00000000 #define DDRSS_PHY_1396_DATA 0x00001142 #define DDRSS_PHY_1397_DATA 0x010207AB diff --git a/arch/arm/dts/k3-j721e-r5-common-proc-board.dts b/arch/arm/dts/k3-j721e-r5-common-proc-board.dts index 2dde65d968..4cfaf8ca3c 100644 --- a/arch/arm/dts/k3-j721e-r5-common-proc-board.dts +++ b/arch/arm/dts/k3-j721e-r5-common-proc-board.dts @@ -6,7 +6,7 @@ /dts-v1/; #include "k3-j721e-som-p0.dtsi" -#include "k3-j721e-ddr-evm-lp4-3733.dtsi" +#include "k3-j721e-ddr-evm-lp4-4266.dtsi" #include "k3-j721e-ddr.dtsi" / { From d2aa5727a55283f17c4b9e0f847fdee5bc3b88bc Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 17 Dec 2020 22:58:07 +0530 Subject: [PATCH 09/42] board: ti: k2g: Add support for K2G ICE with 1GHz Silicon Add board detection support for K2G ICE with FlagChip 1GHz silicon. Signed-off-by: Lokesh Vutla --- board/ti/ks2_evm/board.c | 4 ++-- board/ti/ks2_evm/board.h | 8 ++++++++ board/ti/ks2_evm/board_k2g.c | 7 +++++-- board/ti/ks2_evm/ddr3_k2g.c | 2 +- board/ti/ks2_evm/mux-k2g.h | 2 +- include/configs/k2g_evm.h | 2 ++ 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/board/ti/ks2_evm/board.c b/board/ti/ks2_evm/board.c index c7be540028..53bc12791d 100644 --- a/board/ti/ks2_evm/board.c +++ b/board/ti/ks2_evm/board.c @@ -48,11 +48,11 @@ int dram_init(void) gd->ram_size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, CONFIG_MAX_RAM_BANK_SIZE); #if defined(CONFIG_TI_AEMIF) - if (!board_is_k2g_ice()) + if (!(board_is_k2g_ice() || board_is_k2g_i1())) aemif_init(ARRAY_SIZE(aemif_configs), aemif_configs); #endif - if (!board_is_k2g_ice()) { + if (!(board_is_k2g_ice() || board_is_k2g_i1())) { if (ddr3_size) ddr3_init_ecc(KS2_DDR3A_EMIF_CTRL_BASE, ddr3_size); else diff --git a/board/ti/ks2_evm/board.h b/board/ti/ks2_evm/board.h index d0cfbf5a75..93fc3887f4 100644 --- a/board/ti/ks2_evm/board.h +++ b/board/ti/ks2_evm/board.h @@ -25,6 +25,10 @@ static inline int board_is_k2g_ice(void) { return board_ti_is("66AK2GIC"); } +static inline int board_is_k2g_i1(void) +{ + return board_ti_is("66AK2GI1"); +} #else static inline int board_is_k2g_gp(void) { @@ -34,6 +38,10 @@ static inline int board_is_k2g_ice(void) { return false; } +static inline int board_is_k2g_i1(void) +{ + return false; +} #endif void spl_init_keystone_plls(void); diff --git a/board/ti/ks2_evm/board_k2g.c b/board/ti/ks2_evm/board_k2g.c index a71024bcbc..2be86d6d26 100644 --- a/board/ti/ks2_evm/board_k2g.c +++ b/board/ti/ks2_evm/board_k2g.c @@ -248,7 +248,8 @@ int board_fit_config_name_match(const char *name) else if (!strcmp(name, "keystone-k2g-evm") && (board_ti_is("66AK2GGP") || board_ti_is("66AK2GG1"))) return 0; - else if (!strcmp(name, "keystone-k2g-ice") && board_ti_is("66AK2GIC")) + else if (!strcmp(name, "keystone-k2g-ice") && + (board_ti_is("66AK2GIC") || board_is_k2g_i1())) return 0; else return -1; @@ -322,7 +323,7 @@ int embedded_dtb_select(void) BIT(9)); setbits_le32(K2G_GPIO1_BANK2_BASE + K2G_GPIO_SETDATA_OFFSET, BIT(9)); - } else if (board_is_k2g_ice()) { + } else if (board_is_k2g_ice() || board_is_k2g_i1()) { /* GBE Phy workaround. For Phy to latch the input * configuration, a GPIO reset is asserted at the * Phy reset pin to latch configuration correctly after SoC @@ -364,6 +365,8 @@ int board_late_init(void) env_set("board_name", "66AK2GG1\0"); else if (board_is_k2g_ice()) env_set("board_name", "66AK2GIC\0"); + else if (board_is_k2g_i1()) + env_set("board_name", "66AK2GI1\0"); #endif return 0; } diff --git a/board/ti/ks2_evm/ddr3_k2g.c b/board/ti/ks2_evm/ddr3_k2g.c index 563c5e9950..3000d7245e 100644 --- a/board/ti/ks2_evm/ddr3_k2g.c +++ b/board/ti/ks2_evm/ddr3_k2g.c @@ -174,7 +174,7 @@ u32 ddr3_init(void) } else if (board_is_k2g_gp()) { ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_800_2g); ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_800_2g); - } else if (board_is_k2g_ice()) { + } else if (board_is_k2g_ice() || board_is_k2g_i1()) { ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_800_512mb); ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_800_512mb); } diff --git a/board/ti/ks2_evm/mux-k2g.h b/board/ti/ks2_evm/mux-k2g.h index 3ecf571c5c..fa6c92cbdf 100644 --- a/board/ti/ks2_evm/mux-k2g.h +++ b/board/ti/ks2_evm/mux-k2g.h @@ -377,7 +377,7 @@ void k2g_mux_config(void) configure_pin_mux(k2g_generic_pin_cfg); } else if (board_is_k2g_gp() || board_is_k2g_g1()) { configure_pin_mux(k2g_evm_pin_cfg); - } else if (board_is_k2g_ice()) { + } else if (board_is_k2g_ice() || board_is_k2g_i1()) { configure_pin_mux(k2g_ice_evm_pin_cfg); } else { puts("Unknown board, cannot configure pinmux."); diff --git a/include/configs/k2g_evm.h b/include/configs/k2g_evm.h index 83466b9e0c..4471eb4f6a 100644 --- a/include/configs/k2g_evm.h +++ b/include/configs/k2g_evm.h @@ -35,6 +35,8 @@ "setenv name_fdt keystone-k2g-evm.dtb; " \ "else if test $board_name = 66AK2GIC; then " \ "setenv name_fdt keystone-k2g-ice.dtb; " \ + "else if test $board_name = 66AK2GI1; then " \ + "setenv name_fdt keystone-k2g-ice.dtb; " \ "else if test $name_fdt = undefined; then " \ "echo WARNING: Could not determine device tree to use;"\ "fi;fi;fi;fi; setenv fdtfile ${name_fdt}\0" \ From ffa66029050b0615df77263d35f283a2e715eafb Mon Sep 17 00:00:00 2001 From: Felix Brack Date: Fri, 18 Dec 2020 09:03:50 +0100 Subject: [PATCH 10/42] arm:pdu001: Use pseudo partition UUID for LINUX kernel boot paramter root As more and more LINUX drivers are modified to use asynchronous probing instead of synchronous probing, relying on device names being equal in U-Boot and LINUX is not possible anymore. This is also true for block device names like mmc0, mmc1 ect. With LINUX kernel commit a1a4891 the probing type for the sdhci-omap driver has been set to asynchronous mode too (probe_type is now PROBE_PREFER_ASYNCHRONOUS). In the case of the PDU001 board this results in the devices mmc0 and mmc1 being swapped between U-Boot and LINUX. Device mmc0 in U-Boot becomes mmc1 in LINUX an vice versa. Hence using device name identifiers with LINUX kernel parameter root does not work anymore. This patch changes the LINUX kernel boot parameter root to use the pseudo (since we use MBR not GPT) partition UUID to locate the partition hosting the root file system. Signed-off-by: Felix Brack --- include/configs/pdu001.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/configs/pdu001.h b/include/configs/pdu001.h index e4b14c5ecd..53342ce193 100644 --- a/include/configs/pdu001.h +++ b/include/configs/pdu001.h @@ -37,9 +37,10 @@ #define CONFIG_BOOTCOMMAND \ "run eval_boot_device;" \ + "part uuid mmc ${mmc_boot}:${root_fs_partition} root_fs_partuuid;" \ "setenv bootargs console=${console} " \ "vt.global_cursor_default=0 " \ - "root=/dev/mmcblk${mmc_boot}p${root_fs_partition} " \ + "root=PARTUUID=${root_fs_partuuid} " \ "rootfstype=ext4 " \ "rootwait " \ "rootdelay=1;" \ From 5688f3bf0b741886452bb9c065d4c64ab25faae0 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:27 +0100 Subject: [PATCH 11/42] clk: export generic routines Export routines that can be used by other drivers avoiding duplicating code. Signed-off-by: Dario Binacchi Reviewed-by: Simon Glass --- drivers/clk/clk-divider.c | 24 +++++++-------- include/linux/clk-provider.h | 57 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 8f59d7fb72..9df50a5e72 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -28,8 +28,8 @@ #define UBOOT_DM_CLK_CCF_DIVIDER "ccf_clk_divider" -static unsigned int _get_table_div(const struct clk_div_table *table, - unsigned int val) +unsigned int clk_divider_get_table_div(const struct clk_div_table *table, + unsigned int val) { const struct clk_div_table *clkt; @@ -49,7 +49,7 @@ static unsigned int _get_div(const struct clk_div_table *table, if (flags & CLK_DIVIDER_MAX_AT_ZERO) return val ? val : clk_div_mask(width) + 1; if (table) - return _get_table_div(table, val); + return clk_divider_get_table_div(table, val); return val + 1; } @@ -89,8 +89,8 @@ static ulong clk_divider_recalc_rate(struct clk *clk) divider->flags, divider->width); } -static bool _is_valid_table_div(const struct clk_div_table *table, - unsigned int div) +bool clk_divider_is_valid_table_div(const struct clk_div_table *table, + unsigned int div) { const struct clk_div_table *clkt; @@ -100,18 +100,18 @@ static bool _is_valid_table_div(const struct clk_div_table *table, return false; } -static bool _is_valid_div(const struct clk_div_table *table, unsigned int div, - unsigned long flags) +bool clk_divider_is_valid_div(const struct clk_div_table *table, + unsigned int div, unsigned long flags) { if (flags & CLK_DIVIDER_POWER_OF_TWO) return is_power_of_2(div); if (table) - return _is_valid_table_div(table, div); + return clk_divider_is_valid_table_div(table, div); return true; } -static unsigned int _get_table_val(const struct clk_div_table *table, - unsigned int div) +unsigned int clk_divider_get_table_val(const struct clk_div_table *table, + unsigned int div) { const struct clk_div_table *clkt; @@ -131,7 +131,7 @@ static unsigned int _get_val(const struct clk_div_table *table, if (flags & CLK_DIVIDER_MAX_AT_ZERO) return (div == clk_div_mask(width) + 1) ? 0 : div; if (table) - return _get_table_val(table, div); + return clk_divider_get_table_val(table, div); return div - 1; } int divider_get_val(unsigned long rate, unsigned long parent_rate, @@ -142,7 +142,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate, div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); - if (!_is_valid_div(table, div, flags)) + if (!clk_divider_is_valid_div(table, div, flags)) return -EINVAL; value = _get_val(table, div, flags, width); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 75b16353da..c871ea646d 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -76,6 +76,19 @@ struct clk_mux { extern const struct clk_ops clk_mux_ops; u8 clk_mux_get_parent(struct clk *clk); +/** + * clk_mux_index_to_val() - Convert the parent index to the register value + * + * It returns the value to write in the hardware register to output the selected + * input clock parent. + * + * @table: array of register values corresponding to the parent index (optional) + * @flags: hardware-specific flags + * @index: parent clock index + * @return the register value + */ +unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index); + struct clk_gate { struct clk clk; void __iomem *reg; @@ -125,6 +138,50 @@ struct clk_divider { #define CLK_DIVIDER_READ_ONLY BIT(5) #define CLK_DIVIDER_MAX_AT_ZERO BIT(6) extern const struct clk_ops clk_divider_ops; + +/** + * clk_divider_get_table_div() - convert the register value to the divider + * + * @table: array of register values corresponding to valid dividers + * @val: value to convert + * @return the divider + */ +unsigned int clk_divider_get_table_div(const struct clk_div_table *table, + unsigned int val); + +/** + * clk_divider_get_table_val() - convert the divider to the register value + * + * It returns the value to write in the hardware register to divide the input + * clock rate by @div. + * + * @table: array of register values corresponding to valid dividers + * @div: requested divider + * @return the register value + */ +unsigned int clk_divider_get_table_val(const struct clk_div_table *table, + unsigned int div); + +/** + * clk_divider_is_valid_div() - check if the divider is valid + * + * @table: array of valid dividers (optional) + * @div: divider to check + * @flags: hardware-specific flags + * @return true if the divider is valid, false otherwise + */ +bool clk_divider_is_valid_div(const struct clk_div_table *table, + unsigned int div, unsigned long flags); + +/** + * clk_divider_is_valid_table_div - check if the divider is in the @table array + * + * @table: array of valid dividers + * @div: divider to check + * @return true if the divider is found in the @table array, false otherwise + */ +bool clk_divider_is_valid_table_div(const struct clk_div_table *table, + unsigned int div); unsigned long divider_recalc_rate(struct clk *hw, unsigned long parent_rate, unsigned int val, const struct clk_div_table *table, From 2f59d8f2e0dac8763fbee00ecd257cb8667b2df9 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:28 +0100 Subject: [PATCH 12/42] dt-bindings: bus: ti-sysc: resync with Linux 5.9-rc7 Add support for PRUSS SYSC type: The PRUSS module has a SYSCFG which is unique. The SYSCFG has two additional unique fields called STANDBY_INIT and SUB_MWAIT in addition to regular IDLE_MODE and STANDBY_MODE fields. Add the bindings for this new sysc type. Add support for MCAN on dra76x: The dra76x MCAN generic interconnect module has a its own format for the bits in the control registers. Signed-off-by: Dario Binacchi --- include/dt-bindings/bus/ti-sysc.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/dt-bindings/bus/ti-sysc.h b/include/dt-bindings/bus/ti-sysc.h index 2c005376ac..eae4274543 100644 --- a/include/dt-bindings/bus/ti-sysc.h +++ b/include/dt-bindings/bus/ti-sysc.h @@ -15,6 +15,12 @@ /* SmartReflex sysc found on 36xx and later */ #define SYSC_OMAP3_SR_ENAWAKEUP (1 << 26) +#define SYSC_DRA7_MCAN_ENAWAKEUP (1 << 4) + +/* PRUSS sysc found on AM33xx/AM43xx/AM57xx */ +#define SYSC_PRUSS_SUB_MWAIT (1 << 5) +#define SYSC_PRUSS_STANDBY_INIT (1 << 4) + /* SYSCONFIG STANDBYMODE/MIDLEMODE/SIDLEMODE supported by hardware */ #define SYSC_IDLE_FORCE 0 #define SYSC_IDLE_NO 1 From 92cc4e1c21e27b604665f080973837c3618297a3 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:29 +0100 Subject: [PATCH 13/42] bus: ti: add minimal sysc interconnect target driver We can handle the sysc interconnect target module in a generic way for many TI SoCs. Initially let's just enable domain clocks before the children are probed. The code is loosely based on the drivers/bus/ti-sysc.c of the Linux kernel version 5.9-rc7. For DT binding details see: - Documentation/devicetree/bindings/bus/ti-sysc.txt Signed-off-by: Dario Binacchi --- arch/arm/Kconfig | 1 + configs/nokia_rx51_defconfig | 1 + drivers/bus/Kconfig | 7 ++ drivers/bus/Makefile | 1 + drivers/bus/ti-sysc.c | 166 +++++++++++++++++++++++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 drivers/bus/ti-sysc.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fbe90875ae..6b5235e740 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -799,6 +799,7 @@ config ARCH_OMAP2PLUS select SPL_BOARD_INIT if SPL select SPL_STACK_R if SPL select SUPPORT_SPL + imply TI_SYSC if DM && OF_CONTROL imply FIT config ARCH_MESON diff --git a/configs/nokia_rx51_defconfig b/configs/nokia_rx51_defconfig index d0c8929525..30a02e2bc3 100644 --- a/configs/nokia_rx51_defconfig +++ b/configs/nokia_rx51_defconfig @@ -4,6 +4,7 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_SYS_TEXT_BASE=0x80008000 CONFIG_NR_DRAM_BANKS=2 CONFIG_TARGET_NOKIA_RX51=y +# CONFIG_TI_SYSC is not set # CONFIG_FIT is not set CONFIG_BOOTDELAY=30 CONFIG_AUTOBOOT_KEYED=y diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 07a33c6287..733bec5a56 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -5,6 +5,13 @@ menu "Bus devices" +config TI_SYSC + bool "TI sysc interconnect target module driver" + depends on ARCH_OMAP2PLUS + help + Generic driver for Texas Instruments interconnect target module + found on many TI SoCs. + config UNIPHIER_SYSTEM_BUS bool "UniPhier System Bus driver" depends on ARCH_UNIPHIER diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 0b97fc1f8b..875bb4ed42 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -3,4 +3,5 @@ # Makefile for the bus drivers. # +obj-$(CONFIG_TI_SYSC) += ti-sysc.o obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c new file mode 100644 index 0000000000..4e3d610300 --- /dev/null +++ b/drivers/bus/ti-sysc.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments sysc interconnect target driver + * + * Copyright (C) 2020 Dario Binacchi + */ + +#include +#include +#include +#include + +enum ti_sysc_clocks { + TI_SYSC_FCK, + TI_SYSC_ICK, + TI_SYSC_MAX_CLOCKS, +}; + +static const char *const clock_names[] = {"fck", "ick"}; + +struct ti_sysc_priv { + int clocks_count; + struct clk clocks[TI_SYSC_MAX_CLOCKS]; +}; + +static const struct udevice_id ti_sysc_ids[] = { + {.compatible = "ti,sysc-omap2"}, + {.compatible = "ti,sysc-omap4"}, + {.compatible = "ti,sysc-omap4-simple"}, + {.compatible = "ti,sysc-omap3430-sr"}, + {.compatible = "ti,sysc-omap3630-sr"}, + {.compatible = "ti,sysc-omap4-sr"}, + {.compatible = "ti,sysc-omap3-sham"}, + {.compatible = "ti,sysc-omap-aes"}, + {.compatible = "ti,sysc-mcasp"}, + {.compatible = "ti,sysc-usb-host-fs"}, + {} +}; + +static int ti_sysc_get_one_clock(struct udevice *dev, enum ti_sysc_clocks index) +{ + struct ti_sysc_priv *priv = dev_get_priv(dev); + const char *name; + int err; + + switch (index) { + case TI_SYSC_FCK: + break; + case TI_SYSC_ICK: + break; + default: + return -EINVAL; + } + + name = clock_names[index]; + + err = clk_get_by_name(dev, name, &priv->clocks[index]); + if (err) { + if (err == -ENODATA) + return 0; + + dev_err(dev, "failed to get %s clock\n", name); + return err; + } + + return 0; +} + +static int ti_sysc_put_clocks(struct udevice *dev) +{ + struct ti_sysc_priv *priv = dev_get_priv(dev); + int err; + + err = clk_release_all(priv->clocks, priv->clocks_count); + if (err) + dev_err(dev, "failed to release all clocks\n"); + + return err; +} + +static int ti_sysc_get_clocks(struct udevice *dev) +{ + struct ti_sysc_priv *priv = dev_get_priv(dev); + int i, err; + + for (i = 0; i < TI_SYSC_MAX_CLOCKS; i++) { + err = ti_sysc_get_one_clock(dev, i); + if (!err) + priv->clocks_count++; + else if (err != -ENOENT) + return err; + } + + return 0; +} + +static int ti_sysc_child_post_remove(struct udevice *dev) +{ + struct ti_sysc_priv *priv = dev_get_priv(dev->parent); + int i, err; + + for (i = 0; i < priv->clocks_count; i++) { + err = clk_disable(&priv->clocks[i]); + if (err) { + dev_err(dev->parent, "failed to disable %s clock\n", + clock_names[i]); + return err; + } + } + + return 0; +} + +static int ti_sysc_child_pre_probe(struct udevice *dev) +{ + struct ti_sysc_priv *priv = dev_get_priv(dev->parent); + int i, err; + + for (i = 0; i < priv->clocks_count; i++) { + err = clk_enable(&priv->clocks[i]); + if (err) { + dev_err(dev->parent, "failed to enable %s clock\n", + clock_names[i]); + return err; + } + } + + return 0; +} + +static int ti_sysc_remove(struct udevice *dev) +{ + return ti_sysc_put_clocks(dev); +} + +static int ti_sysc_probe(struct udevice *dev) +{ + int err; + + err = ti_sysc_get_clocks(dev); + if (err) + goto clocks_err; + + return 0; + +clocks_err: + ti_sysc_put_clocks(dev); + return err; +} + +UCLASS_DRIVER(ti_sysc) = { + .id = UCLASS_SIMPLE_BUS, + .name = "ti_sysc", + .post_bind = dm_scan_fdt_dev +}; + +U_BOOT_DRIVER(ti_sysc) = { + .name = "ti_sysc", + .id = UCLASS_SIMPLE_BUS, + .of_match = ti_sysc_ids, + .probe = ti_sysc_probe, + .remove = ti_sysc_remove, + .child_pre_probe = ti_sysc_child_pre_probe, + .child_post_remove = ti_sysc_child_post_remove, + .priv_auto = sizeof(struct ti_sysc_priv) +}; From 6337d53fdf45df764bc9946d927172397f183d37 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:30 +0100 Subject: [PATCH 14/42] arm: dts: sync am33xx with Linux 5.9-rc7 There have been several changes to the am33xx.dtsi, so this patch re-syncs it with Linux. Let's add proper interconnect hierarchy for l4 interconnect instances with the related ti-sysc interconnect module data as documented in Documentation/devicetree/bindings/bus/ti-sysc.txt of the Linux kernel. With l4 interconnect hierarchy and ti-sysc interconnect target module data in place, we can simply move all the related child devices to their proper location and enable probing using ti-sysc. The am33xx-clock.dtsi file is the same as that of the Linux kernel, except for the reg property of the node l4-wkup-clkctrl@0. As for the am33xx.dtsi file, all the devices with drivers not yet implemented and those I was able to test with this patch have been moved to am33xx-l4.dtsi. In case of any regressions, problem devices can be reverted by moving them back and removing the related interconnect target module node. Signed-off-by: Dario Binacchi --- arch/arm/dts/am335x-draco.dtsi | 11 +- arch/arm/dts/am335x-evm.dts | 2 +- arch/arm/dts/am335x-evmsk.dts | 2 +- arch/arm/dts/am335x-guardian-u-boot.dtsi | 5 - arch/arm/dts/am335x-pxm2.dtsi | 2 +- arch/arm/dts/am335x-rut.dts | 2 +- arch/arm/dts/am335x-shc.dts | 2 +- arch/arm/dts/am33xx-clocks.dtsi | 106 +- arch/arm/dts/am33xx-l4.dtsi | 1962 ++++++++++++++++++++++ arch/arm/dts/am33xx.dtsi | 717 +++----- 10 files changed, 2271 insertions(+), 540 deletions(-) create mode 100644 arch/arm/dts/am33xx-l4.dtsi diff --git a/arch/arm/dts/am335x-draco.dtsi b/arch/arm/dts/am335x-draco.dtsi index b38ff55e1d..2c125fcec9 100644 --- a/arch/arm/dts/am335x-draco.dtsi +++ b/arch/arm/dts/am335x-draco.dtsi @@ -20,11 +20,6 @@ }; ocp { - uart0: serial@44e09000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - status = "okay"; - }; i2c0: i2c@44e0b000 { pinctrl-names = "default"; @@ -112,6 +107,12 @@ status = "disabled"; }; +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + &uart4 { status = "disabled"; }; diff --git a/arch/arm/dts/am335x-evm.dts b/arch/arm/dts/am335x-evm.dts index 0bda4d4429..07288fb188 100644 --- a/arch/arm/dts/am335x-evm.dts +++ b/arch/arm/dts/am335x-evm.dts @@ -486,7 +486,7 @@ &epwmss0 { status = "okay"; - ecap0: ecap@48300100 { + ecap0: ecap@100 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&ecap0_pins>; diff --git a/arch/arm/dts/am335x-evmsk.dts b/arch/arm/dts/am335x-evmsk.dts index 5762967cf7..c94c33b595 100644 --- a/arch/arm/dts/am335x-evmsk.dts +++ b/arch/arm/dts/am335x-evmsk.dts @@ -531,7 +531,7 @@ &epwmss2 { status = "okay"; - ecap2: ecap@48304100 { + ecap2: ecap@100 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&ecap2_pins>; diff --git a/arch/arm/dts/am335x-guardian-u-boot.dtsi b/arch/arm/dts/am335x-guardian-u-boot.dtsi index 705ef335bf..eae027c541 100644 --- a/arch/arm/dts/am335x-guardian-u-boot.dtsi +++ b/arch/arm/dts/am335x-guardian-u-boot.dtsi @@ -26,11 +26,6 @@ u-boot,dm-pre-reloc; }; -&rtc { - clocks = <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; - clock-names = "int-clk"; -}; - &scm { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/dts/am335x-pxm2.dtsi b/arch/arm/dts/am335x-pxm2.dtsi index 19bd7e2420..645d221507 100644 --- a/arch/arm/dts/am335x-pxm2.dtsi +++ b/arch/arm/dts/am335x-pxm2.dtsi @@ -148,7 +148,7 @@ &epwmss0 { status = "okay"; - ecap0: ecap@48300100 { + ecap0: ecap@100 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&ecap0_pins>; diff --git a/arch/arm/dts/am335x-rut.dts b/arch/arm/dts/am335x-rut.dts index 145247344f..cc06f5d23a 100644 --- a/arch/arm/dts/am335x-rut.dts +++ b/arch/arm/dts/am335x-rut.dts @@ -174,7 +174,7 @@ &epwmss0 { status = "okay"; - ecap0: ecap@48300100 { + ecap0: ecap@100 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&ecap0_pins>; diff --git a/arch/arm/dts/am335x-shc.dts b/arch/arm/dts/am335x-shc.dts index 8e35c439e5..a41a0606b1 100644 --- a/arch/arm/dts/am335x-shc.dts +++ b/arch/arm/dts/am335x-shc.dts @@ -136,7 +136,7 @@ &epwmss1 { status = "okay"; - ehrpwm1: pwm@48302200 { + ehrpwm1: pwm@200 { pinctrl-names = "default"; pinctrl-0 = <&ehrpwm1_pins>; status = "okay"; diff --git a/arch/arm/dts/am33xx-clocks.dtsi b/arch/arm/dts/am33xx-clocks.dtsi index 95d5c9d136..87c4410ee2 100644 --- a/arch/arm/dts/am33xx-clocks.dtsi +++ b/arch/arm/dts/am33xx-clocks.dtsi @@ -334,49 +334,49 @@ timer1_fck: timer1_fck@528 { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>; + clocks = <&sys_clkin_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>; reg = <0x0528>; }; timer2_fck: timer2_fck@508 { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; reg = <0x0508>; }; timer3_fck: timer3_fck@50c { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; reg = <0x050c>; }; timer4_fck: timer4_fck@510 { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; reg = <0x0510>; }; timer5_fck: timer5_fck@518 { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; reg = <0x0518>; }; timer6_fck: timer6_fck@51c { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; reg = <0x051c>; }; timer7_fck: timer7_fck@504 { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; reg = <0x0504>; }; @@ -407,7 +407,7 @@ wdt1_fck: wdt1_fck@538 { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&clk_rc32k_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clocks = <&clk_rc32k_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; reg = <0x0538>; }; @@ -477,7 +477,7 @@ gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@53c { #clock-cells = <0>; compatible = "ti,mux-clock"; - clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; reg = <0x053c>; }; @@ -539,77 +539,131 @@ }; &prcm { - l4_per_cm: l4_per_cm@0 { + l4_per_cm: l4_per-cm@0 { compatible = "ti,omap4-cm"; - reg = <0x0 0x200>; + reg = <0x0 0x400>; #address-cells = <1>; #size-cells = <1>; - ranges = <0 0x0 0x200>; + ranges = <0 0x0 0x400>; - l4_per_clkctrl: clk@14 { + l4ls_clkctrl: l4ls-clkctrl@38 { compatible = "ti,clkctrl"; - reg = <0x14 0x13c>; + reg = <0x38 0x2c>, <0x6c 0x28>, <0xac 0xc>, <0xc0 0x1c>, <0xec 0xc>, <0x10c 0x8>, <0x130 0x4>; + #clock-cells = <2>; + }; + + l3s_clkctrl: l3s-clkctrl@1c { + compatible = "ti,clkctrl"; + reg = <0x1c 0x4>, <0x30 0x8>, <0x68 0x4>, <0xf8 0x4>; + #clock-cells = <2>; + }; + + l3_clkctrl: l3-clkctrl@24 { + compatible = "ti,clkctrl"; + reg = <0x24 0xc>, <0x94 0x10>, <0xbc 0x4>, <0xdc 0x8>, <0xfc 0x8>; + #clock-cells = <2>; + }; + + l4hs_clkctrl: l4hs-clkctrl@120 { + compatible = "ti,clkctrl"; + reg = <0x120 0x4>; + #clock-cells = <2>; + }; + + pruss_ocp_clkctrl: pruss-ocp-clkctrl@e8 { + compatible = "ti,clkctrl"; + reg = <0xe8 0x4>; + #clock-cells = <2>; + }; + + cpsw_125mhz_clkctrl: cpsw-125mhz-clkctrl@0 { + compatible = "ti,clkctrl"; + reg = <0x0 0x18>; + #clock-cells = <2>; + }; + + lcdc_clkctrl: lcdc-clkctrl@18 { + compatible = "ti,clkctrl"; + reg = <0x18 0x4>; + #clock-cells = <2>; + }; + + clk_24mhz_clkctrl: clk-24mhz-clkctrl@14c { + compatible = "ti,clkctrl"; + reg = <0x14c 0x4>; #clock-cells = <2>; }; }; - l4_wkup_cm: l4_wkup_cm@400 { + wkup_cm: wkup-cm@400 { compatible = "ti,omap4-cm"; reg = <0x400 0x100>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x400 0x100>; - l4_wkup_clkctrl: clk@4 { + l4_wkup_clkctrl: l4-wkup-clkctrl@0 { compatible = "ti,clkctrl"; - reg = <0x4 0xd4>; + reg = <0x4 0x10>, <0xb4 0x24>; + #clock-cells = <2>; + }; + + l3_aon_clkctrl: l3-aon-clkctrl@14 { + compatible = "ti,clkctrl"; + reg = <0x14 0x4>; + #clock-cells = <2>; + }; + + l4_wkup_aon_clkctrl: l4-wkup-aon-clkctrl@b0 { + compatible = "ti,clkctrl"; + reg = <0xb0 0x4>; #clock-cells = <2>; }; }; - mpu_cm: mpu_cm@600 { + mpu_cm: mpu-cm@600 { compatible = "ti,omap4-cm"; reg = <0x600 0x100>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x600 0x100>; - mpu_clkctrl: clk@4 { + mpu_clkctrl: mpu-clkctrl@0 { compatible = "ti,clkctrl"; - reg = <0x4 0x4>; + reg = <0x0 0x8>; #clock-cells = <2>; }; }; - l4_rtc_cm: l4_rtc_cm@800 { + l4_rtc_cm: l4-rtc-cm@800 { compatible = "ti,omap4-cm"; reg = <0x800 0x100>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x800 0x100>; - l4_rtc_clkctrl: clk@0 { + l4_rtc_clkctrl: l4-rtc-clkctrl@0 { compatible = "ti,clkctrl"; reg = <0x0 0x4>; #clock-cells = <2>; }; }; - gfx_l3_cm: gfx_l3_cm@900 { + gfx_l3_cm: gfx-l3-cm@900 { compatible = "ti,omap4-cm"; reg = <0x900 0x100>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x900 0x100>; - gfx_l3_clkctrl: clk@4 { + gfx_l3_clkctrl: gfx-l3-clkctrl@0 { compatible = "ti,clkctrl"; - reg = <0x4 0x4>; + reg = <0x0 0x8>; #clock-cells = <2>; }; }; - l4_cefuse_cm: l4_cefuse_cm@a00 { + l4_cefuse_cm: l4-cefuse-cm@a00 { compatible = "ti,omap4-cm"; reg = <0xa00 0x100>; #address-cells = <1>; diff --git a/arch/arm/dts/am33xx-l4.dtsi b/arch/arm/dts/am33xx-l4.dtsi new file mode 100644 index 0000000000..257991e2ad --- /dev/null +++ b/arch/arm/dts/am33xx-l4.dtsi @@ -0,0 +1,1962 @@ +&l4_wkup { /* 0x44c00000 */ + compatible = "ti,am33xx-l4-wkup", "simple-bus"; + reg = <0x44c00000 0x800>, + <0x44c00800 0x800>, + <0x44c01000 0x400>, + <0x44c01400 0x400>; + reg-names = "ap", "la", "ia0", "ia1"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x44c00000 0x100000>, /* segment 0 */ + <0x00100000 0x44d00000 0x100000>, /* segment 1 */ + <0x00200000 0x44e00000 0x100000>; /* segment 2 */ + + segment@0 { /* 0x44c00000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */ + <0x00000800 0x00000800 0x000800>, /* ap 1 */ + <0x00001000 0x00001000 0x000400>, /* ap 2 */ + <0x00001400 0x00001400 0x000400>; /* ap 3 */ + }; + + segment@100000 { /* 0x44d00000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00100000 0x004000>, /* ap 4 */ + <0x00004000 0x00104000 0x001000>, /* ap 5 */ + <0x00080000 0x00180000 0x002000>, /* ap 6 */ + <0x00082000 0x00182000 0x001000>; /* ap 7 */ + + target-module@0 { /* 0x44d00000, ap 4 28.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x0 0x4>; + reg-names = "rev"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x4000>; + status = "disabled"; + }; + + target-module@80000 { /* 0x44d80000, ap 6 10.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x80000 0x2000>; + }; + }; + + segment@200000 { /* 0x44e00000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00200000 0x002000>, /* ap 8 */ + <0x00002000 0x00202000 0x001000>, /* ap 9 */ + <0x00003000 0x00203000 0x001000>, /* ap 10 */ + <0x00004000 0x00204000 0x001000>, /* ap 11 */ + <0x00005000 0x00205000 0x001000>, /* ap 12 */ + <0x00006000 0x00206000 0x001000>, /* ap 13 */ + <0x00007000 0x00207000 0x001000>, /* ap 14 */ + <0x00008000 0x00208000 0x001000>, /* ap 15 */ + <0x00009000 0x00209000 0x001000>, /* ap 16 */ + <0x0000a000 0x0020a000 0x001000>, /* ap 17 */ + <0x0000b000 0x0020b000 0x001000>, /* ap 18 */ + <0x0000c000 0x0020c000 0x001000>, /* ap 19 */ + <0x0000d000 0x0020d000 0x001000>, /* ap 20 */ + <0x0000f000 0x0020f000 0x001000>, /* ap 21 */ + <0x00010000 0x00210000 0x010000>, /* ap 22 */ + <0x00020000 0x00220000 0x010000>, /* ap 23 */ + <0x00030000 0x00230000 0x001000>, /* ap 24 */ + <0x00031000 0x00231000 0x001000>, /* ap 25 */ + <0x00032000 0x00232000 0x001000>, /* ap 26 */ + <0x00033000 0x00233000 0x001000>, /* ap 27 */ + <0x00034000 0x00234000 0x001000>, /* ap 28 */ + <0x00035000 0x00235000 0x001000>, /* ap 29 */ + <0x00036000 0x00236000 0x001000>, /* ap 30 */ + <0x00037000 0x00237000 0x001000>, /* ap 31 */ + <0x00038000 0x00238000 0x001000>, /* ap 32 */ + <0x00039000 0x00239000 0x001000>, /* ap 33 */ + <0x0003a000 0x0023a000 0x001000>, /* ap 34 */ + <0x0003e000 0x0023e000 0x001000>, /* ap 35 */ + <0x0003f000 0x0023f000 0x001000>, /* ap 36 */ + <0x0000e000 0x0020e000 0x001000>, /* ap 37 */ + <0x00040000 0x00240000 0x040000>, /* ap 38 */ + <0x00080000 0x00280000 0x001000>; /* ap 39 */ + + target-module@0 { /* 0x44e00000, ap 8 58.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0 0x4>; + reg-names = "rev"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x2000>; + + prcm: prcm@0 { + compatible = "ti,am3-prcm", "simple-bus"; + reg = <0 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x2000>; + + prcm_clocks: clocks { + #address-cells = <1>; + #size-cells = <0>; + }; + + prcm_clockdomains: clockdomains { + }; + }; + }; + + target-module@3000 { /* 0x44e03000, ap 10 0a.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3000 0x1000>; + }; + + target-module@5000 { /* 0x44e05000, ap 12 30.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x5000 0x1000>; + }; + + gpio0_target: target-module@7000 { /* 0x44e07000, ap 14 20.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x7000 0x4>, + <0x7010 0x4>, + <0x7114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): wkup_pwrdm, l4_wkup_clkdm */ + clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_GPIO1_CLKCTRL 0>, + <&l4_wkup_clkctrl AM3_L4_WKUP_GPIO1_CLKCTRL 18>; + clock-names = "fck", "dbclk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x7000 0x1000>; + }; + + target-module@9000 { /* 0x44e09000, ap 16 04.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x9050 0x4>, + <0x9054 0x4>, + <0x9058 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): wkup_pwrdm, l4_wkup_clkdm */ + clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_UART1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x9000 0x1000>; + + uart0: serial@0 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + clock-frequency = <48000000>; + reg = <0x0 0x1000>; + interrupts = <72>; + status = "disabled"; + dmas = <&edma 26 0>, <&edma 27 0>; + dma-names = "tx", "rx"; + }; + }; + + target-module@b000 { /* 0x44e0b000, ap 18 48.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xb000 0x8>, + <0xb010 0x8>, + <0xb090 0x8>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): wkup_pwrdm, l4_wkup_clkdm */ + clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_I2C1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xb000 0x1000>; + }; + + target-module@d000 { /* 0x44e0d000, ap 20 38.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0xd000 0x4>, + <0xd010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): wkup_pwrdm, l4_wkup_clkdm */ + clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_ADC_TSC_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x0000d000 0x00001000>, + <0x00001000 0x0000e000 0x00001000>; + + tscadc: tscadc@0 { + compatible = "ti,am3359-tscadc"; + reg = <0x0 0x1000>; + interrupts = <16>; + status = "disabled"; + dmas = <&edma 53 0>, <&edma 57 0>; + dma-names = "fifo0", "fifo1"; + + tsc { + compatible = "ti,am3359-tsc"; + }; + am335x_adc: adc { + #io-channel-cells = <1>; + compatible = "ti,am3359-adc"; + }; + }; + + }; + + target-module@10000 { /* 0x44e10000, ap 22 0c.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x10000 0x4>; + reg-names = "rev"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00010000 0x00010000>, + <0x00010000 0x00020000 0x00010000>; + + scm: scm@0 { + compatible = "ti,am3-scm", "simple-bus"; + reg = <0x0 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + #pinctrl-cells = <1>; + ranges = <0 0 0x2000>; + + am33xx_pinmux: pinmux@800 { + compatible = "pinctrl-single"; + reg = <0x800 0x238>; + #pinctrl-cells = <2>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x7f>; + }; + + scm_conf: scm_conf@0 { + compatible = "syscon", "simple-bus"; + reg = <0x0 0x800>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x800>; + + phy_gmii_sel: phy-gmii-sel { + compatible = "ti,am3352-phy-gmii-sel"; + reg = <0x650 0x4>; + #phy-cells = <2>; + }; + + scm_clocks: clocks { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + wkup_m3_ipc: wkup_m3_ipc@1324 { + compatible = "ti,am3352-wkup-m3-ipc"; + reg = <0x1324 0x24>; + interrupts = <78>; + ti,rproc = <&wkup_m3>; + mboxes = <&mailbox &mbox_wkupm3>; + }; + + edma_xbar: dma-router@f90 { + compatible = "ti,am335x-edma-crossbar"; + reg = <0xf90 0x40>; + #dma-cells = <3>; + dma-requests = <32>; + dma-masters = <&edma>; + }; + + scm_clockdomains: clockdomains { + }; + }; + }; + + timer1_target: target-module@31000 { /* 0x44e31000, ap 25 40.0 */ + compatible = "ti,sysc-omap2-timer", "ti,sysc"; + reg = <0x31000 0x4>, + <0x31010 0x4>, + <0x31014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): wkup_pwrdm, l4_wkup_clkdm */ + clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_TIMER1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x31000 0x1000>; + + timer1: timer@0 { + compatible = "ti,am335x-timer-1ms"; + reg = <0x0 0x400>; + interrupts = <67>; + ti,timer-alwon; + clocks = <&timer1_fck>; + clock-names = "fck"; + }; + }; + + target-module@33000 { /* 0x44e33000, ap 27 18.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x33000 0x1000>; + }; + + target-module@35000 { /* 0x44e35000, ap 29 50.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x35000 0x4>, + <0x35010 0x4>, + <0x35014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_EMUFREE | + SYSC_OMAP2_SOFTRESET)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): wkup_pwrdm, l4_wkup_clkdm */ + clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_WD_TIMER2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x35000 0x1000>; + }; + + target-module@37000 { /* 0x44e37000, ap 31 08.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x37000 0x1000>; + }; + + target-module@39000 { /* 0x44e39000, ap 33 02.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x39000 0x1000>; + }; + + target-module@3e000 { /* 0x44e3e000, ap 35 60.0 */ + compatible = "ti,sysc-omap4-simple", "ti,sysc"; + reg = <0x3e074 0x4>, + <0x3e078 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): rtc_pwrdm, l4_rtc_clkdm */ + clocks = <&l4_rtc_clkctrl AM3_L4_RTC_RTC_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3e000 0x1000>; + + rtc: rtc@0 { + compatible = "ti,am3352-rtc", "ti,da830-rtc"; + reg = <0x0 0x1000>; + interrupts = <75 76>; + }; + }; + + target-module@40000 { /* 0x44e40000, ap 38 68.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x40000 0x40000>; + }; + }; +}; + +&l4_fw { /* 0x47c00000 */ + compatible = "ti,am33xx-l4-fw", "simple-bus"; + reg = <0x47c00000 0x800>, + <0x47c00800 0x800>, + <0x47c01000 0x400>; + reg-names = "ap", "la", "ia0"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x47c00000 0x1000000>; /* segment 0 */ + + segment@0 { /* 0x47c00000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */ + <0x00000800 0x00000800 0x000800>, /* ap 1 */ + <0x00001000 0x00001000 0x000400>, /* ap 2 */ + <0x0000c000 0x0000c000 0x001000>, /* ap 3 */ + <0x0000d000 0x0000d000 0x001000>, /* ap 4 */ + <0x0000e000 0x0000e000 0x001000>, /* ap 5 */ + <0x0000f000 0x0000f000 0x001000>, /* ap 6 */ + <0x00010000 0x00010000 0x001000>, /* ap 7 */ + <0x00011000 0x00011000 0x001000>, /* ap 8 */ + <0x0001a000 0x0001a000 0x001000>, /* ap 9 */ + <0x0001b000 0x0001b000 0x001000>, /* ap 10 */ + <0x00024000 0x00024000 0x001000>, /* ap 11 */ + <0x00025000 0x00025000 0x001000>, /* ap 12 */ + <0x00026000 0x00026000 0x001000>, /* ap 13 */ + <0x00027000 0x00027000 0x001000>, /* ap 14 */ + <0x00030000 0x00030000 0x001000>, /* ap 15 */ + <0x00031000 0x00031000 0x001000>, /* ap 16 */ + <0x00038000 0x00038000 0x001000>, /* ap 17 */ + <0x00039000 0x00039000 0x001000>, /* ap 18 */ + <0x0003a000 0x0003a000 0x001000>, /* ap 19 */ + <0x0003b000 0x0003b000 0x001000>, /* ap 20 */ + <0x0003e000 0x0003e000 0x001000>, /* ap 21 */ + <0x0003f000 0x0003f000 0x001000>, /* ap 22 */ + <0x0003c000 0x0003c000 0x001000>, /* ap 23 */ + <0x00040000 0x00040000 0x001000>, /* ap 24 */ + <0x00046000 0x00046000 0x001000>, /* ap 25 */ + <0x00047000 0x00047000 0x001000>, /* ap 26 */ + <0x00044000 0x00044000 0x001000>, /* ap 27 */ + <0x00045000 0x00045000 0x001000>, /* ap 28 */ + <0x00028000 0x00028000 0x001000>, /* ap 29 */ + <0x00029000 0x00029000 0x001000>, /* ap 30 */ + <0x00032000 0x00032000 0x001000>, /* ap 31 */ + <0x00033000 0x00033000 0x001000>, /* ap 32 */ + <0x0003d000 0x0003d000 0x001000>, /* ap 33 */ + <0x00041000 0x00041000 0x001000>, /* ap 34 */ + <0x00042000 0x00042000 0x001000>, /* ap 35 */ + <0x00043000 0x00043000 0x001000>, /* ap 36 */ + <0x00014000 0x00014000 0x001000>, /* ap 37 */ + <0x00015000 0x00015000 0x001000>; /* ap 38 */ + + target-module@c000 { /* 0x47c0c000, ap 3 04.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xc000 0x1000>; + }; + + target-module@e000 { /* 0x47c0e000, ap 5 0c.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe000 0x1000>; + }; + + target-module@10000 { /* 0x47c10000, ap 7 20.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x10000 0x1000>; + }; + + target-module@14000 { /* 0x47c14000, ap 37 3c.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x14000 0x1000>; + }; + + target-module@1a000 { /* 0x47c1a000, ap 9 08.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x1a000 0x1000>; + }; + + target-module@24000 { /* 0x47c24000, ap 11 28.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x24000 0x1000>; + }; + + target-module@26000 { /* 0x47c26000, ap 13 30.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x26000 0x1000>; + }; + + target-module@28000 { /* 0x47c28000, ap 29 40.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x28000 0x1000>; + }; + + target-module@30000 { /* 0x47c30000, ap 15 14.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x30000 0x1000>; + }; + + target-module@32000 { /* 0x47c32000, ap 31 06.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x32000 0x1000>; + }; + + target-module@38000 { /* 0x47c38000, ap 17 18.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x38000 0x1000>; + }; + + target-module@3a000 { /* 0x47c3a000, ap 19 1c.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3a000 0x1000>; + }; + + target-module@3c000 { /* 0x47c3c000, ap 23 38.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3c000 0x1000>; + }; + + target-module@3e000 { /* 0x47c3e000, ap 21 10.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3e000 0x1000>; + }; + + target-module@40000 { /* 0x47c40000, ap 24 02.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x40000 0x1000>; + }; + + target-module@42000 { /* 0x47c42000, ap 35 34.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x42000 0x1000>; + }; + + target-module@44000 { /* 0x47c44000, ap 27 24.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x44000 0x1000>; + }; + + target-module@46000 { /* 0x47c46000, ap 25 2c.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x46000 0x1000>; + }; + }; +}; + +&l4_fast { /* 0x4a000000 */ + compatible = "ti,am33xx-l4-fast", "simple-bus"; + reg = <0x4a000000 0x800>, + <0x4a000800 0x800>, + <0x4a001000 0x400>; + reg-names = "ap", "la", "ia0"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x4a000000 0x1000000>; /* segment 0 */ + + segment@0 { /* 0x4a000000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */ + <0x00000800 0x00000800 0x000800>, /* ap 1 */ + <0x00001000 0x00001000 0x000400>, /* ap 2 */ + <0x00100000 0x00100000 0x008000>, /* ap 3 */ + <0x00108000 0x00108000 0x001000>, /* ap 4 */ + <0x00180000 0x00180000 0x020000>, /* ap 5 */ + <0x001a0000 0x001a0000 0x001000>, /* ap 6 */ + <0x00200000 0x00200000 0x080000>, /* ap 7 */ + <0x00280000 0x00280000 0x001000>, /* ap 8 */ + <0x00300000 0x00300000 0x080000>, /* ap 9 */ + <0x00380000 0x00380000 0x001000>; /* ap 10 */ + + target-module@100000 { /* 0x4a100000, ap 3 08.0 */ + compatible = "ti,sysc-omap4-simple", "ti,sysc"; + reg = <0x101200 0x4>, + <0x101208 0x4>, + <0x101204 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <0>; + ti,sysc-midle = , + ; + ti,sysc-sidle = , + ; + ti,syss-mask = <1>; + clocks = <&cpsw_125mhz_clkctrl AM3_CPSW_125MHZ_CPGMAC0_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x100000 0x8000>; + }; + + target-module@180000 { /* 0x4a180000, ap 5 10.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x180000 0x20000>; + }; + + target-module@200000 { /* 0x4a200000, ap 7 02.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x200000 0x80000>; + }; + + pruss_tm: target-module@300000 { /* 0x4a300000, ap 9 04.0 */ + compatible = "ti,sysc-pruss", "ti,sysc"; + reg = <0x326000 0x4>, + <0x326004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = <(SYSC_PRUSS_STANDBY_INIT | + SYSC_PRUSS_SUB_MWAIT)>; + ti,sysc-midle = , + , + ; + ti,sysc-sidle = , + , + ; + clocks = <&pruss_ocp_clkctrl AM3_PRUSS_OCP_PRUSS_CLKCTRL 0>; + clock-names = "fck"; + resets = <&prm_per 1>; + reset-names = "rstctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x300000 0x80000>; + status = "disabled"; + }; + }; +}; + +&l4_mpuss { /* 0x4b140000 */ + compatible = "ti,am33xx-l4-mpuss", "simple-bus"; + reg = <0x4b144400 0x100>, + <0x4b144800 0x400>; + reg-names = "la", "ap"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x4b140000 0x008000>; /* segment 0 */ + + segment@0 { /* 0x4b140000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00004800 0x00004800 0x000400>, /* ap 0 */ + <0x00001000 0x00001000 0x001000>, /* ap 1 */ + <0x00002000 0x00002000 0x001000>, /* ap 2 */ + <0x00004000 0x00004000 0x000400>, /* ap 3 */ + <0x00005000 0x00005000 0x000400>, /* ap 4 */ + <0x00000000 0x00000000 0x001000>, /* ap 5 */ + <0x00003000 0x00003000 0x001000>, /* ap 6 */ + <0x00000800 0x00000800 0x000800>; /* ap 7 */ + + target-module@0 { /* 0x4b140000, ap 5 02.2 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00000000 0x00001000>, + <0x00001000 0x00001000 0x00001000>, + <0x00002000 0x00002000 0x00001000>; + }; + + target-module@3000 { /* 0x4b143000, ap 6 04.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3000 0x1000>; + }; + }; +}; + +&l4_per { /* 0x48000000 */ + compatible = "ti,am33xx-l4-per", "simple-bus"; + reg = <0x48000000 0x800>, + <0x48000800 0x800>, + <0x48001000 0x400>, + <0x48001400 0x400>, + <0x48001800 0x400>, + <0x48001c00 0x400>; + reg-names = "ap", "la", "ia0", "ia1", "ia2", "ia3"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x48000000 0x100000>, /* segment 0 */ + <0x00100000 0x48100000 0x100000>, /* segment 1 */ + <0x00200000 0x48200000 0x100000>, /* segment 2 */ + <0x00300000 0x48300000 0x100000>, /* segment 3 */ + <0x46000000 0x46000000 0x400000>, /* l3 data port */ + <0x46400000 0x46400000 0x400000>; /* l3 data port */ + + segment@0 { /* 0x48000000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */ + <0x00000800 0x00000800 0x000800>, /* ap 1 */ + <0x00001000 0x00001000 0x000400>, /* ap 2 */ + <0x00001400 0x00001400 0x000400>, /* ap 3 */ + <0x00001800 0x00001800 0x000400>, /* ap 4 */ + <0x00001c00 0x00001c00 0x000400>, /* ap 5 */ + <0x00008000 0x00008000 0x001000>, /* ap 6 */ + <0x00009000 0x00009000 0x001000>, /* ap 7 */ + <0x00016000 0x00016000 0x001000>, /* ap 8 */ + <0x00017000 0x00017000 0x001000>, /* ap 9 */ + <0x00022000 0x00022000 0x001000>, /* ap 10 */ + <0x00023000 0x00023000 0x001000>, /* ap 11 */ + <0x00024000 0x00024000 0x001000>, /* ap 12 */ + <0x00025000 0x00025000 0x001000>, /* ap 13 */ + <0x0002a000 0x0002a000 0x001000>, /* ap 14 */ + <0x0002b000 0x0002b000 0x001000>, /* ap 15 */ + <0x00038000 0x00038000 0x002000>, /* ap 16 */ + <0x0003a000 0x0003a000 0x001000>, /* ap 17 */ + <0x00014000 0x00014000 0x001000>, /* ap 18 */ + <0x00015000 0x00015000 0x001000>, /* ap 19 */ + <0x0003c000 0x0003c000 0x002000>, /* ap 20 */ + <0x0003e000 0x0003e000 0x001000>, /* ap 21 */ + <0x00040000 0x00040000 0x001000>, /* ap 22 */ + <0x00041000 0x00041000 0x001000>, /* ap 23 */ + <0x00042000 0x00042000 0x001000>, /* ap 24 */ + <0x00043000 0x00043000 0x001000>, /* ap 25 */ + <0x00044000 0x00044000 0x001000>, /* ap 26 */ + <0x00045000 0x00045000 0x001000>, /* ap 27 */ + <0x00046000 0x00046000 0x001000>, /* ap 28 */ + <0x00047000 0x00047000 0x001000>, /* ap 29 */ + <0x00048000 0x00048000 0x001000>, /* ap 30 */ + <0x00049000 0x00049000 0x001000>, /* ap 31 */ + <0x0004c000 0x0004c000 0x001000>, /* ap 32 */ + <0x0004d000 0x0004d000 0x001000>, /* ap 33 */ + <0x00050000 0x00050000 0x002000>, /* ap 34 */ + <0x00052000 0x00052000 0x001000>, /* ap 35 */ + <0x00060000 0x00060000 0x001000>, /* ap 36 */ + <0x00061000 0x00061000 0x001000>, /* ap 37 */ + <0x00080000 0x00080000 0x010000>, /* ap 38 */ + <0x00090000 0x00090000 0x001000>, /* ap 39 */ + <0x000a0000 0x000a0000 0x010000>, /* ap 40 */ + <0x000b0000 0x000b0000 0x001000>, /* ap 41 */ + <0x00030000 0x00030000 0x001000>, /* ap 77 */ + <0x00031000 0x00031000 0x001000>, /* ap 78 */ + <0x0004a000 0x0004a000 0x001000>, /* ap 85 */ + <0x0004b000 0x0004b000 0x001000>, /* ap 86 */ + <0x000c8000 0x000c8000 0x001000>, /* ap 87 */ + <0x000c9000 0x000c9000 0x001000>, /* ap 88 */ + <0x000cc000 0x000cc000 0x001000>, /* ap 89 */ + <0x000cd000 0x000cd000 0x001000>, /* ap 90 */ + <0x000ca000 0x000ca000 0x001000>, /* ap 91 */ + <0x000cb000 0x000cb000 0x001000>, /* ap 92 */ + <0x46000000 0x46000000 0x400000>, /* l3 data port */ + <0x46400000 0x46400000 0x400000>; /* l3 data port */ + + target-module@8000 { /* 0x48008000, ap 6 10.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x8000 0x1000>; + }; + + target-module@14000 { /* 0x48014000, ap 18 58.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x14000 0x1000>; + }; + + target-module@16000 { /* 0x48016000, ap 8 3c.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x16000 0x1000>; + }; + + target-module@22000 { /* 0x48022000, ap 10 12.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x22050 0x4>, + <0x22054 0x4>, + <0x22058 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_UART2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x22000 0x1000>; + + uart1: serial@0 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + clock-frequency = <48000000>; + reg = <0x0 0x1000>; + interrupts = <73>; + status = "disabled"; + dmas = <&edma 28 0>, <&edma 29 0>; + dma-names = "tx", "rx"; + }; + }; + + target-module@24000 { /* 0x48024000, ap 12 14.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x24050 0x4>, + <0x24054 0x4>, + <0x24058 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_UART3_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x24000 0x1000>; + + uart2: serial@0 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + clock-frequency = <48000000>; + reg = <0x0 0x1000>; + interrupts = <74>; + status = "disabled"; + dmas = <&edma 30 0>, <&edma 31 0>; + dma-names = "tx", "rx"; + }; + }; + + target-module@2a000 { /* 0x4802a000, ap 14 2a.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x2a000 0x8>, + <0x2a010 0x8>, + <0x2a090 0x8>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_I2C2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x2a000 0x1000>; + }; + + target-module@30000 { /* 0x48030000, ap 77 08.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x30000 0x4>, + <0x30110 0x4>, + <0x30114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_SPI0_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x30000 0x1000>; + + spi0: spi@0 { + compatible = "ti,omap4-mcspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x400>; + interrupts = <65>; + ti,spi-num-cs = <2>; + dmas = <&edma 16 0 + &edma 17 0 + &edma 18 0 + &edma 19 0>; + dma-names = "tx0", "rx0", "tx1", "rx1"; + status = "disabled"; + }; + }; + + target-module@38000 { /* 0x48038000, ap 16 02.0 */ + compatible = "ti,sysc-omap4-simple", "ti,sysc"; + reg = <0x38000 0x4>, + <0x38004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-sidle = , + , + ; + /* Domains (P, C): per_pwrdm, l3s_clkdm */ + clocks = <&l3s_clkctrl AM3_L3S_MCASP0_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x38000 0x2000>, + <0x46000000 0x46000000 0x400000>; + + mcasp0: mcasp@0 { + compatible = "ti,am33xx-mcasp-audio"; + reg = <0x0 0x2000>, + <0x46000000 0x400000>; + reg-names = "mpu", "dat"; + interrupts = <80>, <81>; + interrupt-names = "tx", "rx"; + status = "disabled"; + dmas = <&edma 8 2>, + <&edma 9 2>; + dma-names = "tx", "rx"; + }; + }; + + target-module@3c000 { /* 0x4803c000, ap 20 32.0 */ + compatible = "ti,sysc-omap4-simple", "ti,sysc"; + reg = <0x3c000 0x4>, + <0x3c004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-sidle = , + , + ; + /* Domains (P, C): per_pwrdm, l3s_clkdm */ + clocks = <&l3s_clkctrl AM3_L3S_MCASP1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3c000 0x2000>, + <0x46400000 0x46400000 0x400000>; + + mcasp1: mcasp@0 { + compatible = "ti,am33xx-mcasp-audio"; + reg = <0x0 0x2000>, + <0x46400000 0x400000>; + reg-names = "mpu", "dat"; + interrupts = <82>, <83>; + interrupt-names = "tx", "rx"; + status = "disabled"; + dmas = <&edma 10 2>, + <&edma 11 2>; + dma-names = "tx", "rx"; + }; + }; + + timer2_target: target-module@40000 { /* 0x48040000, ap 22 1e.0 */ + compatible = "ti,sysc-omap4-timer", "ti,sysc"; + reg = <0x40000 0x4>, + <0x40010 0x4>, + <0x40014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_TIMER2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x40000 0x1000>; + + timer2: timer@0 { + compatible = "ti,am335x-timer"; + reg = <0x0 0x400>; + interrupts = <68>; + clocks = <&timer2_fck>; + clock-names = "fck"; + }; + }; + + target-module@42000 { /* 0x48042000, ap 24 1c.0 */ + compatible = "ti,sysc-omap4-timer", "ti,sysc"; + reg = <0x42000 0x4>, + <0x42010 0x4>, + <0x42014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_TIMER3_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x42000 0x1000>; + + timer3: timer@0 { + compatible = "ti,am335x-timer"; + reg = <0x0 0x400>; + interrupts = <69>; + }; + }; + + target-module@44000 { /* 0x48044000, ap 26 26.0 */ + compatible = "ti,sysc-omap4-timer", "ti,sysc"; + reg = <0x44000 0x4>, + <0x44010 0x4>, + <0x44014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_TIMER4_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x44000 0x1000>; + + timer4: timer@0 { + compatible = "ti,am335x-timer"; + reg = <0x0 0x400>; + interrupts = <92>; + ti,timer-pwm; + }; + }; + + target-module@46000 { /* 0x48046000, ap 28 28.0 */ + compatible = "ti,sysc-omap4-timer", "ti,sysc"; + reg = <0x46000 0x4>, + <0x46010 0x4>, + <0x46014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_TIMER5_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x46000 0x1000>; + + timer5: timer@0 { + compatible = "ti,am335x-timer"; + reg = <0x0 0x400>; + interrupts = <93>; + ti,timer-pwm; + }; + }; + + target-module@48000 { /* 0x48048000, ap 30 22.0 */ + compatible = "ti,sysc-omap4-timer", "ti,sysc"; + reg = <0x48000 0x4>, + <0x48010 0x4>, + <0x48014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_TIMER6_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x48000 0x1000>; + + timer6: timer@0 { + compatible = "ti,am335x-timer"; + reg = <0x0 0x400>; + interrupts = <94>; + ti,timer-pwm; + }; + }; + + target-module@4a000 { /* 0x4804a000, ap 85 60.0 */ + compatible = "ti,sysc-omap4-timer", "ti,sysc"; + reg = <0x4a000 0x4>, + <0x4a010 0x4>, + <0x4a014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_TIMER7_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x4a000 0x1000>; + + timer7: timer@0 { + compatible = "ti,am335x-timer"; + reg = <0x0 0x400>; + interrupts = <95>; + ti,timer-pwm; + }; + }; + + target-module@4c000 { /* 0x4804c000, ap 32 36.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x4c000 0x4>, + <0x4c010 0x4>, + <0x4c114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_GPIO2_CLKCTRL 0>, + <&l4ls_clkctrl AM3_L4LS_GPIO2_CLKCTRL 18>; + clock-names = "fck", "dbclk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x4c000 0x1000>; + }; + + target-module@50000 { /* 0x48050000, ap 34 2c.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x50000 0x2000>; + }; + + target-module@60000 { /* 0x48060000, ap 36 0c.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x602fc 0x4>, + <0x60110 0x4>, + <0x60114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_MMC1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x60000 0x1000>; + }; + + target-module@80000 { /* 0x48080000, ap 38 18.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x80000 0x4>, + <0x80010 0x4>, + <0x80014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_ELM_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x80000 0x10000>; + + elm: elm@0 { + compatible = "ti,am3352-elm"; + reg = <0x0 0x2000>; + interrupts = <4>; + status = "disabled"; + }; + }; + + target-module@a0000 { /* 0x480a0000, ap 40 5e.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xa0000 0x10000>; + }; + + target-module@c8000 { /* 0x480c8000, ap 87 06.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0xc8000 0x4>, + <0xc8010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-sidle = , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_MAILBOX_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xc8000 0x1000>; + + mailbox: mailbox@0 { + compatible = "ti,omap4-mailbox"; + reg = <0x0 0x200>; + interrupts = <77>; + #mbox-cells = <1>; + ti,mbox-num-users = <4>; + ti,mbox-num-fifos = <8>; + mbox_wkupm3: wkup_m3 { + ti,mbox-send-noirq; + ti,mbox-tx = <0 0 0>; + ti,mbox-rx = <0 0 3>; + }; + }; + }; + + target-module@ca000 { /* 0x480ca000, ap 91 40.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xca000 0x4>, + <0xca010 0x4>, + <0xca014 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_SPINLOCK_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xca000 0x1000>; + + hwspinlock: spinlock@0 { + compatible = "ti,omap4-hwspinlock"; + reg = <0x0 0x1000>; + #hwlock-cells = <1>; + }; + }; + + target-module@cc000 { /* 0x480cc000, ap 89 0e.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xcc000 0x1000>; + }; + }; + + segment@100000 { /* 0x48100000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0008c000 0x0018c000 0x001000>, /* ap 42 */ + <0x0008d000 0x0018d000 0x001000>, /* ap 43 */ + <0x0008e000 0x0018e000 0x001000>, /* ap 44 */ + <0x0008f000 0x0018f000 0x001000>, /* ap 45 */ + <0x0009c000 0x0019c000 0x001000>, /* ap 46 */ + <0x0009d000 0x0019d000 0x001000>, /* ap 47 */ + <0x000a6000 0x001a6000 0x001000>, /* ap 48 */ + <0x000a7000 0x001a7000 0x001000>, /* ap 49 */ + <0x000a8000 0x001a8000 0x001000>, /* ap 50 */ + <0x000a9000 0x001a9000 0x001000>, /* ap 51 */ + <0x000aa000 0x001aa000 0x001000>, /* ap 52 */ + <0x000ab000 0x001ab000 0x001000>, /* ap 53 */ + <0x000ac000 0x001ac000 0x001000>, /* ap 54 */ + <0x000ad000 0x001ad000 0x001000>, /* ap 55 */ + <0x000ae000 0x001ae000 0x001000>, /* ap 56 */ + <0x000af000 0x001af000 0x001000>, /* ap 57 */ + <0x000b0000 0x001b0000 0x010000>, /* ap 58 */ + <0x000c0000 0x001c0000 0x001000>, /* ap 59 */ + <0x000cc000 0x001cc000 0x002000>, /* ap 60 */ + <0x000ce000 0x001ce000 0x002000>, /* ap 61 */ + <0x000d0000 0x001d0000 0x002000>, /* ap 62 */ + <0x000d2000 0x001d2000 0x002000>, /* ap 63 */ + <0x000d8000 0x001d8000 0x001000>, /* ap 64 */ + <0x000d9000 0x001d9000 0x001000>, /* ap 65 */ + <0x000a0000 0x001a0000 0x001000>, /* ap 79 */ + <0x000a1000 0x001a1000 0x001000>, /* ap 80 */ + <0x000a2000 0x001a2000 0x001000>, /* ap 81 */ + <0x000a3000 0x001a3000 0x001000>, /* ap 82 */ + <0x000a4000 0x001a4000 0x001000>, /* ap 83 */ + <0x000a5000 0x001a5000 0x001000>; /* ap 84 */ + + target-module@8c000 { /* 0x4818c000, ap 42 04.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x8c000 0x1000>; + }; + + target-module@8e000 { /* 0x4818e000, ap 44 0a.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x8e000 0x1000>; + }; + + target-module@9c000 { /* 0x4819c000, ap 46 5a.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x9c000 0x8>, + <0x9c010 0x8>, + <0x9c090 0x8>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_I2C3_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x9c000 0x1000>; + }; + + target-module@a0000 { /* 0x481a0000, ap 79 24.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xa0000 0x4>, + <0xa0110 0x4>, + <0xa0114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_SPI1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xa0000 0x1000>; + + spi1: spi@0 { + compatible = "ti,omap4-mcspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x400>; + interrupts = <125>; + ti,spi-num-cs = <2>; + dmas = <&edma 42 0 + &edma 43 0 + &edma 44 0 + &edma 45 0>; + dma-names = "tx0", "rx0", "tx1", "rx1"; + status = "disabled"; + }; + }; + + target-module@a2000 { /* 0x481a2000, ap 81 2e.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xa2000 0x1000>; + }; + + target-module@a4000 { /* 0x481a4000, ap 83 30.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xa4000 0x1000>; + }; + + target-module@a6000 { /* 0x481a6000, ap 48 16.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xa6050 0x4>, + <0xa6054 0x4>, + <0xa6058 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_UART4_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xa6000 0x1000>; + + uart3: serial@0 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + clock-frequency = <48000000>; + reg = <0x0 0x1000>; + interrupts = <44>; + status = "disabled"; + }; + }; + + target-module@a8000 { /* 0x481a8000, ap 50 20.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xa8050 0x4>, + <0xa8054 0x4>, + <0xa8058 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_UART5_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xa8000 0x1000>; + + uart4: serial@0 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + clock-frequency = <48000000>; + reg = <0x0 0x1000>; + interrupts = <45>; + status = "disabled"; + }; + }; + + target-module@aa000 { /* 0x481aa000, ap 52 1a.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xaa050 0x4>, + <0xaa054 0x4>, + <0xaa058 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_UART6_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xaa000 0x1000>; + + uart5: serial@0 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + clock-frequency = <48000000>; + reg = <0x0 0x1000>; + interrupts = <46>; + status = "disabled"; + }; + }; + + target-module@ac000 { /* 0x481ac000, ap 54 38.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xac000 0x4>, + <0xac010 0x4>, + <0xac114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_GPIO3_CLKCTRL 0>, + <&l4ls_clkctrl AM3_L4LS_GPIO3_CLKCTRL 18>; + clock-names = "fck", "dbclk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xac000 0x1000>; + }; + + target-module@ae000 { /* 0x481ae000, ap 56 3a.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xae000 0x4>, + <0xae010 0x4>, + <0xae114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_GPIO4_CLKCTRL 0>, + <&l4ls_clkctrl AM3_L4LS_GPIO4_CLKCTRL 18>; + clock-names = "fck", "dbclk"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xae000 0x1000>; + }; + + target-module@b0000 { /* 0x481b0000, ap 58 50.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xb0000 0x10000>; + }; + + target-module@cc000 { /* 0x481cc000, ap 60 46.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0xcc020 0x4>; + reg-names = "rev"; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN0_CLKCTRL 0>, + <&dcan0_fck>; + clock-names = "fck", "osc"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xcc000 0x2000>; + + dcan0: can@0 { + compatible = "ti,am3352-d_can"; + reg = <0x0 0x2000>; + clocks = <&dcan0_fck>; + clock-names = "fck"; + syscon-raminit = <&scm_conf 0x644 0>; + interrupts = <52>; + status = "disabled"; + }; + }; + + target-module@d0000 { /* 0x481d0000, ap 62 42.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0xd0020 0x4>; + reg-names = "rev"; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN1_CLKCTRL 0>, + <&dcan1_fck>; + clock-names = "fck", "osc"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xd0000 0x2000>; + + dcan1: can@0 { + compatible = "ti,am3352-d_can"; + reg = <0x0 0x2000>; + clocks = <&dcan1_fck>; + clock-names = "fck"; + syscon-raminit = <&scm_conf 0x644 1>; + interrupts = <55>; + status = "disabled"; + }; + }; + + target-module@d8000 { /* 0x481d8000, ap 64 66.0 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0xd82fc 0x4>, + <0xd8110 0x4>, + <0xd8114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY | + SYSC_OMAP2_ENAWAKEUP | + SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_MMC2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xd8000 0x1000>; + }; + }; + + segment@200000 { /* 0x48200000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + }; + + segment@300000 { /* 0x48300000 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00300000 0x001000>, /* ap 66 */ + <0x00001000 0x00301000 0x001000>, /* ap 67 */ + <0x00002000 0x00302000 0x001000>, /* ap 68 */ + <0x00003000 0x00303000 0x001000>, /* ap 69 */ + <0x00004000 0x00304000 0x001000>, /* ap 70 */ + <0x00005000 0x00305000 0x001000>, /* ap 71 */ + <0x0000e000 0x0030e000 0x001000>, /* ap 72 */ + <0x0000f000 0x0030f000 0x001000>, /* ap 73 */ + <0x00018000 0x00318000 0x004000>, /* ap 74 */ + <0x0001c000 0x0031c000 0x001000>, /* ap 75 */ + <0x00010000 0x00310000 0x002000>, /* ap 76 */ + <0x00012000 0x00312000 0x001000>, /* ap 93 */ + <0x00015000 0x00315000 0x001000>, /* ap 94 */ + <0x00016000 0x00316000 0x001000>, /* ap 95 */ + <0x00017000 0x00317000 0x001000>, /* ap 96 */ + <0x00013000 0x00313000 0x001000>, /* ap 97 */ + <0x00014000 0x00314000 0x001000>, /* ap 98 */ + <0x00020000 0x00320000 0x001000>, /* ap 99 */ + <0x00021000 0x00321000 0x001000>, /* ap 100 */ + <0x00022000 0x00322000 0x001000>, /* ap 101 */ + <0x00023000 0x00323000 0x001000>, /* ap 102 */ + <0x00024000 0x00324000 0x001000>, /* ap 103 */ + <0x00025000 0x00325000 0x001000>; /* ap 104 */ + + target-module@0 { /* 0x48300000, ap 66 48.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x0 0x4>, + <0x4 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-midle = , + , + , + ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_EPWMSS0_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x1000>; + + epwmss0: epwmss@0 { + compatible = "ti,am33xx-pwmss"; + reg = <0x0 0x10>; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + ranges = <0 0 0x1000>; + + ecap0: ecap@100 { + compatible = "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x100 0x80>; + clocks = <&l4ls_gclk>; + clock-names = "fck"; + interrupts = <31>; + interrupt-names = "ecap0"; + status = "disabled"; + }; + + ehrpwm0: pwm@200 { + compatible = "ti,am3352-ehrpwm", + "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x200 0x80>; + clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>; + clock-names = "tbclk", "fck"; + status = "disabled"; + }; + }; + }; + + target-module@2000 { /* 0x48302000, ap 68 52.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x2000 0x4>, + <0x2004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-midle = , + , + , + ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_EPWMSS1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x2000 0x1000>; + + epwmss1: epwmss@0 { + compatible = "ti,am33xx-pwmss"; + reg = <0x0 0x10>; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + ranges = <0 0 0x1000>; + + ecap1: ecap@100 { + compatible = "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x100 0x80>; + clocks = <&l4ls_gclk>; + clock-names = "fck"; + interrupts = <47>; + interrupt-names = "ecap1"; + status = "disabled"; + }; + + ehrpwm1: pwm@200 { + compatible = "ti,am3352-ehrpwm", + "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x200 0x80>; + clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>; + clock-names = "tbclk", "fck"; + status = "disabled"; + }; + }; + }; + + target-module@4000 { /* 0x48304000, ap 70 44.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x4000 0x4>, + <0x4004 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-midle = , + , + , + ; + ti,sysc-sidle = , + , + , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_EPWMSS2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x4000 0x1000>; + + epwmss2: epwmss@0 { + compatible = "ti,am33xx-pwmss"; + reg = <0x0 0x10>; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + ranges = <0 0 0x1000>; + + ecap2: ecap@100 { + compatible = "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x100 0x80>; + clocks = <&l4ls_gclk>; + clock-names = "fck"; + interrupts = <61>; + interrupt-names = "ecap2"; + status = "disabled"; + }; + + ehrpwm2: pwm@200 { + compatible = "ti,am3352-ehrpwm", + "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x200 0x80>; + clocks = <&ehrpwm2_tbclk>, <&l4ls_gclk>; + clock-names = "tbclk", "fck"; + status = "disabled"; + }; + }; + }; + + target-module@e000 { /* 0x4830e000, ap 72 4a.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0xe000 0x4>, + <0xe054 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-midle = , + , + ; + ti,sysc-sidle = , + , + ; + /* Domains (P, C): per_pwrdm, lcdc_clkdm */ + clocks = <&lcdc_clkctrl AM3_LCDC_LCDC_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe000 0x1000>; + + lcdc: lcdc@0 { + compatible = "ti,am33xx-tilcdc"; + reg = <0x0 0x1000>; + interrupts = <36>; + status = "disabled"; + }; + }; + + target-module@10000 { /* 0x48310000, ap 76 4e.1 */ + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x11fe0 0x4>, + <0x11fe4 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-sidle = , + ; + /* Domains (P, C): per_pwrdm, l4ls_clkdm */ + clocks = <&l4ls_clkctrl AM3_L4LS_RNG_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x10000 0x2000>; + + rng: rng@0 { + compatible = "ti,omap4-rng"; + reg = <0x0 0x2000>; + interrupts = <111>; + }; + }; + + target-module@13000 { /* 0x48313000, ap 97 62.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x13000 0x1000>; + }; + + target-module@15000 { /* 0x48315000, ap 94 56.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00015000 0x00001000>, + <0x00001000 0x00016000 0x00001000>; + }; + + target-module@18000 { /* 0x48318000, ap 74 4c.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x18000 0x4000>; + }; + + target-module@20000 { /* 0x48320000, ap 99 34.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x20000 0x1000>; + }; + + target-module@22000 { /* 0x48322000, ap 101 3e.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x22000 0x1000>; + }; + + target-module@24000 { /* 0x48324000, ap 103 68.0 */ + compatible = "ti,sysc"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x24000 0x1000>; + }; + }; +}; diff --git a/arch/arm/dts/am33xx.dtsi b/arch/arm/dts/am33xx.dtsi index d3dd6a16e7..3e5ed00aae 100644 --- a/arch/arm/dts/am33xx.dtsi +++ b/arch/arm/dts/am33xx.dtsi @@ -8,6 +8,7 @@ * kind, whether express or implied. */ +#include #include #include #include @@ -46,6 +47,7 @@ #size-cells = <0>; cpu@0 { compatible = "arm,cortex-a8"; + enable-method = "ti,am3352"; device_type = "cpu"; reg = <0>; @@ -55,6 +57,17 @@ clock-names = "cpu"; clock-latency = <300000>; /* From omap-cpufreq driver */ + cpu-idle-states = <&mpu_gate>; + }; + + idle-states { + mpu_gate: mpu_gate { + compatible = "arm,idle-state"; + entry-latency-us = <40>; + exit-latency-us = <90>; + min-residency-us = <300>; + ti,idle-wkup-m3; + }; }; }; @@ -167,11 +180,6 @@ ti,hwmods = "l3_main"; l4_wkup: l4_wkup@44c00000 { - compatible = "ti,am3-l4-wkup", "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0x44c00000 0x280000>; - wkup_m3: wkup_m3@100000 { compatible = "ti,am3352-wkup-m3"; reg = <0x100000 0x4000>, @@ -180,73 +188,14 @@ ti,hwmods = "wkup_m3"; ti,pm-firmware = "am335x-pm-firmware.elf"; }; - - prcm: prcm@200000 { - compatible = "ti,am3-prcm", "simple-bus"; - reg = <0x200000 0x4000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0x200000 0x4000>; - - prcm_clocks: clocks { - #address-cells = <1>; - #size-cells = <0>; - }; - - prcm_clockdomains: clockdomains { - }; - }; - - scm: scm@210000 { - compatible = "ti,am3-scm", "simple-bus"; - reg = <0x210000 0x2000>; - #address-cells = <1>; - #size-cells = <1>; - #pinctrl-cells = <1>; - ranges = <0 0x210000 0x2000>; - - am33xx_pinmux: pinmux@800 { - compatible = "pinctrl-single"; - reg = <0x800 0x238>; - #address-cells = <1>; - #size-cells = <0>; - #pinctrl-cells = <1>; - pinctrl-single,register-width = <32>; - pinctrl-single,function-mask = <0x7f>; - }; - - scm_conf: scm_conf@0 { - compatible = "syscon", "simple-bus"; - reg = <0x0 0x800>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0 0x800>; - - scm_clocks: clocks { - #address-cells = <1>; - #size-cells = <0>; - }; - }; - - wkup_m3_ipc: wkup_m3_ipc@1324 { - compatible = "ti,am3352-wkup-m3-ipc"; - reg = <0x1324 0x24>; - interrupts = <78>; - ti,rproc = <&wkup_m3>; - mboxes = <&mailbox &mbox_wkupm3>; - }; - - edma_xbar: dma-router@f90 { - compatible = "ti,am335x-edma-crossbar"; - reg = <0xf90 0x40>; - #dma-cells = <3>; - dma-requests = <32>; - dma-masters = <&edma>; - }; - - scm_clockdomains: clockdomains { - }; - }; + }; + l4_per: interconnect@48000000 { + }; + l4_fw: interconnect@47c00000 { + }; + l4_fast: interconnect@4a000000 { + }; + l4_mpuss: interconnect@4b140000 { }; intc: interrupt-controller@48200000 { @@ -256,45 +205,100 @@ reg = <0x48200000 0x1000>; }; - edma: edma@49000000 { - compatible = "ti,edma3-tpcc"; - ti,hwmods = "tpcc"; - reg = <0x49000000 0x10000>; - reg-names = "edma3_cc"; - interrupts = <12 13 14>; - interrupt-names = "edma3_ccint", "edma3_mperr", - "edma3_ccerrint"; - dma-requests = <64>; - #dma-cells = <2>; + target-module@49000000 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x49000000 0x4>; + reg-names = "rev"; + clocks = <&l3_clkctrl AM3_L3_TPCC_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49000000 0x10000>; - ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>, - <&edma_tptc2 0>; + edma: dma@0 { + compatible = "ti,edma3-tpcc"; + reg = <0 0x10000>; + reg-names = "edma3_cc"; + interrupts = <12 13 14>; + interrupt-names = "edma3_ccint", "edma3_mperr", + "edma3_ccerrint"; + dma-requests = <64>; + #dma-cells = <2>; - ti,edma-memcpy-channels = <20 21>; + ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>, + <&edma_tptc2 0>; + + ti,edma-memcpy-channels = <20 21>; + }; }; - edma_tptc0: tptc@49800000 { - compatible = "ti,edma3-tptc"; - ti,hwmods = "tptc0"; - reg = <0x49800000 0x100000>; - interrupts = <112>; - interrupt-names = "edma3_tcerrint"; + target-module@49800000 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x49800000 0x4>, + <0x49800010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM3_L3_TPTC0_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49800000 0x100000>; + + edma_tptc0: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = <112>; + interrupt-names = "edma3_tcerrint"; + }; }; - edma_tptc1: tptc@49900000 { - compatible = "ti,edma3-tptc"; - ti,hwmods = "tptc1"; - reg = <0x49900000 0x100000>; - interrupts = <113>; - interrupt-names = "edma3_tcerrint"; + target-module@49900000 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x49900000 0x4>, + <0x49900010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM3_L3_TPTC1_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49900000 0x100000>; + + edma_tptc1: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = <113>; + interrupt-names = "edma3_tcerrint"; + }; }; - edma_tptc2: tptc@49a00000 { - compatible = "ti,edma3-tptc"; - ti,hwmods = "tptc2"; - reg = <0x49a00000 0x100000>; - interrupts = <114>; - interrupt-names = "edma3_tcerrint"; + target-module@49a00000 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x49a00000 0x4>, + <0x49a00010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = ; + ti,sysc-midle = ; + ti,sysc-sidle = , + ; + clocks = <&l3_clkctrl AM3_L3_TPTC2_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x49a00000 0x100000>; + + edma_tptc2: dma@0 { + compatible = "ti,edma3-tptc"; + reg = <0 0x100000>; + interrupts = <114>; + interrupt-names = "edma3_tcerrint"; + }; }; gpio0: gpio@44e07000 { @@ -341,66 +345,6 @@ interrupts = <62>; }; - uart0: serial@44e09000 { - compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart1"; - clock-frequency = <48000000>; - reg = <0x44e09000 0x2000>; - interrupts = <72>; - status = "disabled"; - dmas = <&edma 26 0>, <&edma 27 0>; - dma-names = "tx", "rx"; - }; - - uart1: serial@48022000 { - compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart2"; - clock-frequency = <48000000>; - reg = <0x48022000 0x2000>; - interrupts = <73>; - status = "disabled"; - dmas = <&edma 28 0>, <&edma 29 0>; - dma-names = "tx", "rx"; - }; - - uart2: serial@48024000 { - compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart3"; - clock-frequency = <48000000>; - reg = <0x48024000 0x2000>; - interrupts = <74>; - status = "disabled"; - dmas = <&edma 30 0>, <&edma 31 0>; - dma-names = "tx", "rx"; - }; - - uart3: serial@481a6000 { - compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart4"; - clock-frequency = <48000000>; - reg = <0x481a6000 0x2000>; - interrupts = <44>; - status = "disabled"; - }; - - uart4: serial@481a8000 { - compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart5"; - clock-frequency = <48000000>; - reg = <0x481a8000 0x2000>; - interrupts = <45>; - status = "disabled"; - }; - - uart5: serial@481aa000 { - compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart6"; - clock-frequency = <48000000>; - reg = <0x481aa000 0x2000>; - interrupts = <46>; - status = "disabled"; - }; - i2c0: i2c@44e0b000 { compatible = "ti,omap4-i2c"; #address-cells = <1>; @@ -466,13 +410,6 @@ status = "disabled"; }; - hwspinlock: spinlock@480ca000 { - compatible = "ti,omap4-hwspinlock"; - reg = <0x480ca000 0x1000>; - ti,hwmods = "spinlock"; - #hwlock-cells = <1>; - }; - wdt2: wdt@44e35000 { compatible = "ti,omap3-wdt"; ti,hwmods = "wd_timer2"; @@ -480,143 +417,6 @@ interrupts = <91>; }; - dcan0: can@481cc000 { - compatible = "ti,am3352-d_can"; - ti,hwmods = "d_can0"; - reg = <0x481cc000 0x2000>; - clocks = <&dcan0_fck>; - clock-names = "fck"; - syscon-raminit = <&scm_conf 0x644 0>; - interrupts = <52>; - status = "disabled"; - }; - - dcan1: can@481d0000 { - compatible = "ti,am3352-d_can"; - ti,hwmods = "d_can1"; - reg = <0x481d0000 0x2000>; - clocks = <&dcan1_fck>; - clock-names = "fck"; - syscon-raminit = <&scm_conf 0x644 1>; - interrupts = <55>; - status = "disabled"; - }; - - mailbox: mailbox@480c8000 { - compatible = "ti,omap4-mailbox"; - reg = <0x480C8000 0x200>; - interrupts = <77>; - ti,hwmods = "mailbox"; - #mbox-cells = <1>; - ti,mbox-num-users = <4>; - ti,mbox-num-fifos = <8>; - mbox_wkupm3: wkup_m3 { - ti,mbox-send-noirq; - ti,mbox-tx = <0 0 0>; - ti,mbox-rx = <0 0 3>; - }; - }; - - timer1: timer@44e31000 { - compatible = "ti,am335x-timer-1ms"; - reg = <0x44e31000 0x400>; - interrupts = <67>; - ti,hwmods = "timer1"; - ti,timer-alwon; - clocks = <&timer1_fck>; - clock-names = "fck"; - }; - - timer2: timer@48040000 { - compatible = "ti,am335x-timer"; - reg = <0x48040000 0x400>; - interrupts = <68>; - ti,hwmods = "timer2"; - clocks = <&timer2_fck>; - clock-names = "fck"; - }; - - timer3: timer@48042000 { - compatible = "ti,am335x-timer"; - reg = <0x48042000 0x400>; - interrupts = <69>; - ti,hwmods = "timer3"; - }; - - timer4: timer@48044000 { - compatible = "ti,am335x-timer"; - reg = <0x48044000 0x400>; - interrupts = <92>; - ti,hwmods = "timer4"; - ti,timer-pwm; - }; - - timer5: timer@48046000 { - compatible = "ti,am335x-timer"; - reg = <0x48046000 0x400>; - interrupts = <93>; - ti,hwmods = "timer5"; - ti,timer-pwm; - }; - - timer6: timer@48048000 { - compatible = "ti,am335x-timer"; - reg = <0x48048000 0x400>; - interrupts = <94>; - ti,hwmods = "timer6"; - ti,timer-pwm; - }; - - timer7: timer@4804a000 { - compatible = "ti,am335x-timer"; - reg = <0x4804a000 0x400>; - interrupts = <95>; - ti,hwmods = "timer7"; - ti,timer-pwm; - }; - - rtc: rtc@44e3e000 { - compatible = "ti,am3352-rtc", "ti,da830-rtc"; - reg = <0x44e3e000 0x1000>; - interrupts = <75 - 76>; - ti,hwmods = "rtc"; - clocks = <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; - clock-names = "int-clk"; - }; - - spi0: spi@48030000 { - compatible = "ti,omap4-mcspi"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x48030000 0x400>; - interrupts = <65>; - ti,spi-num-cs = <2>; - ti,hwmods = "spi0"; - dmas = <&edma 16 0 - &edma 17 0 - &edma 18 0 - &edma 19 0>; - dma-names = "tx0", "rx0", "tx1", "rx1"; - status = "disabled"; - }; - - spi1: spi@481a0000 { - compatible = "ti,omap4-mcspi"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x481a0000 0x400>; - interrupts = <125>; - ti,spi-num-cs = <2>; - ti,hwmods = "spi1"; - dmas = <&edma 42 0 - &edma 43 0 - &edma 44 0 - &edma 45 0>; - dma-names = "tx0", "rx0", "tx1", "rx1"; - status = "disabled"; - }; - usb: usb@47400000 { compatible = "ti,am33xx-usb"; reg = <0x47400000 0x1000>; @@ -731,121 +531,18 @@ "tx14", "tx15"; }; - cppi41dma: dma-controller@47402000 { + cppi41dma: dma-controller@2000 { compatible = "ti,am3359-cppi41"; - reg = <0x47400000 0x1000 - 0x47402000 0x1000 - 0x47403000 0x1000 - 0x47404000 0x4000>; + reg = <0x0000 0x1000>, + <0x2000 0x1000>, + <0x3000 0x1000>, + <0x4000 0x4000>; reg-names = "glue", "controller", "scheduler", "queuemgr"; interrupts = <17>; interrupt-names = "glue"; #dma-cells = <2>; #dma-channels = <30>; #dma-requests = <256>; - status = "disabled"; - }; - }; - - epwmss0: epwmss@48300000 { - compatible = "ti,am33xx-pwmss"; - reg = <0x48300000 0x10>; - ti,hwmods = "epwmss0"; - #address-cells = <1>; - #size-cells = <1>; - status = "disabled"; - ranges = <0x48300100 0x48300100 0x80 /* ECAP */ - 0x48300180 0x48300180 0x80 /* EQEP */ - 0x48300200 0x48300200 0x80>; /* EHRPWM */ - - ecap0: ecap@48300100 { - compatible = "ti,am3352-ecap", - "ti,am33xx-ecap"; - #pwm-cells = <3>; - reg = <0x48300100 0x80>; - clocks = <&l4ls_gclk>; - clock-names = "fck"; - interrupts = <31>; - interrupt-names = "ecap0"; - status = "disabled"; - }; - - ehrpwm0: pwm@48300200 { - compatible = "ti,am3352-ehrpwm", - "ti,am33xx-ehrpwm"; - #pwm-cells = <3>; - reg = <0x48300200 0x80>; - clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>; - clock-names = "tbclk", "fck"; - status = "disabled"; - }; - }; - - epwmss1: epwmss@48302000 { - compatible = "ti,am33xx-pwmss"; - reg = <0x48302000 0x10>; - ti,hwmods = "epwmss1"; - #address-cells = <1>; - #size-cells = <1>; - status = "disabled"; - ranges = <0x48302100 0x48302100 0x80 /* ECAP */ - 0x48302180 0x48302180 0x80 /* EQEP */ - 0x48302200 0x48302200 0x80>; /* EHRPWM */ - - ecap1: ecap@48302100 { - compatible = "ti,am3352-ecap", - "ti,am33xx-ecap"; - #pwm-cells = <3>; - reg = <0x48302100 0x80>; - clocks = <&l4ls_gclk>; - clock-names = "fck"; - interrupts = <47>; - interrupt-names = "ecap1"; - status = "disabled"; - }; - - ehrpwm1: pwm@48302200 { - compatible = "ti,am3352-ehrpwm", - "ti,am33xx-ehrpwm"; - #pwm-cells = <3>; - reg = <0x48302200 0x80>; - clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>; - clock-names = "tbclk", "fck"; - status = "disabled"; - }; - }; - - epwmss2: epwmss@48304000 { - compatible = "ti,am33xx-pwmss"; - reg = <0x48304000 0x10>; - ti,hwmods = "epwmss2"; - #address-cells = <1>; - #size-cells = <1>; - status = "disabled"; - ranges = <0x48304100 0x48304100 0x80 /* ECAP */ - 0x48304180 0x48304180 0x80 /* EQEP */ - 0x48304200 0x48304200 0x80>; /* EHRPWM */ - - ecap2: ecap@48304100 { - compatible = "ti,am3352-ecap", - "ti,am33xx-ecap"; - #pwm-cells = <3>; - reg = <0x48304100 0x80>; - clocks = <&l4ls_gclk>; - clock-names = "fck"; - interrupts = <61>; - interrupt-names = "ecap2"; - status = "disabled"; - }; - - ehrpwm2: pwm@48304200 { - compatible = "ti,am3352-ehrpwm", - "ti,am33xx-ehrpwm"; - #pwm-cells = <3>; - reg = <0x48304200 0x80>; - clocks = <&ehrpwm2_tbclk>, <&l4ls_gclk>; - clock-names = "tbclk", "fck"; - status = "disabled"; }; }; @@ -904,60 +601,26 @@ }; }; - ocmcram: ocmcram@40300000 { + ocmcram: sram@40300000 { compatible = "mmio-sram"; reg = <0x40300000 0x10000>; /* 64k */ ranges = <0x0 0x40300000 0x10000>; #address-cells = <1>; #size-cells = <1>; - pm_sram_code: pm-sram-code@0 { + pm_sram_code: pm-code-sram@0 { compatible = "ti,sram"; reg = <0x0 0x1000>; protect-exec; }; - pm_sram_data: pm-sram-data@1000 { + pm_sram_data: pm-data-sram@1000 { compatible = "ti,sram"; reg = <0x1000 0x1000>; pool; }; }; - elm: elm@48080000 { - compatible = "ti,am3352-elm"; - reg = <0x48080000 0x2000>; - interrupts = <4>; - ti,hwmods = "elm"; - status = "disabled"; - }; - - lcdc: lcdc@4830e000 { - compatible = "ti,am33xx-tilcdc"; - reg = <0x4830e000 0x1000>; - interrupts = <36>; - ti,hwmods = "lcdc"; - status = "disabled"; - }; - - tscadc: tscadc@44e0d000 { - compatible = "ti,am3359-tscadc"; - reg = <0x44e0d000 0x1000>; - interrupts = <16>; - ti,hwmods = "adc_tsc"; - status = "disabled"; - dmas = <&edma 53 0>, <&edma 57 0>; - dma-names = "fifo0", "fifo1"; - - tsc { - compatible = "ti,am3359-tsc"; - }; - am335x_adc: adc { - #io-channel-cells = <1>; - compatible = "ti,am3359-adc"; - }; - }; - emif: emif@4c000000 { compatible = "ti,emif-am3352"; reg = <0x4c000000 0x1000000>; @@ -987,60 +650,116 @@ status = "disabled"; }; - sham: sham@53100000 { - compatible = "ti,omap4-sham"; - ti,hwmods = "sham"; - reg = <0x53100000 0x200>; - interrupts = <109>; - dmas = <&edma 36 0>; - dma-names = "rx"; + sham_target: target-module@53100000 { + compatible = "ti,sysc-omap3-sham", "ti,sysc"; + reg = <0x53100100 0x4>, + <0x53100110 0x4>, + <0x53100114 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l3_clkdm */ + clocks = <&l3_clkctrl AM3_L3_SHAM_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x53100000 0x1000>; + + sham: sham@0 { + compatible = "ti,omap4-sham"; + reg = <0 0x200>; + interrupts = <109>; + dmas = <&edma 36 0>; + dma-names = "rx"; + }; }; - aes: aes@53500000 { - compatible = "ti,omap4-aes"; - ti,hwmods = "aes"; - reg = <0x53500000 0xa0>; - interrupts = <103>; - dmas = <&edma 6 0>, - <&edma 5 0>; - dma-names = "tx", "rx"; + aes_target: target-module@53500000 { + compatible = "ti,sysc-omap2", "ti,sysc"; + reg = <0x53500080 0x4>, + <0x53500084 0x4>, + <0x53500088 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP2_SOFTRESET | + SYSC_OMAP2_AUTOIDLE)>; + ti,sysc-sidle = , + , + , + ; + ti,syss-mask = <1>; + /* Domains (P, C): per_pwrdm, l3_clkdm */ + clocks = <&l3_clkctrl AM3_L3_AES_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x53500000 0x1000>; + + aes: aes@0 { + compatible = "ti,omap4-aes"; + reg = <0 0xa0>; + interrupts = <103>; + dmas = <&edma 6 0>, + <&edma 5 0>; + dma-names = "tx", "rx"; + }; }; - mcasp0: mcasp@48038000 { - compatible = "ti,am33xx-mcasp-audio"; - ti,hwmods = "mcasp0"; - reg = <0x48038000 0x2000>, - <0x46000000 0x400000>; - reg-names = "mpu", "dat"; - interrupts = <80>, <81>; - interrupt-names = "tx", "rx"; - status = "disabled"; - dmas = <&edma 8 2>, - <&edma 9 2>; - dma-names = "tx", "rx"; - }; + target-module@56000000 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x5600fe00 0x4>, + <0x5600fe10 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-midle = , + , + ; + ti,sysc-sidle = , + , + ; + clocks = <&gfx_l3_clkctrl AM3_GFX_L3_GFX_CLKCTRL 0>; + clock-names = "fck"; + resets = <&prm_gfx 0>; + reset-names = "rstctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x56000000 0x1000000>; - mcasp1: mcasp@4803c000 { - compatible = "ti,am33xx-mcasp-audio"; - ti,hwmods = "mcasp1"; - reg = <0x4803C000 0x2000>, - <0x46400000 0x400000>; - reg-names = "mpu", "dat"; - interrupts = <82>, <83>; - interrupt-names = "tx", "rx"; - status = "disabled"; - dmas = <&edma 10 2>, - <&edma 11 2>; - dma-names = "tx", "rx"; - }; - - rng: rng@48310000 { - compatible = "ti,omap4-rng"; - ti,hwmods = "rng"; - reg = <0x48310000 0x2000>; - interrupts = <111>; + /* + * Closed source PowerVR driver, no child device + * binding or driver in mainline + */ }; }; }; +#include "am33xx-l4.dtsi" #include "am33xx-clocks.dtsi" + +&prcm { + prm_per: prm@c00 { + compatible = "ti,am3-prm-inst", "ti,omap-prm-inst"; + reg = <0xc00 0x100>; + #reset-cells = <1>; + }; + + prm_wkup: prm@d00 { + compatible = "ti,am3-prm-inst", "ti,omap-prm-inst"; + reg = <0xd00 0x100>; + #reset-cells = <1>; + }; + + prm_device: prm@f00 { + compatible = "ti,am3-prm-inst", "ti,omap-prm-inst"; + reg = <0xf00 0x100>; + #reset-cells = <1>; + }; + + prm_gfx: prm@1100 { + compatible = "ti,am3-prm-inst", "ti,omap-prm-inst"; + reg = <0x1100 0x100>; + #reset-cells = <1>; + }; +}; From 2983ad55a13e9afcdf1a3d8f55eea038c0a0e8a3 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:31 +0100 Subject: [PATCH 15/42] clk: add clk_round_rate() It returns the rate which will be set if you ask clk_set_rate() to set that rate. It provides a way to query exactly what rate you'll get if you call clk_set_rate() with that same argument. So essentially, clk_round_rate() and clk_set_rate() are equivalent except the former does not modify the clock hardware in any way. Signed-off-by: Dario Binacchi Reviewed-by: Simon Glass Reviewed-by: Sean Anderson --- arch/sandbox/include/asm/clk.h | 9 +++++++++ drivers/clk/clk-uclass.c | 15 +++++++++++++++ drivers/clk/clk_sandbox.c | 17 +++++++++++++++++ drivers/clk/clk_sandbox_test.c | 10 ++++++++++ include/clk-uclass.h | 8 ++++++++ include/clk.h | 28 ++++++++++++++++++++++++++++ test/dm/clk.c | 22 ++++++++++++++++++++++ 7 files changed, 109 insertions(+) diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h index c184c4bffc..0294baee27 100644 --- a/arch/sandbox/include/asm/clk.h +++ b/arch/sandbox/include/asm/clk.h @@ -105,6 +105,15 @@ int sandbox_clk_test_get_bulk(struct udevice *dev); * @return: The rate of the clock. */ ulong sandbox_clk_test_get_rate(struct udevice *dev, int id); +/** + * sandbox_clk_test_round_rate - Ask the sandbox clock test device to round a + * clock's rate. + * + * @dev: The sandbox clock test (client) device. + * @id: The test device's clock ID to configure. + * @return: The rounded rate of the clock. + */ +ulong sandbox_clk_test_round_rate(struct udevice *dev, int id, ulong rate); /** * sandbox_clk_test_set_rate - Ask the sandbox clock test device to set a * clock's rate. diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 5cfd00ce77..b75056718b 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -523,6 +523,21 @@ long long clk_get_parent_rate(struct clk *clk) return pclk->rate; } +ulong clk_round_rate(struct clk *clk, ulong rate) +{ + const struct clk_ops *ops; + + debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate); + if (!clk_valid(clk)) + return 0; + + ops = clk_dev_ops(clk->dev); + if (!ops->round_rate) + return -ENOSYS; + + return ops->round_rate(clk, rate); +} + ulong clk_set_rate(struct clk *clk, ulong rate) { const struct clk_ops *ops; diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c index 2c6c0e239f..b28b67b448 100644 --- a/drivers/clk/clk_sandbox.c +++ b/drivers/clk/clk_sandbox.c @@ -30,6 +30,22 @@ static ulong sandbox_clk_get_rate(struct clk *clk) return priv->rate[clk->id]; } +static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate) +{ + struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); + + if (!priv->probed) + return -ENODEV; + + if (clk->id >= SANDBOX_CLK_ID_COUNT) + return -EINVAL; + + if (!rate) + return -EINVAL; + + return rate; +} + static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate) { struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); @@ -103,6 +119,7 @@ static int sandbox_clk_free(struct clk *clk) } static struct clk_ops sandbox_clk_ops = { + .round_rate = sandbox_clk_round_rate, .get_rate = sandbox_clk_get_rate, .set_rate = sandbox_clk_set_rate, .enable = sandbox_clk_enable, diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c index e9eb738684..c4e4481508 100644 --- a/drivers/clk/clk_sandbox_test.c +++ b/drivers/clk/clk_sandbox_test.c @@ -86,6 +86,16 @@ ulong sandbox_clk_test_get_rate(struct udevice *dev, int id) return clk_get_rate(sbct->clkps[id]); } +ulong sandbox_clk_test_round_rate(struct udevice *dev, int id, ulong rate) +{ + struct sandbox_clk_test *sbct = dev_get_priv(dev); + + if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT) + return -EINVAL; + + return clk_round_rate(sbct->clkps[id], rate); +} + ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate) { struct sandbox_clk_test *sbct = dev_get_priv(dev); diff --git a/include/clk-uclass.h b/include/clk-uclass.h index dac42dab36..50e8681b55 100644 --- a/include/clk-uclass.h +++ b/include/clk-uclass.h @@ -61,6 +61,14 @@ struct clk_ops { * @return 0 if OK, or a negative error code. */ int (*rfree)(struct clk *clock); + /** + * round_rate() - Adjust a rate to the exact rate a clock can provide. + * + * @clk: The clock to manipulate. + * @rate: Desidered clock rate in Hz. + * @return rounded rate in Hz, or -ve error code. + */ + ulong (*round_rate)(struct clk *clk, ulong rate); /** * get_rate() - Get current clock rate. * diff --git a/include/clk.h b/include/clk.h index a62e2efa2c..ca6b85fa6f 100644 --- a/include/clk.h +++ b/include/clk.h @@ -366,6 +366,29 @@ struct clk *clk_get_parent(struct clk *clk); */ long long clk_get_parent_rate(struct clk *clk); +/** + * clk_round_rate() - Adjust a rate to the exact rate a clock can provide + * + * This answers the question "if I were to pass @rate to clk_set_rate(), + * what clock rate would I end up with?" without changing the hardware + * in any way. In other words: + * + * rate = clk_round_rate(clk, r); + * + * and: + * + * rate = clk_set_rate(clk, r); + * + * are equivalent except the former does not modify the clock hardware + * in any way. + * + * @clk: A clock struct that was previously successfully requested by + * clk_request/get_by_*(). + * @rate: desired clock rate in Hz. + * @return rounded rate in Hz, or -ve error code. + */ +ulong clk_round_rate(struct clk *clk, ulong rate); + /** * clk_set_rate() - Set current clock rate. * @@ -482,6 +505,11 @@ static inline long long clk_get_parent_rate(struct clk *clk) return -ENOSYS; } +static inline ulong clk_round_rate(struct clk *clk, ulong rate) +{ + return -ENOSYS; +} + static inline ulong clk_set_rate(struct clk *clk, ulong rate) { return -ENOSYS; diff --git a/test/dm/clk.c b/test/dm/clk.c index edca3b49f6..21997ed892 100644 --- a/test/dm/clk.c +++ b/test/dm/clk.c @@ -112,6 +112,28 @@ static int dm_test_clk(struct unit_test_state *uts) rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_I2C, 0); ut_assert(IS_ERR_VALUE(rate)); + ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C)); + + ut_asserteq(5000, sandbox_clk_test_round_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI, + 5000)); + ut_asserteq(7000, sandbox_clk_test_round_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C, + 7000)); + + ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_SPI)); + ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test, + SANDBOX_CLK_TEST_ID_I2C)); + + rate = sandbox_clk_test_round_rate(dev_test, SANDBOX_CLK_TEST_ID_SPI, 0); + ut_assert(IS_ERR_VALUE(rate)); + rate = sandbox_clk_test_round_rate(dev_test, SANDBOX_CLK_TEST_ID_I2C, 0); + ut_assert(IS_ERR_VALUE(rate)); + ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test, SANDBOX_CLK_TEST_ID_SPI)); ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test, From d09f063a04bea982ef554105f73bfbaf56dc5ab4 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:32 +0100 Subject: [PATCH 16/42] clk: ti: add mux clock driver The driver manages a register-mapped multiplexer with multiple input clock signals or parents, one of which can be selected as output. It uses routines provided by the common clock framework (ccf). The code is based on the drivers/clk/ti/mux.c driver of the Linux kernel version 5.9-rc7. For DT binding details see: - Documentation/devicetree/bindings/clock/ti/mux.txt Signed-off-by: Dario Binacchi --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/ti/Kconfig | 10 ++ drivers/clk/ti/Makefile | 6 + drivers/clk/ti/clk-mux.c | 276 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 294 insertions(+) create mode 100644 drivers/clk/ti/Kconfig create mode 100644 drivers/clk/ti/Makefile create mode 100644 drivers/clk/ti/clk-mux.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 4dfbad7986..9e54929039 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -179,6 +179,7 @@ source "drivers/clk/renesas/Kconfig" source "drivers/clk/sunxi/Kconfig" source "drivers/clk/sifive/Kconfig" source "drivers/clk/tegra/Kconfig" +source "drivers/clk/ti/Kconfig" source "drivers/clk/uniphier/Kconfig" config ICS8N3QV01 diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index d1e295ac7c..2581fe0a19 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_COMPOSITE_CCF) += clk-composite.o obj-y += analogbits/ obj-y += imx/ obj-y += tegra/ +obj-y += ti/ obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_MTMIPS) += mtmips/ diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig new file mode 100644 index 0000000000..be4f26817f --- /dev/null +++ b/drivers/clk/ti/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Dario Binacchi +# + +config CLK_TI_MUX + bool "TI mux clock driver" + depends on CLK && OF_CONTROL && CLK_CCF + help + This enables the mux clock driver support on TI's SoCs. diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile new file mode 100644 index 0000000000..5faf68d30e --- /dev/null +++ b/drivers/clk/ti/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Dario Binacchi +# + +obj-$(CONFIG_CLK_TI_MUX) += clk-mux.o diff --git a/drivers/clk/ti/clk-mux.c b/drivers/clk/ti/clk-mux.c new file mode 100644 index 0000000000..1e22a50910 --- /dev/null +++ b/drivers/clk/ti/clk-mux.c @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI multiplexer clock support + * + * Copyright (C) 2020 Dario Binacchi + * + * Based on Linux kernel drivers/clk/ti/mux.c + */ + +#include +#include +#include +#include +#include +#include + +struct clk_ti_mux_priv { + struct clk_bulk parents; + fdt_addr_t reg; + u32 flags; + u32 mux_flags; + u32 mask; + u32 shift; + s32 latch; +}; + +static void clk_ti_mux_rmw(u32 val, u32 mask, fdt_addr_t reg) +{ + u32 v; + + v = readl(reg); + v &= ~mask; + v |= val; + writel(v, reg); +} + +static void clk_ti_mux_latch(fdt_addr_t reg, s8 shift) +{ + u32 latch; + + if (shift < 0) + return; + + latch = 1 << shift; + + clk_ti_mux_rmw(latch, latch, reg); + clk_ti_mux_rmw(0, latch, reg); + readl(reg); /* OCP barrier */ +} + +static struct clk *clk_ti_mux_get_parent_by_index(struct clk_bulk *parents, + int index) +{ + if (index < 0 || !parents) + return ERR_PTR(-EINVAL); + + if (index >= parents->count) + return ERR_PTR(-ENODEV); + + return &parents->clks[index]; +} + +static int clk_ti_mux_get_parent_index(struct clk_bulk *parents, + struct clk *parent) +{ + int i; + + if (!parents || !parent) + return -EINVAL; + + for (i = 0; i < parents->count; i++) { + if (parents->clks[i].dev == parent->dev) + return i; + } + + return -ENODEV; +} + +static int clk_ti_mux_get_index(struct clk *clk) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(clk->dev); + u32 val; + + val = readl(priv->reg); + val >>= priv->shift; + val &= priv->mask; + + if (val && (priv->flags & CLK_MUX_INDEX_BIT)) + val = ffs(val) - 1; + + if (val && (priv->flags & CLK_MUX_INDEX_ONE)) + val--; + + if (val >= priv->parents.count) + return -EINVAL; + + return val; +} + +static int clk_ti_mux_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(clk->dev); + int index; + u32 val; + + index = clk_ti_mux_get_parent_index(&priv->parents, parent); + if (index < 0) { + dev_err(clk->dev, "failed to get parent clock\n"); + return index; + } + + index = clk_mux_index_to_val(NULL, priv->flags, index); + + if (priv->flags & CLK_MUX_HIWORD_MASK) { + val = priv->mask << (priv->shift + 16); + } else { + val = readl(priv->reg); + val &= ~(priv->mask << priv->shift); + } + + val |= index << priv->shift; + writel(val, priv->reg); + clk_ti_mux_latch(priv->reg, priv->latch); + return 0; +} + +static ulong clk_ti_mux_set_rate(struct clk *clk, ulong rate) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(clk->dev); + struct clk *parent; + int index; + + if ((clk->flags & CLK_SET_RATE_PARENT) == 0) + return -ENOSYS; + + index = clk_ti_mux_get_index(clk); + parent = clk_ti_mux_get_parent_by_index(&priv->parents, index); + if (IS_ERR(parent)) + return PTR_ERR(parent); + + rate = clk_set_rate(parent, rate); + dev_dbg(clk->dev, "rate=%ld\n", rate); + return rate; +} + +static ulong clk_ti_mux_get_rate(struct clk *clk) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(clk->dev); + int index; + struct clk *parent; + ulong rate; + + index = clk_ti_mux_get_index(clk); + parent = clk_ti_mux_get_parent_by_index(&priv->parents, index); + if (IS_ERR(parent)) + return PTR_ERR(parent); + + rate = clk_get_rate(parent); + dev_dbg(clk->dev, "rate=%ld\n", rate); + return rate; +} + +static ulong clk_ti_mux_round_rate(struct clk *clk, ulong rate) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(clk->dev); + struct clk *parent; + int index; + + if ((clk->flags & CLK_SET_RATE_PARENT) == 0) + return -ENOSYS; + + index = clk_ti_mux_get_index(clk); + parent = clk_ti_mux_get_parent_by_index(&priv->parents, index); + if (IS_ERR(parent)) + return PTR_ERR(parent); + + rate = clk_round_rate(parent, rate); + dev_dbg(clk->dev, "rate=%ld\n", rate); + return rate; +} + +static int clk_ti_mux_request(struct clk *clk) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(clk->dev); + struct clk *parent; + int index; + + clk->flags = priv->flags; + + index = clk_ti_mux_get_index(clk); + parent = clk_ti_mux_get_parent_by_index(&priv->parents, index); + if (IS_ERR(parent)) + return PTR_ERR(parent); + + return clk_ti_mux_set_parent(clk, parent); +} + +static struct clk_ops clk_ti_mux_ops = { + .request = clk_ti_mux_request, + .round_rate = clk_ti_mux_round_rate, + .get_rate = clk_ti_mux_get_rate, + .set_rate = clk_ti_mux_set_rate, + .set_parent = clk_ti_mux_set_parent, +}; + +static int clk_ti_mux_remove(struct udevice *dev) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(dev); + int err; + + err = clk_release_all(priv->parents.clks, priv->parents.count); + if (err) + dev_dbg(dev, "could not release all parents' clocks\n"); + + return err; +} + +static int clk_ti_mux_probe(struct udevice *dev) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(dev); + int err; + + err = clk_get_bulk(dev, &priv->parents); + if (err || priv->parents.count < 2) { + dev_err(dev, "mux-clock must have parents\n"); + return err ? err : -EFAULT; + } + + /* Generate bit-mask based on parents info */ + priv->mask = priv->parents.count; + if (!(priv->mux_flags & CLK_MUX_INDEX_ONE)) + priv->mask--; + + priv->mask = (1 << fls(priv->mask)) - 1; + return 0; +} + +static int clk_ti_mux_of_to_plat(struct udevice *dev) +{ + struct clk_ti_mux_priv *priv = dev_get_priv(dev); + + priv->reg = dev_read_addr(dev); + if (priv->reg == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get register\n"); + return -EINVAL; + } + + dev_dbg(dev, "reg=0x%08lx\n", priv->reg); + priv->shift = dev_read_u32_default(dev, "ti,bit-shift", 0); + priv->latch = dev_read_s32_default(dev, "ti,latch-bit", -EINVAL); + + priv->flags = CLK_SET_RATE_NO_REPARENT; + if (dev_read_bool(dev, "ti,set-rate-parent")) + priv->flags |= CLK_SET_RATE_PARENT; + + if (dev_read_bool(dev, "ti,index-starts-at-one")) + priv->mux_flags |= CLK_MUX_INDEX_ONE; + + return 0; +} + +static const struct udevice_id clk_ti_mux_of_match[] = { + {.compatible = "ti,mux-clock"}, + {}, +}; + +U_BOOT_DRIVER(clk_ti_mux) = { + .name = "ti_mux_clock", + .id = UCLASS_CLK, + .of_match = clk_ti_mux_of_match, + .ofdata_to_platdata = clk_ti_mux_of_to_plat, + .probe = clk_ti_mux_probe, + .remove = clk_ti_mux_remove, + .priv_auto = sizeof(struct clk_ti_mux_priv), + .ops = &clk_ti_mux_ops, +}; From 9d76120083131cf087bbc028249bf88a91208504 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:33 +0100 Subject: [PATCH 17/42] arm: ti: am33xx: add DPLL_EN_FAST_RELOCK_BYPASS macro Add missing DPLL_EN_FAST_RELOCK_BYPASS macro. Used to put the DPLL in idle bypass fast relock mode. Signed-off-by: Dario Binacchi --- arch/arm/include/asm/arch-am33xx/clock.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/include/asm/arch-am33xx/clock.h b/arch/arm/include/asm/arch-am33xx/clock.h index dc7a9b188d..5d775902bb 100644 --- a/arch/arm/include/asm/arch-am33xx/clock.h +++ b/arch/arm/include/asm/arch-am33xx/clock.h @@ -66,6 +66,7 @@ #define DPLL_EN_STOP 1 #define DPLL_EN_MN_BYPASS 4 #define DPLL_EN_LOW_POWER_BYPASS 5 +#define DPLL_EN_FAST_RELOCK_BYPASS 6 #define DPLL_EN_LOCK 7 /* CM_IDLEST_DPLL fields */ From 756d64e43e20be558e6e49f2ccee2f747feb4a4d Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:34 +0100 Subject: [PATCH 18/42] clk: ti: am33xx: add DPLL clock drivers The digital phase-locked loop (DPLL) provides all interface clocks and functional clocks to the processor of the AM33xx device. The AM33xx device integrates five different DPLLs: * Core DPLL * Per DPLL * LCD DPLL * DDR DPLL * MPU DPLL The patch adds support for the compatible strings: * "ti,am3-dpll-core-clock" * "ti,am3-dpll-no-gate-clock" * "ti,am3-dpll-no-gate-j-type-clock" * "ti,am3-dpll-x2-clock" The code is loosely based on the drivers/clk/ti/dpll.c drivers of the Linux kernel version 5.9-rc7. For DT binding details see: - Documentation/devicetree/bindings/clock/ti/dpll.txt Signed-off-by: Dario Binacchi --- drivers/clk/ti/Kconfig | 7 + drivers/clk/ti/Makefile | 1 + drivers/clk/ti/clk-am3-dpll-x2.c | 79 +++++++++ drivers/clk/ti/clk-am3-dpll.c | 268 +++++++++++++++++++++++++++++++ 4 files changed, 355 insertions(+) create mode 100644 drivers/clk/ti/clk-am3-dpll-x2.c create mode 100644 drivers/clk/ti/clk-am3-dpll.c diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig index be4f26817f..c430dd9b8a 100644 --- a/drivers/clk/ti/Kconfig +++ b/drivers/clk/ti/Kconfig @@ -3,6 +3,13 @@ # Copyright (C) 2020 Dario Binacchi # +config CLK_TI_AM3_DPLL + bool "TI AM33XX Digital Phase-Locked Loop (DPLL) clock drivers" + depends on CLK && OF_CONTROL + help + This enables the DPLL clock drivers support on AM33XX SoCs. The DPLL + provides all interface clocks and functional clocks to the processor. + config CLK_TI_MUX bool "TI mux clock driver" depends on CLK && OF_CONTROL && CLK_CCF diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile index 5faf68d30e..9e14b83cfe 100644 --- a/drivers/clk/ti/Makefile +++ b/drivers/clk/ti/Makefile @@ -3,4 +3,5 @@ # Copyright (C) 2020 Dario Binacchi # +obj-$(CONFIG_CLK_TI_AM3_DPLL) += clk-am3-dpll.o clk-am3-dpll-x2.o obj-$(CONFIG_CLK_TI_MUX) += clk-mux.o diff --git a/drivers/clk/ti/clk-am3-dpll-x2.c b/drivers/clk/ti/clk-am3-dpll-x2.c new file mode 100644 index 0000000000..3cf279d6a3 --- /dev/null +++ b/drivers/clk/ti/clk-am3-dpll-x2.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI DPLL x2 clock support + * + * Copyright (C) 2020 Dario Binacchi + * + * Loosely based on Linux kernel drivers/clk/ti/dpll.c + */ + +#include +#include +#include +#include +#include + +struct clk_ti_am3_dpll_x2_priv { + struct clk parent; +}; + +static ulong clk_ti_am3_dpll_x2_get_rate(struct clk *clk) +{ + struct clk_ti_am3_dpll_x2_priv *priv = dev_get_priv(clk->dev); + unsigned long rate; + + rate = clk_get_rate(&priv->parent); + if (IS_ERR_VALUE(rate)) + return rate; + + rate *= 2; + dev_dbg(clk->dev, "rate=%ld\n", rate); + return rate; +} + +const struct clk_ops clk_ti_am3_dpll_x2_ops = { + .get_rate = clk_ti_am3_dpll_x2_get_rate, +}; + +static int clk_ti_am3_dpll_x2_remove(struct udevice *dev) +{ + struct clk_ti_am3_dpll_x2_priv *priv = dev_get_priv(dev); + int err; + + err = clk_release_all(&priv->parent, 1); + if (err) { + dev_err(dev, "failed to release parent clock\n"); + return err; + } + + return 0; +} + +static int clk_ti_am3_dpll_x2_probe(struct udevice *dev) +{ + struct clk_ti_am3_dpll_x2_priv *priv = dev_get_priv(dev); + int err; + + err = clk_get_by_index(dev, 0, &priv->parent); + if (err) { + dev_err(dev, "%s: failed to get parent clock\n", __func__); + return err; + } + + return 0; +} + +static const struct udevice_id clk_ti_am3_dpll_x2_of_match[] = { + {.compatible = "ti,am3-dpll-x2-clock"}, + {} +}; + +U_BOOT_DRIVER(clk_ti_am3_dpll_x2) = { + .name = "ti_am3_dpll_x2_clock", + .id = UCLASS_CLK, + .of_match = clk_ti_am3_dpll_x2_of_match, + .probe = clk_ti_am3_dpll_x2_probe, + .remove = clk_ti_am3_dpll_x2_remove, + .priv_auto = sizeof(struct clk_ti_am3_dpll_x2_priv), + .ops = &clk_ti_am3_dpll_x2_ops, +}; diff --git a/drivers/clk/ti/clk-am3-dpll.c b/drivers/clk/ti/clk-am3-dpll.c new file mode 100644 index 0000000000..7916a24538 --- /dev/null +++ b/drivers/clk/ti/clk-am3-dpll.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI DPLL clock support + * + * Copyright (C) 2020 Dario Binacchi + * + * Loosely based on Linux kernel drivers/clk/ti/dpll.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct clk_ti_am3_dpll_drv_data { + ulong max_rate; +}; + +struct clk_ti_am3_dpll_priv { + fdt_addr_t clkmode_reg; + fdt_addr_t idlest_reg; + fdt_addr_t clksel_reg; + struct clk clk_bypass; + struct clk clk_ref; + u16 last_rounded_mult; + u8 last_rounded_div; + ulong max_rate; +}; + +static ulong clk_ti_am3_dpll_round_rate(struct clk *clk, ulong rate) +{ + struct clk_ti_am3_dpll_priv *priv = dev_get_priv(clk->dev); + ulong ret, ref_rate, r; + int m, d, err_min, err; + int mult = INT_MAX, div = INT_MAX; + + if (priv->max_rate && rate > priv->max_rate) { + dev_warn(clk->dev, "%ld is to high a rate, lowered to %ld\n", + rate, priv->max_rate); + rate = priv->max_rate; + } + + ret = -EFAULT; + err = rate; + err_min = rate; + ref_rate = clk_get_rate(&priv->clk_ref); + for (d = 1; err_min && d <= 128; d++) { + for (m = 2; m <= 2047; m++) { + r = (ref_rate * m) / d; + err = abs(r - rate); + if (err < err_min) { + err_min = err; + ret = r; + mult = m; + div = d; + + if (err == 0) + break; + } else if (r > rate) { + break; + } + } + } + + priv->last_rounded_mult = mult; + priv->last_rounded_div = div; + dev_dbg(clk->dev, "rate=%ld, best_rate=%ld, mult=%d, div=%d\n", rate, + ret, mult, div); + return ret; +} + +static ulong clk_ti_am3_dpll_set_rate(struct clk *clk, ulong rate) +{ + struct clk_ti_am3_dpll_priv *priv = dev_get_priv(clk->dev); + u32 v; + ulong round_rate; + + round_rate = clk_ti_am3_dpll_round_rate(clk, rate); + if (IS_ERR_VALUE(round_rate)) + return round_rate; + + v = readl(priv->clksel_reg); + + /* enter bypass mode */ + clrsetbits_le32(priv->clkmode_reg, CM_CLKMODE_DPLL_DPLL_EN_MASK, + DPLL_EN_MN_BYPASS << CM_CLKMODE_DPLL_EN_SHIFT); + + /* wait for bypass mode */ + if (!wait_on_value(ST_DPLL_CLK_MASK, 0, + (void *)priv->idlest_reg, LDELAY)) + dev_err(clk->dev, "failed bypassing dpll\n"); + + /* set M & N */ + v &= ~CM_CLKSEL_DPLL_M_MASK; + v |= (priv->last_rounded_mult << CM_CLKSEL_DPLL_M_SHIFT) & + CM_CLKSEL_DPLL_M_MASK; + + v &= ~CM_CLKSEL_DPLL_N_MASK; + v |= ((priv->last_rounded_div - 1) << CM_CLKSEL_DPLL_N_SHIFT) & + CM_CLKSEL_DPLL_N_MASK; + + writel(v, priv->clksel_reg); + + /* lock dpll */ + clrsetbits_le32(priv->clkmode_reg, CM_CLKMODE_DPLL_DPLL_EN_MASK, + DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT); + + /* wait till the dpll locks */ + if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK, + (void *)priv->idlest_reg, LDELAY)) { + dev_err(clk->dev, "failed locking dpll\n"); + hang(); + } + + return round_rate; +} + +static ulong clk_ti_am3_dpll_get_rate(struct clk *clk) +{ + struct clk_ti_am3_dpll_priv *priv = dev_get_priv(clk->dev); + u64 rate; + u32 m, n, v; + + /* Return bypass rate if DPLL is bypassed */ + v = readl(priv->clkmode_reg); + v &= CM_CLKMODE_DPLL_EN_MASK; + v >>= CM_CLKMODE_DPLL_EN_SHIFT; + + switch (v) { + case DPLL_EN_MN_BYPASS: + case DPLL_EN_LOW_POWER_BYPASS: + case DPLL_EN_FAST_RELOCK_BYPASS: + rate = clk_get_rate(&priv->clk_bypass); + dev_dbg(clk->dev, "rate=%lld\n", rate); + return rate; + } + + v = readl(priv->clksel_reg); + m = v & CM_CLKSEL_DPLL_M_MASK; + m >>= CM_CLKSEL_DPLL_M_SHIFT; + n = v & CM_CLKSEL_DPLL_N_MASK; + n >>= CM_CLKSEL_DPLL_N_SHIFT; + + rate = clk_get_rate(&priv->clk_ref) * m; + do_div(rate, n + 1); + dev_dbg(clk->dev, "rate=%lld\n", rate); + return rate; +} + +const struct clk_ops clk_ti_am3_dpll_ops = { + .round_rate = clk_ti_am3_dpll_round_rate, + .get_rate = clk_ti_am3_dpll_get_rate, + .set_rate = clk_ti_am3_dpll_set_rate, +}; + +static int clk_ti_am3_dpll_remove(struct udevice *dev) +{ + struct clk_ti_am3_dpll_priv *priv = dev_get_priv(dev); + int err; + + err = clk_release_all(&priv->clk_bypass, 1); + if (err) { + dev_err(dev, "failed to release bypass clock\n"); + return err; + } + + err = clk_release_all(&priv->clk_ref, 1); + if (err) { + dev_err(dev, "failed to release reference clock\n"); + return err; + } + + return 0; +} + +static int clk_ti_am3_dpll_probe(struct udevice *dev) +{ + struct clk_ti_am3_dpll_priv *priv = dev_get_priv(dev); + int err; + + err = clk_get_by_index(dev, 0, &priv->clk_ref); + if (err) { + dev_err(dev, "failed to get reference clock\n"); + return err; + } + + err = clk_get_by_index(dev, 1, &priv->clk_bypass); + if (err) { + dev_err(dev, "failed to get bypass clock\n"); + return err; + } + + return 0; +} + +static int clk_ti_am3_dpll_of_to_plat(struct udevice *dev) +{ + struct clk_ti_am3_dpll_priv *priv = dev_get_priv(dev); + struct clk_ti_am3_dpll_drv_data *data = + (struct clk_ti_am3_dpll_drv_data *)dev_get_driver_data(dev); + + priv->max_rate = data->max_rate; + + priv->clkmode_reg = dev_read_addr_index(dev, 0); + if (priv->clkmode_reg == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get clkmode register\n"); + return -EINVAL; + } + + dev_dbg(dev, "clkmode_reg=0x%08lx\n", priv->clkmode_reg); + + priv->idlest_reg = dev_read_addr_index(dev, 1); + if (priv->idlest_reg == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get idlest register\n"); + return -EINVAL; + } + + dev_dbg(dev, "idlest_reg=0x%08lx\n", priv->idlest_reg); + + priv->clksel_reg = dev_read_addr_index(dev, 2); + if (priv->clksel_reg == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get clksel register\n"); + return -EINVAL; + } + + dev_dbg(dev, "clksel_reg=0x%08lx\n", priv->clksel_reg); + + return 0; +} + +static const struct clk_ti_am3_dpll_drv_data dpll_no_gate_data = { + .max_rate = 1000000000 +}; + +static const struct clk_ti_am3_dpll_drv_data dpll_no_gate_j_type_data = { + .max_rate = 2000000000 +}; + +static const struct clk_ti_am3_dpll_drv_data dpll_core_data = { + .max_rate = 1000000000 +}; + +static const struct udevice_id clk_ti_am3_dpll_of_match[] = { + {.compatible = "ti,am3-dpll-core-clock", + .data = (ulong)&dpll_core_data}, + {.compatible = "ti,am3-dpll-no-gate-clock", + .data = (ulong)&dpll_no_gate_data}, + {.compatible = "ti,am3-dpll-no-gate-j-type-clock", + .data = (ulong)&dpll_no_gate_j_type_data}, + {} +}; + +U_BOOT_DRIVER(clk_ti_am3_dpll) = { + .name = "ti_am3_dpll_clock", + .id = UCLASS_CLK, + .of_match = clk_ti_am3_dpll_of_match, + .ofdata_to_platdata = clk_ti_am3_dpll_of_to_plat, + .probe = clk_ti_am3_dpll_probe, + .remove = clk_ti_am3_dpll_remove, + .priv_auto = sizeof(struct clk_ti_am3_dpll_priv), + .ops = &clk_ti_am3_dpll_ops, +}; From ea45b8f28d0638e49ff361814ebe7e8bdd536a48 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:35 +0100 Subject: [PATCH 19/42] clk: ti: add divider clock driver The patch adds support for TI divider clock binding. The driver uses routines provided by the common clock framework (ccf). The code is based on the drivers/clk/ti/divider.c driver of the Linux kernel version 5.9-rc7. For DT binding details see: - Documentation/devicetree/bindings/clock/ti/divider.txt Signed-off-by: Dario Binacchi --- drivers/clk/ti/Kconfig | 6 + drivers/clk/ti/Makefile | 3 + drivers/clk/ti/clk-divider.c | 381 +++++++++++++++++++++++++++++++++++ drivers/clk/ti/clk-mux.c | 27 +-- drivers/clk/ti/clk.c | 34 ++++ drivers/clk/ti/clk.h | 13 ++ 6 files changed, 439 insertions(+), 25 deletions(-) create mode 100644 drivers/clk/ti/clk-divider.c create mode 100644 drivers/clk/ti/clk.c create mode 100644 drivers/clk/ti/clk.h diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig index c430dd9b8a..87eea86c6f 100644 --- a/drivers/clk/ti/Kconfig +++ b/drivers/clk/ti/Kconfig @@ -10,6 +10,12 @@ config CLK_TI_AM3_DPLL This enables the DPLL clock drivers support on AM33XX SoCs. The DPLL provides all interface clocks and functional clocks to the processor. +config CLK_TI_DIVIDER + bool "TI divider clock driver" + depends on CLK && OF_CONTROL && CLK_CCF + help + This enables the divider clock driver support on TI's SoCs. + config CLK_TI_MUX bool "TI mux clock driver" depends on CLK && OF_CONTROL && CLK_CCF diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile index 9e14b83cfe..fd7094cff0 100644 --- a/drivers/clk/ti/Makefile +++ b/drivers/clk/ti/Makefile @@ -3,5 +3,8 @@ # Copyright (C) 2020 Dario Binacchi # +obj-$(CONFIG_ARCH_OMAP2PLUS) += clk.o + obj-$(CONFIG_CLK_TI_AM3_DPLL) += clk-am3-dpll.o clk-am3-dpll-x2.o +obj-$(CONFIG_CLK_TI_DIVIDER) += clk-divider.o obj-$(CONFIG_CLK_TI_MUX) += clk-mux.o diff --git a/drivers/clk/ti/clk-divider.c b/drivers/clk/ti/clk-divider.c new file mode 100644 index 0000000000..a862637785 --- /dev/null +++ b/drivers/clk/ti/clk-divider.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI divider clock support + * + * Copyright (C) 2020 Dario Binacchi + * + * Loosely based on Linux kernel drivers/clk/ti/divider.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clk.h" + +/* + * The reverse of DIV_ROUND_UP: The maximum number which + * divided by m is r + */ +#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1) + +struct clk_ti_divider_priv { + struct clk parent; + fdt_addr_t reg; + const struct clk_div_table *table; + u8 shift; + u8 flags; + u8 div_flags; + s8 latch; + u16 min; + u16 max; + u16 mask; +}; + +static unsigned int _get_div(const struct clk_div_table *table, ulong flags, + unsigned int val) +{ + if (flags & CLK_DIVIDER_ONE_BASED) + return val; + + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return 1 << val; + + if (table) + return clk_divider_get_table_div(table, val); + + return val + 1; +} + +static unsigned int _get_val(const struct clk_div_table *table, ulong flags, + unsigned int div) +{ + if (flags & CLK_DIVIDER_ONE_BASED) + return div; + + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return __ffs(div); + + if (table) + return clk_divider_get_table_val(table, div); + + return div - 1; +} + +static int _div_round_up(const struct clk_div_table *table, ulong parent_rate, + ulong rate) +{ + const struct clk_div_table *clkt; + int up = INT_MAX; + int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); + + for (clkt = table; clkt->div; clkt++) { + if (clkt->div == div) + return clkt->div; + else if (clkt->div < div) + continue; + + if ((clkt->div - div) < (up - div)) + up = clkt->div; + } + + return up; +} + +static int _div_round(const struct clk_div_table *table, ulong parent_rate, + ulong rate) +{ + if (table) + return _div_round_up(table, parent_rate, rate); + + return DIV_ROUND_UP(parent_rate, rate); +} + +static int clk_ti_divider_best_div(struct clk *clk, ulong rate, + ulong *best_parent_rate) +{ + struct clk_ti_divider_priv *priv = dev_get_priv(clk->dev); + ulong parent_rate, parent_round_rate, max_div; + ulong best_rate, r; + int i, best_div = 0; + + parent_rate = clk_get_rate(&priv->parent); + if (IS_ERR_VALUE(parent_rate)) + return parent_rate; + + if (!rate) + rate = 1; + + if (!(clk->flags & CLK_SET_RATE_PARENT)) { + best_div = _div_round(priv->table, parent_rate, rate); + if (best_div == 0) + best_div = 1; + + if (best_div > priv->max) + best_div = priv->max; + + *best_parent_rate = parent_rate; + return best_div; + } + + max_div = min(ULONG_MAX / rate, (ulong)priv->max); + for (best_rate = 0, i = 1; i <= max_div; i++) { + if (!clk_divider_is_valid_div(priv->table, priv->div_flags, i)) + continue; + + /* + * It's the most ideal case if the requested rate can be + * divided from parent clock without needing to change + * parent rate, so return the divider immediately. + */ + if ((rate * i) == parent_rate) { + *best_parent_rate = parent_rate; + dev_dbg(clk->dev, "rate=%ld, best_rate=%ld, div=%d\n", + rate, rate, i); + return i; + } + + parent_round_rate = clk_round_rate(&priv->parent, + MULT_ROUND_UP(rate, i)); + if (IS_ERR_VALUE(parent_round_rate)) + continue; + + r = DIV_ROUND_UP(parent_round_rate, i); + if (r <= rate && r > best_rate) { + best_div = i; + best_rate = r; + *best_parent_rate = parent_round_rate; + if (best_rate == rate) + break; + } + } + + if (best_div == 0) { + best_div = priv->max; + parent_round_rate = clk_round_rate(&priv->parent, 1); + if (IS_ERR_VALUE(parent_round_rate)) + return parent_round_rate; + } + + dev_dbg(clk->dev, "rate=%ld, best_rate=%ld, div=%d\n", rate, best_rate, + best_div); + + return best_div; +} + +static ulong clk_ti_divider_round_rate(struct clk *clk, ulong rate) +{ + ulong parent_rate; + int div; + + div = clk_ti_divider_best_div(clk, rate, &parent_rate); + if (div < 0) + return div; + + return DIV_ROUND_UP(parent_rate, div); +} + +static ulong clk_ti_divider_set_rate(struct clk *clk, ulong rate) +{ + struct clk_ti_divider_priv *priv = dev_get_priv(clk->dev); + ulong parent_rate; + int div; + u32 val, v; + + div = clk_ti_divider_best_div(clk, rate, &parent_rate); + if (div < 0) + return div; + + if (clk->flags & CLK_SET_RATE_PARENT) { + parent_rate = clk_set_rate(&priv->parent, parent_rate); + if (IS_ERR_VALUE(parent_rate)) + return parent_rate; + } + + val = _get_val(priv->table, priv->div_flags, div); + + v = readl(priv->reg); + v &= ~(priv->mask << priv->shift); + v |= val << priv->shift; + writel(v, priv->reg); + clk_ti_latch(priv->reg, priv->latch); + + return clk_get_rate(clk); +} + +static ulong clk_ti_divider_get_rate(struct clk *clk) +{ + struct clk_ti_divider_priv *priv = dev_get_priv(clk->dev); + ulong rate, parent_rate; + unsigned int div; + u32 v; + + parent_rate = clk_get_rate(&priv->parent); + if (IS_ERR_VALUE(parent_rate)) + return parent_rate; + + v = readl(priv->reg) >> priv->shift; + v &= priv->mask; + + div = _get_div(priv->table, priv->div_flags, v); + if (!div) { + if (!(priv->div_flags & CLK_DIVIDER_ALLOW_ZERO)) + dev_warn(clk->dev, + "zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n"); + return parent_rate; + } + + rate = DIV_ROUND_UP(parent_rate, div); + dev_dbg(clk->dev, "rate=%ld\n", rate); + return rate; +} + +static int clk_ti_divider_request(struct clk *clk) +{ + struct clk_ti_divider_priv *priv = dev_get_priv(clk->dev); + + clk->flags = priv->flags; + return 0; +} + +const struct clk_ops clk_ti_divider_ops = { + .request = clk_ti_divider_request, + .round_rate = clk_ti_divider_round_rate, + .get_rate = clk_ti_divider_get_rate, + .set_rate = clk_ti_divider_set_rate +}; + +static int clk_ti_divider_remove(struct udevice *dev) +{ + struct clk_ti_divider_priv *priv = dev_get_priv(dev); + int err; + + err = clk_release_all(&priv->parent, 1); + if (err) { + dev_err(dev, "failed to release parent clock\n"); + return err; + } + + return 0; +} + +static int clk_ti_divider_probe(struct udevice *dev) +{ + struct clk_ti_divider_priv *priv = dev_get_priv(dev); + int err; + + err = clk_get_by_index(dev, 0, &priv->parent); + if (err) { + dev_err(dev, "failed to get parent clock\n"); + return err; + } + + return 0; +} + +static int clk_ti_divider_of_to_plat(struct udevice *dev) +{ + struct clk_ti_divider_priv *priv = dev_get_priv(dev); + struct clk_div_table *table = NULL; + u32 val, valid_div; + u32 min_div = 0; + u32 max_val, max_div = 0; + u16 mask; + int i, div_num; + + priv->reg = dev_read_addr(dev); + dev_dbg(dev, "reg=0x%08lx\n", priv->reg); + priv->shift = dev_read_u32_default(dev, "ti,bit-shift", 0); + priv->latch = dev_read_s32_default(dev, "ti,latch-bit", -EINVAL); + if (dev_read_bool(dev, "ti,index-starts-at-one")) + priv->div_flags |= CLK_DIVIDER_ONE_BASED; + + if (dev_read_bool(dev, "ti,index-power-of-two")) + priv->div_flags |= CLK_DIVIDER_POWER_OF_TWO; + + if (dev_read_bool(dev, "ti,set-rate-parent")) + priv->flags |= CLK_SET_RATE_PARENT; + + if (dev_read_prop(dev, "ti,dividers", &div_num)) { + div_num /= sizeof(u32); + + /* Determine required size for divider table */ + for (i = 0, valid_div = 0; i < div_num; i++) { + dev_read_u32_index(dev, "ti,dividers", i, &val); + if (val) + valid_div++; + } + + if (!valid_div) { + dev_err(dev, "no valid dividers\n"); + return -EINVAL; + } + + table = calloc(valid_div + 1, sizeof(*table)); + if (!table) + return -ENOMEM; + + for (i = 0, valid_div = 0; i < div_num; i++) { + dev_read_u32_index(dev, "ti,dividers", i, &val); + if (!val) + continue; + + table[valid_div].div = val; + table[valid_div].val = i; + valid_div++; + if (val > max_div) + max_div = val; + + if (!min_div || val < min_div) + min_div = val; + } + + max_val = max_div; + } else { + /* Divider table not provided, determine min/max divs */ + min_div = dev_read_u32_default(dev, "ti,min-div", 1); + if (dev_read_u32(dev, "ti,max-div", &max_div)) { + dev_err(dev, "missing 'max-div' property\n"); + return -EFAULT; + } + + max_val = max_div; + if (!(priv->div_flags & CLK_DIVIDER_ONE_BASED) && + !(priv->div_flags & CLK_DIVIDER_POWER_OF_TWO)) + max_val--; + } + + priv->table = table; + priv->min = min_div; + priv->max = max_div; + + if (priv->div_flags & CLK_DIVIDER_POWER_OF_TWO) + mask = fls(max_val) - 1; + else + mask = max_val; + + priv->mask = (1 << fls(mask)) - 1; + return 0; +} + +static const struct udevice_id clk_ti_divider_of_match[] = { + {.compatible = "ti,divider-clock"}, + {} +}; + +U_BOOT_DRIVER(clk_ti_divider) = { + .name = "ti_divider_clock", + .id = UCLASS_CLK, + .of_match = clk_ti_divider_of_match, + .ofdata_to_platdata = clk_ti_divider_of_to_plat, + .probe = clk_ti_divider_probe, + .remove = clk_ti_divider_remove, + .priv_auto = sizeof(struct clk_ti_divider_priv), + .ops = &clk_ti_divider_ops, +}; diff --git a/drivers/clk/ti/clk-mux.c b/drivers/clk/ti/clk-mux.c index 1e22a50910..419502c389 100644 --- a/drivers/clk/ti/clk-mux.c +++ b/drivers/clk/ti/clk-mux.c @@ -13,6 +13,7 @@ #include #include #include +#include "clk.h" struct clk_ti_mux_priv { struct clk_bulk parents; @@ -24,30 +25,6 @@ struct clk_ti_mux_priv { s32 latch; }; -static void clk_ti_mux_rmw(u32 val, u32 mask, fdt_addr_t reg) -{ - u32 v; - - v = readl(reg); - v &= ~mask; - v |= val; - writel(v, reg); -} - -static void clk_ti_mux_latch(fdt_addr_t reg, s8 shift) -{ - u32 latch; - - if (shift < 0) - return; - - latch = 1 << shift; - - clk_ti_mux_rmw(latch, latch, reg); - clk_ti_mux_rmw(0, latch, reg); - readl(reg); /* OCP barrier */ -} - static struct clk *clk_ti_mux_get_parent_by_index(struct clk_bulk *parents, int index) { @@ -120,7 +97,7 @@ static int clk_ti_mux_set_parent(struct clk *clk, struct clk *parent) val |= index << priv->shift; writel(val, priv->reg); - clk_ti_mux_latch(priv->reg, priv->latch); + clk_ti_latch(priv->reg, priv->latch); return 0; } diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c new file mode 100644 index 0000000000..e44b90ad6a --- /dev/null +++ b/drivers/clk/ti/clk.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI clock utilities + * + * Copyright (C) 2020 Dario Binacchi + */ + +#include +#include +#include "clk.h" + +static void clk_ti_rmw(u32 val, u32 mask, fdt_addr_t reg) +{ + u32 v; + + v = readl(reg); + v &= ~mask; + v |= val; + writel(v, reg); +} + +void clk_ti_latch(fdt_addr_t reg, s8 shift) +{ + u32 latch; + + if (shift < 0) + return; + + latch = 1 << shift; + + clk_ti_rmw(latch, latch, reg); + clk_ti_rmw(0, latch, reg); + readl(reg); /* OCP barrier */ +} diff --git a/drivers/clk/ti/clk.h b/drivers/clk/ti/clk.h new file mode 100644 index 0000000000..601c3823f7 --- /dev/null +++ b/drivers/clk/ti/clk.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * TI clock utilities header + * + * Copyright (C) 2020 Dario Binacchi + */ + +#ifndef _CLK_TI_H +#define _CLK_TI_H + +void clk_ti_latch(fdt_addr_t reg, s8 shift); + +#endif /* #ifndef _CLK_TI_H */ From 58e1af972f4f8855561ec018e7a9c565d53c4639 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:36 +0100 Subject: [PATCH 20/42] clk: ti: add gate clock driver The patch adds support for TI gate clock binding. The code is based on the drivers/clk/ti/gate.c driver of the Linux kernel version 5.9-rc7. For DT binding details see: - Documentation/devicetree/bindings/clock/ti/gate.txt Signed-off-by: Dario Binacchi --- drivers/clk/ti/Kconfig | 6 +++ drivers/clk/ti/Makefile | 1 + drivers/clk/ti/clk-gate.c | 93 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 drivers/clk/ti/clk-gate.c diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig index 87eea86c6f..30959a316a 100644 --- a/drivers/clk/ti/Kconfig +++ b/drivers/clk/ti/Kconfig @@ -16,6 +16,12 @@ config CLK_TI_DIVIDER help This enables the divider clock driver support on TI's SoCs. +config CLK_TI_GATE + bool "TI gate clock driver" + depends on CLK && OF_CONTROL + help + This enables the gate clock driver support on TI's SoCs. + config CLK_TI_MUX bool "TI mux clock driver" depends on CLK && OF_CONTROL && CLK_CCF diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile index fd7094cff0..f8aa735c83 100644 --- a/drivers/clk/ti/Makefile +++ b/drivers/clk/ti/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_ARCH_OMAP2PLUS) += clk.o obj-$(CONFIG_CLK_TI_AM3_DPLL) += clk-am3-dpll.o clk-am3-dpll-x2.o obj-$(CONFIG_CLK_TI_DIVIDER) += clk-divider.o +obj-$(CONFIG_CLK_TI_GATE) += clk-gate.o obj-$(CONFIG_CLK_TI_MUX) += clk-mux.o diff --git a/drivers/clk/ti/clk-gate.c b/drivers/clk/ti/clk-gate.c new file mode 100644 index 0000000000..236eaed6df --- /dev/null +++ b/drivers/clk/ti/clk-gate.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI gate clock support + * + * Copyright (C) 2020 Dario Binacchi + * + * Loosely based on Linux kernel drivers/clk/ti/gate.c + */ + +#include +#include +#include +#include +#include +#include + +struct clk_ti_gate_priv { + fdt_addr_t reg; + u8 enable_bit; + u32 flags; + bool invert_enable; +}; + +static int clk_ti_gate_disable(struct clk *clk) +{ + struct clk_ti_gate_priv *priv = dev_get_priv(clk->dev); + u32 v; + + v = readl(priv->reg); + if (priv->invert_enable) + v |= (1 << priv->enable_bit); + else + v &= ~(1 << priv->enable_bit); + + writel(v, priv->reg); + /* No OCP barrier needed here since it is a disable operation */ + return 0; +} + +static int clk_ti_gate_enable(struct clk *clk) +{ + struct clk_ti_gate_priv *priv = dev_get_priv(clk->dev); + u32 v; + + v = readl(priv->reg); + if (priv->invert_enable) + v &= ~(1 << priv->enable_bit); + else + v |= (1 << priv->enable_bit); + + writel(v, priv->reg); + /* OCP barrier */ + v = readl(priv->reg); + return 0; +} + +static int clk_ti_gate_of_to_plat(struct udevice *dev) +{ + struct clk_ti_gate_priv *priv = dev_get_priv(dev); + + priv->reg = dev_read_addr(dev); + if (priv->reg == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get control register\n"); + return -EINVAL; + } + + dev_dbg(dev, "reg=0x%08lx\n", priv->reg); + priv->enable_bit = dev_read_u32_default(dev, "ti,bit-shift", 0); + if (dev_read_bool(dev, "ti,set-rate-parent")) + priv->flags |= CLK_SET_RATE_PARENT; + + priv->invert_enable = dev_read_bool(dev, "ti,set-bit-to-disable"); + return 0; +} + +static struct clk_ops clk_ti_gate_ops = { + .enable = clk_ti_gate_enable, + .disable = clk_ti_gate_disable, +}; + +static const struct udevice_id clk_ti_gate_of_match[] = { + { .compatible = "ti,gate-clock" }, + { }, +}; + +U_BOOT_DRIVER(clk_ti_gate) = { + .name = "ti_gate_clock", + .id = UCLASS_CLK, + .of_match = clk_ti_gate_of_match, + .ofdata_to_platdata = clk_ti_gate_of_to_plat, + .priv_auto = sizeof(struct clk_ti_gate_priv), + .ops = &clk_ti_gate_ops, +}; From c28baf6c70a1f47524075c497ded2c5bc805f2a3 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:37 +0100 Subject: [PATCH 21/42] arm: dts: am335x: include am33xx-u-boot.dtsi Include the SoC U-boot DTS in each am335x--u-boot.dtsi. Signed-off-by: Dario Binacchi --- arch/arm/dts/am335x-chiliboard-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-evm-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-evmsk-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-guardian-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-icev2-u-boot.dtsi | 3 +++ arch/arm/dts/am335x-pdu001-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-pxm50-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-regor-rdk-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-rut-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-shc-u-boot.dtsi | 2 ++ arch/arm/dts/am335x-wega-rdk-u-boot.dtsi | 2 ++ 11 files changed, 23 insertions(+) diff --git a/arch/arm/dts/am335x-chiliboard-u-boot.dtsi b/arch/arm/dts/am335x-chiliboard-u-boot.dtsi index 4f9d308039..06a13872ee 100644 --- a/arch/arm/dts/am335x-chiliboard-u-boot.dtsi +++ b/arch/arm/dts/am335x-chiliboard-u-boot.dtsi @@ -4,6 +4,8 @@ * Author: Marcin Niestroj */ +#include "am33xx-u-boot.dtsi" + / { chosen { stdout-path = &uart0; diff --git a/arch/arm/dts/am335x-evm-u-boot.dtsi b/arch/arm/dts/am335x-evm-u-boot.dtsi index d7b049ef20..400a1d2cec 100644 --- a/arch/arm/dts/am335x-evm-u-boot.dtsi +++ b/arch/arm/dts/am335x-evm-u-boot.dtsi @@ -3,6 +3,8 @@ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ */ +#include "am33xx-u-boot.dtsi" + / { panel { u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/am335x-evmsk-u-boot.dtsi b/arch/arm/dts/am335x-evmsk-u-boot.dtsi index 599fb377e6..96798330b1 100644 --- a/arch/arm/dts/am335x-evmsk-u-boot.dtsi +++ b/arch/arm/dts/am335x-evmsk-u-boot.dtsi @@ -5,6 +5,8 @@ * Copyright (C) 2020 Dario Binacchi */ +#include "am33xx-u-boot.dtsi" + / { panel { u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/am335x-guardian-u-boot.dtsi b/arch/arm/dts/am335x-guardian-u-boot.dtsi index eae027c541..c866ce83f3 100644 --- a/arch/arm/dts/am335x-guardian-u-boot.dtsi +++ b/arch/arm/dts/am335x-guardian-u-boot.dtsi @@ -4,6 +4,8 @@ * Copyright (C) 2018 Robert Bosch Power Tools GmbH */ +#include "am33xx-u-boot.dtsi" + / { ocp { u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/am335x-icev2-u-boot.dtsi b/arch/arm/dts/am335x-icev2-u-boot.dtsi index cc9569af03..67bfac916e 100644 --- a/arch/arm/dts/am335x-icev2-u-boot.dtsi +++ b/arch/arm/dts/am335x-icev2-u-boot.dtsi @@ -2,6 +2,9 @@ /* * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ */ + +#include "am33xx-u-boot.dtsi" + / { xtal25mhz: xtal25mhz { compatible = "fixed-clock"; diff --git a/arch/arm/dts/am335x-pdu001-u-boot.dtsi b/arch/arm/dts/am335x-pdu001-u-boot.dtsi index a799fe9bc3..4f4fc411f9 100644 --- a/arch/arm/dts/am335x-pdu001-u-boot.dtsi +++ b/arch/arm/dts/am335x-pdu001-u-boot.dtsi @@ -3,6 +3,8 @@ * Copyright (C) 2018 EETS GmbH - https://www.eets.ch/ */ +#include "am33xx-u-boot.dtsi" + / { ocp { u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/am335x-pxm50-u-boot.dtsi b/arch/arm/dts/am335x-pxm50-u-boot.dtsi index 77dfe6e262..65ed948c58 100644 --- a/arch/arm/dts/am335x-pxm50-u-boot.dtsi +++ b/arch/arm/dts/am335x-pxm50-u-boot.dtsi @@ -5,6 +5,8 @@ * Copyright (C) 2020 Dario Binacchi */ +#include "am33xx-u-boot.dtsi" + / { panel { u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/am335x-regor-rdk-u-boot.dtsi b/arch/arm/dts/am335x-regor-rdk-u-boot.dtsi index 1ddd715875..4052d0ee21 100644 --- a/arch/arm/dts/am335x-regor-rdk-u-boot.dtsi +++ b/arch/arm/dts/am335x-regor-rdk-u-boot.dtsi @@ -3,6 +3,8 @@ * Copyright (C) 2020 Linumiz */ +#include "am33xx-u-boot.dtsi" + / { chosen { #address-cells = <1>; diff --git a/arch/arm/dts/am335x-rut-u-boot.dtsi b/arch/arm/dts/am335x-rut-u-boot.dtsi index b2b4aa596a..b16f75a764 100644 --- a/arch/arm/dts/am335x-rut-u-boot.dtsi +++ b/arch/arm/dts/am335x-rut-u-boot.dtsi @@ -5,6 +5,8 @@ * Copyright (C) 2020 Dario Binacchi */ +#include "am33xx-u-boot.dtsi" + / { panel { u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/am335x-shc-u-boot.dtsi b/arch/arm/dts/am335x-shc-u-boot.dtsi index 2975839ea7..359ae05209 100644 --- a/arch/arm/dts/am335x-shc-u-boot.dtsi +++ b/arch/arm/dts/am335x-shc-u-boot.dtsi @@ -3,6 +3,8 @@ * Copyright (C) 2019 Heiko Schocher */ +#include "am33xx-u-boot.dtsi" + / { ocp { u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/am335x-wega-rdk-u-boot.dtsi b/arch/arm/dts/am335x-wega-rdk-u-boot.dtsi index 634f1b0712..28fd62e231 100644 --- a/arch/arm/dts/am335x-wega-rdk-u-boot.dtsi +++ b/arch/arm/dts/am335x-wega-rdk-u-boot.dtsi @@ -3,6 +3,8 @@ * Copyright (C) 2019 DENX Software Engineering GmbH */ +#include "am33xx-u-boot.dtsi" + / { chosen { #address-cells = <1>; From bc34f0ba83fa28cef9fed045d7296dcae7861aed Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:38 +0100 Subject: [PATCH 22/42] ti: am33xx: fix do_enable_clocks() to accept NULL parameters Up till this commit passing NULL as input parameter was allowed, but not handled properly. When a NULL parameter was passed to the function a data abort was raised. Signed-off-by: Dario Binacchi Reviewed-by: Simon Glass --- arch/arm/mach-omap2/am33xx/clock.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/am33xx/clock.c b/arch/arm/mach-omap2/am33xx/clock.c index 8819062aaa..130ee6c6e3 100644 --- a/arch/arm/mach-omap2/am33xx/clock.c +++ b/arch/arm/mach-omap2/am33xx/clock.c @@ -194,13 +194,14 @@ void do_enable_clocks(u32 *const *clk_domains, u32 i, max = 100; /* Put the clock domains in SW_WKUP mode */ - for (i = 0; (i < max) && clk_domains[i]; i++) { + for (i = 0; (i < max) && clk_domains && clk_domains[i]; i++) { enable_clock_domain(clk_domains[i], CD_CLKCTRL_CLKTRCTRL_SW_WKUP); } /* Clock modules that need to be put in SW_EXPLICIT_EN mode */ - for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) { + for (i = 0; (i < max) && clk_modules_explicit_en && + clk_modules_explicit_en[i]; i++) { enable_clock_module(clk_modules_explicit_en[i], MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN, wait_for_enable); @@ -215,12 +216,13 @@ void do_disable_clocks(u32 *const *clk_domains, /* Clock modules that need to be put in SW_DISABLE */ - for (i = 0; (i < max) && clk_modules_disable[i]; i++) + for (i = 0; (i < max) && clk_modules_disable && clk_modules_disable[i]; + i++) disable_clock_module(clk_modules_disable[i], wait_for_disable); /* Put the clock domains in SW_SLEEP mode */ - for (i = 0; (i < max) && clk_domains[i]; i++) + for (i = 0; (i < max) && clk_domains && clk_domains[i]; i++) disable_clock_domain(clk_domains[i]); } From 215bd541b8bb71fa97b4dc158f7c533be23043ef Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:06:39 +0100 Subject: [PATCH 23/42] clk: ti: add support for clkctrl clocks Until now the clkctrl clocks have been enabled/disabled through platform routines. Thanks to this patch they can be enabled and configured directly by the probed devices that need to use them. For DT binding details see Linux doc: - Documentation/devicetree/bindings/clock/ti-clkctrl.txt Signed-off-by: Dario Binacchi --- drivers/clk/ti/Kconfig | 6 ++ drivers/clk/ti/Makefile | 1 + drivers/clk/ti/clk-ctrl.c | 154 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 drivers/clk/ti/clk-ctrl.c diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig index 30959a316a..9e257a2eb7 100644 --- a/drivers/clk/ti/Kconfig +++ b/drivers/clk/ti/Kconfig @@ -10,6 +10,12 @@ config CLK_TI_AM3_DPLL This enables the DPLL clock drivers support on AM33XX SoCs. The DPLL provides all interface clocks and functional clocks to the processor. +config CLK_TI_CTRL + bool "TI OMAP4 clock controller" + depends on CLK && OF_CONTROL + help + This enables the clock controller driver support on TI's SoCs. + config CLK_TI_DIVIDER bool "TI divider clock driver" depends on CLK && OF_CONTROL && CLK_CCF diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile index f8aa735c83..ed45f18311 100644 --- a/drivers/clk/ti/Makefile +++ b/drivers/clk/ti/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_OMAP2PLUS) += clk.o obj-$(CONFIG_CLK_TI_AM3_DPLL) += clk-am3-dpll.o clk-am3-dpll-x2.o +obj-$(CONFIG_CLK_TI_CTRL) += clk-ctrl.o obj-$(CONFIG_CLK_TI_DIVIDER) += clk-divider.o obj-$(CONFIG_CLK_TI_GATE) += clk-gate.o obj-$(CONFIG_CLK_TI_MUX) += clk-mux.o diff --git a/drivers/clk/ti/clk-ctrl.c b/drivers/clk/ti/clk-ctrl.c new file mode 100644 index 0000000000..940e8d6caf --- /dev/null +++ b/drivers/clk/ti/clk-ctrl.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * OMAP clock controller support + * + * Copyright (C) 2020 Dario Binacchi + */ + +#include +#include +#include +#include +#include + +struct clk_ti_ctrl_offs { + fdt_addr_t start; + fdt_size_t end; +}; + +struct clk_ti_ctrl_priv { + int offs_num; + struct clk_ti_ctrl_offs *offs; +}; + +static int clk_ti_ctrl_check_offs(struct clk *clk, fdt_addr_t offs) +{ + struct clk_ti_ctrl_priv *priv = dev_get_priv(clk->dev); + int i; + + for (i = 0; i < priv->offs_num; i++) { + if (offs >= priv->offs[i].start && offs <= priv->offs[i].end) + return 0; + } + + return -EFAULT; +} + +static int clk_ti_ctrl_disable(struct clk *clk) +{ + struct clk_ti_ctrl_priv *priv = dev_get_priv(clk->dev); + u32 *clk_modules[2] = { }; + fdt_addr_t offs; + int err; + + offs = priv->offs[0].start + clk->id; + err = clk_ti_ctrl_check_offs(clk, offs); + if (err) { + dev_err(clk->dev, "invalid offset: 0x%lx\n", offs); + return err; + } + + clk_modules[0] = (u32 *)(offs); + dev_dbg(clk->dev, "module address=%p\n", clk_modules[0]); + do_disable_clocks(NULL, clk_modules, 1); + return 0; +} + +static int clk_ti_ctrl_enable(struct clk *clk) +{ + struct clk_ti_ctrl_priv *priv = dev_get_priv(clk->dev); + u32 *clk_modules[2] = { }; + fdt_addr_t offs; + int err; + + offs = priv->offs[0].start + clk->id; + err = clk_ti_ctrl_check_offs(clk, offs); + if (err) { + dev_err(clk->dev, "invalid offset: 0x%lx\n", offs); + return err; + } + + clk_modules[0] = (u32 *)(offs); + dev_dbg(clk->dev, "module address=%p\n", clk_modules[0]); + do_enable_clocks(NULL, clk_modules, 1); + return 0; +} + +static ulong clk_ti_ctrl_get_rate(struct clk *clk) +{ + return 0; +} + +static int clk_ti_ctrl_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + if (args->args_count != 2) { + dev_err(clk->dev, "invaild args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args_count) + clk->id = args->args[0]; + else + clk->id = 0; + + dev_dbg(clk->dev, "name=%s, id=%ld\n", clk->dev->name, clk->id); + return 0; +} + +static int clk_ti_ctrl_of_to_plat(struct udevice *dev) +{ + struct clk_ti_ctrl_priv *priv = dev_get_priv(dev); + fdt_size_t fdt_size; + int i, size; + + size = dev_read_size(dev, "reg"); + if (size < 0) { + dev_err(dev, "failed to get 'reg' size\n"); + return size; + } + + priv->offs_num = size / 2 / sizeof(u32); + dev_dbg(dev, "size=%d, regs_num=%d\n", size, priv->offs_num); + + priv->offs = kmalloc_array(priv->offs_num, sizeof(*priv->offs), + GFP_KERNEL); + if (!priv->offs) + return -ENOMEM; + + for (i = 0; i < priv->offs_num; i++) { + priv->offs[i].start = + dev_read_addr_size_index(dev, i, &fdt_size); + if (priv->offs[i].start == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get offset %d\n", i); + return -EINVAL; + } + + priv->offs[i].end = priv->offs[i].start + fdt_size; + dev_dbg(dev, "start=0x%08lx, end=0x%08lx\n", + priv->offs[i].start, priv->offs[i].end); + } + + return 0; +} + +static struct clk_ops clk_ti_ctrl_ops = { + .of_xlate = clk_ti_ctrl_of_xlate, + .enable = clk_ti_ctrl_enable, + .disable = clk_ti_ctrl_disable, + .get_rate = clk_ti_ctrl_get_rate, +}; + +static const struct udevice_id clk_ti_ctrl_ids[] = { + {.compatible = "ti,clkctrl"}, + {}, +}; + +U_BOOT_DRIVER(clk_ti_ctrl) = { + .name = "ti_ctrl_clk", + .id = UCLASS_CLK, + .of_match = clk_ti_ctrl_ids, + .ofdata_to_platdata = clk_ti_ctrl_of_to_plat, + .ops = &clk_ti_ctrl_ops, + .priv_auto = sizeof(struct clk_ti_ctrl_priv), +}; From 06c94c2463fa4ce85f162851cac2112e9b5bdf9f Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:18 +0100 Subject: [PATCH 24/42] clk: ti: omap4: add clock manager driver This minimal driver is only used to bind child devices. For DT binding details see Linux doc: - Documentation/devicetree/bindings/arm/omap/prcm.txt Signed-off-by: Dario Binacchi --- drivers/clk/ti/Makefile | 2 +- drivers/clk/ti/omap4-cm.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/ti/omap4-cm.c diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile index ed45f18311..dbd343069c 100644 --- a/drivers/clk/ti/Makefile +++ b/drivers/clk/ti/Makefile @@ -3,7 +3,7 @@ # Copyright (C) 2020 Dario Binacchi # -obj-$(CONFIG_ARCH_OMAP2PLUS) += clk.o +obj-$(CONFIG_ARCH_OMAP2PLUS) += clk.o omap4-cm.o obj-$(CONFIG_CLK_TI_AM3_DPLL) += clk-am3-dpll.o clk-am3-dpll-x2.o obj-$(CONFIG_CLK_TI_CTRL) += clk-ctrl.o diff --git a/drivers/clk/ti/omap4-cm.c b/drivers/clk/ti/omap4-cm.c new file mode 100644 index 0000000000..3cdc9b2888 --- /dev/null +++ b/drivers/clk/ti/omap4-cm.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * OMAP4 clock manager (cm) + * + * Copyright (C) 2020 Dario Binacchi + */ + +#include +#include +#include + +static const struct udevice_id ti_omap4_cm_ids[] = { + {.compatible = "ti,omap4-cm"}, + {} +}; + +U_BOOT_DRIVER(ti_omap4_cm) = { + .name = "ti_omap4_cm", + .id = UCLASS_SIMPLE_BUS, + .of_match = ti_omap4_cm_ids, + .bind = dm_scan_fdt_dev, +}; From abdf1a357124b257971b05159f332c7f1f3e9ff8 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:19 +0100 Subject: [PATCH 25/42] arm: dts: am335x: enable prcm_clocks auto binding Adding the 'simple-bus' compatible string to the prcm_clocks node will allow its automatic binding. Signed-off-by: Dario Binacchi --- arch/arm/dts/am33xx-u-boot.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/dts/am33xx-u-boot.dtsi b/arch/arm/dts/am33xx-u-boot.dtsi index 78f5e2c4d3..2426ece680 100644 --- a/arch/arm/dts/am33xx-u-boot.dtsi +++ b/arch/arm/dts/am33xx-u-boot.dtsi @@ -9,3 +9,7 @@ u-boot,dm-pre-reloc; }; }; + +&prcm_clocks { + compatible = "simple-bus"; +}; From 52b61c944ce536f975d095d4fa32d8bb656661fd Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:20 +0100 Subject: [PATCH 26/42] clk: move clk-ti-sci driver to 'ti' directory The patch moves the clk-ti-sci.c file to the 'ti' directory along with all the other TI's drivers, and renames it clk-sci.c. Signed-off-by: Dario Binacchi --- drivers/clk/Kconfig | 8 -------- drivers/clk/Makefile | 1 - drivers/clk/ti/Kconfig | 8 ++++++++ drivers/clk/ti/Makefile | 1 + drivers/clk/{clk-ti-sci.c => ti/clk-sci.c} | 0 5 files changed, 9 insertions(+), 9 deletions(-) rename drivers/clk/{clk-ti-sci.c => ti/clk-sci.c} (100%) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 9e54929039..db06f276ec 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -98,14 +98,6 @@ config CLK_STM32F This clock driver adds support for RCC clock management for STM32F4 and STM32F7 SoCs. -config CLK_TI_SCI - bool "TI System Control Interface (TI SCI) clock driver" - depends on CLK && TI_SCI_PROTOCOL && OF_CONTROL - help - This enables the clock driver support over TI System Control Interface - available on some new TI's SoCs. If you wish to use clock resources - managed by the TI System Controller, say Y here. Otherwise, say N. - config CLK_HSDK bool "Enable cgu clock driver for HSDK boards" depends on CLK && TARGET_HSDK diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 2581fe0a19..f8383e523d 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -48,6 +48,5 @@ obj-$(CONFIG_SANDBOX) += clk_sandbox.o obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o obj-$(CONFIG_SANDBOX_CLK_CCF) += clk_sandbox_ccf.o obj-$(CONFIG_STM32H7) += clk_stm32h7.o -obj-$(CONFIG_CLK_TI_SCI) += clk-ti-sci.o obj-$(CONFIG_CLK_VERSAL) += clk_versal.o obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o diff --git a/drivers/clk/ti/Kconfig b/drivers/clk/ti/Kconfig index 9e257a2eb7..2dc86d44a9 100644 --- a/drivers/clk/ti/Kconfig +++ b/drivers/clk/ti/Kconfig @@ -33,3 +33,11 @@ config CLK_TI_MUX depends on CLK && OF_CONTROL && CLK_CCF help This enables the mux clock driver support on TI's SoCs. + +config CLK_TI_SCI + bool "TI System Control Interface (TI SCI) clock driver" + depends on CLK && TI_SCI_PROTOCOL && OF_CONTROL + help + This enables the clock driver support over TI System Control Interface + available on some new TI's SoCs. If you wish to use clock resources + managed by the TI System Controller, say Y here. Otherwise, say N. diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile index dbd343069c..9f56b47736 100644 --- a/drivers/clk/ti/Makefile +++ b/drivers/clk/ti/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_CLK_TI_CTRL) += clk-ctrl.o obj-$(CONFIG_CLK_TI_DIVIDER) += clk-divider.o obj-$(CONFIG_CLK_TI_GATE) += clk-gate.o obj-$(CONFIG_CLK_TI_MUX) += clk-mux.o +obj-$(CONFIG_CLK_TI_SCI) += clk-sci.o diff --git a/drivers/clk/clk-ti-sci.c b/drivers/clk/ti/clk-sci.c similarity index 100% rename from drivers/clk/clk-ti-sci.c rename to drivers/clk/ti/clk-sci.c From d64b9cdcd475eb7f07b49741ded87e24dae4a5fc Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:21 +0100 Subject: [PATCH 27/42] fdt: translate address if #size-cells = <0> The __of_translate_address routine translates an address from the device tree into a CPU physical address. A note in the description of the routine explains that the crossing of any level with since inherited from IBM. This does not happen for Texas Instruments, or at least for the beaglebone device tree. Without this patch, in fact, the translation into physical addresses of the registers contained in the am33xx-clocks.dtsi nodes would not be possible. They all have a parent with #size-cells = <0>. The CONFIG_OF_TRANSLATE_ZERO_SIZE_CELLS symbol makes translation possible even in the case of crossing levels with #size-cells = <0>. The patch acts conservatively on address translation, except for removing a check within the of_translate_one function in the drivers/core/of_addr.c file: + ranges = of_get_property(parent, rprop, &rlen); - if (ranges == NULL && !of_empty_ranges_quirk(parent)) { - debug("no ranges; cannot translate\n"); - return 1; - } if (ranges == NULL || rlen == 0) { offset = of_read_number(addr, na); memset(addr, 0, pna * 4); debug("empty ranges; 1:1 translation\n"); There are two reasons: 1 The function of_empty_ranges_quirk always returns false, invalidating the following if statement in case of null ranges. Therefore one of the two checks is useless. 2 The implementation of the of_translate_one function found in the common/fdt_support.c file has removed this check while keeping the one about the 1:1 translation. The patch adds a test and modifies a check for the correctness of an address in the case of enabling translation also for zero size cells. The added test checks translations of addresses generated by nodes of a device tree similar to those you can find in the files am33xx.dtsi and am33xx-clocks.dtsi for which the patch was created. The patch was also tested on a beaglebone black board. The addresses generated for the registers of the loaded drivers are those specified by the AM335x reference manual. Signed-off-by: Dario Binacchi Tested-by: Dario Binacchi Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 21 ++++++++++ common/fdt_support.c | 6 ++- drivers/core/Kconfig | 12 ++++++ drivers/core/fdtaddr.c | 2 +- drivers/core/of_addr.c | 13 ++---- drivers/core/ofnode.c | 7 +++- drivers/core/root.c | 3 ++ include/asm-generic/global_data.h | 24 +++++++++++ test/dm/test-fdt.c | 68 +++++++++++++++++++++++++++++++ 9 files changed, 141 insertions(+), 15 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index c9b9b7b75e..efc440a1f8 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -42,6 +42,7 @@ fdt-dummy1 = "/translation-test@8000/dev@1,100"; fdt-dummy2 = "/translation-test@8000/dev@2,200"; fdt-dummy3 = "/translation-test@8000/noxlatebus@3,300/dev@42"; + fdt-dummy4 = "/translation-test@8000/xlatebus@4,400/devs/dev@19"; usb0 = &usb_0; usb1 = &usb_1; usb2 = &usb_2; @@ -1082,6 +1083,7 @@ 1 0x100 0x9000 0x1000 2 0x200 0xA000 0x1000 3 0x300 0xB000 0x1000 + 4 0x400 0xC000 0x1000 >; dma-ranges = <0 0x000 0x10000000 0x1000 @@ -1118,6 +1120,25 @@ reg = <0x42>; }; }; + + xlatebus@4,400 { + compatible = "sandbox,zero-size-cells-bus"; + reg = <4 0x400 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 4 0x400 0x1000>; + + devs { + #address-cells = <1>; + #size-cells = <0>; + + dev@19 { + compatible = "denx,u-boot-fdt-dummy"; + reg = <0x19>; + }; + }; + }; + }; osd { diff --git a/common/fdt_support.c b/common/fdt_support.c index 5ae75df3c6..638eca983e 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -20,6 +20,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + /** * fdt_getprop_u32_default_node - Return a node's property or a default * @@ -996,8 +998,8 @@ void fdt_del_node_and_alias(void *blob, const char *alias) /* Max address size we deal with */ #define OF_MAX_ADDR_CELLS 4 #define OF_BAD_ADDR FDT_ADDR_T_NONE -#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ - (ns) > 0) +#define OF_CHECK_COUNTS(na, ns) (((na) > 0 && (na) <= OF_MAX_ADDR_CELLS) && \ + ((ns) > 0 || gd_size_cells_0())) /* Debug utility */ #ifdef DEBUG diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index 65a503e76d..dbfe51c6e8 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -247,6 +247,18 @@ config OF_TRANSLATE used for the address translation. This function is faster and smaller in size than fdt_translate_address(). +config OF_TRANSLATE_ZERO_SIZE_CELLS + bool "Enable translation for zero size cells" + depends on OF_TRANSLATE + default n + help + The routine used to translate an FDT address into a physical CPU + address was developed by IBM. It considers that crossing any level + with #size-cells = <0> makes translation impossible, even if it is + not the way it was specified. + Enabling this option makes translation possible even in the case + of crossing levels with #size-cells = <0>. + config SPL_OF_TRANSLATE bool "Translate addresses using fdt_translate_address in SPL" depends on SPL_DM && SPL_OF_CONTROL diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index 8b48aa5bc5..ed55f69de1 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -49,7 +49,7 @@ fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index) reg += index * (na + ns); - if (ns) { + if (ns || gd_size_cells_0()) { /* * Use the full-fledged translate function for complex * bus setups. diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c index ca34d84922..bbe80136ba 100644 --- a/drivers/core/of_addr.c +++ b/drivers/core/of_addr.c @@ -18,7 +18,8 @@ /* Max address size we deal with */ #define OF_MAX_ADDR_CELLS 4 #define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS) -#define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0) +#define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && \ + ((ns) > 0 || gd_size_cells_0())) static struct of_bus *of_match_bus(struct device_node *np); @@ -162,11 +163,6 @@ const __be32 *of_get_address(const struct device_node *dev, int index, } EXPORT_SYMBOL(of_get_address); -static int of_empty_ranges_quirk(const struct device_node *np) -{ - return false; -} - static int of_translate_one(const struct device_node *parent, struct of_bus *bus, struct of_bus *pbus, __be32 *addr, int na, int ns, int pna, @@ -193,11 +189,8 @@ static int of_translate_one(const struct device_node *parent, * As far as we know, this damage only exists on Apple machines, so * This code is only enabled on powerpc. --gcl */ + ranges = of_get_property(parent, rprop, &rlen); - if (ranges == NULL && !of_empty_ranges_quirk(parent)) { - debug("no ranges; cannot translate\n"); - return 1; - } if (ranges == NULL || rlen == 0) { offset = of_read_number(addr, na); memset(addr, 0, pna * 4); diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 2a6e43ddc6..7a5f4c0a73 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -316,7 +316,8 @@ fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size) ns = of_n_size_cells(ofnode_to_np(node)); - if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) { + if (IS_ENABLED(CONFIG_OF_TRANSLATE) && + (ns > 0 || gd_size_cells_0())) { return of_translate_address(ofnode_to_np(node), prop_val); } else { na = of_n_addr_cells(ofnode_to_np(node)); @@ -690,8 +691,10 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, ns = of_n_size_cells(np); *sizep = of_read_number(prop + na, ns); - if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0) + if (CONFIG_IS_ENABLED(OF_TRANSLATE) && + (ns > 0 || gd_size_cells_0())) { return of_translate_address(np, prop); + } else return of_read_number(prop, na); } else { diff --git a/drivers/core/root.c b/drivers/core/root.c index 78de7cdf87..2bfa75b472 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -132,6 +132,9 @@ int dm_init(bool of_live) { int ret; + if (IS_ENABLED(CONFIG_OF_TRANSLATE_ZERO_SIZE_CELLS)) + gd->dm_flags |= GD_DM_FLG_SIZE_CELLS_0; + if (gd->dm_root) { dm_warn("Virtual root driver already exists!\n"); return -EINVAL; diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 31e249177c..efa09a1943 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -183,6 +183,12 @@ struct global_data { struct global_data *new_gd; #ifdef CONFIG_DM + /** + * @dm_flags: additional flags for Driver Model + * + * See &enum gd_dm_flags + */ + unsigned long dm_flags; /** * @dm_root: root instance for Driver Model */ @@ -471,6 +477,12 @@ struct global_data { #define gd_acpi_ctx() NULL #endif +#if CONFIG_IS_ENABLED(DM) +#define gd_size_cells_0() (gd->dm_flags & GD_DM_FLG_SIZE_CELLS_0) +#else +#define gd_size_cells_0() (0) +#endif + /** * enum gd_flags - global data flags * @@ -555,6 +567,18 @@ enum gd_flags { GD_FLG_SMP_READY = 0x40000, }; +/** + * enum gd_dm_flags - global data flags for Driver Model + * + * See field dm_flags of &struct global_data. + */ +enum gd_dm_flags { + /** + * @GD_DM_FLG_SIZE_CELLS_0: Enable #size-cells=<0> translation + */ + GD_DM_FLG_SIZE_CELLS_0 = 0x00001, +}; + #endif /* __ASSEMBLY__ */ #endif /* __ASM_GENERIC_GBL_DATA_H */ diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index b53539055b..31fb6663a2 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -549,6 +550,64 @@ U_BOOT_DRIVER(fdt_dummy_drv) = { .id = UCLASS_TEST_DUMMY, }; +static int zero_size_cells_bus_bind(struct udevice *dev) +{ + ofnode child; + int err; + + ofnode_for_each_subnode(child, dev_ofnode(dev)) { + if (ofnode_get_property(child, "compatible", NULL)) + continue; + + err = device_bind_driver_to_node(dev, + "zero_size_cells_bus_child_drv", + "zero_size_cells_bus_child", + child, NULL); + if (err) { + dev_err(dev, "%s: failed to bind %s\n", __func__, + ofnode_get_name(child)); + return err; + } + } + + return 0; +} + +static const struct udevice_id zero_size_cells_bus_ids[] = { + { .compatible = "sandbox,zero-size-cells-bus" }, + { } +}; + +U_BOOT_DRIVER(zero_size_cells_bus) = { + .name = "zero_size_cells_bus_drv", + .id = UCLASS_TEST_DUMMY, + .of_match = zero_size_cells_bus_ids, + .bind = zero_size_cells_bus_bind, +}; + +static int zero_size_cells_bus_child_bind(struct udevice *dev) +{ + ofnode child; + int err; + + ofnode_for_each_subnode(child, dev_ofnode(dev)) { + err = lists_bind_fdt(dev, child, NULL, false); + if (err) { + dev_err(dev, "%s: lists_bind_fdt, err=%d\n", + __func__, err); + return err; + } + } + + return 0; +} + +U_BOOT_DRIVER(zero_size_cells_bus_child_drv) = { + .name = "zero_size_cells_bus_child_drv", + .id = UCLASS_TEST_DUMMY, + .bind = zero_size_cells_bus_child_bind, +}; + static int dm_test_fdt_translation(struct unit_test_state *uts) { struct udevice *dev; @@ -570,8 +629,17 @@ static int dm_test_fdt_translation(struct unit_test_state *uts) /* No translation for busses with #size-cells == 0 */ ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 3, &dev)); ut_asserteq_str("dev@42", dev->name); + /* No translation for busses with #size-cells == 0 */ ut_asserteq(0x42, dev_read_addr(dev)); + /* Translation for busses with #size-cells == 0 */ + gd->dm_flags |= GD_DM_FLG_SIZE_CELLS_0; + ut_asserteq(0x8042, dev_read_addr(dev)); + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 4, &dev)); + ut_asserteq_str("dev@19", dev->name); + ut_asserteq(0xc019, dev_read_addr(dev)); + gd->dm_flags &= ~GD_DM_FLG_SIZE_CELLS_0; + /* dma address translation */ ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, &dev)); dma_addr[0] = cpu_to_be32(0); From 11326f379329d979bc39d26896190b799103a407 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:22 +0100 Subject: [PATCH 28/42] omap: timer: fix the rate setting The prescaler (PTV) setting must be taken into account even when the timer input clock frequency has been set. Signed-off-by: Dario Binacchi --- drivers/timer/omap-timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/timer/omap-timer.c b/drivers/timer/omap-timer.c index 7ac20d78dd..721e385fd1 100644 --- a/drivers/timer/omap-timer.c +++ b/drivers/timer/omap-timer.c @@ -19,8 +19,6 @@ #define TCLR_PRE_EN BIT(5) /* Pre-scaler enable */ #define TCLR_PTV_SHIFT (2) /* Pre-scaler shift value */ -#define TIMER_CLOCK (V_SCLK / (2 << CONFIG_SYS_PTV)) - struct omap_gptimer_regs { unsigned int tidr; /* offset 0x00 */ unsigned char res1[12]; @@ -61,7 +59,9 @@ static int omap_timer_probe(struct udevice *dev) struct omap_timer_priv *priv = dev_get_priv(dev); if (!uc_priv->clock_rate) - uc_priv->clock_rate = TIMER_CLOCK; + uc_priv->clock_rate = V_SCLK; + + uc_priv->clock_rate /= (2 << CONFIG_SYS_PTV); /* start the counter ticking up, reload value on overflow */ writel(0, &priv->regs->tldr); From 8322fdcedfa44dd22eab07c2dc32f0b3b02ec797 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:23 +0100 Subject: [PATCH 29/42] arm: dts: am335x: enable scm_clocks auto binding Adding the 'simple-bus' compatible string to the scm_clocks node will allow its automatic binding. Signed-off-by: Dario Binacchi --- arch/arm/dts/am33xx-u-boot.dtsi | 4 ++++ arch/arm/dts/dm8168-evm-u-boot.dtsi | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 arch/arm/dts/dm8168-evm-u-boot.dtsi diff --git a/arch/arm/dts/am33xx-u-boot.dtsi b/arch/arm/dts/am33xx-u-boot.dtsi index 2426ece680..61d10b841b 100644 --- a/arch/arm/dts/am33xx-u-boot.dtsi +++ b/arch/arm/dts/am33xx-u-boot.dtsi @@ -13,3 +13,7 @@ &prcm_clocks { compatible = "simple-bus"; }; + +&scm_clocks { + compatible = "simple-bus"; +}; diff --git a/arch/arm/dts/dm8168-evm-u-boot.dtsi b/arch/arm/dts/dm8168-evm-u-boot.dtsi new file mode 100644 index 0000000000..de0bb9bc81 --- /dev/null +++ b/arch/arm/dts/dm8168-evm-u-boot.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * dm8168-evm U-Boot Additions + * + * Copyright (C) 2020 Dario Binacchi + */ + +/ { + ocp { + u-boot,dm-pre-reloc; + }; +}; From ade7f0d00e598387fe67475d54511df4fe25d83f Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:24 +0100 Subject: [PATCH 30/42] pwm: ti: am33xx: add enhanced pwm driver Enhanced high resolution PWM module (EHRPWM) hardware can be used to generate PWM output over 2 channels. This commit adds PWM driver support for EHRPWM device present on AM33XX SOC. The code is based on the drivers/pwm/pwm-tiehrpwm.c driver of the Linux kernel version 5.9-rc7. For DT binding details see: - Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt Signed-off-by: Dario Binacchi --- drivers/pwm/Kconfig | 7 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm-ti-ehrpwm.c | 468 ++++++++++++++++++++++++++++++++++++ 3 files changed, 476 insertions(+) create mode 100644 drivers/pwm/pwm-ti-ehrpwm.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b3bd5c6bb7..ccf81abbe9 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -75,3 +75,10 @@ config PWM_SUNXI help This PWM is found on H3, A64 and other Allwinner SoCs. It supports a programmable period and duty cycle. A 16-bit counter is used. + +config PWM_TI_EHRPWM + bool "Enable support for EHRPWM PWM" + depends on DM_PWM && ARCH_OMAP2PLUS + default y + help + PWM driver support for the EHRPWM controller found on TI SOCs. diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index f21ae7d76e..0b9d2698a3 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_PWM_SANDBOX) += sandbox_pwm.o obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o obj-$(CONFIG_PWM_SUNXI) += sunxi_pwm.o +obj-$(CONFIG_PWM_TI_EHRPWM) += pwm-ti-ehrpwm.o diff --git a/drivers/pwm/pwm-ti-ehrpwm.c b/drivers/pwm/pwm-ti-ehrpwm.c new file mode 100644 index 0000000000..ac3d731d22 --- /dev/null +++ b/drivers/pwm/pwm-ti-ehrpwm.c @@ -0,0 +1,468 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EHRPWM PWM driver + * + * Copyright (C) 2020 Dario Binacchi + * + * Based on Linux kernel drivers/pwm/pwm-tiehrpwm.c + */ + +#include +#include +#include +#include +#include +#include +#include + +#define NSEC_PER_SEC 1000000000L + +/* Time base module registers */ +#define TI_EHRPWM_TBCTL 0x00 +#define TI_EHRPWM_TBPRD 0x0A + +#define TI_EHRPWM_TBCTL_PRDLD_MASK BIT(3) +#define TI_EHRPWM_TBCTL_PRDLD_SHDW 0 +#define TI_EHRPWM_TBCTL_PRDLD_IMDT BIT(3) +#define TI_EHRPWM_TBCTL_CLKDIV_MASK GENMASK(12, 7) +#define TI_EHRPWM_TBCTL_CTRMODE_MASK GENMASK(1, 0) +#define TI_EHRPWM_TBCTL_CTRMODE_UP 0 +#define TI_EHRPWM_TBCTL_CTRMODE_DOWN BIT(0) +#define TI_EHRPWM_TBCTL_CTRMODE_UPDOWN BIT(1) +#define TI_EHRPWM_TBCTL_CTRMODE_FREEZE GENMASK(1, 0) + +#define TI_EHRPWM_TBCTL_HSPCLKDIV_SHIFT 7 +#define TI_EHRPWM_TBCTL_CLKDIV_SHIFT 10 + +#define TI_EHRPWM_CLKDIV_MAX 7 +#define TI_EHRPWM_HSPCLKDIV_MAX 7 +#define TI_EHRPWM_PERIOD_MAX 0xFFFF + +/* Counter compare module registers */ +#define TI_EHRPWM_CMPA 0x12 +#define TI_EHRPWM_CMPB 0x14 + +/* Action qualifier module registers */ +#define TI_EHRPWM_AQCTLA 0x16 +#define TI_EHRPWM_AQCTLB 0x18 +#define TI_EHRPWM_AQSFRC 0x1A +#define TI_EHRPWM_AQCSFRC 0x1C + +#define TI_EHRPWM_AQCTL_CBU_MASK GENMASK(9, 8) +#define TI_EHRPWM_AQCTL_CBU_FRCLOW BIT(8) +#define TI_EHRPWM_AQCTL_CBU_FRCHIGH BIT(9) +#define TI_EHRPWM_AQCTL_CBU_FRCTOGGLE GENMASK(9, 8) +#define TI_EHRPWM_AQCTL_CAU_MASK GENMASK(5, 4) +#define TI_EHRPWM_AQCTL_CAU_FRCLOW BIT(4) +#define TI_EHRPWM_AQCTL_CAU_FRCHIGH BIT(5) +#define TI_EHRPWM_AQCTL_CAU_FRCTOGGLE GENMASK(5, 4) +#define TI_EHRPWM_AQCTL_PRD_MASK GENMASK(3, 2) +#define TI_EHRPWM_AQCTL_PRD_FRCLOW BIT(2) +#define TI_EHRPWM_AQCTL_PRD_FRCHIGH BIT(3) +#define TI_EHRPWM_AQCTL_PRD_FRCTOGGLE GENMASK(3, 2) +#define TI_EHRPWM_AQCTL_ZRO_MASK GENMASK(1, 0) +#define TI_EHRPWM_AQCTL_ZRO_FRCLOW BIT(0) +#define TI_EHRPWM_AQCTL_ZRO_FRCHIGH BIT(1) +#define TI_EHRPWM_AQCTL_ZRO_FRCTOGGLE GENMASK(1, 0) + +#define TI_EHRPWM_AQCTL_CHANA_POLNORMAL (TI_EHRPWM_AQCTL_CAU_FRCLOW | \ + TI_EHRPWM_AQCTL_PRD_FRCHIGH | \ + TI_EHRPWM_AQCTL_ZRO_FRCHIGH) +#define TI_EHRPWM_AQCTL_CHANA_POLINVERSED (TI_EHRPWM_AQCTL_CAU_FRCHIGH | \ + TI_EHRPWM_AQCTL_PRD_FRCLOW | \ + TI_EHRPWM_AQCTL_ZRO_FRCLOW) +#define TI_EHRPWM_AQCTL_CHANB_POLNORMAL (TI_EHRPWM_AQCTL_CBU_FRCLOW | \ + TI_EHRPWM_AQCTL_PRD_FRCHIGH | \ + TI_EHRPWM_AQCTL_ZRO_FRCHIGH) +#define TI_EHRPWM_AQCTL_CHANB_POLINVERSED (TI_EHRPWM_AQCTL_CBU_FRCHIGH | \ + TI_EHRPWM_AQCTL_PRD_FRCLOW | \ + TI_EHRPWM_AQCTL_ZRO_FRCLOW) + +#define TI_EHRPWM_AQSFRC_RLDCSF_MASK GENMASK(7, 6) +#define TI_EHRPWM_AQSFRC_RLDCSF_ZRO 0 +#define TI_EHRPWM_AQSFRC_RLDCSF_PRD BIT(6) +#define TI_EHRPWM_AQSFRC_RLDCSF_ZROPRD BIT(7) +#define TI_EHRPWM_AQSFRC_RLDCSF_IMDT GENMASK(7, 6) + +#define TI_EHRPWM_AQCSFRC_CSFB_MASK GENMASK(3, 2) +#define TI_EHRPWM_AQCSFRC_CSFB_FRCDIS 0 +#define TI_EHRPWM_AQCSFRC_CSFB_FRCLOW BIT(2) +#define TI_EHRPWM_AQCSFRC_CSFB_FRCHIGH BIT(3) +#define TI_EHRPWM_AQCSFRC_CSFB_DISSWFRC GENMASK(3, 2) +#define TI_EHRPWM_AQCSFRC_CSFA_MASK GENMASK(1, 0) +#define TI_EHRPWM_AQCSFRC_CSFA_FRCDIS 0 +#define TI_EHRPWM_AQCSFRC_CSFA_FRCLOW BIT(0) +#define TI_EHRPWM_AQCSFRC_CSFA_FRCHIGH BIT(1) +#define TI_EHRPWM_AQCSFRC_CSFA_DISSWFRC GENMASK(1, 0) + +#define TI_EHRPWM_NUM_CHANNELS 2 + +struct ti_ehrpwm_priv { + fdt_addr_t regs; + u32 clk_rate; + struct clk tbclk; + unsigned long period_cycles[TI_EHRPWM_NUM_CHANNELS]; + bool polarity_reversed[TI_EHRPWM_NUM_CHANNELS]; +}; + +static void ti_ehrpwm_modify(u16 val, u16 mask, fdt_addr_t reg) +{ + unsigned short v; + + v = readw(reg); + v &= ~mask; + v |= val & mask; + writew(v, reg); +} + +static int ti_ehrpwm_set_invert(struct udevice *dev, uint channel, + bool polarity) +{ + struct ti_ehrpwm_priv *priv = dev_get_priv(dev); + + if (channel >= TI_EHRPWM_NUM_CHANNELS) + return -ENOSPC; + + /* Configuration of polarity in hardware delayed, do at enable */ + priv->polarity_reversed[channel] = polarity; + return 0; +} + +/** + * set_prescale_div - Set up the prescaler divider function + * @rqst_prescaler: prescaler value min + * @prescale_div: prescaler value set + * @tb_clk_div: Time Base Control prescaler bits + */ +static int set_prescale_div(unsigned long rqst_prescaler, u16 *prescale_div, + u16 *tb_clk_div) +{ + unsigned int clkdiv, hspclkdiv; + + for (clkdiv = 0; clkdiv <= TI_EHRPWM_CLKDIV_MAX; clkdiv++) { + for (hspclkdiv = 0; hspclkdiv <= TI_EHRPWM_HSPCLKDIV_MAX; + hspclkdiv++) { + /* + * calculations for prescaler value : + * prescale_div = HSPCLKDIVIDER * CLKDIVIDER. + * HSPCLKDIVIDER = 2 ** hspclkdiv + * CLKDIVIDER = (1), if clkdiv == 0 *OR* + * (2 * clkdiv), if clkdiv != 0 + * + * Configure prescale_div value such that period + * register value is less than 65535. + */ + + *prescale_div = (1 << clkdiv) * + (hspclkdiv ? (hspclkdiv * 2) : 1); + if (*prescale_div > rqst_prescaler) { + *tb_clk_div = + (clkdiv << TI_EHRPWM_TBCTL_CLKDIV_SHIFT) | + (hspclkdiv << + TI_EHRPWM_TBCTL_HSPCLKDIV_SHIFT); + return 0; + } + } + } + + return 1; +} + +static void ti_ehrpwm_configure_polarity(struct udevice *dev, uint channel) +{ + struct ti_ehrpwm_priv *priv = dev_get_priv(dev); + u16 aqctl_val, aqctl_mask; + unsigned int aqctl_reg; + + /* + * Configure PWM output to HIGH/LOW level on counter + * reaches compare register value and LOW/HIGH level + * on counter value reaches period register value and + * zero value on counter + */ + if (channel == 1) { + aqctl_reg = TI_EHRPWM_AQCTLB; + aqctl_mask = TI_EHRPWM_AQCTL_CBU_MASK; + + if (priv->polarity_reversed[channel]) + aqctl_val = TI_EHRPWM_AQCTL_CHANB_POLINVERSED; + else + aqctl_val = TI_EHRPWM_AQCTL_CHANB_POLNORMAL; + } else { + aqctl_reg = TI_EHRPWM_AQCTLA; + aqctl_mask = TI_EHRPWM_AQCTL_CAU_MASK; + + if (priv->polarity_reversed[channel]) + aqctl_val = TI_EHRPWM_AQCTL_CHANA_POLINVERSED; + else + aqctl_val = TI_EHRPWM_AQCTL_CHANA_POLNORMAL; + } + + aqctl_mask |= TI_EHRPWM_AQCTL_PRD_MASK | TI_EHRPWM_AQCTL_ZRO_MASK; + ti_ehrpwm_modify(aqctl_val, aqctl_mask, priv->regs + aqctl_reg); +} + +/* + * period_ns = 10^9 * (ps_divval * period_cycles) / PWM_CLK_RATE + * duty_ns = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE + */ +static int ti_ehrpwm_set_config(struct udevice *dev, uint channel, + uint period_ns, uint duty_ns) +{ + struct ti_ehrpwm_priv *priv = dev_get_priv(dev); + u32 period_cycles, duty_cycles; + u16 ps_divval, tb_divval; + unsigned int i, cmp_reg; + unsigned long long c; + + if (channel >= TI_EHRPWM_NUM_CHANNELS) + return -ENOSPC; + + if (period_ns > NSEC_PER_SEC) + return -ERANGE; + + c = priv->clk_rate; + c = c * period_ns; + do_div(c, NSEC_PER_SEC); + period_cycles = (unsigned long)c; + + if (period_cycles < 1) { + period_cycles = 1; + duty_cycles = 1; + } else { + c = priv->clk_rate; + c = c * duty_ns; + do_div(c, NSEC_PER_SEC); + duty_cycles = (unsigned long)c; + } + + dev_dbg(dev, "channel=%d, period_ns=%d, duty_ns=%d\n", + channel, period_ns, duty_ns); + + /* + * Period values should be same for multiple PWM channels as IP uses + * same period register for multiple channels. + */ + for (i = 0; i < TI_EHRPWM_NUM_CHANNELS; i++) { + if (priv->period_cycles[i] && + priv->period_cycles[i] != period_cycles) { + /* + * Allow channel to reconfigure period if no other + * channels being configured. + */ + if (i == channel) + continue; + + dev_err(dev, "period value conflicts with channel %u\n", + i); + return -EINVAL; + } + } + + priv->period_cycles[channel] = period_cycles; + + /* Configure clock prescaler to support Low frequency PWM wave */ + if (set_prescale_div(period_cycles / TI_EHRPWM_PERIOD_MAX, &ps_divval, + &tb_divval)) { + dev_err(dev, "unsupported values\n"); + return -EINVAL; + } + + /* Update clock prescaler values */ + ti_ehrpwm_modify(tb_divval, TI_EHRPWM_TBCTL_CLKDIV_MASK, + priv->regs + TI_EHRPWM_TBCTL); + + /* Update period & duty cycle with presacler division */ + period_cycles = period_cycles / ps_divval; + duty_cycles = duty_cycles / ps_divval; + + /* Configure shadow loading on Period register */ + ti_ehrpwm_modify(TI_EHRPWM_TBCTL_PRDLD_SHDW, TI_EHRPWM_TBCTL_PRDLD_MASK, + priv->regs + TI_EHRPWM_TBCTL); + + writew(period_cycles, priv->regs + TI_EHRPWM_TBPRD); + + /* Configure ehrpwm counter for up-count mode */ + ti_ehrpwm_modify(TI_EHRPWM_TBCTL_CTRMODE_UP, + TI_EHRPWM_TBCTL_CTRMODE_MASK, + priv->regs + TI_EHRPWM_TBCTL); + + if (channel == 1) + /* Channel 1 configured with compare B register */ + cmp_reg = TI_EHRPWM_CMPB; + else + /* Channel 0 configured with compare A register */ + cmp_reg = TI_EHRPWM_CMPA; + + writew(duty_cycles, priv->regs + cmp_reg); + return 0; +} + +static int ti_ehrpwm_disable(struct udevice *dev, uint channel) +{ + struct ti_ehrpwm_priv *priv = dev_get_priv(dev); + u16 aqcsfrc_val, aqcsfrc_mask; + int err; + + if (channel >= TI_EHRPWM_NUM_CHANNELS) + return -ENOSPC; + + /* Action Qualifier puts PWM output low forcefully */ + if (channel) { + aqcsfrc_val = TI_EHRPWM_AQCSFRC_CSFB_FRCLOW; + aqcsfrc_mask = TI_EHRPWM_AQCSFRC_CSFB_MASK; + } else { + aqcsfrc_val = TI_EHRPWM_AQCSFRC_CSFA_FRCLOW; + aqcsfrc_mask = TI_EHRPWM_AQCSFRC_CSFA_MASK; + } + + /* Update shadow register first before modifying active register */ + ti_ehrpwm_modify(TI_EHRPWM_AQSFRC_RLDCSF_ZRO, + TI_EHRPWM_AQSFRC_RLDCSF_MASK, + priv->regs + TI_EHRPWM_AQSFRC); + + ti_ehrpwm_modify(aqcsfrc_val, aqcsfrc_mask, + priv->regs + TI_EHRPWM_AQCSFRC); + + /* + * Changes to immediate action on Action Qualifier. This puts + * Action Qualifier control on PWM output from next TBCLK + */ + ti_ehrpwm_modify(TI_EHRPWM_AQSFRC_RLDCSF_IMDT, + TI_EHRPWM_AQSFRC_RLDCSF_MASK, + priv->regs + TI_EHRPWM_AQSFRC); + + ti_ehrpwm_modify(aqcsfrc_val, aqcsfrc_mask, + priv->regs + TI_EHRPWM_AQCSFRC); + + /* Disabling TBCLK on PWM disable */ + err = clk_disable(&priv->tbclk); + if (err) { + dev_err(dev, "failed to disable tbclk\n"); + return err; + } + + return 0; +} + +static int ti_ehrpwm_enable(struct udevice *dev, uint channel) +{ + struct ti_ehrpwm_priv *priv = dev_get_priv(dev); + u16 aqcsfrc_val, aqcsfrc_mask; + int err; + + if (channel >= TI_EHRPWM_NUM_CHANNELS) + return -ENOSPC; + + /* Disabling Action Qualifier on PWM output */ + if (channel) { + aqcsfrc_val = TI_EHRPWM_AQCSFRC_CSFB_FRCDIS; + aqcsfrc_mask = TI_EHRPWM_AQCSFRC_CSFB_MASK; + } else { + aqcsfrc_val = TI_EHRPWM_AQCSFRC_CSFA_FRCDIS; + aqcsfrc_mask = TI_EHRPWM_AQCSFRC_CSFA_MASK; + } + + /* Changes to shadow mode */ + ti_ehrpwm_modify(TI_EHRPWM_AQSFRC_RLDCSF_ZRO, + TI_EHRPWM_AQSFRC_RLDCSF_MASK, + priv->regs + TI_EHRPWM_AQSFRC); + + ti_ehrpwm_modify(aqcsfrc_val, aqcsfrc_mask, + priv->regs + TI_EHRPWM_AQCSFRC); + + /* Channels polarity can be configured from action qualifier module */ + ti_ehrpwm_configure_polarity(dev, channel); + + err = clk_enable(&priv->tbclk); + if (err) { + dev_err(dev, "failed to enable tbclk\n"); + return err; + } + + return 0; +} + +static int ti_ehrpwm_set_enable(struct udevice *dev, uint channel, bool enable) +{ + if (enable) + return ti_ehrpwm_enable(dev, channel); + + return ti_ehrpwm_disable(dev, channel); +} + +static int ti_ehrpwm_of_to_plat(struct udevice *dev) +{ + struct ti_ehrpwm_priv *priv = dev_get_priv(dev); + + priv->regs = dev_read_addr(dev); + if (priv->regs == FDT_ADDR_T_NONE) { + dev_err(dev, "invalid address\n"); + return -EINVAL; + } + + dev_dbg(dev, "regs=0x%08lx\n", priv->regs); + return 0; +} + +static int ti_ehrpwm_remove(struct udevice *dev) +{ + struct ti_ehrpwm_priv *priv = dev_get_priv(dev); + + clk_release_all(&priv->tbclk, 1); + return 0; +} + +static int ti_ehrpwm_probe(struct udevice *dev) +{ + struct ti_ehrpwm_priv *priv = dev_get_priv(dev); + struct clk clk; + int err; + + err = clk_get_by_name(dev, "fck", &clk); + if (err) { + dev_err(dev, "failed to get clock\n"); + return err; + } + + priv->clk_rate = clk_get_rate(&clk); + if (IS_ERR_VALUE(priv->clk_rate) || !priv->clk_rate) { + dev_err(dev, "failed to get clock rate\n"); + if (IS_ERR_VALUE(priv->clk_rate)) + return priv->clk_rate; + + return -EINVAL; + } + + /* Acquire tbclk for Time Base EHRPWM submodule */ + err = clk_get_by_name(dev, "tbclk", &priv->tbclk); + if (err) { + dev_err(dev, "failed to get tbclk clock\n"); + return err; + } + + return 0; +} + +static const struct pwm_ops ti_ehrpwm_ops = { + .set_config = ti_ehrpwm_set_config, + .set_enable = ti_ehrpwm_set_enable, + .set_invert = ti_ehrpwm_set_invert, +}; + +static const struct udevice_id ti_ehrpwm_ids[] = { + {.compatible = "ti,am3352-ehrpwm"}, + {.compatible = "ti,am33xx-ehrpwm"}, + {} +}; + +U_BOOT_DRIVER(ti_ehrpwm) = { + .name = "ti_ehrpwm", + .id = UCLASS_PWM, + .of_match = ti_ehrpwm_ids, + .ops = &ti_ehrpwm_ops, + .ofdata_to_platdata = ti_ehrpwm_of_to_plat, + .probe = ti_ehrpwm_probe, + .remove = ti_ehrpwm_remove, + .priv_auto = sizeof(struct ti_ehrpwm_priv), +}; From 0f4effb05b275f36c490673313317cfe897c9b79 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:25 +0100 Subject: [PATCH 31/42] bus: ti: am33xx: add pwm subsystem driver The TI PWMSS driver is a simple bus driver for providing clock and power management for the PWM peripherals on TI AM33xx SoCs, namely eCAP, eHRPWM and eQEP. For DT binding details see Linux doc: - Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt Signed-off-by: Dario Binacchi --- drivers/bus/Kconfig | 6 ++++++ drivers/bus/Makefile | 1 + drivers/bus/ti-pwmss.c | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 drivers/bus/ti-pwmss.c diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 733bec5a56..d742ed333b 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -5,6 +5,12 @@ menu "Bus devices" +config TI_PWMSS + bool + default y if ARCH_OMAP2PLUS && PWM_TI_EHRPWM + help + PWM Subsystem driver support for AM33xx SOC. + config TI_SYSC bool "TI sysc interconnect target module driver" depends on ARCH_OMAP2PLUS diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 875bb4ed42..a2e71c7b3b 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -3,5 +3,6 @@ # Makefile for the bus drivers. # +obj-$(CONFIG_TI_PWMSS) += ti-pwmss.o obj-$(CONFIG_TI_SYSC) += ti-sysc.o obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o diff --git a/drivers/bus/ti-pwmss.c b/drivers/bus/ti-pwmss.c new file mode 100644 index 0000000000..265b4cf83b --- /dev/null +++ b/drivers/bus/ti-pwmss.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Pulse-Width Modulation Subsystem (pwmss) + * + * Copyright (C) 2020 Dario Binacchi + */ + +#include +#include + +static const struct udevice_id ti_pwmss_ids[] = { + {.compatible = "ti,am33xx-pwmss"}, + {} +}; + +U_BOOT_DRIVER(ti_pwmss) = { + .name = "ti_pwmss", + .id = UCLASS_SIMPLE_BUS, + .of_match = ti_pwmss_ids, + .bind = dm_scan_fdt_dev, +}; From 15daa4860bf3c49f53ae76812e0033e4d5faa0a2 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:26 +0100 Subject: [PATCH 32/42] dm: core: add a function to decode display timings The patch adds a function to get display timings from the device tree node attached to the device. Signed-off-by: Dario Binacchi Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 46 ++++++++++++++++++++++ drivers/core/read.c | 6 +++ include/dm/read.h | 24 ++++++++++++ test/dm/test-fdt.c | 80 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index efc440a1f8..f86cd0d3b2 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -142,6 +142,52 @@ <&muxcontroller1>; mux-control-names = "mux0", "mux1", "mux2", "mux3", "mux4"; mux-syscon = <&syscon3>; + display-timings { + timing0: 240x320 { + clock-frequency = <6500000>; + hactive = <240>; + vactive = <320>; + hfront-porch = <6>; + hback-porch = <7>; + hsync-len = <1>; + vback-porch = <5>; + vfront-porch = <8>; + vsync-len = <2>; + hsync-active = <1>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + interlaced; + doublescan; + doubleclk; + }; + timing1: 480x800 { + clock-frequency = <9000000>; + hactive = <480>; + vactive = <800>; + hfront-porch = <10>; + hback-porch = <59>; + hsync-len = <12>; + vback-porch = <15>; + vfront-porch = <17>; + vsync-len = <16>; + hsync-active = <0>; + vsync-active = <1>; + de-active = <0>; + pixelclk-active = <0>; + }; + timing2: 800x480 { + clock-frequency = <33500000>; + hactive = <800>; + vactive = <480>; + hback-porch = <89>; + hfront-porch = <164>; + vback-porch = <23>; + vfront-porch = <10>; + hsync-len = <11>; + vsync-len = <13>; + }; + }; }; junk { diff --git a/drivers/core/read.c b/drivers/core/read.c index fc74d64814..4d9b5dd038 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -379,3 +379,9 @@ int dev_read_pci_bus_range(const struct udevice *dev, return 0; } + +int dev_decode_display_timing(const struct udevice *dev, int index, + struct display_timing *config) +{ + return ofnode_decode_display_timing(dev_ofnode(dev), index, config); +} diff --git a/include/dm/read.h b/include/dm/read.h index fc987f7759..c875e11a13 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -678,6 +678,23 @@ int dev_get_child_count(const struct udevice *dev); */ int dev_read_pci_bus_range(const struct udevice *dev, struct resource *res); +/** + * dev_decode_display_timing() - decode display timings + * + * Decode display timings from the supplied 'display-timings' node. + * See doc/device-tree-bindings/video/display-timing.txt for binding + * information. + * + * @dev: device to read DT display timings from. The node linked to the device + * contains a child node called 'display-timings' which in turn contains + * one or more display timing nodes. + * @index: index number to read (0=first timing subnode) + * @config: place to put timings + * @return 0 if OK, -FDT_ERR_NOTFOUND if not found + */ +int dev_decode_display_timing(const struct udevice *dev, int index, + struct display_timing *config); + #else /* CONFIG_DM_DEV_READ_INLINE is enabled */ static inline int dev_read_u32(const struct udevice *dev, @@ -1000,6 +1017,13 @@ static inline int dev_get_child_count(const struct udevice *dev) return ofnode_get_child_count(dev_ofnode(dev)); } +static inline int dev_decode_display_timing(const struct udevice *dev, + int index, + struct display_timing *config) +{ + return ofnode_decode_display_timing(dev_ofnode(dev), index, config); +} + #endif /* CONFIG_DM_DEV_READ_INLINE */ /** diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 31fb6663a2..b5ac9bba24 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -1152,3 +1152,83 @@ static int dm_test_ofdata_order(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_ofdata_order, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test dev_decode_display_timing() */ +static int dm_test_decode_display_timing(struct unit_test_state *uts) +{ + struct udevice *dev; + struct display_timing timing; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_assertok(dev_decode_display_timing(dev, 0, &timing)); + ut_assert(timing.hactive.typ == 240); + ut_assert(timing.hback_porch.typ == 7); + ut_assert(timing.hfront_porch.typ == 6); + ut_assert(timing.hsync_len.typ == 1); + ut_assert(timing.vactive.typ == 320); + ut_assert(timing.vback_porch.typ == 5); + ut_assert(timing.vfront_porch.typ == 8); + ut_assert(timing.vsync_len.typ == 2); + ut_assert(timing.pixelclock.typ == 6500000); + ut_assert(timing.flags & DISPLAY_FLAGS_HSYNC_HIGH); + ut_assert(!(timing.flags & DISPLAY_FLAGS_HSYNC_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_VSYNC_HIGH)); + ut_assert(timing.flags & DISPLAY_FLAGS_VSYNC_LOW); + ut_assert(timing.flags & DISPLAY_FLAGS_DE_HIGH); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DE_LOW)); + ut_assert(timing.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE); + ut_assert(!(timing.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)); + ut_assert(timing.flags & DISPLAY_FLAGS_INTERLACED); + ut_assert(timing.flags & DISPLAY_FLAGS_DOUBLESCAN); + ut_assert(timing.flags & DISPLAY_FLAGS_DOUBLECLK); + + ut_assertok(dev_decode_display_timing(dev, 1, &timing)); + ut_assert(timing.hactive.typ == 480); + ut_assert(timing.hback_porch.typ == 59); + ut_assert(timing.hfront_porch.typ == 10); + ut_assert(timing.hsync_len.typ == 12); + ut_assert(timing.vactive.typ == 800); + ut_assert(timing.vback_porch.typ == 15); + ut_assert(timing.vfront_porch.typ == 17); + ut_assert(timing.vsync_len.typ == 16); + ut_assert(timing.pixelclock.typ == 9000000); + ut_assert(!(timing.flags & DISPLAY_FLAGS_HSYNC_HIGH)); + ut_assert(timing.flags & DISPLAY_FLAGS_HSYNC_LOW); + ut_assert(timing.flags & DISPLAY_FLAGS_VSYNC_HIGH); + ut_assert(!(timing.flags & DISPLAY_FLAGS_VSYNC_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DE_HIGH)); + ut_assert(timing.flags & DISPLAY_FLAGS_DE_LOW); + ut_assert(!(timing.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)); + ut_assert(timing.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE); + ut_assert(!(timing.flags & DISPLAY_FLAGS_INTERLACED)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DOUBLESCAN)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DOUBLECLK)); + + ut_assertok(dev_decode_display_timing(dev, 2, &timing)); + ut_assert(timing.hactive.typ == 800); + ut_assert(timing.hback_porch.typ == 89); + ut_assert(timing.hfront_porch.typ == 164); + ut_assert(timing.hsync_len.typ == 11); + ut_assert(timing.vactive.typ == 480); + ut_assert(timing.vback_porch.typ == 23); + ut_assert(timing.vfront_porch.typ == 10); + ut_assert(timing.vsync_len.typ == 13); + ut_assert(timing.pixelclock.typ == 33500000); + ut_assert(!(timing.flags & DISPLAY_FLAGS_HSYNC_HIGH)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_HSYNC_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_VSYNC_HIGH)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_VSYNC_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DE_HIGH)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DE_LOW)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_INTERLACED)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DOUBLESCAN)); + ut_assert(!(timing.flags & DISPLAY_FLAGS_DOUBLECLK)); + + ut_assert(dev_decode_display_timing(dev, 3, &timing)); + return 0; +} +DM_TEST(dm_test_decode_display_timing, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); From ff94c15a3cf1ded3b851c65bb86168f6428e0d06 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:27 +0100 Subject: [PATCH 33/42] video: omap: add panel driver The previous version of am335x-fb.c contained the functionalities of two drivers that this patch has split. It was a video type driver that used the same registration compatible string that now registers a panel type driver. The proof of this is that two compatible strings were referred to within the same driver. There are now two drivers, each with its own compatible string, functions and API. Furthermore, the panel driver, in addition to decoding the display timings, is now also able to manage the backlight. Signed-off-by: Dario Binacchi Reviewed-by: Simon Glass --- arch/arm/dts/am335x-brppt1-mmc.dts | 17 +- arch/arm/dts/am335x-brppt1-nand.dts | 17 +- arch/arm/dts/am335x-brppt1-spi.dts | 17 +- arch/arm/dts/am335x-brsmarc1.dts | 20 +- arch/arm/dts/am335x-brxre1.dts | 21 +- arch/arm/dts/am335x-evm-u-boot.dtsi | 15 +- arch/arm/dts/am335x-evmsk-u-boot.dtsi | 14 +- arch/arm/dts/am335x-guardian-u-boot.dtsi | 18 +- arch/arm/dts/am335x-pdu001-u-boot.dtsi | 18 +- arch/arm/dts/am335x-pxm50-u-boot.dtsi | 14 +- arch/arm/dts/am335x-rut-u-boot.dtsi | 14 +- drivers/video/Makefile | 1 + drivers/video/am335x-fb.c | 257 ++++++++++------------- drivers/video/am335x-fb.h | 31 +++ drivers/video/tilcdc-panel.c | 172 +++++++++++++++ drivers/video/tilcdc-panel.h | 14 ++ 16 files changed, 465 insertions(+), 195 deletions(-) create mode 100644 drivers/video/tilcdc-panel.c create mode 100644 drivers/video/tilcdc-panel.h diff --git a/arch/arm/dts/am335x-brppt1-mmc.dts b/arch/arm/dts/am335x-brppt1-mmc.dts index 6f919711f0..bd2f6c2e3e 100644 --- a/arch/arm/dts/am335x-brppt1-mmc.dts +++ b/arch/arm/dts/am335x-brppt1-mmc.dts @@ -53,8 +53,6 @@ bkl-pwm = <&pwmbacklight>; bkl-tps = <&tps_bl>; - u-boot,dm-pre-reloc; - panel-info { ac-bias = <255>; ac-bias-intrpt = <0>; @@ -238,8 +236,19 @@ status = "okay"; }; -&lcdc { - status = "disabled"; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + status = "disabled"; + }; + }; + }; }; &elm { diff --git a/arch/arm/dts/am335x-brppt1-nand.dts b/arch/arm/dts/am335x-brppt1-nand.dts index 9d4340f591..67c609739f 100644 --- a/arch/arm/dts/am335x-brppt1-nand.dts +++ b/arch/arm/dts/am335x-brppt1-nand.dts @@ -53,8 +53,6 @@ bkl-pwm = <&pwmbacklight>; bkl-tps = <&tps_bl>; - u-boot,dm-pre-reloc; - panel-info { ac-bias = <255>; ac-bias-intrpt = <0>; @@ -228,8 +226,19 @@ status = "disabled"; }; -&lcdc { - status = "disabled"; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + status = "disabled"; + }; + }; + }; }; &elm { diff --git a/arch/arm/dts/am335x-brppt1-spi.dts b/arch/arm/dts/am335x-brppt1-spi.dts index c078af8fba..ce3dce204d 100644 --- a/arch/arm/dts/am335x-brppt1-spi.dts +++ b/arch/arm/dts/am335x-brppt1-spi.dts @@ -54,8 +54,6 @@ bkl-pwm = <&pwmbacklight>; bkl-tps = <&tps_bl>; - u-boot,dm-pre-reloc; - panel-info { ac-bias = <255>; ac-bias-intrpt = <0>; @@ -259,8 +257,19 @@ status = "okay"; }; -&lcdc { - status = "disabled"; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + status = "disabled"; + }; + }; + }; }; &elm { diff --git a/arch/arm/dts/am335x-brsmarc1.dts b/arch/arm/dts/am335x-brsmarc1.dts index 7e9516e8f8..25cdb11164 100644 --- a/arch/arm/dts/am335x-brsmarc1.dts +++ b/arch/arm/dts/am335x-brsmarc1.dts @@ -59,7 +59,6 @@ /*backlight = <&tps_bl>; */ compatible = "ti,tilcdc,panel"; status = "okay"; - u-boot,dm-pre-reloc; panel-info { ac-bias = <255>; @@ -298,10 +297,21 @@ status = "okay"; }; -&lcdc { - status = "okay"; - ti,no-reset-on-init; - ti,no-idle-on-init; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; + }; + }; + }; }; &elm { diff --git a/arch/arm/dts/am335x-brxre1.dts b/arch/arm/dts/am335x-brxre1.dts index 6091a12fb7..485c8e3613 100644 --- a/arch/arm/dts/am335x-brxre1.dts +++ b/arch/arm/dts/am335x-brxre1.dts @@ -79,8 +79,6 @@ backlight = <&tps_bl>; - u-boot,dm-pre-reloc; - panel-info { ac-bias = <255>; ac-bias-intrpt = <0>; @@ -254,10 +252,21 @@ status = "okay"; }; -&lcdc { - status = "okay"; - ti,no-reset-on-init; - ti,no-idle-on-init; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; + }; + }; + }; }; &elm { diff --git a/arch/arm/dts/am335x-evm-u-boot.dtsi b/arch/arm/dts/am335x-evm-u-boot.dtsi index 400a1d2cec..4cf5f9928d 100644 --- a/arch/arm/dts/am335x-evm-u-boot.dtsi +++ b/arch/arm/dts/am335x-evm-u-boot.dtsi @@ -5,13 +5,20 @@ #include "am33xx-u-boot.dtsi" -/ { - panel { - u-boot,dm-pre-reloc; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + }; + }; }; }; - &mmc3 { status = "disabled"; }; diff --git a/arch/arm/dts/am335x-evmsk-u-boot.dtsi b/arch/arm/dts/am335x-evmsk-u-boot.dtsi index 96798330b1..1003f4d31a 100644 --- a/arch/arm/dts/am335x-evmsk-u-boot.dtsi +++ b/arch/arm/dts/am335x-evmsk-u-boot.dtsi @@ -7,8 +7,16 @@ #include "am33xx-u-boot.dtsi" -/ { - panel { - u-boot,dm-pre-reloc; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + }; + }; }; }; diff --git a/arch/arm/dts/am335x-guardian-u-boot.dtsi b/arch/arm/dts/am335x-guardian-u-boot.dtsi index c866ce83f3..986f58e664 100644 --- a/arch/arm/dts/am335x-guardian-u-boot.dtsi +++ b/arch/arm/dts/am335x-guardian-u-boot.dtsi @@ -10,16 +10,26 @@ ocp { u-boot,dm-pre-reloc; }; - - panel { - u-boot,dm-pre-reloc; - }; }; &l4_wkup { u-boot,dm-pre-reloc; }; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + }; + }; + }; +}; + &mmc1 { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/dts/am335x-pdu001-u-boot.dtsi b/arch/arm/dts/am335x-pdu001-u-boot.dtsi index 4f4fc411f9..686a152fd9 100644 --- a/arch/arm/dts/am335x-pdu001-u-boot.dtsi +++ b/arch/arm/dts/am335x-pdu001-u-boot.dtsi @@ -9,16 +9,26 @@ ocp { u-boot,dm-pre-reloc; }; - - panel { - u-boot,dm-pre-reloc; - }; }; &l4_wkup { u-boot,dm-pre-reloc; }; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + }; + }; + }; +}; + &scm { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/dts/am335x-pxm50-u-boot.dtsi b/arch/arm/dts/am335x-pxm50-u-boot.dtsi index 65ed948c58..e5af9fdf89 100644 --- a/arch/arm/dts/am335x-pxm50-u-boot.dtsi +++ b/arch/arm/dts/am335x-pxm50-u-boot.dtsi @@ -7,8 +7,16 @@ #include "am33xx-u-boot.dtsi" -/ { - panel { - u-boot,dm-pre-reloc; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + }; + }; }; }; diff --git a/arch/arm/dts/am335x-rut-u-boot.dtsi b/arch/arm/dts/am335x-rut-u-boot.dtsi index b16f75a764..a38c2dc607 100644 --- a/arch/arm/dts/am335x-rut-u-boot.dtsi +++ b/arch/arm/dts/am335x-rut-u-boot.dtsi @@ -7,8 +7,16 @@ #include "am33xx-u-boot.dtsi" -/ { - panel { - u-boot,dm-pre-reloc; +&l4_per { + + segment@300000 { + + target-module@e000 { + u-boot,dm-pre-reloc; + + lcdc: lcdc@0 { + u-boot,dm-pre-reloc; + }; + }; }; }; diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9db96aa891..4629f28cbb 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o obj-$(CONFIG_DM_VIDEO) += video_bmp.o obj-$(CONFIG_PANEL) += panel-uclass.o obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o +obj-$(CONFIG_AM335X_LCD) += tilcdc-panel.o endif obj-${CONFIG_EXYNOS_FB} += exynos/ diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c index e99a9185a2..a3464ae6a0 100644 --- a/drivers/video/am335x-fb.c +++ b/drivers/video/am335x-fb.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include "am335x-fb.h" +#include "tilcdc-panel.h" #define LCDC_FMAX 200000000 @@ -323,7 +325,7 @@ int am335xfb_init(struct am335x_lcdpanel *panel) #else /* CONFIG_DM_VIDEO */ -#define FBSIZE(t, p) (((t)->hactive.typ * (t)->vactive.typ * (p)->bpp) >> 3) +#define FBSIZE(t, p) (((t).hactive.typ * (t).vactive.typ * (p).bpp) >> 3) enum { LCD_MAX_WIDTH = 2048, @@ -331,39 +333,8 @@ enum { LCD_MAX_LOG2_BPP = VIDEO_BPP32, }; -/** - * tilcdc_panel_info: Panel parameters - * - * @ac_bias: AC Bias Pin Frequency - * @ac_bias_intrpt: AC Bias Pin Transitions per Interrupt - * @dma_burst_sz: DMA burst size - * @bpp: Bits per pixel - * @fdd: FIFO DMA Request Delay - * @tft_alt_mode: TFT Alternative Signal Mapping (Only for active) - * @invert_pxl_clk: Invert pixel clock - * @sync_edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling - * @sync_ctrl: Horizontal and Vertical Sync: Control: 0=ignore - * @raster_order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most - * @fifo_th: DMA FIFO threshold - */ -struct tilcdc_panel_info { - u32 ac_bias; - u32 ac_bias_intrpt; - u32 dma_burst_sz; - u32 bpp; - u32 fdd; - bool tft_alt_mode; - bool invert_pxl_clk; - u32 sync_edge; - u32 sync_ctrl; - u32 raster_order; - u32 fifo_th; -}; - struct am335x_fb_priv { struct am335x_lcdhw *regs; - struct tilcdc_panel_info panel; - struct display_timing timing; }; static int am335x_fb_remove(struct udevice *dev) @@ -381,16 +352,71 @@ static int am335x_fb_probe(struct udevice *dev) struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct am335x_fb_priv *priv = dev_get_priv(dev); struct am335x_lcdhw *regs = priv->regs; - struct tilcdc_panel_info *panel = &priv->panel; - struct display_timing *timing = &priv->timing; + struct udevice *panel; + struct tilcdc_panel_info info; + struct display_timing timing; struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; u32 reg; + int err; /* Before relocation we don't need to do anything */ if (!(gd->flags & GD_FLG_RELOC)) return 0; - am335x_fb_set_pixel_clk_rate(regs, timing->pixelclock.typ); + err = uclass_get_device(UCLASS_PANEL, 0, &panel); + if (err) { + dev_err(dev, "failed to get panel\n"); + return err; + } + + err = panel_get_display_timing(panel, &timing); + if (err) { + dev_err(dev, "failed to get display timing\n"); + return err; + } + + if (timing.pixelclock.typ > (LCDC_FMAX / 2)) { + dev_err(dev, "invalid display clock-frequency: %d Hz\n", + timing.pixelclock.typ); + return -EINVAL; + } + + if (timing.hactive.typ > LCD_MAX_WIDTH) + timing.hactive.typ = LCD_MAX_WIDTH; + + if (timing.vactive.typ > LCD_MAX_HEIGHT) + timing.vactive.typ = LCD_MAX_HEIGHT; + + err = tilcdc_panel_get_display_info(panel, &info); + if (err) { + dev_err(dev, "failed to get panel info\n"); + return err; + } + + switch (info.bpp) { + case 16: + case 24: + case 32: + break; + default: + dev_err(dev, "invalid seting, bpp: %d\n", info.bpp); + return -EINVAL; + } + + switch (info.dma_burst_sz) { + case 1: + case 2: + case 4: + case 8: + case 16: + break; + default: + dev_err(dev, "invalid setting, dma-burst-sz: %d\n", + info.dma_burst_sz); + return -EINVAL; + } + + am335x_fb_set_pixel_clk_rate(regs, timing.pixelclock.typ); /* clock source for LCDC from dispPLL M2 */ writel(0, &cmdpll->clklcdcpixelclk); @@ -411,14 +437,14 @@ static int am335x_fb_probe(struct udevice *dev) writel(reg, ®s->ctrl); writel(uc_plat->base, ®s->lcddma_fb0_base); - writel(uc_plat->base + FBSIZE(timing, panel), + writel(uc_plat->base + FBSIZE(timing, info), ®s->lcddma_fb0_ceiling); writel(uc_plat->base, ®s->lcddma_fb1_base); - writel(uc_plat->base + FBSIZE(timing, panel), + writel(uc_plat->base + FBSIZE(timing, info), ®s->lcddma_fb1_ceiling); - reg = LCDC_DMA_CTRL_FIFO_TH(panel->fifo_th); - switch (panel->dma_burst_sz) { + reg = LCDC_DMA_CTRL_FIFO_TH(info.fifo_th); + switch (info.dma_burst_sz) { case 1: reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_1); break; @@ -438,155 +464,84 @@ static int am335x_fb_probe(struct udevice *dev) writel(reg, ®s->lcddma_ctrl); - writel(LCDC_RASTER_TIMING_0_HORLSB(timing->hactive.typ) | - LCDC_RASTER_TIMING_0_HORMSB(timing->hactive.typ) | - LCDC_RASTER_TIMING_0_HFPLSB(timing->hfront_porch.typ) | - LCDC_RASTER_TIMING_0_HBPLSB(timing->hback_porch.typ) | - LCDC_RASTER_TIMING_0_HSWLSB(timing->hsync_len.typ), + writel(LCDC_RASTER_TIMING_0_HORLSB(timing.hactive.typ) | + LCDC_RASTER_TIMING_0_HORMSB(timing.hactive.typ) | + LCDC_RASTER_TIMING_0_HFPLSB(timing.hfront_porch.typ) | + LCDC_RASTER_TIMING_0_HBPLSB(timing.hback_porch.typ) | + LCDC_RASTER_TIMING_0_HSWLSB(timing.hsync_len.typ), ®s->raster_timing0); - writel(LCDC_RASTER_TIMING_1_VBP(timing->vback_porch.typ) | - LCDC_RASTER_TIMING_1_VFP(timing->vfront_porch.typ) | - LCDC_RASTER_TIMING_1_VSW(timing->vsync_len.typ) | - LCDC_RASTER_TIMING_1_VERLSB(timing->vactive.typ), + writel(LCDC_RASTER_TIMING_1_VBP(timing.vback_porch.typ) | + LCDC_RASTER_TIMING_1_VFP(timing.vfront_porch.typ) | + LCDC_RASTER_TIMING_1_VSW(timing.vsync_len.typ) | + LCDC_RASTER_TIMING_1_VERLSB(timing.vactive.typ), ®s->raster_timing1); - reg = LCDC_RASTER_TIMING_2_ACB(panel->ac_bias) | - LCDC_RASTER_TIMING_2_ACBI(panel->ac_bias_intrpt) | - LCDC_RASTER_TIMING_2_HSWMSB(timing->hsync_len.typ) | - LCDC_RASTER_TIMING_2_VERMSB(timing->vactive.typ) | - LCDC_RASTER_TIMING_2_HBPMSB(timing->hback_porch.typ) | - LCDC_RASTER_TIMING_2_HFPMSB(timing->hfront_porch.typ); + reg = LCDC_RASTER_TIMING_2_ACB(info.ac_bias) | + LCDC_RASTER_TIMING_2_ACBI(info.ac_bias_intrpt) | + LCDC_RASTER_TIMING_2_HSWMSB(timing.hsync_len.typ) | + LCDC_RASTER_TIMING_2_VERMSB(timing.vactive.typ) | + LCDC_RASTER_TIMING_2_HBPMSB(timing.hback_porch.typ) | + LCDC_RASTER_TIMING_2_HFPMSB(timing.hfront_porch.typ); - if (timing->flags & DISPLAY_FLAGS_VSYNC_LOW) + if (timing.flags & DISPLAY_FLAGS_VSYNC_LOW) reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT; - if (timing->flags & DISPLAY_FLAGS_HSYNC_LOW) + if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW) reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT; - if (panel->invert_pxl_clk) + if (info.invert_pxl_clk) reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT; - if (panel->sync_edge) + if (info.sync_edge) reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL; - if (panel->sync_ctrl) + if (info.sync_ctrl) reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL; writel(reg, ®s->raster_timing2); reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE | - LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(panel->fdd); + LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(info.fdd); - if (panel->tft_alt_mode) + if (info.tft_alt_mode) reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE; - if (panel->bpp == 24) + if (info.bpp == 24) reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE; - else if (panel->bpp == 32) + else if (info.bpp == 32) reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE | LCDC_RASTER_CTRL_TFT_24BPP_UNPACK; - if (panel->raster_order) + if (info.raster_order) reg |= LCDC_RASTER_CTRL_DATA_ORDER; writel(reg, ®s->raster_ctrl); - uc_priv->xsize = timing->hactive.typ; - uc_priv->ysize = timing->vactive.typ; - uc_priv->bpix = log_2_n_round_up(panel->bpp); + uc_priv->xsize = timing.hactive.typ; + uc_priv->ysize = timing.vactive.typ; + uc_priv->bpix = log_2_n_round_up(info.bpp); + + err = panel_enable_backlight(panel); + if (err) { + dev_err(dev, "failed to enable panel backlight\n"); + return err; + } + return 0; } -static int am335x_fb_of_to_plat(struct udevice *dev) +static int am335x_fb_ofdata_to_platdata(struct udevice *dev) { struct am335x_fb_priv *priv = dev_get_priv(dev); - struct tilcdc_panel_info *panel = &priv->panel; - struct display_timing *timing = &priv->timing; - ofnode node; - int err; - node = ofnode_by_compatible(ofnode_null(), "ti,am33xx-tilcdc"); - if (!ofnode_valid(node)) { - dev_err(dev, "missing 'ti,am33xx-tilcdc' node\n"); - return -ENXIO; + priv->regs = (struct am335x_lcdhw *)dev_read_addr(dev); + if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get base address\n"); + return -EINVAL; } - priv->regs = (struct am335x_lcdhw *)ofnode_get_addr(node); dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs); - - err = ofnode_decode_display_timing(dev_ofnode(dev), 0, timing); - if (err) { - dev_err(dev, "failed to get display timing\n"); - return err; - } - - if (timing->pixelclock.typ > (LCDC_FMAX / 2)) { - dev_err(dev, "invalid display clock-frequency: %d Hz\n", - timing->pixelclock.typ); - return -EINVAL; - } - - if (timing->hactive.typ > LCD_MAX_WIDTH) - timing->hactive.typ = LCD_MAX_WIDTH; - - if (timing->vactive.typ > LCD_MAX_HEIGHT) - timing->vactive.typ = LCD_MAX_HEIGHT; - - node = ofnode_find_subnode(dev_ofnode(dev), "panel-info"); - if (!ofnode_valid(node)) { - dev_err(dev, "missing 'panel-info' node\n"); - return -ENXIO; - } - - err |= ofnode_read_u32(node, "ac-bias", &panel->ac_bias); - err |= ofnode_read_u32(node, "ac-bias-intrpt", &panel->ac_bias_intrpt); - err |= ofnode_read_u32(node, "dma-burst-sz", &panel->dma_burst_sz); - err |= ofnode_read_u32(node, "bpp", &panel->bpp); - err |= ofnode_read_u32(node, "fdd", &panel->fdd); - err |= ofnode_read_u32(node, "sync-edge", &panel->sync_edge); - err |= ofnode_read_u32(node, "sync-ctrl", &panel->sync_ctrl); - err |= ofnode_read_u32(node, "raster-order", &panel->raster_order); - err |= ofnode_read_u32(node, "fifo-th", &panel->fifo_th); - if (err) { - dev_err(dev, "failed to get panel info\n"); - return err; - } - - switch (panel->bpp) { - case 16: - case 24: - case 32: - break; - default: - dev_err(dev, "invalid seting, bpp: %d\n", panel->bpp); - return -EINVAL; - } - - switch (panel->dma_burst_sz) { - case 1: - case 2: - case 4: - case 8: - case 16: - break; - default: - dev_err(dev, "invalid setting, dma-burst-sz: %d\n", - panel->dma_burst_sz); - return -EINVAL; - } - - /* optional */ - panel->tft_alt_mode = ofnode_read_bool(node, "tft-alt-mode"); - panel->invert_pxl_clk = ofnode_read_bool(node, "invert-pxl-clk"); - - dev_dbg(dev, "LCD: %dx%d, bpp=%d, clk=%d Hz\n", timing->hactive.typ, - timing->vactive.typ, panel->bpp, timing->pixelclock.typ); - dev_dbg(dev, " hbp=%d, hfp=%d, hsw=%d\n", timing->hback_porch.typ, - timing->hfront_porch.typ, timing->hsync_len.typ); - dev_dbg(dev, " vbp=%d, vfp=%d, vsw=%d\n", timing->vback_porch.typ, - timing->vfront_porch.typ, timing->vsync_len.typ); - return 0; } @@ -602,7 +557,7 @@ static int am335x_fb_bind(struct udevice *dev) } static const struct udevice_id am335x_fb_ids[] = { - { .compatible = "ti,tilcdc,panel" }, + { .compatible = "ti,am33xx-tilcdc" }, { } }; diff --git a/drivers/video/am335x-fb.h b/drivers/video/am335x-fb.h index c9f92bc389..4952dd96e9 100644 --- a/drivers/video/am335x-fb.h +++ b/drivers/video/am335x-fb.h @@ -70,6 +70,37 @@ struct am335x_lcdpanel { int am335xfb_init(struct am335x_lcdpanel *panel); +#else /* CONFIG_DM_VIDEO */ + +/** + * tilcdc_panel_info: Panel parameters + * + * @ac_bias: AC Bias Pin Frequency + * @ac_bias_intrpt: AC Bias Pin Transitions per Interrupt + * @dma_burst_sz: DMA burst size + * @bpp: Bits per pixel + * @fdd: FIFO DMA Request Delay + * @tft_alt_mode: TFT Alternative Signal Mapping (Only for active) + * @invert_pxl_clk: Invert pixel clock + * @sync_edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling + * @sync_ctrl: Horizontal and Vertical Sync: Control: 0=ignore + * @raster_order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most + * @fifo_th: DMA FIFO threshold + */ +struct tilcdc_panel_info { + u32 ac_bias; + u32 ac_bias_intrpt; + u32 dma_burst_sz; + u32 bpp; + u32 fdd; + bool tft_alt_mode; + bool invert_pxl_clk; + u32 sync_edge; + u32 sync_ctrl; + u32 raster_order; + u32 fifo_th; +}; + #endif /* CONFIG_DM_VIDEO */ #endif /* AM335X_FB_H */ diff --git a/drivers/video/tilcdc-panel.c b/drivers/video/tilcdc-panel.c new file mode 100644 index 0000000000..84303a6b71 --- /dev/null +++ b/drivers/video/tilcdc-panel.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * OMAP panel support + * + * Copyright (C) 2020 Dario Binacchi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "am335x-fb.h" + +struct tilcdc_panel_priv { + struct tilcdc_panel_info info; + struct display_timing timing; + struct udevice *backlight; + struct gpio_desc enable; +}; + +static int tilcdc_panel_enable_backlight(struct udevice *dev) +{ + struct tilcdc_panel_priv *priv = dev_get_priv(dev); + + if (dm_gpio_is_valid(&priv->enable)) + dm_gpio_set_value(&priv->enable, 1); + + if (priv->backlight) + return backlight_enable(priv->backlight); + + return 0; +} + +static int tilcdc_panel_set_backlight(struct udevice *dev, int percent) +{ + struct tilcdc_panel_priv *priv = dev_get_priv(dev); + + if (dm_gpio_is_valid(&priv->enable)) + dm_gpio_set_value(&priv->enable, 1); + + if (priv->backlight) + return backlight_set_brightness(priv->backlight, percent); + + return 0; +} + +int tilcdc_panel_get_display_info(struct udevice *dev, + struct tilcdc_panel_info *info) +{ + struct tilcdc_panel_priv *priv = dev_get_priv(dev); + + memcpy(info, &priv->info, sizeof(*info)); + return 0; +} + +static int tilcdc_panel_get_display_timing(struct udevice *dev, + struct display_timing *timing) +{ + struct tilcdc_panel_priv *priv = dev_get_priv(dev); + + memcpy(timing, &priv->timing, sizeof(*timing)); + return 0; +} + +static int tilcdc_panel_remove(struct udevice *dev) +{ + struct tilcdc_panel_priv *priv = dev_get_priv(dev); + + if (dm_gpio_is_valid(&priv->enable)) + dm_gpio_free(dev, &priv->enable); + + return 0; +} + +static int tilcdc_panel_probe(struct udevice *dev) +{ + struct tilcdc_panel_priv *priv = dev_get_priv(dev); + int err; + + err = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", &priv->backlight); + if (err) + dev_warn(dev, "failed to get backlight\n"); + + err = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable, + GPIOD_IS_OUT); + if (err) { + dev_warn(dev, "failed to get enable GPIO\n"); + if (err != -ENOENT) + return err; + } + + return 0; +} + +static int tilcdc_panel_of_to_plat(struct udevice *dev) +{ + struct tilcdc_panel_priv *priv = dev_get_priv(dev); + ofnode node; + int err; + + err = ofnode_decode_display_timing(dev_ofnode(dev), 0, &priv->timing); + if (err) { + dev_err(dev, "failed to get display timing\n"); + return err; + } + + node = dev_read_subnode(dev, "panel-info"); + if (!ofnode_valid(node)) { + dev_err(dev, "missing 'panel-info' node\n"); + return -ENXIO; + } + + err |= ofnode_read_u32(node, "ac-bias", &priv->info.ac_bias); + err |= ofnode_read_u32(node, "ac-bias-intrpt", + &priv->info.ac_bias_intrpt); + err |= ofnode_read_u32(node, "dma-burst-sz", &priv->info.dma_burst_sz); + err |= ofnode_read_u32(node, "bpp", &priv->info.bpp); + err |= ofnode_read_u32(node, "fdd", &priv->info.fdd); + err |= ofnode_read_u32(node, "sync-edge", &priv->info.sync_edge); + err |= ofnode_read_u32(node, "sync-ctrl", &priv->info.sync_ctrl); + err |= ofnode_read_u32(node, "raster-order", &priv->info.raster_order); + err |= ofnode_read_u32(node, "fifo-th", &priv->info.fifo_th); + if (err) { + dev_err(dev, "failed to get panel info\n"); + return err; + } + + /* optional */ + priv->info.tft_alt_mode = ofnode_read_bool(node, "tft-alt-mode"); + priv->info.invert_pxl_clk = ofnode_read_bool(node, "invert-pxl-clk"); + + dev_dbg(dev, "LCD: %dx%d, bpp=%d, clk=%d Hz\n", + priv->timing.hactive.typ, priv->timing.vactive.typ, + priv->info.bpp, priv->timing.pixelclock.typ); + dev_dbg(dev, " hbp=%d, hfp=%d, hsw=%d\n", + priv->timing.hback_porch.typ, priv->timing.hfront_porch.typ, + priv->timing.hsync_len.typ); + dev_dbg(dev, " vbp=%d, vfp=%d, vsw=%d\n", + priv->timing.vback_porch.typ, priv->timing.vfront_porch.typ, + priv->timing.vsync_len.typ); + + return 0; +} + +static const struct panel_ops tilcdc_panel_ops = { + .enable_backlight = tilcdc_panel_enable_backlight, + .set_backlight = tilcdc_panel_set_backlight, + .get_display_timing = tilcdc_panel_get_display_timing, +}; + +static const struct udevice_id tilcdc_panel_ids[] = { + {.compatible = "ti,tilcdc,panel"}, + {} +}; + +U_BOOT_DRIVER(tilcdc_panel) = { + .name = "tilcdc_panel", + .id = UCLASS_PANEL, + .of_match = tilcdc_panel_ids, + .ops = &tilcdc_panel_ops, + .ofdata_to_platdata = tilcdc_panel_of_to_plat, + .probe = tilcdc_panel_probe, + .remove = tilcdc_panel_remove, + .priv_auto = sizeof(struct tilcdc_panel_priv), +}; diff --git a/drivers/video/tilcdc-panel.h b/drivers/video/tilcdc-panel.h new file mode 100644 index 0000000000..6b40731304 --- /dev/null +++ b/drivers/video/tilcdc-panel.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Dario Binacchi + */ + +#ifndef _TILCDC_PANEL_H +#define _TILCDC_PANEL_H + +#include "am335x-fb.h" + +int tilcdc_panel_get_display_info(struct udevice *dev, + struct tilcdc_panel_info *info); + +#endif /* _TILCDC_PANEL_H */ From e58e5067fb318958791aed5baf2d21e3d78653d7 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:28 +0100 Subject: [PATCH 34/42] video: omap: drop domain clock enabling by SOC api Enabling the domain clock is performed by the sysc interconnect target module driver during the video device probing. Signed-off-by: Dario Binacchi --- arch/arm/mach-omap2/am33xx/clock_am33xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/am33xx/clock_am33xx.c b/arch/arm/mach-omap2/am33xx/clock_am33xx.c index 2427933c8b..cf71192360 100644 --- a/arch/arm/mach-omap2/am33xx/clock_am33xx.c +++ b/arch/arm/mach-omap2/am33xx/clock_am33xx.c @@ -226,7 +226,7 @@ void enable_basic_clocks(void) &cmper->usb0clkctrl, &cmper->emiffwclkctrl, &cmper->emifclkctrl, -#if CONFIG_IS_ENABLED(AM335X_LCD) +#if CONFIG_IS_ENABLED(AM335X_LCD) && !CONFIG_IS_ENABLED(DM_VIDEO) &cmper->lcdclkctrl, &cmper->lcdcclkstctrl, #endif From 91337f59dd6f5ca4baf1cdc86156fff65f7efb38 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:29 +0100 Subject: [PATCH 35/42] video: omap: set LCD clock rate through DM API The patch configures the display DPLL using the functions provided by the driver model API for the clock. The device tree contains everything needed to get the DPLL clock. The round rate function developed for calculating the DPLL multiplier and divisor and the platform routines for accessing the DPLL registers are removed from the LCD driver code because they are implemented inside the DPLL clock driver. Signed-off-by: Dario Binacchi --- drivers/video/am335x-fb.c | 129 ++++++++++++++++++++++++++++++-------- 1 file changed, 103 insertions(+), 26 deletions(-) diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c index a3464ae6a0..a31f403a84 100644 --- a/drivers/video/am335x-fb.c +++ b/drivers/video/am335x-fb.c @@ -12,6 +12,7 @@ * - starts output DMA from gd->fb_base buffer */ #include +#include #include #include #include @@ -112,6 +113,27 @@ struct am335x_lcdhw { unsigned int clkc_reset; /* 0x70 */ }; +DECLARE_GLOBAL_DATA_PTR; + +#if !CONFIG_IS_ENABLED(DM_VIDEO) + +#if !defined(LCD_CNTL_BASE) +#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!" +#endif + +/* Macro definitions */ +#define FBSIZE(x) (((x)->hactive * (x)->vactive * (x)->bpp) >> 3) + +#define LCDC_RASTER_TIMING_2_INVMASK(x) ((x) & GENMASK(25, 20)) + +static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE; + +int lcd_get_size(int *line_length) +{ + *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; + return *line_length * panel_info.vl_row + 0x20; +} + struct dpll_data { unsigned long rounded_rate; u16 rounded_m; @@ -119,8 +141,6 @@ struct dpll_data { u8 rounded_div; }; -DECLARE_GLOBAL_DATA_PTR; - /** * am335x_dpll_round_rate() - Round a target rate for an OMAP DPLL * @@ -199,25 +219,6 @@ static ulong am335x_fb_set_pixel_clk_rate(struct am335x_lcdhw *regs, ulong rate) return round_rate; } -#if !CONFIG_IS_ENABLED(DM_VIDEO) - -#if !defined(LCD_CNTL_BASE) -#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!" -#endif - -/* Macro definitions */ -#define FBSIZE(x) (((x)->hactive * (x)->vactive * (x)->bpp) >> 3) - -#define LCDC_RASTER_TIMING_2_INVMASK(x) ((x) & GENMASK(25, 20)) - -static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE; - -int lcd_get_size(int *line_length) -{ - *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; - return *line_length * panel_info.vl_row + 0x20; -} - int am335xfb_init(struct am335x_lcdpanel *panel) { u32 raster_ctrl = 0; @@ -335,14 +336,58 @@ enum { struct am335x_fb_priv { struct am335x_lcdhw *regs; + struct clk gclk; + struct clk dpll_m2_clk; }; +static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate) +{ + struct am335x_fb_priv *priv = dev_get_priv(dev); + struct am335x_lcdhw *regs = priv->regs; + ulong mult_rate, mult_round_rate, best_err, err; + u32 v; + int div, i; + + best_err = rate; + div = 0; + for (i = 2; i <= 255; i++) { + mult_rate = rate * i; + mult_round_rate = clk_round_rate(&priv->gclk, mult_rate); + if (IS_ERR_VALUE(mult_round_rate)) + return mult_round_rate; + + err = mult_rate - mult_round_rate; + if (err < best_err) { + best_err = err; + div = i; + if (err == 0) + break; + } + } + + if (div == 0) { + dev_err(dev, "failed to find a divisor\n"); + return -EFAULT; + } + + mult_rate = clk_set_rate(&priv->gclk, rate * div); + v = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK; + v |= LCDC_CTRL_CLK_DIVISOR(div); + writel(v, ®s->ctrl); + rate = mult_rate / div; + dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err); + return rate; +} + static int am335x_fb_remove(struct udevice *dev) { struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); + struct am335x_fb_priv *priv = dev_get_priv(dev); uc_plat->base -= 0x20; uc_plat->size += 0x20; + clk_release_all(&priv->gclk, 1); + clk_release_all(&priv->dpll_m2_clk, 1); return 0; } @@ -352,10 +397,10 @@ static int am335x_fb_probe(struct udevice *dev) struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct am335x_fb_priv *priv = dev_get_priv(dev); struct am335x_lcdhw *regs = priv->regs; - struct udevice *panel; + struct udevice *panel, *clk_dev; struct tilcdc_panel_info info; struct display_timing timing; - struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; + ulong rate; u32 reg; int err; @@ -416,10 +461,42 @@ static int am335x_fb_probe(struct udevice *dev) return -EINVAL; } - am335x_fb_set_pixel_clk_rate(regs, timing.pixelclock.typ); + err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev); + if (err) { + dev_err(dev, "failed to get lcd_gclk device\n"); + return err; + } - /* clock source for LCDC from dispPLL M2 */ - writel(0, &cmdpll->clklcdcpixelclk); + err = clk_request(clk_dev, &priv->gclk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ); + if (IS_ERR_VALUE(rate)) { + dev_err(dev, "failed to set pixel clock rate\n"); + return rate; + } + + err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4", &clk_dev); + if (err) { + dev_err(dev, "failed to get dpll_disp_m2 clock device\n"); + return err; + } + + err = clk_request(clk_dev, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to set %s clock as %s's parent\n", + priv->dpll_m2_clk.dev->name, priv->gclk.dev->name); + return err; + } /* palette default entry */ memset((void *)uc_plat->base, 0, 0x20); From 35ab1b6ef7f3a804babbb77d28041967539cd5e6 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:30 +0100 Subject: [PATCH 36/42] video: omap: split the legacy code from the DM code The schedule for deprecating the features of the pre-driver-model puts 2019.17 as the deadline for the video subsystem. Furthermore, the latest patches applied to the am335x-fb.c module have decreased the amount of code shared with the pre-driver-model implementation. Splitting the two implementations into two modules improves the readability of the code and will make it easier to drop the pre-driver-model code. I have not created a header file with the data structures and the constants for accessing the LCD controller registers, but I preferred to keep them inside the two c modules. This is a code replication until the pre-driver-model version is dropped. Signed-off-by: Dario Binacchi --- drivers/video/Makefile | 5 +- drivers/video/am335x-fb.c | 335 --------------------------- drivers/video/am335x-fb.h | 35 --- drivers/video/tilcdc-panel.c | 2 +- drivers/video/tilcdc-panel.h | 2 +- drivers/video/tilcdc.c | 425 +++++++++++++++++++++++++++++++++++ drivers/video/tilcdc.h | 38 ++++ 7 files changed, 468 insertions(+), 374 deletions(-) create mode 100644 drivers/video/tilcdc.c create mode 100644 drivers/video/tilcdc.h diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 4629f28cbb..5f0f7b440c 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,7 +16,9 @@ obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o obj-$(CONFIG_DM_VIDEO) += video_bmp.o obj-$(CONFIG_PANEL) += panel-uclass.o obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o -obj-$(CONFIG_AM335X_LCD) += tilcdc-panel.o +obj-$(CONFIG_AM335X_LCD) += tilcdc.o tilcdc-panel.o +else +obj-$(CONFIG_AM335X_LCD) += am335x-fb.o endif obj-${CONFIG_EXYNOS_FB} += exynos/ @@ -24,7 +26,6 @@ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-${CONFIG_VIDEO_STM32} += stm32/ obj-${CONFIG_VIDEO_TEGRA124} += tegra124/ -obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o obj-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c index a31f403a84..5fa6f794ec 100644 --- a/drivers/video/am335x-fb.c +++ b/drivers/video/am335x-fb.c @@ -12,22 +12,16 @@ * - starts output DMA from gd->fb_base buffer */ #include -#include -#include #include #include -#include -#include #include #include #include #include #include -#include #include #include #include "am335x-fb.h" -#include "tilcdc-panel.h" #define LCDC_FMAX 200000000 @@ -115,8 +109,6 @@ struct am335x_lcdhw { DECLARE_GLOBAL_DATA_PTR; -#if !CONFIG_IS_ENABLED(DM_VIDEO) - #if !defined(LCD_CNTL_BASE) #error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!" #endif @@ -323,330 +315,3 @@ int am335xfb_init(struct am335x_lcdpanel *panel) return 0; } - -#else /* CONFIG_DM_VIDEO */ - -#define FBSIZE(t, p) (((t).hactive.typ * (t).vactive.typ * (p).bpp) >> 3) - -enum { - LCD_MAX_WIDTH = 2048, - LCD_MAX_HEIGHT = 2048, - LCD_MAX_LOG2_BPP = VIDEO_BPP32, -}; - -struct am335x_fb_priv { - struct am335x_lcdhw *regs; - struct clk gclk; - struct clk dpll_m2_clk; -}; - -static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate) -{ - struct am335x_fb_priv *priv = dev_get_priv(dev); - struct am335x_lcdhw *regs = priv->regs; - ulong mult_rate, mult_round_rate, best_err, err; - u32 v; - int div, i; - - best_err = rate; - div = 0; - for (i = 2; i <= 255; i++) { - mult_rate = rate * i; - mult_round_rate = clk_round_rate(&priv->gclk, mult_rate); - if (IS_ERR_VALUE(mult_round_rate)) - return mult_round_rate; - - err = mult_rate - mult_round_rate; - if (err < best_err) { - best_err = err; - div = i; - if (err == 0) - break; - } - } - - if (div == 0) { - dev_err(dev, "failed to find a divisor\n"); - return -EFAULT; - } - - mult_rate = clk_set_rate(&priv->gclk, rate * div); - v = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK; - v |= LCDC_CTRL_CLK_DIVISOR(div); - writel(v, ®s->ctrl); - rate = mult_rate / div; - dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err); - return rate; -} - -static int am335x_fb_remove(struct udevice *dev) -{ - struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); - struct am335x_fb_priv *priv = dev_get_priv(dev); - - uc_plat->base -= 0x20; - uc_plat->size += 0x20; - clk_release_all(&priv->gclk, 1); - clk_release_all(&priv->dpll_m2_clk, 1); - return 0; -} - -static int am335x_fb_probe(struct udevice *dev) -{ - struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); - struct video_priv *uc_priv = dev_get_uclass_priv(dev); - struct am335x_fb_priv *priv = dev_get_priv(dev); - struct am335x_lcdhw *regs = priv->regs; - struct udevice *panel, *clk_dev; - struct tilcdc_panel_info info; - struct display_timing timing; - ulong rate; - u32 reg; - int err; - - /* Before relocation we don't need to do anything */ - if (!(gd->flags & GD_FLG_RELOC)) - return 0; - - err = uclass_get_device(UCLASS_PANEL, 0, &panel); - if (err) { - dev_err(dev, "failed to get panel\n"); - return err; - } - - err = panel_get_display_timing(panel, &timing); - if (err) { - dev_err(dev, "failed to get display timing\n"); - return err; - } - - if (timing.pixelclock.typ > (LCDC_FMAX / 2)) { - dev_err(dev, "invalid display clock-frequency: %d Hz\n", - timing.pixelclock.typ); - return -EINVAL; - } - - if (timing.hactive.typ > LCD_MAX_WIDTH) - timing.hactive.typ = LCD_MAX_WIDTH; - - if (timing.vactive.typ > LCD_MAX_HEIGHT) - timing.vactive.typ = LCD_MAX_HEIGHT; - - err = tilcdc_panel_get_display_info(panel, &info); - if (err) { - dev_err(dev, "failed to get panel info\n"); - return err; - } - - switch (info.bpp) { - case 16: - case 24: - case 32: - break; - default: - dev_err(dev, "invalid seting, bpp: %d\n", info.bpp); - return -EINVAL; - } - - switch (info.dma_burst_sz) { - case 1: - case 2: - case 4: - case 8: - case 16: - break; - default: - dev_err(dev, "invalid setting, dma-burst-sz: %d\n", - info.dma_burst_sz); - return -EINVAL; - } - - err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev); - if (err) { - dev_err(dev, "failed to get lcd_gclk device\n"); - return err; - } - - err = clk_request(clk_dev, &priv->gclk); - if (err) { - dev_err(dev, "failed to get %s clock\n", clk_dev->name); - return err; - } - - rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ); - if (IS_ERR_VALUE(rate)) { - dev_err(dev, "failed to set pixel clock rate\n"); - return rate; - } - - err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4", &clk_dev); - if (err) { - dev_err(dev, "failed to get dpll_disp_m2 clock device\n"); - return err; - } - - err = clk_request(clk_dev, &priv->dpll_m2_clk); - if (err) { - dev_err(dev, "failed to get %s clock\n", clk_dev->name); - return err; - } - - err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk); - if (err) { - dev_err(dev, "failed to set %s clock as %s's parent\n", - priv->dpll_m2_clk.dev->name, priv->gclk.dev->name); - return err; - } - - /* palette default entry */ - memset((void *)uc_plat->base, 0, 0x20); - *(unsigned int *)uc_plat->base = 0x4000; - /* point fb behind palette */ - uc_plat->base += 0x20; - uc_plat->size -= 0x20; - - writel(LCDC_CLKC_ENABLE_CORECLKEN | LCDC_CLKC_ENABLE_LIDDCLKEN | - LCDC_CLKC_ENABLE_DMACLKEN, ®s->clkc_enable); - writel(0, ®s->raster_ctrl); - - reg = readl(®s->ctrl) & LCDC_CTRL_CLK_DIVISOR_MASK; - reg |= LCDC_CTRL_RASTER_MODE; - writel(reg, ®s->ctrl); - - writel(uc_plat->base, ®s->lcddma_fb0_base); - writel(uc_plat->base + FBSIZE(timing, info), - ®s->lcddma_fb0_ceiling); - writel(uc_plat->base, ®s->lcddma_fb1_base); - writel(uc_plat->base + FBSIZE(timing, info), - ®s->lcddma_fb1_ceiling); - - reg = LCDC_DMA_CTRL_FIFO_TH(info.fifo_th); - switch (info.dma_burst_sz) { - case 1: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_1); - break; - case 2: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_2); - break; - case 4: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_4); - break; - case 8: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_8); - break; - case 16: - reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16); - break; - } - - writel(reg, ®s->lcddma_ctrl); - - writel(LCDC_RASTER_TIMING_0_HORLSB(timing.hactive.typ) | - LCDC_RASTER_TIMING_0_HORMSB(timing.hactive.typ) | - LCDC_RASTER_TIMING_0_HFPLSB(timing.hfront_porch.typ) | - LCDC_RASTER_TIMING_0_HBPLSB(timing.hback_porch.typ) | - LCDC_RASTER_TIMING_0_HSWLSB(timing.hsync_len.typ), - ®s->raster_timing0); - - writel(LCDC_RASTER_TIMING_1_VBP(timing.vback_porch.typ) | - LCDC_RASTER_TIMING_1_VFP(timing.vfront_porch.typ) | - LCDC_RASTER_TIMING_1_VSW(timing.vsync_len.typ) | - LCDC_RASTER_TIMING_1_VERLSB(timing.vactive.typ), - ®s->raster_timing1); - - reg = LCDC_RASTER_TIMING_2_ACB(info.ac_bias) | - LCDC_RASTER_TIMING_2_ACBI(info.ac_bias_intrpt) | - LCDC_RASTER_TIMING_2_HSWMSB(timing.hsync_len.typ) | - LCDC_RASTER_TIMING_2_VERMSB(timing.vactive.typ) | - LCDC_RASTER_TIMING_2_HBPMSB(timing.hback_porch.typ) | - LCDC_RASTER_TIMING_2_HFPMSB(timing.hfront_porch.typ); - - if (timing.flags & DISPLAY_FLAGS_VSYNC_LOW) - reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT; - - if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW) - reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT; - - if (info.invert_pxl_clk) - reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT; - - if (info.sync_edge) - reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL; - - if (info.sync_ctrl) - reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL; - - writel(reg, ®s->raster_timing2); - - reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE | - LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(info.fdd); - - if (info.tft_alt_mode) - reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE; - - if (info.bpp == 24) - reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE; - else if (info.bpp == 32) - reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE | - LCDC_RASTER_CTRL_TFT_24BPP_UNPACK; - - if (info.raster_order) - reg |= LCDC_RASTER_CTRL_DATA_ORDER; - - writel(reg, ®s->raster_ctrl); - - uc_priv->xsize = timing.hactive.typ; - uc_priv->ysize = timing.vactive.typ; - uc_priv->bpix = log_2_n_round_up(info.bpp); - - err = panel_enable_backlight(panel); - if (err) { - dev_err(dev, "failed to enable panel backlight\n"); - return err; - } - - return 0; -} - -static int am335x_fb_ofdata_to_platdata(struct udevice *dev) -{ - struct am335x_fb_priv *priv = dev_get_priv(dev); - - priv->regs = (struct am335x_lcdhw *)dev_read_addr(dev); - if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) { - dev_err(dev, "failed to get base address\n"); - return -EINVAL; - } - - dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs); - return 0; -} - -static int am335x_fb_bind(struct udevice *dev) -{ - struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); - - uc_plat->size = ((LCD_MAX_WIDTH * LCD_MAX_HEIGHT * - (1 << LCD_MAX_LOG2_BPP)) >> 3) + 0x20; - - dev_dbg(dev, "frame buffer size 0x%x\n", uc_plat->size); - return 0; -} - -static const struct udevice_id am335x_fb_ids[] = { - { .compatible = "ti,am33xx-tilcdc" }, - { } -}; - -U_BOOT_DRIVER(am335x_fb) = { - .name = "am335x_fb", - .id = UCLASS_VIDEO, - .of_match = am335x_fb_ids, - .bind = am335x_fb_bind, - .of_to_plat = am335x_fb_of_to_plat, - .probe = am335x_fb_probe, - .remove = am335x_fb_remove, - .priv_auto = sizeof(struct am335x_fb_priv), -}; - -#endif /* CONFIG_DM_VIDEO */ diff --git a/drivers/video/am335x-fb.h b/drivers/video/am335x-fb.h index 4952dd96e9..ad9b015e09 100644 --- a/drivers/video/am335x-fb.h +++ b/drivers/video/am335x-fb.h @@ -7,8 +7,6 @@ #ifndef AM335X_FB_H #define AM335X_FB_H -#if !CONFIG_IS_ENABLED(DM_VIDEO) - #define HSVS_CONTROL BIT(25) /* * 0 = lcd_lp and lcd_fp are driven on * opposite edges of pixel clock than @@ -70,37 +68,4 @@ struct am335x_lcdpanel { int am335xfb_init(struct am335x_lcdpanel *panel); -#else /* CONFIG_DM_VIDEO */ - -/** - * tilcdc_panel_info: Panel parameters - * - * @ac_bias: AC Bias Pin Frequency - * @ac_bias_intrpt: AC Bias Pin Transitions per Interrupt - * @dma_burst_sz: DMA burst size - * @bpp: Bits per pixel - * @fdd: FIFO DMA Request Delay - * @tft_alt_mode: TFT Alternative Signal Mapping (Only for active) - * @invert_pxl_clk: Invert pixel clock - * @sync_edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling - * @sync_ctrl: Horizontal and Vertical Sync: Control: 0=ignore - * @raster_order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most - * @fifo_th: DMA FIFO threshold - */ -struct tilcdc_panel_info { - u32 ac_bias; - u32 ac_bias_intrpt; - u32 dma_burst_sz; - u32 bpp; - u32 fdd; - bool tft_alt_mode; - bool invert_pxl_clk; - u32 sync_edge; - u32 sync_ctrl; - u32 raster_order; - u32 fifo_th; -}; - -#endif /* CONFIG_DM_VIDEO */ - #endif /* AM335X_FB_H */ diff --git a/drivers/video/tilcdc-panel.c b/drivers/video/tilcdc-panel.c index 84303a6b71..b90dfae4ae 100644 --- a/drivers/video/tilcdc-panel.c +++ b/drivers/video/tilcdc-panel.c @@ -15,7 +15,7 @@ #include #include #include -#include "am335x-fb.h" +#include "tilcdc.h" struct tilcdc_panel_priv { struct tilcdc_panel_info info; diff --git a/drivers/video/tilcdc-panel.h b/drivers/video/tilcdc-panel.h index 6b40731304..6bcfbf8a8b 100644 --- a/drivers/video/tilcdc-panel.h +++ b/drivers/video/tilcdc-panel.h @@ -6,7 +6,7 @@ #ifndef _TILCDC_PANEL_H #define _TILCDC_PANEL_H -#include "am335x-fb.h" +#include "tilcdc.h" int tilcdc_panel_get_display_info(struct udevice *dev, struct tilcdc_panel_info *info); diff --git a/drivers/video/tilcdc.c b/drivers/video/tilcdc.c new file mode 100644 index 0000000000..d13cc11801 --- /dev/null +++ b/drivers/video/tilcdc.c @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Dario Binacchi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tilcdc.h" +#include "tilcdc-panel.h" + +#define LCDC_FMAX 200000000 + +/* LCD Control Register */ +#define LCDC_CTRL_CLK_DIVISOR_MASK GENMASK(15, 8) +#define LCDC_CTRL_RASTER_MODE BIT(0) +#define LCDC_CTRL_CLK_DIVISOR(x) (((x) & GENMASK(7, 0)) << 8) +/* LCD Clock Enable Register */ +#define LCDC_CLKC_ENABLE_CORECLKEN BIT(0) +#define LCDC_CLKC_ENABLE_LIDDCLKEN BIT(1) +#define LCDC_CLKC_ENABLE_DMACLKEN BIT(2) +/* LCD DMA Control Register */ +#define LCDC_DMA_CTRL_BURST_SIZE(x) (((x) & GENMASK(2, 0)) << 4) +#define LCDC_DMA_CTRL_BURST_1 0x0 +#define LCDC_DMA_CTRL_BURST_2 0x1 +#define LCDC_DMA_CTRL_BURST_4 0x2 +#define LCDC_DMA_CTRL_BURST_8 0x3 +#define LCDC_DMA_CTRL_BURST_16 0x4 +#define LCDC_DMA_CTRL_FIFO_TH(x) (((x) & GENMASK(2, 0)) << 8) +/* LCD Timing_0 Register */ +#define LCDC_RASTER_TIMING_0_HORMSB(x) ((((x) - 1) & BIT(10)) >> 7) +#define LCDC_RASTER_TIMING_0_HORLSB(x) (((((x) >> 4) - 1) & GENMASK(5, 0)) << 4) +#define LCDC_RASTER_TIMING_0_HSWLSB(x) ((((x) - 1) & GENMASK(5, 0)) << 10) +#define LCDC_RASTER_TIMING_0_HFPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 16) +#define LCDC_RASTER_TIMING_0_HBPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 24) +/* LCD Timing_1 Register */ +#define LCDC_RASTER_TIMING_1_VERLSB(x) (((x) - 1) & GENMASK(9, 0)) +#define LCDC_RASTER_TIMING_1_VSW(x) ((((x) - 1) & GENMASK(5, 0)) << 10) +#define LCDC_RASTER_TIMING_1_VFP(x) (((x) & GENMASK(7, 0)) << 16) +#define LCDC_RASTER_TIMING_1_VBP(x) (((x) & GENMASK(7, 0)) << 24) +/* LCD Timing_2 Register */ +#define LCDC_RASTER_TIMING_2_HFPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 8) +#define LCDC_RASTER_TIMING_2_HBPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 4) +#define LCDC_RASTER_TIMING_2_ACB(x) (((x) & GENMASK(7, 0)) << 8) +#define LCDC_RASTER_TIMING_2_ACBI(x) (((x) & GENMASK(3, 0)) << 16) +#define LCDC_RASTER_TIMING_2_VSYNC_INVERT BIT(20) +#define LCDC_RASTER_TIMING_2_HSYNC_INVERT BIT(21) +#define LCDC_RASTER_TIMING_2_PXCLK_INVERT BIT(22) +#define LCDC_RASTER_TIMING_2_DE_INVERT BIT(23) +#define LCDC_RASTER_TIMING_2_HSVS_RISEFALL BIT(24) +#define LCDC_RASTER_TIMING_2_HSVS_CONTROL BIT(25) +#define LCDC_RASTER_TIMING_2_VERMSB(x) ((((x) - 1) & BIT(10)) << 16) +#define LCDC_RASTER_TIMING_2_HSWMSB(x) ((((x) - 1) & GENMASK(9, 6)) << 21) +/* LCD Raster Ctrl Register */ +#define LCDC_RASTER_CTRL_ENABLE BIT(0) +#define LCDC_RASTER_CTRL_TFT_MODE BIT(7) +#define LCDC_RASTER_CTRL_DATA_ORDER BIT(8) +#define LCDC_RASTER_CTRL_REQDLY(x) (((x) & GENMASK(7, 0)) << 12) +#define LCDC_RASTER_CTRL_PALMODE_RAWDATA (0x02 << 20) +#define LCDC_RASTER_CTRL_TFT_ALT_ENABLE BIT(23) +#define LCDC_RASTER_CTRL_TFT_24BPP_MODE BIT(25) +#define LCDC_RASTER_CTRL_TFT_24BPP_UNPACK BIT(26) + +enum { + LCDC_MAX_WIDTH = 2048, + LCDC_MAX_HEIGHT = 2048, + LCDC_MAX_LOG2_BPP = VIDEO_BPP32, +}; + +struct tilcdc_regs { + u32 pid; + u32 ctrl; + u32 gap0; + u32 lidd_ctrl; + u32 lidd_cs0_conf; + u32 lidd_cs0_addr; + u32 lidd_cs0_data; + u32 lidd_cs1_conf; + u32 lidd_cs1_addr; + u32 lidd_cs1_data; + u32 raster_ctrl; + u32 raster_timing0; + u32 raster_timing1; + u32 raster_timing2; + u32 raster_subpanel; + u32 raster_subpanel2; + u32 lcddma_ctrl; + u32 lcddma_fb0_base; + u32 lcddma_fb0_ceiling; + u32 lcddma_fb1_base; + u32 lcddma_fb1_ceiling; + u32 sysconfig; + u32 irqstatus_raw; + u32 irqstatus; + u32 irqenable_set; + u32 irqenable_clear; + u32 gap1; + u32 clkc_enable; + u32 clkc_reset; +}; + +struct tilcdc_priv { + struct tilcdc_regs *regs; + struct clk gclk; + struct clk dpll_m2_clk; +}; + +DECLARE_GLOBAL_DATA_PTR; + +static ulong tilcdc_set_pixel_clk_rate(struct udevice *dev, ulong rate) +{ + struct tilcdc_priv *priv = dev_get_priv(dev); + struct tilcdc_regs *regs = priv->regs; + ulong mult_rate, mult_round_rate, best_err, err; + u32 v; + int div, i; + + best_err = rate; + div = 0; + for (i = 2; i <= 255; i++) { + mult_rate = rate * i; + mult_round_rate = clk_round_rate(&priv->gclk, mult_rate); + if (IS_ERR_VALUE(mult_round_rate)) + return mult_round_rate; + + err = mult_rate - mult_round_rate; + if (err < best_err) { + best_err = err; + div = i; + if (err == 0) + break; + } + } + + if (div == 0) { + dev_err(dev, "failed to find a divisor\n"); + return -EFAULT; + } + + mult_rate = clk_set_rate(&priv->gclk, rate * div); + v = readl(®s->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK; + v |= LCDC_CTRL_CLK_DIVISOR(div); + writel(v, ®s->ctrl); + rate = mult_rate / div; + dev_dbg(dev, "rate=%ld, div=%d, err=%ld\n", rate, div, err); + return rate; +} + +static int tilcdc_remove(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + struct tilcdc_priv *priv = dev_get_priv(dev); + + uc_plat->base -= 0x20; + uc_plat->size += 0x20; + clk_release_all(&priv->gclk, 1); + clk_release_all(&priv->dpll_m2_clk, 1); + return 0; +} + +static int tilcdc_probe(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct tilcdc_priv *priv = dev_get_priv(dev); + struct tilcdc_regs *regs = priv->regs; + struct udevice *panel, *clk_dev; + struct tilcdc_panel_info info; + struct display_timing timing; + ulong rate; + u32 reg; + int err; + + /* Before relocation we don't need to do anything */ + if (!(gd->flags & GD_FLG_RELOC)) + return 0; + + err = uclass_get_device(UCLASS_PANEL, 0, &panel); + if (err) { + dev_err(dev, "failed to get panel\n"); + return err; + } + + err = panel_get_display_timing(panel, &timing); + if (err) { + dev_err(dev, "failed to get display timing\n"); + return err; + } + + if (timing.pixelclock.typ > (LCDC_FMAX / 2)) { + dev_err(dev, "invalid display clock-frequency: %d Hz\n", + timing.pixelclock.typ); + return -EINVAL; + } + + if (timing.hactive.typ > LCDC_MAX_WIDTH) + timing.hactive.typ = LCDC_MAX_WIDTH; + + if (timing.vactive.typ > LCDC_MAX_HEIGHT) + timing.vactive.typ = LCDC_MAX_HEIGHT; + + err = tilcdc_panel_get_display_info(panel, &info); + if (err) { + dev_err(dev, "failed to get panel info\n"); + return err; + } + + switch (info.bpp) { + case 16: + case 24: + case 32: + break; + default: + dev_err(dev, "invalid seting, bpp: %d\n", info.bpp); + return -EINVAL; + } + + switch (info.dma_burst_sz) { + case 1: + case 2: + case 4: + case 8: + case 16: + break; + default: + dev_err(dev, "invalid setting, dma-burst-sz: %d\n", + info.dma_burst_sz); + return -EINVAL; + } + + err = uclass_get_device_by_name(UCLASS_CLK, "lcd_gclk@534", &clk_dev); + if (err) { + dev_err(dev, "failed to get lcd_gclk device\n"); + return err; + } + + err = clk_request(clk_dev, &priv->gclk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + rate = tilcdc_set_pixel_clk_rate(dev, timing.pixelclock.typ); + if (IS_ERR_VALUE(rate)) { + dev_err(dev, "failed to set pixel clock rate\n"); + return rate; + } + + err = uclass_get_device_by_name(UCLASS_CLK, "dpll_disp_m2_ck@4a4", + &clk_dev); + if (err) { + dev_err(dev, "failed to get dpll_disp_m2 clock device\n"); + return err; + } + + err = clk_request(clk_dev, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to get %s clock\n", clk_dev->name); + return err; + } + + err = clk_set_parent(&priv->gclk, &priv->dpll_m2_clk); + if (err) { + dev_err(dev, "failed to set %s clock as %s's parent\n", + priv->dpll_m2_clk.dev->name, priv->gclk.dev->name); + return err; + } + + /* palette default entry */ + memset((void *)uc_plat->base, 0, 0x20); + *(unsigned int *)uc_plat->base = 0x4000; + /* point fb behind palette */ + uc_plat->base += 0x20; + uc_plat->size -= 0x20; + + writel(LCDC_CLKC_ENABLE_CORECLKEN | LCDC_CLKC_ENABLE_LIDDCLKEN | + LCDC_CLKC_ENABLE_DMACLKEN, ®s->clkc_enable); + writel(0, ®s->raster_ctrl); + + reg = readl(®s->ctrl) & LCDC_CTRL_CLK_DIVISOR_MASK; + reg |= LCDC_CTRL_RASTER_MODE; + writel(reg, ®s->ctrl); + + reg = (timing.hactive.typ * timing.vactive.typ * info.bpp) >> 3; + reg += uc_plat->base; + writel(uc_plat->base, ®s->lcddma_fb0_base); + writel(reg, ®s->lcddma_fb0_ceiling); + writel(uc_plat->base, ®s->lcddma_fb1_base); + writel(reg, ®s->lcddma_fb1_ceiling); + + reg = LCDC_DMA_CTRL_FIFO_TH(info.fifo_th); + switch (info.dma_burst_sz) { + case 1: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_1); + break; + case 2: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_2); + break; + case 4: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_4); + break; + case 8: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_8); + break; + case 16: + reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16); + break; + } + + writel(reg, ®s->lcddma_ctrl); + + writel(LCDC_RASTER_TIMING_0_HORLSB(timing.hactive.typ) | + LCDC_RASTER_TIMING_0_HORMSB(timing.hactive.typ) | + LCDC_RASTER_TIMING_0_HFPLSB(timing.hfront_porch.typ) | + LCDC_RASTER_TIMING_0_HBPLSB(timing.hback_porch.typ) | + LCDC_RASTER_TIMING_0_HSWLSB(timing.hsync_len.typ), + ®s->raster_timing0); + + writel(LCDC_RASTER_TIMING_1_VBP(timing.vback_porch.typ) | + LCDC_RASTER_TIMING_1_VFP(timing.vfront_porch.typ) | + LCDC_RASTER_TIMING_1_VSW(timing.vsync_len.typ) | + LCDC_RASTER_TIMING_1_VERLSB(timing.vactive.typ), + ®s->raster_timing1); + + reg = LCDC_RASTER_TIMING_2_ACB(info.ac_bias) | + LCDC_RASTER_TIMING_2_ACBI(info.ac_bias_intrpt) | + LCDC_RASTER_TIMING_2_HSWMSB(timing.hsync_len.typ) | + LCDC_RASTER_TIMING_2_VERMSB(timing.vactive.typ) | + LCDC_RASTER_TIMING_2_HBPMSB(timing.hback_porch.typ) | + LCDC_RASTER_TIMING_2_HFPMSB(timing.hfront_porch.typ); + + if (timing.flags & DISPLAY_FLAGS_VSYNC_LOW) + reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT; + + if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW) + reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT; + + if (info.invert_pxl_clk) + reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT; + + if (info.sync_edge) + reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL; + + if (info.sync_ctrl) + reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL; + + writel(reg, ®s->raster_timing2); + + reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE | + LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(info.fdd); + + if (info.tft_alt_mode) + reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE; + + if (info.bpp == 24) + reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE; + else if (info.bpp == 32) + reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE | + LCDC_RASTER_CTRL_TFT_24BPP_UNPACK; + + if (info.raster_order) + reg |= LCDC_RASTER_CTRL_DATA_ORDER; + + writel(reg, ®s->raster_ctrl); + + uc_priv->xsize = timing.hactive.typ; + uc_priv->ysize = timing.vactive.typ; + uc_priv->bpix = log_2_n_round_up(info.bpp); + + err = panel_enable_backlight(panel); + if (err) { + dev_err(dev, "failed to enable panel backlight\n"); + return err; + } + + return 0; +} + +static int tilcdc_of_to_plat(struct udevice *dev) +{ + struct tilcdc_priv *priv = dev_get_priv(dev); + + priv->regs = (struct tilcdc_regs *)dev_read_addr(dev); + if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get base address\n"); + return -EINVAL; + } + + dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs); + return 0; +} + +static int tilcdc_bind(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + + uc_plat->size = ((LCDC_MAX_WIDTH * LCDC_MAX_HEIGHT * + (1 << LCDC_MAX_LOG2_BPP)) >> 3) + 0x20; + + dev_dbg(dev, "frame buffer size 0x%x\n", uc_plat->size); + return 0; +} + +static const struct udevice_id tilcdc_ids[] = { + {.compatible = "ti,am33xx-tilcdc"}, + {} +}; + +U_BOOT_DRIVER(tilcdc) = { + .name = "tilcdc", + .id = UCLASS_VIDEO, + .of_match = tilcdc_ids, + .bind = tilcdc_bind, + .ofdata_to_platdata = tilcdc_of_to_plat, + .probe = tilcdc_probe, + .remove = tilcdc_remove, + .priv_auto = sizeof(struct tilcdc_priv) +}; diff --git a/drivers/video/tilcdc.h b/drivers/video/tilcdc.h new file mode 100644 index 0000000000..2645921df6 --- /dev/null +++ b/drivers/video/tilcdc.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Dario Binacchi + */ + +#ifndef _TILCDC_H +#define _TILCDC_H + +/** + * tilcdc_panel_info: Panel parameters + * + * @ac_bias: AC Bias Pin Frequency + * @ac_bias_intrpt: AC Bias Pin Transitions per Interrupt + * @dma_burst_sz: DMA burst size + * @bpp: Bits per pixel + * @fdd: FIFO DMA Request Delay + * @tft_alt_mode: TFT Alternative Signal Mapping (Only for active) + * @invert_pxl_clk: Invert pixel clock + * @sync_edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling + * @sync_ctrl: Horizontal and Vertical Sync: Control: 0=ignore + * @raster_order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most + * @fifo_th: DMA FIFO threshold + */ +struct tilcdc_panel_info { + u32 ac_bias; + u32 ac_bias_intrpt; + u32 dma_burst_sz; + u32 bpp; + u32 fdd; + bool tft_alt_mode; + bool invert_pxl_clk; + u32 sync_edge; + u32 sync_ctrl; + u32 raster_order; + u32 fifo_th; +}; + +#endif /* _TILCDC_H */ From 260cbc9af283e02bd184d0becd3466222f2e1db1 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:31 +0100 Subject: [PATCH 37/42] video: omap: move drivers to 'ti' directory Add drivers/video/ti/ folder and move all TI's code in this folder for better maintenance. Signed-off-by: Dario Binacchi --- board/BuR/common/bur_common.h | 2 +- board/BuR/common/common.c | 2 +- drivers/video/Kconfig | 5 +---- drivers/video/Makefile | 4 +--- drivers/video/ti/Kconfig | 8 ++++++++ drivers/video/ti/Makefile | 10 ++++++++++ drivers/video/{ => ti}/am335x-fb.c | 0 drivers/video/{ => ti}/am335x-fb.h | 0 drivers/video/{ => ti}/tilcdc-panel.c | 0 drivers/video/{ => ti}/tilcdc-panel.h | 0 drivers/video/{ => ti}/tilcdc.c | 0 drivers/video/{ => ti}/tilcdc.h | 0 12 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 drivers/video/ti/Kconfig create mode 100644 drivers/video/ti/Makefile rename drivers/video/{ => ti}/am335x-fb.c (100%) rename drivers/video/{ => ti}/am335x-fb.h (100%) rename drivers/video/{ => ti}/tilcdc-panel.c (100%) rename drivers/video/{ => ti}/tilcdc-panel.h (100%) rename drivers/video/{ => ti}/tilcdc.c (100%) rename drivers/video/{ => ti}/tilcdc.h (100%) diff --git a/board/BuR/common/bur_common.h b/board/BuR/common/bur_common.h index c64ebe93b0..79c9af1466 100644 --- a/board/BuR/common/bur_common.h +++ b/board/BuR/common/bur_common.h @@ -12,7 +12,7 @@ #define _BUR_COMMON_H_ #if !CONFIG_IS_ENABLED(DM_VIDEO) -#include <../../../drivers/video/am335x-fb.h> +#include <../../../drivers/video/ti/am335x-fb.h> int load_lcdtiming(struct am335x_lcdpanel *panel); #endif diff --git a/board/BuR/common/common.c b/board/BuR/common/common.c index 0a5104a48f..f676d7baa6 100644 --- a/board/BuR/common/common.c +++ b/board/BuR/common/common.c @@ -27,7 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; #include #include #include -#include "../../../drivers/video/am335x-fb.h" +#include "../../../drivers/video/ti/am335x-fb.h" void lcdbacklight(int on) { diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 71363409f0..a3f8eeba5d 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -546,10 +546,7 @@ config ATMEL_HLCD help HLCDC supports video output to an attached LCD panel. -config AM335X_LCD - bool "Enable AM335x video support" - help - Supports video output to an attached LCD panel. +source "drivers/video/ti/Kconfig" config LOGICORE_DP_TX bool "Enable Logicore DP TX driver" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 5f0f7b440c..76e3914678 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,15 +16,13 @@ obj-$(CONFIG_DM_VIDEO) += video-uclass.o vidconsole-uclass.o obj-$(CONFIG_DM_VIDEO) += video_bmp.o obj-$(CONFIG_PANEL) += panel-uclass.o obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o -obj-$(CONFIG_AM335X_LCD) += tilcdc.o tilcdc-panel.o -else -obj-$(CONFIG_AM335X_LCD) += am335x-fb.o endif obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-${CONFIG_VIDEO_STM32} += stm32/ obj-${CONFIG_VIDEO_TEGRA124} += tegra124/ +obj-y += ti/ obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o diff --git a/drivers/video/ti/Kconfig b/drivers/video/ti/Kconfig new file mode 100644 index 0000000000..3081e9e8c0 --- /dev/null +++ b/drivers/video/ti/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Dario Binacchi +# +config AM335X_LCD + bool "Enable AM335x video support" + help + Supports video output to an attached LCD panel. diff --git a/drivers/video/ti/Makefile b/drivers/video/ti/Makefile new file mode 100644 index 0000000000..ddddd59216 --- /dev/null +++ b/drivers/video/ti/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Dario Binacchi +# + +ifdef CONFIG_DM_VIDEO +obj-$(CONFIG_AM335X_LCD) += tilcdc.o tilcdc-panel.o +else +obj-$(CONFIG_AM335X_LCD) += am335x-fb.o +endif diff --git a/drivers/video/am335x-fb.c b/drivers/video/ti/am335x-fb.c similarity index 100% rename from drivers/video/am335x-fb.c rename to drivers/video/ti/am335x-fb.c diff --git a/drivers/video/am335x-fb.h b/drivers/video/ti/am335x-fb.h similarity index 100% rename from drivers/video/am335x-fb.h rename to drivers/video/ti/am335x-fb.h diff --git a/drivers/video/tilcdc-panel.c b/drivers/video/ti/tilcdc-panel.c similarity index 100% rename from drivers/video/tilcdc-panel.c rename to drivers/video/ti/tilcdc-panel.c diff --git a/drivers/video/tilcdc-panel.h b/drivers/video/ti/tilcdc-panel.h similarity index 100% rename from drivers/video/tilcdc-panel.h rename to drivers/video/ti/tilcdc-panel.h diff --git a/drivers/video/tilcdc.c b/drivers/video/ti/tilcdc.c similarity index 100% rename from drivers/video/tilcdc.c rename to drivers/video/ti/tilcdc.c diff --git a/drivers/video/tilcdc.h b/drivers/video/ti/tilcdc.h similarity index 100% rename from drivers/video/tilcdc.h rename to drivers/video/ti/tilcdc.h From ba149a5b7b111b61b264fa68a7b6d829d35c631d Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 30 Dec 2020 00:16:32 +0100 Subject: [PATCH 38/42] board: ti: am335x-ice: get CDCE913 clock device With support for other clock drivers, the potentially supported CDCE913 device can no longer be probed without specifying its DT node name. Signed-off-by: Dario Binacchi --- board/ti/am335x/board.c | 2 +- board/ti/am43xx/board.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index 40d2e0238f..3cc0e4b91c 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -879,7 +879,7 @@ int board_late_init(void) } /* Just probe the potentially supported cdce913 device */ - uclass_get_device(UCLASS_CLK, 0, &dev); + uclass_get_device_by_name(UCLASS_CLK, "cdce913@65", &dev); return 0; } diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index de49590031..62ed37cb48 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -744,7 +744,7 @@ int board_late_init(void) #endif /* Just probe the potentially supported cdce913 device */ - uclass_get_device(UCLASS_CLK, 0, &dev); + uclass_get_device_by_name(UCLASS_CLK, "cdce913@65", &dev); return 0; } From 25c5b6517854ffc80d4cc3a86d0e69942abb8e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 30 Nov 2020 20:10:34 +0100 Subject: [PATCH 39/42] Nokia RX-51: Do not try calling both ext2load and ext4load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those two commands now doing same thing, reading from ext2/3/4 filesystem. So remove useless duplicated call. Signed-off-by: Pali Rohár Acked-by: Pavel Machek --- include/configs/nokia_rx51.h | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/include/configs/nokia_rx51.h b/include/configs/nokia_rx51.h index 6879f52a0c..3f2700d8e2 100644 --- a/include/configs/nokia_rx51.h +++ b/include/configs/nokia_rx51.h @@ -169,8 +169,6 @@ int rx51_kp_getc(struct stdio_dev *sdev); "trymmcboot=if run switchmmc; then " \ "setenv mmctype fat;" \ "run trymmcallpartboot;" \ - "setenv mmctype ext2;" \ - "run trymmcallpartboot;" \ "setenv mmctype ext4;" \ "run trymmcallpartboot;" \ "fi\0" \ @@ -179,19 +177,10 @@ int rx51_kp_getc(struct stdio_dev *sdev); "preboot=setenv mmcnum 1; setenv mmcpart 1;" \ "setenv mmcscriptfile bootmenu.scr;" \ "if run switchmmc; then " \ - "setenv mmcdone true;" \ "setenv mmctype fat;" \ - "if run scriptload; then true; else " \ - "setenv mmctype ext2;" \ - "if run scriptload; then true; else " \ - "setenv mmctype ext4;" \ - "if run scriptload; then true; else " \ - "setenv mmcdone false;" \ - "fi;" \ - "fi;" \ - "fi;" \ - "if ${mmcdone}; then " \ - "run scriptboot;" \ + "if run scriptload; then run scriptboot; else " \ + "setenv mmctype ext4;" \ + "if run scriptload; then run scriptboot; fi;" \ "fi;" \ "fi;" \ "if run slide; then true; else " \ From 1ce0e1cbcc8c7943f7f98e57417430ae183a0aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Sun, 29 Nov 2020 17:15:05 +0100 Subject: [PATCH 40/42] Nokia RX-51: Add test for U-Boot serial console MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new test which checks that U-Boot for Nokia RX-51 running in qemu can print test line to serial console and also checks that test line appeared on qemu serial console. Signed-off-by: Pali Rohár Reviewed-by: Pavel Machek --- test/nokia_rx51_test.sh | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/test/nokia_rx51_test.sh b/test/nokia_rx51_test.sh index 23fa935310..ee45e8d6dd 100755 --- a/test/nokia_rx51_test.sh +++ b/test/nokia_rx51_test.sh @@ -150,6 +150,15 @@ fakeroot sh -c ' ' /usr/sbin/ubinize -o ubi.img -p 128KiB -m 2048 -s 512 ubi.ini +# Generate bootmenu for U-Boot serial console testing +cat > bootmenu_uboot << EOF +setenv bootmenu_0 'Serial console test=echo; echo "Testing serial console"; echo; echo "Successfully booted"; echo; poweroff'; +setenv bootmenu_1; +setenv bootmenu_delay 1; +setenv bootdelay 1; +EOF +./mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n bootmenu_uboot -d bootmenu_uboot bootmenu_uboot.scr + # Generate bootmenu for eMMC booting cat > bootmenu_emmc << EOF setenv bootmenu_0 'uImage-2.6.28-omap1 from eMMC=setenv mmcnum 1; setenv mmcpart 1; setenv mmctype fat; setenv bootargs; setenv setup_omap_atag 1; setenv mmckernfile uImage-2.6.28-omap1; run trymmckernboot'; @@ -177,6 +186,11 @@ dd if=kernel_2.6.28/boot/zImage-2.6.28-20103103+0m5.fiasco of=zImage-2.6.28-omap cp u-boot.bin combined_hack.bin dd if=uImage-2.6.28-omap1 of=combined_hack.bin bs=1024 seek=$((2048-2)) +# Generate FAT32 eMMC image for U-Boot serial console testing +truncate -s 50MiB emmc_uboot.img +mformat -m 0xf8 -F -h 4 -s 16 -c 1 -t $((50*1024*1024/(4*16*512))) :: -i emmc_uboot.img +mcopy bootmenu_uboot.scr ::/bootmenu.scr -i emmc_uboot.img + # Generate FAT32 eMMC image for eMMC booting truncate -s 50MiB emmc_emmc.img mformat -m 0xf8 -F -h 4 -s 16 -c 1 -t $((50*1024*1024/(4*16*512))) :: -i emmc_emmc.img @@ -188,6 +202,10 @@ truncate -s 50MiB emmc_nand.img mformat -m 0xf8 -F -h 4 -s 16 -c 1 -t $((50*1024*1024/(4*16*512))) :: -i emmc_nand.img mcopy bootmenu_nand.scr ::/bootmenu.scr -i emmc_nand.img +# Generate MTD image for U-Boot serial console testing +rm -f mtd_uboot.img +./qflasher -v -x xloader-qemu.bin -s secondary-qemu.bin -k u-boot.bin -m rx51 -o mtd_uboot.img + # Generate MTD image for RAM booting from bootloader nolo images, compiled image and rootfs image rm -f mtd_ram.img ./qflasher -v -x xloader-qemu.bin -s secondary-qemu.bin -k combined.bin -r ubi.img -m rx51 -o mtd_ram.img @@ -208,6 +226,18 @@ echo "========== Running test images in n900 qemu ==========" echo "======================================================" echo +# Run MTD image in qemu and wait for 300s if U-Boot prints testing string to serial console and poweroff +rm -f qemu_uboot.log +./qemu-system-arm -M n900 -mtdblock mtd_uboot.img -sd emmc_uboot.img -serial /dev/stdout -display none > qemu_uboot.log & +qemu_pid=$! +tail -F qemu_uboot.log & +tail_pid=$! +sleep 300 & +sleep_pid=$! +wait -n $sleep_pid $qemu_pid || true +kill -9 $tail_pid $sleep_pid $qemu_pid 2>/dev/null || true +wait || true + # Run MTD image in qemu and wait for 300s if kernel from RAM is correctly booted rm -f qemu_ram.log ./qemu-system-arm -M n900 -mtdblock mtd_ram.img -serial /dev/stdout -display none > qemu_ram.log & @@ -250,13 +280,14 @@ echo "========== Results ==========" echo "=============================" echo +if grep -q 'Successfully booted' qemu_uboot.log; then echo "U-Boot serial console is working"; else echo "U-Boot serial console test failed"; fi if grep -q 'Successfully booted' qemu_ram.log; then echo "Kernel was successfully booted from RAM"; else echo "Failed to boot kernel from RAM"; fi if grep -q 'Successfully booted' qemu_emmc.log; then echo "Kernel was successfully booted from eMMC"; else echo "Failed to boot kernel from eMMC"; fi if grep -q 'Successfully booted' qemu_nand.log; then echo "Kernel was successfully booted from OneNAND"; else echo "Failed to boot kernel from OneNAND"; fi echo -if grep -q 'Successfully booted' qemu_ram.log && grep -q 'Successfully booted' qemu_emmc.log && grep -q 'Successfully booted' qemu_nand.log; then +if grep -q 'Successfully booted' qemu_uboot.log && grep -q 'Successfully booted' qemu_ram.log && grep -q 'Successfully booted' qemu_emmc.log && grep -q 'Successfully booted' qemu_nand.log; then echo "All tests passed" exit 0 else From 965db9fb0cd06895426539f20ed5145fbc1ef5aa Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 6 Jan 2021 13:20:31 -0600 Subject: [PATCH 41/42] arm: dts: k3-*-r5-*-board: Add GTC clock Add GTC Clock definition as index 0 clock so that we can use the clock node in the driver later on. Signed-off-by: Nishanth Menon --- arch/arm/dts/k3-am654-r5-base-board.dts | 1 + arch/arm/dts/k3-j7200-r5-common-proc-board.dts | 1 + arch/arm/dts/k3-j721e-r5-common-proc-board.dts | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm/dts/k3-am654-r5-base-board.dts b/arch/arm/dts/k3-am654-r5-base-board.dts index d43a4edc71..f12510259d 100644 --- a/arch/arm/dts/k3-am654-r5-base-board.dts +++ b/arch/arm/dts/k3-am654-r5-base-board.dts @@ -36,6 +36,7 @@ power-domains = <&k3_pds 61 TI_SCI_PD_EXCLUSIVE>, <&k3_pds 202 TI_SCI_PD_EXCLUSIVE>; resets = <&k3_reset 202 0>; + clocks = <&k3_clks 61 0>; assigned-clocks = <&k3_clks 202 0>; assigned-clock-rates = <800000000>; ti,sci = <&dmsc>; diff --git a/arch/arm/dts/k3-j7200-r5-common-proc-board.dts b/arch/arm/dts/k3-j7200-r5-common-proc-board.dts index db63d93777..2ac887b180 100644 --- a/arch/arm/dts/k3-j7200-r5-common-proc-board.dts +++ b/arch/arm/dts/k3-j7200-r5-common-proc-board.dts @@ -32,6 +32,7 @@ power-domains = <&k3_pds 61 TI_SCI_PD_EXCLUSIVE>, <&k3_pds 202 TI_SCI_PD_EXCLUSIVE>; resets = <&k3_reset 202 0>; + clocks = <&k3_clks 61 1>; assigned-clocks = <&k3_clks 202 2>, <&k3_clks 61 1>; assigned-clock-rates = <2000000000>, <200000000>; ti,sci = <&dmsc>; diff --git a/arch/arm/dts/k3-j721e-r5-common-proc-board.dts b/arch/arm/dts/k3-j721e-r5-common-proc-board.dts index 4cfaf8ca3c..25f2ada5a8 100644 --- a/arch/arm/dts/k3-j721e-r5-common-proc-board.dts +++ b/arch/arm/dts/k3-j721e-r5-common-proc-board.dts @@ -28,6 +28,7 @@ power-domains = <&k3_pds 61 TI_SCI_PD_EXCLUSIVE>, <&k3_pds 202 TI_SCI_PD_EXCLUSIVE>; resets = <&k3_reset 202 0>; + clocks = <&k3_clks 61 1>; assigned-clocks = <&k3_clks 202 2>, <&k3_clks 61 1>; assigned-clock-rates = <2000000000>, <200000000>; ti,sci = <&dmsc>; From ea3f5348063ebe4f41be7d1ba3ef0afe56a04a40 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 6 Jan 2021 13:20:32 -0600 Subject: [PATCH 42/42] remoteproc: ti_k3_arm64: Program CNTFID0 register in GTC ARMv8's generic timer[1] picks up it's graycode from GTC. However, the frequency of the GTC is supposed to be programmed in CNTFID0[2] register prior to enabling the GTC in CNTCR[3] register. In K3 architecture, GTC provides a central time to many parts of the SoC including graycode to the generic timer in the ARMv8 subsystem. However, due to the central nature and the need to enable the counter early in the boot process, the R5 based u-boot enables GTC and programs it's frequency based on central needs of the system. This may not be a constant 200MHz based on the system. The bootloader is supposed to program the FID0 register with the correct frequency it has sourced for GTC from the central system controller OR from PLLs as appropriate, and TF-A is supposed[4] to use that as the frequency for it's local timer. Currently we are programming just the CNTCR[3] register to enable the GTC, however we dont let TF-A know the frequency that GTC is actually running at. A mismatch in programmed frequency and what we program for generic timer will, as we can imagine, all kind of weird mayhem. So, program the CNTFID0 register with the clock frequency. Note: assigned-clock-rates should have set the clock frequency, so the only operation we need to explicitly do is to retrieve the frequency and program it in FID0 register. Since the valid in K3 for GTC clock frequencies are < U32_MAX, we can just cast the ulong and continue. [1] https://developer.arm.com/documentation/100095/0002/generic-timer/generic-timer-register-summary/aarch64-generic-timer-register-summary [2] https://developer.arm.com/docs/ddi0595/h/external-system-registers/cntfid0 [3] https://developer.arm.com/docs/ddi0595/h/external-system-registers/cntcr [4] https://github.com/ARM-software/arm-trusted-firmware/commit/6a22d9ea3c7fa28d053d3ba264b49b7396a86f9e Signed-off-by: Nishanth Menon --- drivers/remoteproc/ti_k3_arm64_rproc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/remoteproc/ti_k3_arm64_rproc.c b/drivers/remoteproc/ti_k3_arm64_rproc.c index 1041f3805f..1f2415dc1a 100644 --- a/drivers/remoteproc/ti_k3_arm64_rproc.c +++ b/drivers/remoteproc/ti_k3_arm64_rproc.c @@ -23,6 +23,7 @@ #define INVALID_ID 0xffff #define GTC_CNTCR_REG 0x0 +#define GTC_CNTFID0_REG 0x20 #define GTC_CNTR_EN 0x3 /** @@ -31,6 +32,7 @@ * @rproc_rst: rproc reset control data * @sci: Pointer to TISCI handle * @tsp: TISCI processor control helper structure + * @gtc_clk: GTC clock description * @gtc_base: Timer base address. */ struct k3_arm64_privdata { @@ -38,6 +40,7 @@ struct k3_arm64_privdata { struct power_domain gtc_pwrdmn; struct reset_ctl rproc_rst; struct ti_sci_proc tsp; + struct clk gtc_clk; void *gtc_base; }; @@ -73,6 +76,7 @@ static int k3_arm64_load(struct udevice *dev, ulong addr, ulong size) static int k3_arm64_start(struct udevice *dev) { struct k3_arm64_privdata *rproc = dev_get_priv(dev); + ulong gtc_rate; int ret; dev_dbg(dev, "%s\n", __func__); @@ -83,6 +87,11 @@ static int k3_arm64_start(struct udevice *dev) return ret; } + gtc_rate = clk_get_rate(&rproc->gtc_clk); + dev_dbg(dev, "GTC RATE= %d\n", (u32) gtc_rate); + /* Store the clock frequency down for GTC users to pick up */ + writel((u32)gtc_rate, rproc->gtc_base + GTC_CNTFID0_REG); + /* Enable the timer before starting remote core */ writel(GTC_CNTR_EN, rproc->gtc_base + GTC_CNTCR_REG); @@ -169,6 +178,12 @@ static int k3_arm64_of_to_priv(struct udevice *dev, return ret; } + ret = clk_get_by_index(dev, 0, &rproc->gtc_clk); + if (ret) { + dev_err(dev, "clk_get failed: %d\n", ret); + return ret; + } + ret = reset_get_by_index(dev, 0, &rproc->rproc_rst); if (ret) { dev_err(dev, "reset_get() failed: %d\n", ret);