Merge https://gitlab.denx.de/u-boot/custodians/u-boot-x86
authorTom Rini <trini@konsulko.com>
Thu, 9 Jul 2020 13:54:22 +0000 (09:54 -0400)
committerTom Rini <trini@konsulko.com>
Thu, 9 Jul 2020 13:54:22 +0000 (09:54 -0400)
- Add two- and three-argument versions of CONFIG_IS_ENABLED in
  linux/kconfig.h
- Adds a new feature which supports copying modified parts of
  the frame buffer to the uncached hardware buffer
- Enable the copy framebuffer on various x86 targets

54 files changed:
MAINTAINERS
arch/arm/dts/armada-388-helios4-u-boot.dtsi
arch/arm/dts/armada-388-helios4.dts
arch/arm/dts/kirkwood-d2net-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/kirkwood-is2-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/kirkwood-net2big-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/kirkwood-ns2-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/kirkwood-ns2lite-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/kirkwood-ns2max-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/kirkwood-ns2mini-u-boot.dtsi [new file with mode: 0644]
arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
arch/sandbox/include/asm/rtc.h
board/LaCie/net2big_v2/MAINTAINERS
board/LaCie/net2big_v2/net2big_v2.c
board/LaCie/netspace_v2/MAINTAINERS
board/LaCie/netspace_v2/netspace_v2.c
cmd/Kconfig
cmd/Makefile
cmd/rtc.c [new file with mode: 0644]
configs/cortina_presidio-asic-emmc_defconfig
configs/d2net_v2_defconfig
configs/helios4_defconfig
configs/inetspace_v2_defconfig
configs/net2big_v2_defconfig
configs/netspace_lite_v2_defconfig
configs/netspace_max_v2_defconfig
configs/netspace_mini_v2_defconfig
configs/netspace_v2_defconfig
configs/sandbox64_defconfig
configs/sandbox_defconfig
configs/sandbox_flattree_defconfig
doc/device-tree-bindings/i2c/i2c-cortina.txt [new file with mode: 0644]
doc/device-tree-bindings/i2c/octeon-i2c.txt [new file with mode: 0644]
doc/device-tree-bindings/pwm/pwm-sifive.txt [new file with mode: 0644]
drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c
drivers/i2c/Kconfig
drivers/i2c/Makefile
drivers/i2c/i2c-cortina.c [new file with mode: 0644]
drivers/i2c/i2c-cortina.h [new file with mode: 0644]
drivers/i2c/imx_lpi2c.c
drivers/i2c/octeon_i2c.c [new file with mode: 0644]
drivers/i2c/stm32f7_i2c.c
drivers/net/mvpp2.c
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/pwm-sifive.c [new file with mode: 0644]
drivers/rtc/i2c_rtc_emul.c
drivers/rtc/pcf2127.c
drivers/rtc/rtc-uclass.c
drivers/rtc/sandbox_rtc.c
include/configs/helios4.h
include/configs/lacie_kw.h
include/rtc.h
test/dm/rtc.c

index e3f3e5f..2a281a9 100644 (file)
@@ -182,6 +182,8 @@ F:  drivers/gpio/cortina_gpio.c
 F:     drivers/watchdog/cortina_wdt.c
 F:     drivers/serial/serial_cortina.c
 F:     drivers/mmc/ca_dw_mmc.c
+F:     drivers/i2c/i2c-cortina.c
+F:     drivers/i2c/i2c-cortina.h
 
 ARM/CZ.NIC TURRIS MOX SUPPORT
 M:     Marek Behun <marek.behun@nic.cz>
@@ -740,6 +742,8 @@ F:  drivers/gpio/cortina_gpio.c
 F:     drivers/watchdog/cortina_wdt.c
 F:     drivers/serial/serial_cortina.c
 F:     drivers/mmc/ca_dw_mmc.c
+F:     drivers/i2c/i2c-cortina.c
+F:     drivers/i2c/i2c-cortina.h
 
 MIPS MSCC
 M:     Gregory CLEMENT <gregory.clement@bootlin.com>
index f0da9f4..0753889 100644 (file)
@@ -14,6 +14,9 @@
 
 &spi1 {
        u-boot,dm-spl;
+       spi-flash@0 {
+               u-boot,dm-spl;
+       };
 };
 
 &w25q32 {
        u-boot,dm-spl;
 };
 
+&gpio0 {
+       u-boot,dm-spl;
+};
+
+&ahci0 {
+       u-boot,dm-spl;
+};
+
+&ahci1 {
+       u-boot,dm-spl;
+};
+
 &sdhci {
        u-boot,dm-spl;
 };
index a154e0f..fb49df2 100644 (file)
        soc {
                internal-regs {
                        i2c@11000 {
-                               clock-frequency = <400000>;
-                               pinctrl-0 = <&i2c0_pins>;
-                               pinctrl-names = "default";
-                               status = "okay";
-
                                /*
                                 * PCA9655 GPIO expander, up to 1MHz clock.
                                 *  0-Board Revision bit 0 #
                                                gpio-hog;
                                                gpios = <5 GPIO_ACTIVE_HIGH>;
                                                input;
-                                               line-name =
-                                               "usb-overcurrent-status";
+                                               line-name = "usb-overcurrent-status";
                                        };
                                };
 
                                bus-width = <4>;
                                cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
                                no-1-8-v;
-                               pinctrl-0 = <&microsom_sdhci_pins
+                               pinctrl-0 = <&helios_sdhci_pins
                                             &helios_sdhci_cd_pins>;
                                pinctrl-names = "default";
                                status = "okay";
                                        marvell,pins = "mpp20";
                                        marvell,function = "gpio";
                                };
+                               helios_sdhci_pins: helios-sdhci-pins {
+                                       marvell,pins = "mpp21", "mpp28",
+                                                      "mpp37", "mpp38",
+                                                      "mpp39", "mpp40";
+                                       marvell,function = "sd0";
+                               };
                                helios_led_pins: helios-led-pins {
                                        marvell,pins = "mpp24", "mpp25",
                                                       "mpp49", "mpp50",
diff --git a/arch/arm/dts/kirkwood-d2net-u-boot.dtsi b/arch/arm/dts/kirkwood-d2net-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1f3b185
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+       aliases {
+               spi0 = &spi0;
+       };
+};
diff --git a/arch/arm/dts/kirkwood-is2-u-boot.dtsi b/arch/arm/dts/kirkwood-is2-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1f3b185
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+       aliases {
+               spi0 = &spi0;
+       };
+};
diff --git a/arch/arm/dts/kirkwood-net2big-u-boot.dtsi b/arch/arm/dts/kirkwood-net2big-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1f3b185
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+       aliases {
+               spi0 = &spi0;
+       };
+};
diff --git a/arch/arm/dts/kirkwood-ns2-u-boot.dtsi b/arch/arm/dts/kirkwood-ns2-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1f3b185
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+       aliases {
+               spi0 = &spi0;
+       };
+};
diff --git a/arch/arm/dts/kirkwood-ns2lite-u-boot.dtsi b/arch/arm/dts/kirkwood-ns2lite-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1f3b185
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+       aliases {
+               spi0 = &spi0;
+       };
+};
diff --git a/arch/arm/dts/kirkwood-ns2max-u-boot.dtsi b/arch/arm/dts/kirkwood-ns2max-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1f3b185
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+       aliases {
+               spi0 = &spi0;
+       };
+};
diff --git a/arch/arm/dts/kirkwood-ns2mini-u-boot.dtsi b/arch/arm/dts/kirkwood-ns2mini-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1f3b185
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+       aliases {
+               spi0 = &spi0;
+       };
+};
index 67a00cf..2454730 100644 (file)
@@ -533,7 +533,7 @@ struct op_params pex_and_usb3_tx_config_params3[] = {
 struct op_params pex_by4_config_params[] = {
        /* unit_base_reg, unit_offset, mask, data, wait_time, num_of_loops */
        {GLOBAL_CLK_SRC_HI, 0x800, 0x7, {0x5, 0x0, 0x0, 0x2}, 0, 0},
-       /* Lane Alignement enable */
+       /* Lane Alignment enable */
        {LANE_ALIGN_REG0, 0x800, 0x1000, {0x0, 0x0, 0x0, 0x0}, 0, 0},
        /* Max PLL phy config */
        {CALIBRATION_CTRL_REG, 0x800, 0x1000, {0x1000, 0x1000, 0x1000, 0x1000},
@@ -672,12 +672,29 @@ struct op_params usb2_power_up_params[] = {
        {0xc200c, 0x0 /*NA*/, 0x1000000, {0x1000000}, 0, 0},
        /* Phy0 register 3  - TX Channel control 0 */
        {0xc400c, 0x0 /*NA*/, 0x1000000, {0x1000000}, 0, 0},
-       /* check PLLCAL_DONE is set and IMPCAL_DONE is set */
+       /* Decrease the amplitude of the low speed eye to meet the spec */
+       {0xc000c, 0x0 /*NA*/, 0xf000, {0x1000}, 0, 0},
+       {0xc200c, 0x0 /*NA*/, 0xf000, {0x1000}, 0, 0},
+       {0xc400c, 0x0 /*NA*/, 0xf000, {0x1000}, 0, 0},
+       /* Change the High speed impedance threshold */
+       {0xc0008, 0x0 /*NA*/, 0x700, {0x600}, 0, 0},
+       {0xc2008, 0x0 /*NA*/, 0x700, {0x600}, 0, 0},
+       {0xc4008, 0x0 /*NA*/, 0x700, {0x600}, 0, 0},
+       /* Change the squelch level of the receiver to meet the receiver electrical measurements (squelch and receiver sensitivity tests) */
+       {0xc0014, 0x0 /*NA*/, 0xf, {0x8}, 0, 0},
+       {0xc2014, 0x0 /*NA*/, 0xf, {0x8}, 0, 0},
+       {0xc4014, 0x0 /*NA*/, 0xf, {0x8}, 0, 0},
+       /* Check PLLCAL_DONE is set and IMPCAL_DONE is set */
        {0xc0008, 0x0 /*NA*/, 0x80800000, {0x80800000}, 1, 1000},
-       /* check REG_SQCAL_DONE  is set */
+       /* Check REG_SQCAL_DONE  is set */
        {0xc0018, 0x0 /*NA*/, 0x80000000, {0x80000000}, 1, 1000},
-       /* check PLL_READY  is set */
-       {0xc0000, 0x0 /*NA*/, 0x80000000, {0x80000000}, 1, 1000}
+       /* Check PLL_READY  is set */
+       {0xc0000, 0x0 /*NA*/, 0x80000000, {0x80000000}, 1, 1000},
+       /* Start calibrate of high seed impedance */
+       {0xc0008, 0x0 /*NA*/, 0x2000, {0x2000}, 0, 0},
+       {0x0, 0x0 /*NA*/, 0x0, {0x0}, 10, 0},
+       /* De-assert  the calibration signal */
+       {0xc0008, 0x0 /*NA*/, 0x2000, {0x0}, 0, 0},
 };
 
 /*
index 1fbfea7..5bb032f 100644 (file)
@@ -21,6 +21,11 @@ enum {
 
        REG_RESET       = 0x20,
 
+       REG_AUX0        = 0x30,
+       REG_AUX1,
+       REG_AUX2,
+       REG_AUX3,
+
        REG_COUNT       = 0x80,
 };
 
index 8fec703..7046e1b 100644 (file)
@@ -1,6 +1,12 @@
 NET2BIG_V2 BOARD
 M:     Simon Guinot <simon.guinot@sequanux.org>
 S:     Maintained
+F:     arch/arm/dts/kirkwood-d2net.dts
+F:     arch/arm/dts/kirkwood-d2net-u-boot.dtsi
+F:     arch/arm/dts/kirkwood-d2net.dtsi
+F:     arch/arm/dts/kirkwood-net2big.dts
+F:     arch/arm/dts/kirkwood-net2big-u-boot.dtsi
+F:     arch/arm/dts/kirkwood-netxbig.dtsi
 F:     board/LaCie/net2big_v2/
 F:     include/configs/lacie_kw.h
 F:     configs/d2net_v2_defconfig
index dbd8b57..e94c9a6 100644 (file)
@@ -239,7 +239,7 @@ int misc_init_r(void)
 /* Configure and initialize PHY */
 void reset_phy(void)
 {
-       mv_phy_88e1116_init("egiga0", 8);
+       mv_phy_88e1116_init("ethernet-controller@72000", 8);
 }
 #endif
 
index 55fd50d..1cc4f71 100644 (file)
@@ -1,14 +1,21 @@
-NETSPACE_V2 BOARD
+NETSPACE_V2 BOARDS
 M:     Simon Guinot <simon.guinot@sequanux.org>
 S:     Maintained
+F:     arch/arm/dts/kirkwood-is2.dts
+F:     arch/arm/dts/kirkwood-is2-u-boot.dtsi
+F:     arch/arm/dts/kirkwood-ns2-common.dtsi
+F:     arch/arm/dts/kirkwood-ns2.dts
+F:     arch/arm/dts/kirkwood-ns2lite.dts
+F:     arch/arm/dts/kirkwood-ns2lite-u-boot.dtsi
+F:     arch/arm/dts/kirkwood-ns2max.dts
+F:     arch/arm/dts/kirkwood-ns2max-u-boot.dtsi
+F:     arch/arm/dts/kirkwood-ns2mini.dts
+F:     arch/arm/dts/kirkwood-ns2mini-u-boot.dtsi
+F:     arch/arm/dts/kirkwood-ns2-u-boot.dtsi
 F:     board/LaCie/netspace_v2/
 F:     include/configs/lacie_kw.h
 F:     configs/inetspace_v2_defconfig
-F:     configs/netspace_max_v2_defconfig
-F:     configs/netspace_v2_defconfig
-
-NETSPACE_LITE_V2 BOARD
-#M:    -
-S:     Maintained
 F:     configs/netspace_lite_v2_defconfig
+F:     configs/netspace_max_v2_defconfig
 F:     configs/netspace_mini_v2_defconfig
+F:     configs/netspace_v2_defconfig
index 011cc56..33246b2 100644 (file)
@@ -100,9 +100,9 @@ int misc_init_r(void)
 void reset_phy(void)
 {
 #if defined(CONFIG_NETSPACE_LITE_V2) || defined(CONFIG_NETSPACE_MINI_V2)
-       mv_phy_88e1318_init("egiga0", 0);
+       mv_phy_88e1318_init("ethernet-controller@72000", 0);
 #else
-       mv_phy_88e1116_init("egiga0", 8);
+       mv_phy_88e1116_init("ethernet-controller@72000", 8);
 #endif
 }
 #endif
index 2b823dd..846c905 100644 (file)
@@ -1739,6 +1739,12 @@ config CMD_DATE
          Enable the 'date' command for getting/setting the time/date in RTC
          devices.
 
+config CMD_RTC
+       bool "rtc"
+       depends on DM_RTC
+       help
+         Enable the 'rtc' command for low-level access to RTC devices.
+
 config CMD_TIME
        bool "time"
        help
index 7008dd4..dc412d1 100644 (file)
@@ -122,6 +122,7 @@ obj-$(CONFIG_CMD_REISER) += reiser.o
 obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o
 obj-$(CONFIG_CMD_RNG) += rng.o
 obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
+obj-$(CONFIG_CMD_RTC) += rtc.o
 obj-$(CONFIG_SANDBOX) += host.o
 obj-$(CONFIG_CMD_SATA) += sata.o
 obj-$(CONFIG_CMD_NVME) += nvme.o
diff --git a/cmd/rtc.c b/cmd/rtc.c
new file mode 100644 (file)
index 0000000..b4f61b2
--- /dev/null
+++ b/cmd/rtc.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <hexdump.h>
+#include <i2c.h>
+#include <mapmem.h>
+#include <rtc.h>
+
+#define MAX_RTC_BYTES 32
+
+static int do_rtc_read(struct udevice *dev, int argc, char * const argv[])
+{
+       u8 buf[MAX_RTC_BYTES];
+       int reg, len, ret, r;
+
+       if (argc < 2 || argc > 3)
+               return CMD_RET_USAGE;
+
+       reg = simple_strtoul(argv[0], NULL, 16);
+       len = simple_strtoul(argv[1], NULL, 16);
+
+       if (argc == 3) {
+               u8 *addr;
+
+               addr = map_sysmem(simple_strtoul(argv[2], NULL, 16), len);
+               ret = dm_rtc_read(dev, reg, addr, len);
+               unmap_sysmem(addr);
+               if (ret) {
+                       printf("dm_rtc_read() failed: %d\n", ret);
+                       return CMD_RET_FAILURE;
+               }
+               return CMD_RET_SUCCESS;
+       }
+
+       while (len) {
+               r = min_t(int, len, sizeof(buf));
+               ret = dm_rtc_read(dev, reg, buf, r);
+               if (ret) {
+                       printf("dm_rtc_read() failed: %d\n", ret);
+                       return CMD_RET_FAILURE;
+               }
+               print_buffer(reg, buf, 1, r, 0);
+               len -= r;
+               reg += r;
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_rtc_write(struct udevice *dev, int argc, char * const argv[])
+{
+       u8 buf[MAX_RTC_BYTES];
+       int reg, len, ret;
+       const char *s;
+       int slen;
+
+       if (argc < 2 || argc > 3)
+               return CMD_RET_USAGE;
+
+       reg = simple_strtoul(argv[0], NULL, 16);
+
+       if (argc == 3) {
+               u8 *addr;
+
+               len = simple_strtoul(argv[1], NULL, 16);
+               addr = map_sysmem(simple_strtoul(argv[2], NULL, 16), len);
+               ret = dm_rtc_write(dev, reg, addr, len);
+               unmap_sysmem(addr);
+               if (ret) {
+                       printf("dm_rtc_write() failed: %d\n", ret);
+                       return CMD_RET_FAILURE;
+               }
+               return CMD_RET_SUCCESS;
+       }
+
+       s = argv[1];
+       slen = strlen(s);
+
+       if (slen % 2) {
+               printf("invalid hex string\n");
+               return CMD_RET_FAILURE;
+       }
+
+       while (slen) {
+               len = min_t(int, slen / 2, sizeof(buf));
+               if (hex2bin(buf, s, len)) {
+                       printf("invalid hex string\n");
+                       return CMD_RET_FAILURE;
+               }
+
+               ret = dm_rtc_write(dev, reg, buf, len);
+               if (ret) {
+                       printf("dm_rtc_write() failed: %d\n", ret);
+                       return CMD_RET_FAILURE;
+               }
+               s += 2 * len;
+               slen -= 2 * len;
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
+int do_rtc(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+       static int curr_rtc;
+       struct udevice *dev;
+       int ret, idx;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       argc--;
+       argv++;
+
+       if (!strcmp(argv[0], "list")) {
+               struct uclass *uc;
+
+               idx = 0;
+               uclass_id_foreach_dev(UCLASS_RTC, dev, uc) {
+                       printf("RTC #%d - %s\n", idx++, dev->name);
+               }
+               if (!idx) {
+                       printf("*** no RTC devices available ***\n");
+                       return CMD_RET_FAILURE;
+               }
+               return CMD_RET_SUCCESS;
+       }
+
+       idx = curr_rtc;
+       if (!strcmp(argv[0], "dev") && argc >= 2)
+               idx = simple_strtoul(argv[1], NULL, 10);
+
+       ret = uclass_get_device(UCLASS_RTC, idx, &dev);
+       if (ret) {
+               printf("Cannot find RTC #%d: err=%d\n", idx, ret);
+               return CMD_RET_FAILURE;
+       }
+
+       if (!strcmp(argv[0], "dev")) {
+               /* Show the existing or newly selected RTC */
+               if (argc >= 2)
+                       curr_rtc = idx;
+               printf("RTC #%d - %s\n", idx, dev->name);
+               return CMD_RET_SUCCESS;
+       }
+
+       if (!strcmp(argv[0], "read"))
+               return do_rtc_read(dev, argc - 1, argv + 1);
+
+       if (!strcmp(argv[0], "write"))
+               return do_rtc_write(dev, argc - 1, argv + 1);
+
+       return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+       rtc,    5,      0,      do_rtc,
+       "RTC subsystem",
+       "list                        - show available rtc devices\n"
+       "rtc dev [n]                     - show or set current rtc device\n"
+       "rtc read <reg> <count>          - read and display 8-bit registers starting at <reg>\n"
+       "rtc read <reg> <count> <addr>   - read 8-bit registers starting at <reg> to memory <addr>\n"
+       "rtc write <reg> <hexstring>     - write 8-bit registers starting at <reg>\n"
+       "rtc write <reg> <count> <addr>  - write from memory <addr> to 8-bit registers starting at <reg>\n"
+);
index e10008a..e45e23c 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_SHOW_BOOT_PROGRESS=y
 CONFIG_BOOTDELAY=3
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SYS_PROMPT="G3#"
+CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_PART=y
 CONFIG_CMD_WDT=y
@@ -24,6 +25,8 @@ CONFIG_DEFAULT_DEVICE_TREE="ca-presidio-engboard"
 # CONFIG_NET is not set
 CONFIG_DM=y
 CONFIG_CORTINA_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_CA=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_CORTINA=y
index fe3c6c4..31a5d91 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_ENV_OFFSET=0x70000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_IDENT_STRING=" D2 v2"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="D2NET_V2"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -20,9 +21,8 @@ CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="d2v2> "
 CONFIG_CMD_EEPROM=y
-CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
-CONFIG_CMD_SF=y
+CONFIG_CMD_SATA=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
@@ -39,15 +39,20 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=20000000
 CONFIG_ENV_ADDR=0x70000
-CONFIG_MVSATA_IDE=y
+CONFIG_DM=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_DM_ETH=y
 CONFIG_MVGBE=y
 CONFIG_MII=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 1edd832..2085887 100644 (file)
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_CPU_INIT=y
+CONFIG_SYS_THUMB_BUILD=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_SYS_TEXT_BASE=0x00800000
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
@@ -24,40 +25,47 @@ CONFIG_USE_PREBOOT=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x141
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET=0x1
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_CMD_TLV_EEPROM=y
+CONFIG_SPL_CMD_TLV_EEPROM=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_MVEBU_BUBT=y
 # CONFIG_SPL_PARTITION_UUIDS is not set
 CONFIG_DEFAULT_DEVICE_TREE="armada-388-helios4"
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_SCSI_AHCI=y
+CONFIG_AHCI_MVEBU=y
 CONFIG_DM_PCA953X=y
 CONFIG_DM_I2C=y
-CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
-CONFIG_I2C_DEFAULT_BUS_NUMBER=0x1
 CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_I2C_EEPROM=y
+CONFIG_SPL_I2C_EEPROM=y
 CONFIG_DM_MMC=y
+CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_MV=y
 CONFIG_MTD=y
 CONFIG_SF_DEFAULT_BUS=1
-CONFIG_SF_DEFAULT_SPEED=104000000
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
 CONFIG_PHY_MARVELL=y
 CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
 CONFIG_SCSI=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
index 6144eb5..b597397 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_ENV_OFFSET=0x70000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_IDENT_STRING=" IS v2"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="INETSPACE_V2"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -20,9 +21,8 @@ CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ns2> "
 CONFIG_CMD_EEPROM=y
-CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
-CONFIG_CMD_SF=y
+CONFIG_CMD_SATA=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
@@ -39,15 +39,20 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=20000000
 CONFIG_ENV_ADDR=0x70000
-CONFIG_MVSATA_IDE=y
+CONFIG_DM=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_DM_ETH=y
 CONFIG_MVGBE=y
 CONFIG_MII=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 1389d30..bba8503 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_ENV_OFFSET=0x70000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_IDENT_STRING=" 2Big v2"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="NET2BIG_V2"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -20,9 +21,8 @@ CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="2big2> "
 CONFIG_CMD_EEPROM=y
-CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
-CONFIG_CMD_SF=y
+CONFIG_CMD_SATA=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
@@ -39,15 +39,20 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=20000000
 CONFIG_ENV_ADDR=0x70000
-CONFIG_MVSATA_IDE=y
+CONFIG_DM=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_DM_ETH=y
 CONFIG_MVGBE=y
 CONFIG_MII=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index c744d2c..bfa93db 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_ENV_OFFSET=0x70000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_IDENT_STRING=" NS v2 Lite"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="NETSPACE_LITE_V2"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -20,9 +21,8 @@ CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ns2> "
 CONFIG_CMD_EEPROM=y
-CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
-CONFIG_CMD_SF=y
+CONFIG_CMD_SATA=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
@@ -39,15 +39,21 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=20000000
 CONFIG_ENV_ADDR=0x70000
-CONFIG_MVSATA_IDE=y
+CONFIG_DM=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_DM_ETH=y
 CONFIG_MVGBE=y
 CONFIG_MII=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE=y
index 8602729..d0f7503 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_ENV_OFFSET=0x70000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_IDENT_STRING=" NS Max v2"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="NETSPACE_MAX_V2"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -20,9 +21,8 @@ CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ns2> "
 CONFIG_CMD_EEPROM=y
-CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
-CONFIG_CMD_SF=y
+CONFIG_CMD_SATA=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
@@ -39,15 +39,21 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=20000000
 CONFIG_ENV_ADDR=0x70000
-CONFIG_MVSATA_IDE=y
+CONFIG_DM=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_DM_ETH=y
 CONFIG_MVGBE=y
 CONFIG_MII=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE=y
index ba9301d..6cfaccf 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_ENV_OFFSET=0x70000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_IDENT_STRING=" NS v2 Mini"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="NETSPACE_MINI_V2"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -20,9 +21,8 @@ CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ns2> "
 CONFIG_CMD_EEPROM=y
-CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
-CONFIG_CMD_SF=y
+CONFIG_CMD_SATA=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
@@ -37,12 +37,16 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=20000000
 CONFIG_ENV_ADDR=0x70000
-CONFIG_MVSATA_IDE=y
+CONFIG_DM=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_DM_ETH=y
 CONFIG_MVGBE=y
 CONFIG_MII=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
index 6ba1ef4..1bd148f 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_ENV_OFFSET=0x70000
 CONFIG_ENV_SECT_SIZE=0x10000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_IDENT_STRING=" NS v2"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="NETSPACE_V2"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -20,9 +21,8 @@ CONFIG_MISC_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ns2> "
 CONFIG_CMD_EEPROM=y
-CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
-CONFIG_CMD_SF=y
+CONFIG_CMD_SATA=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
@@ -39,15 +39,20 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=20000000
 CONFIG_ENV_ADDR=0x70000
-CONFIG_MVSATA_IDE=y
+CONFIG_DM=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_DM_ETH=y
 CONFIG_MVGBE=y
 CONFIG_MII=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index ac604b5..dcf2f44 100644 (file)
@@ -60,6 +60,7 @@ CONFIG_CMD_LINK_LOCAL=y
 CONFIG_CMD_ETHSW=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_RTC=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_SOUND=y
index 8a9ec87..9b74e40 100644 (file)
@@ -69,6 +69,7 @@ CONFIG_CMD_ETHSW=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_BOOTCOUNT=y
 CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_RTC=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_SOUND=y
index dfcc435..4158b9b 100644 (file)
@@ -49,6 +49,7 @@ CONFIG_CMD_SNTP=y
 CONFIG_CMD_DNS=y
 CONFIG_CMD_LINK_LOCAL=y
 CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_RTC=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIMER=y
 CONFIG_CMD_SOUND=y
diff --git a/doc/device-tree-bindings/i2c/i2c-cortina.txt b/doc/device-tree-bindings/i2c/i2c-cortina.txt
new file mode 100644 (file)
index 0000000..59d5235
--- /dev/null
@@ -0,0 +1,18 @@
+* I2C for Cortina platforms
+
+Required properties :
+- compatible : Must be "cortina,ca-i2c"
+- reg : Offset and length of the register set for the device
+
+Recommended properties :
+- clock-frequency : desired I2C bus clock frequency in Hz. If not specified,
+                   default value is 100000. Possible values are 100000,
+                   400000 and 1000000.
+
+Examples :
+
+       i2c: i2c@f4329120 {
+               compatible = "cortina,ca-i2c";
+               reg = <0x0 0xf4329120 0x28>;
+               clock-frequency = <400000>;
+       };
diff --git a/doc/device-tree-bindings/i2c/octeon-i2c.txt b/doc/device-tree-bindings/i2c/octeon-i2c.txt
new file mode 100644 (file)
index 0000000..9c1908e
--- /dev/null
@@ -0,0 +1,24 @@
+* I2C controller embedded in Marvell Octeon platforms
+
+Required properties :
+- compatible : Must be "cavium,octeon-7890-twsi" or a compatible string
+- reg : Offset and length of the register set for the device
+- clocks: Must contain the input clock of the I2C instance
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties :
+- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified,
+  the default 100 kHz frequency will be used. As only Normal, Fast and Fast+
+  modes are implemented, possible values are 100000, 400000 and 1000000.
+
+Example :
+
+       i2c0: i2c@1180000001000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "cavium,octeon-7890-twsi";
+               reg = <0x11800 0x00001000 0x0 0x200>;
+               clock-frequency = <100000>;
+               clocks = <&sclk>;
+       };
diff --git a/doc/device-tree-bindings/pwm/pwm-sifive.txt b/doc/device-tree-bindings/pwm/pwm-sifive.txt
new file mode 100644 (file)
index 0000000..9a98837
--- /dev/null
@@ -0,0 +1,31 @@
+SiFive PWM controller
+
+Unlike most other PWM controllers, the SiFive PWM controller currently only
+supports one period for all channels in the PWM. All PWMs need to run at
+the same period. The period also has significant restrictions on the values
+it can achieve, which the driver rounds to the nearest achievable period.
+PWM RTL that corresponds to the IP block version numbers can be found
+here:
+
+https://github.com/sifive/sifive-blocks/tree/master/src/main/scala/devices/pwm
+
+Required properties:
+- compatible: Should be "sifive,<chip>-pwm" and "sifive,pwm<version>".
+  Supported compatible strings are: "sifive,fu540-c000-pwm" for the SiFive
+  PWM v0 as integrated onto the SiFive FU540 chip, and "sifive,pwm0" for the
+  SiFive PWM v0 IP block with no chip integration tweaks.
+- reg: physical base address and length of the controller's registers
+- clocks: Should contain a clock identifier for the PWM's parent clock.
+- #pwm-cells: Should be 3.
+- interrupts: one interrupt per PWM channel
+
+Examples:
+
+pwm:  pwm@10020000 {
+       compatible = "sifive,fu540-c000-pwm", "sifive,pwm0";
+       reg = <0x0 0x10020000 0x0 0x1000>;
+       clocks = <&tlclk>;
+       interrupt-parent = <&plic>;
+       interrupts = <42 43 44 45>;
+       #pwm-cells = <3>;
+};
index df832ac..58ffb20 100644 (file)
@@ -11,7 +11,7 @@
 #define VREF_MAX_INDEX                 7
 #define MAX_VALUE                      (1024 - 1)
 #define MIN_VALUE                      (-MAX_VALUE)
-#define GET_RD_SAMPLE_DELAY(data, cs)  ((data >> rd_sample_mask[cs]) & 0xf)
+#define GET_RD_SAMPLE_DELAY(data, cs)  ((data >> rd_sample_mask[cs]) & 0x1f)
 
 u32 ca_delay;
 int ddr3_tip_centr_skip_min_win_check = 0;
@@ -91,8 +91,8 @@ int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id)
                        min_read_sample = read_sample[cs_num];
        }
 
-       min_read_sample = min_read_sample - 1;
-       max_read_sample = max_read_sample + 4 + (max_phase + 1) / 2 + 1;
+       min_read_sample = min_read_sample + 2;
+       max_read_sample = max_read_sample + 7 + (max_phase + 1) / 2 + 1;
        if (min_read_sample >= 0xf)
                min_read_sample = 0xf;
        if (max_read_sample >= 0x1f)
index f8b18de..87d11b6 100644 (file)
@@ -93,6 +93,14 @@ config SYS_I2C_CADENCE
          Say yes here to select Cadence I2C Host Controller. This controller is
          e.g. used by Xilinx Zynq.
 
+config SYS_I2C_CA
+       tristate "Cortina-Access I2C Controller"
+       depends on DM_I2C && CORTINA_PLATFORM
+       default n
+       help
+         Add support for the Cortina Access I2C host controller.
+         Say yes here to select Cortina-Access I2C Host Controller.
+
 config SYS_I2C_DAVINCI
        bool "Davinci I2C Controller"
        depends on (ARCH_KEYSTONE || ARCH_DAVINCI)
@@ -374,6 +382,16 @@ config SYS_I2C_SANDBOX
          bus. Devices can be attached to the bus using the device tree
          which specifies the driver to use.  See sandbox.dts as an example.
 
+config SYS_I2C_OCTEON
+       bool "Octeon II/III/TX/TX2 I2C driver"
+       depends on (ARCH_OCTEON || ARCH_OCTEONTX || ARCH_OCTEONTX2) && DM_I2C
+       default y
+       help
+         Add support for the Marvell Octeon I2C driver. This is used with
+         various Octeon parts such as Octeon II/III and OcteonTX/TX2. All
+         chips have several I2C ports and all are provided, controlled by
+         the device tree.
+
 config SYS_I2C_S3C24X0
        bool "Samsung I2C driver"
        depends on ARCH_EXYNOS4 && DM_I2C
index 62935b7..174081e 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_SYS_I2C) += i2c_core.o
 obj-$(CONFIG_SYS_I2C_ASPEED) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
+obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
 ifdef CONFIG_DM_PCI
@@ -27,6 +28,7 @@ obj-$(CONFIG_SYS_I2C_LPC32XX) += lpc32xx_i2c.o
 obj-$(CONFIG_SYS_I2C_MESON) += meson_i2c.o
 obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o
 obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
+obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o
 obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
 obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o
 obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
diff --git a/drivers/i2c/i2c-cortina.c b/drivers/i2c/i2c-cortina.c
new file mode 100644 (file)
index 0000000..036fc42
--- /dev/null
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020
+ * Arthur Li, Cortina Access, arthur.li@cortina-access.com.
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <log.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <mapmem.h>
+#include "i2c-cortina.h"
+
+static void set_speed(struct i2c_regs *regs, int i2c_spd)
+{
+       union ca_biw_cfg i2c_cfg;
+
+       i2c_cfg.wrd = readl(&regs->i2c_cfg);
+       i2c_cfg.bf.core_en = 0;
+       writel(i2c_cfg.wrd, &regs->i2c_cfg);
+
+       switch (i2c_spd) {
+       case IC_SPEED_MODE_FAST_PLUS:
+               i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
+                                 (5 * I2C_SPEED_FAST_PLUS_RATE) - 1;
+               break;
+
+       case IC_SPEED_MODE_STANDARD:
+               i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
+                                 (5 * I2C_SPEED_STANDARD_RATE) - 1;
+               break;
+
+       case IC_SPEED_MODE_FAST:
+       default:
+               i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
+                                 (5 * I2C_SPEED_FAST_RATE) - 1;
+               break;
+       }
+
+       i2c_cfg.bf.core_en = 1;
+       writel(i2c_cfg.wrd, &regs->i2c_cfg);
+}
+
+static int ca_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+       struct ca_i2c *priv = dev_get_priv(bus);
+       int i2c_spd;
+
+       if (speed >= I2C_SPEED_FAST_PLUS_RATE) {
+               i2c_spd = IC_SPEED_MODE_FAST_PLUS;
+               priv->speed = I2C_SPEED_FAST_PLUS_RATE;
+       } else if (speed >= I2C_SPEED_FAST_RATE) {
+               i2c_spd = IC_SPEED_MODE_FAST;
+               priv->speed = I2C_SPEED_FAST_RATE;
+       } else {
+               i2c_spd = IC_SPEED_MODE_STANDARD;
+               priv->speed = I2C_SPEED_STANDARD_RATE;
+       }
+
+       set_speed(priv->regs, i2c_spd);
+
+       return 0;
+}
+
+static int ca_i2c_get_bus_speed(struct udevice *bus)
+{
+       struct ca_i2c *priv = dev_get_priv(bus);
+
+       return priv->speed;
+}
+
+static void ca_i2c_init(struct i2c_regs *regs)
+{
+       union ca_biw_cfg i2c_cfg;
+
+       i2c_cfg.wrd = readl(&regs->i2c_cfg);
+       i2c_cfg.bf.core_en = 0;
+       i2c_cfg.bf.biw_soft_reset = 1;
+       writel(i2c_cfg.wrd, &regs->i2c_cfg);
+       mdelay(10);
+       i2c_cfg.bf.biw_soft_reset = 0;
+       writel(i2c_cfg.wrd, &regs->i2c_cfg);
+
+       set_speed(regs, IC_SPEED_MODE_STANDARD);
+
+       i2c_cfg.wrd = readl(&regs->i2c_cfg);
+       i2c_cfg.bf.core_en = 1;
+       writel(i2c_cfg.wrd, &regs->i2c_cfg);
+}
+
+static int i2c_wait_complete(struct i2c_regs *regs)
+{
+       union ca_biw_ctrl i2c_ctrl;
+       unsigned long start_time_bb = get_timer(0);
+
+       i2c_ctrl.wrd = readl(&regs->i2c_ctrl);
+
+       while (i2c_ctrl.bf.biwdone == 0) {
+               i2c_ctrl.wrd = readl(&regs->i2c_ctrl);
+
+               if (get_timer(start_time_bb) >
+                  (unsigned long)(I2C_BYTE_TO_BB)) {
+                       printf("%s not done!!!\n", __func__);
+                       return -ETIMEDOUT;
+               }
+       }
+
+       /* Clear done bit */
+       writel(i2c_ctrl.wrd, &regs->i2c_ctrl);
+
+       return 0;
+}
+
+static void i2c_setaddress(struct i2c_regs *regs, unsigned int i2c_addr,
+                          int write_read)
+{
+       writel(i2c_addr | write_read, &regs->i2c_txr);
+
+       writel(BIW_CTRL_START | BIW_CTRL_WRITE,
+              &regs->i2c_ctrl);
+
+       i2c_wait_complete(regs);
+}
+
+static int i2c_wait_for_bus_busy(struct i2c_regs *regs)
+{
+       union ca_biw_ack i2c_ack;
+       unsigned long start_time_bb = get_timer(0);
+
+       i2c_ack.wrd = readl(&regs->i2c_ack);
+
+       while (i2c_ack.bf.biw_busy) {
+               i2c_ack.wrd = readl(&regs->i2c_ack);
+
+               if (get_timer(start_time_bb) >
+                  (unsigned long)(I2C_BYTE_TO_BB)) {
+                       printf("%s: timeout!\n", __func__);
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
+static int i2c_xfer_init(struct i2c_regs *regs, uint8_t chip, uint addr,
+                        int alen, int write_read)
+{
+       int addr_len = alen;
+
+       if (i2c_wait_for_bus_busy(regs))
+               return 1;
+
+       /* First cycle must write addr + offset */
+       chip = ((chip & 0x7F) << 1);
+       if (alen == 0 && write_read == I2C_CMD_RD)
+               i2c_setaddress(regs, chip, I2C_CMD_RD);
+       else
+               i2c_setaddress(regs, chip, I2C_CMD_WT);
+
+       while (alen) {
+               alen--;
+               writel(addr, &regs->i2c_txr);
+               if (write_read == I2C_CMD_RD)
+                       writel(BIW_CTRL_WRITE | BIW_CTRL_STOP,
+                              &regs->i2c_ctrl);
+               else
+                       writel(BIW_CTRL_WRITE, &regs->i2c_ctrl);
+               i2c_wait_complete(regs);
+       }
+
+       /* Send address again with Read flag if it's read command */
+       if (write_read == I2C_CMD_RD && addr_len > 0)
+               i2c_setaddress(regs, chip, I2C_CMD_RD);
+
+       return 0;
+}
+
+static int i2c_xfer_finish(struct i2c_regs *regs)
+{
+       /* Dummy read makes bus free */
+       writel(BIW_CTRL_READ | BIW_CTRL_STOP, &regs->i2c_ctrl);
+       i2c_wait_complete(regs);
+
+       if (i2c_wait_for_bus_busy(regs)) {
+               printf("Timed out waiting for bus\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int ca_i2c_read(struct i2c_regs *regs, uint8_t chip, uint addr,
+                      int alen, uint8_t *buffer, int len)
+{
+       unsigned long start_time_rx;
+       int rc = 0;
+
+       rc = i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_RD);
+       if (rc)
+               return rc;
+
+       start_time_rx = get_timer(0);
+       while (len) {
+               /* ACK_IN is ack value to send during read.
+                * ack high only on the very last byte!
+                */
+               if (len == 1)
+                       writel(BIW_CTRL_READ | BIW_CTRL_ACK_IN | BIW_CTRL_STOP,
+                              &regs->i2c_ctrl);
+               else
+                       writel(BIW_CTRL_READ, &regs->i2c_ctrl);
+
+               rc = i2c_wait_complete(regs);
+               udelay(1);
+
+               if (rc == 0) {
+                       *buffer++ =
+                               (uchar) readl(&regs->i2c_rxr);
+                       len--;
+                       start_time_rx = get_timer(0);
+
+               } else if (get_timer(start_time_rx) > I2C_BYTE_TO) {
+                       return -ETIMEDOUT;
+               }
+       }
+       i2c_xfer_finish(regs);
+       return rc;
+}
+
+static int ca_i2c_write(struct i2c_regs *regs, uint8_t chip, uint addr,
+                       int alen, uint8_t *buffer, int len)
+{
+       int rc, nb = len;
+       unsigned long start_time_tx;
+
+       rc = i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_WT);
+       if (rc)
+               return rc;
+
+       start_time_tx = get_timer(0);
+       while (len) {
+               writel(*buffer, &regs->i2c_txr);
+               if (len == 1)
+                       writel(BIW_CTRL_WRITE | BIW_CTRL_STOP,
+                              &regs->i2c_ctrl);
+               else
+                       writel(BIW_CTRL_WRITE, &regs->i2c_ctrl);
+
+               rc = i2c_wait_complete(regs);
+
+               if (rc == 0) {
+                       len--;
+                       buffer++;
+                       start_time_tx = get_timer(0);
+               } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
+static int ca_i2c_probe_chip(struct udevice *bus, uint chip_addr,
+                            uint chip_flags)
+{
+       struct ca_i2c *priv = dev_get_priv(bus);
+       int ret;
+       u32 tmp;
+
+       /* Try to read the first location of the chip */
+       ret = ca_i2c_read(priv->regs, chip_addr, 0, 1, (uchar *)&tmp, 1);
+       if (ret)
+               ca_i2c_init(priv->regs);
+
+       return ret;
+}
+
+static int ca_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+{
+       struct ca_i2c *priv = dev_get_priv(bus);
+       int ret;
+
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
+               if (msg->flags & I2C_M_RD)
+                       ret = ca_i2c_read(priv->regs, msg->addr, 0, 0,
+                                         msg->buf, msg->len);
+               else
+                       ret = ca_i2c_write(priv->regs, msg->addr, 0, 0,
+                                          msg->buf, msg->len);
+
+               if (ret) {
+                       printf("i2c_xfer: %s error\n",
+                              msg->flags & I2C_M_RD ? "read" : "write");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct dm_i2c_ops ca_i2c_ops = {
+       .xfer           = ca_i2c_xfer,
+       .probe_chip     = ca_i2c_probe_chip,
+       .set_bus_speed  = ca_i2c_set_bus_speed,
+       .get_bus_speed  = ca_i2c_get_bus_speed,
+};
+
+static const struct udevice_id ca_i2c_ids[] = {
+       { .compatible = "cortina,ca-i2c", },
+       { }
+};
+
+static int ca_i2c_probe(struct udevice *bus)
+{
+       struct ca_i2c *priv = dev_get_priv(bus);
+
+       ca_i2c_init(priv->regs);
+
+       return 0;
+}
+
+static int ca_i2c_ofdata_to_platdata(struct udevice *bus)
+{
+       struct ca_i2c *priv = dev_get_priv(bus);
+
+       priv->regs = map_sysmem(dev_read_addr(bus), sizeof(struct i2c_regs));
+       if (!priv->regs) {
+               printf("I2C: base address is invalid\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+U_BOOT_DRIVER(i2c_cortina) = {
+       .name   = "i2c_cortina",
+       .id     = UCLASS_I2C,
+       .of_match = ca_i2c_ids,
+       .ofdata_to_platdata = ca_i2c_ofdata_to_platdata,
+       .probe  = ca_i2c_probe,
+       .priv_auto_alloc_size = sizeof(struct ca_i2c),
+       .ops    = &ca_i2c_ops,
+       .flags  = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/i2c/i2c-cortina.h b/drivers/i2c/i2c-cortina.h
new file mode 100644 (file)
index 0000000..7e406b5
--- /dev/null
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019
+ * Cortina Access, <www.cortina-access.com>
+ */
+
+#ifndef __CA_I2C_H_
+#define __CA_I2C_H_
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+
+#if !defined(__ASSEMBLER__) && !defined(__ASSEMBLY__)
+struct i2c_regs {
+       u32 i2c_cfg;
+       u32 i2c_ctrl;
+       u32 i2c_txr;
+       u32 i2c_rxr;
+       u32 i2c_ack;
+       u32 i2c_ie0;
+       u32 i2c_int0;
+       u32 i2c_ie1;
+       u32 i2c_int1;
+       u32 i2c_stat;
+};
+
+union ca_biw_cfg {
+       struct biw_cfg {
+               u32 core_en             : 1;
+               u32 biw_soft_reset      : 1;
+               u32 busywait_en         : 1;
+               u32 stretch_en          : 1;
+               u32 arb_en              : 1;
+               u32 clksync_en          : 1;
+               u32 rsrvd1              : 2;
+               u32 spike_cnt           : 4;
+               u32 rsrvd2              : 4;
+               u32 prer                : 16;
+       } bf;
+       unsigned int wrd;
+};
+
+union ca_biw_ctrl {
+       struct biw_ctrl {
+               u32 biwdone     : 1;
+               u32 rsrvd1      : 2;
+               u32 ack_in      : 1;
+               u32 write       : 1;
+               u32 read        : 1;
+               u32 stop        : 1;
+               u32 start       : 1;
+               u32 rsrvd2      : 24;
+       } bf;
+       unsigned int wrd;
+};
+
+union ca_biw_ack {
+       struct biw_ack {
+               u32 al          :1;
+               u32 biw_busy    :1;
+               u32 ack_out     :1;
+               u32 rsrvd1      :29;
+       } bf;
+       unsigned int wrd;
+};
+#endif /* !__ASSEMBLER__*/
+
+struct ca_i2c {
+       struct i2c_regs *regs;
+       unsigned int speed;
+};
+
+#define I2C_CMD_WT                     0
+#define I2C_CMD_RD                     1
+
+#define BIW_CTRL_DONE          BIT(0)
+#define BIW_CTRL_ACK_IN                BIT(3)
+#define BIW_CTRL_WRITE         BIT(4)
+#define BIW_CTRL_READ          BIT(5)
+#define BIW_CTRL_STOP          BIT(6)
+#define BIW_CTRL_START         BIT(7)
+
+#define I2C_BYTE_TO            (CONFIG_SYS_HZ / 500)
+#define I2C_STOPDET_TO         (CONFIG_SYS_HZ / 500)
+#define I2C_BYTE_TO_BB         (10)
+
+#endif                                                 /* __CA_I2C_H_ */
index c8e42e0..b7b2aaf 100644 (file)
@@ -97,7 +97,8 @@ static int bus_i2c_wait_for_tx_ready(struct imx_lpi2c_reg *regs)
 
 static int bus_i2c_send(struct udevice *bus, u8 *txbuf, int len)
 {
-       struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
+       struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
+       struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)(i2c_bus->base);
        lpi2c_status_t result = LPI2C_SUCESS;
 
        /* empty tx */
@@ -118,7 +119,8 @@ static int bus_i2c_send(struct udevice *bus, u8 *txbuf, int len)
 
 static int bus_i2c_receive(struct udevice *bus, u8 *rxbuf, int len)
 {
-       struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
+       struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
+       struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)(i2c_bus->base);
        lpi2c_status_t result = LPI2C_SUCESS;
        u32 val;
        ulong start_time = get_timer(0);
@@ -162,8 +164,8 @@ static int bus_i2c_receive(struct udevice *bus, u8 *rxbuf, int len)
 static int bus_i2c_start(struct udevice *bus, u8 addr, u8 dir)
 {
        lpi2c_status_t result;
-       struct imx_lpi2c_reg *regs =
-               (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
+       struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
+       struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)(i2c_bus->base);
        u32 val;
 
        result = imx_lpci2c_check_busy_bus(regs);
@@ -199,8 +201,8 @@ static int bus_i2c_start(struct udevice *bus, u8 addr, u8 dir)
 static int bus_i2c_stop(struct udevice *bus)
 {
        lpi2c_status_t result;
-       struct imx_lpi2c_reg *regs =
-               (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
+       struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
+       struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)(i2c_bus->base);
        u32 status;
        ulong start_time;
 
@@ -271,7 +273,7 @@ u32 __weak imx_get_i2cclk(u32 i2c_num)
 static int bus_i2c_set_bus_speed(struct udevice *bus, int speed)
 {
        struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
-       struct imx_lpi2c_reg *regs;
+       struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)(i2c_bus->base);
        u32 val;
        u32 preescale = 0, best_pre = 0, clkhi = 0;
        u32 best_clkhi = 0, abs_error = 0, rate;
@@ -280,8 +282,6 @@ static int bus_i2c_set_bus_speed(struct udevice *bus, int speed)
        bool mode;
        int i;
 
-       regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
-
        if (IS_ENABLED(CONFIG_CLK)) {
                clock_rate = clk_get_rate(&i2c_bus->per_clk);
                if (clock_rate <= 0) {
@@ -348,11 +348,11 @@ static int bus_i2c_set_bus_speed(struct udevice *bus, int speed)
 
 static int bus_i2c_init(struct udevice *bus, int speed)
 {
-       struct imx_lpi2c_reg *regs;
        u32 val;
        int ret;
 
-       regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
+       struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
+       struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)(i2c_bus->base);
        /* reset peripheral */
        writel(LPI2C_MCR_RST_MASK, &regs->mcr);
        writel(0x0, &regs->mcr);
diff --git a/drivers/i2c/octeon_i2c.c b/drivers/i2c/octeon_i2c.c
new file mode 100644 (file)
index 0000000..c11d6ff
--- /dev/null
@@ -0,0 +1,847 @@
+// SPDX-License-Identifier:    GPL-2.0
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <i2c.h>
+#include <pci_ids.h>
+#include <asm/io.h>
+#include <linux/bitfield.h>
+#include <linux/compat.h>
+#include <linux/delay.h>
+
+#define TWSI_SW_TWSI           0x00
+#define TWSI_TWSI_SW           0x08
+#define TWSI_INT               0x10
+#define TWSI_SW_TWSI_EXT       0x18
+
+#define TWSI_SW_DATA_MASK      GENMASK_ULL(31, 0)
+#define TWSI_SW_EOP_IA_MASK    GENMASK_ULL(34, 32)
+#define TWSI_SW_IA_MASK                GENMASK_ULL(39, 35)
+#define TWSI_SW_ADDR_MASK      GENMASK_ULL(49, 40)
+#define TWSI_SW_SCR_MASK       GENMASK_ULL(51, 50)
+#define TWSI_SW_SIZE_MASK      GENMASK_ULL(54, 52)
+#define TWSI_SW_SOVR           BIT_ULL(55)
+#define TWSI_SW_R              BIT_ULL(56)
+#define TWSI_SW_OP_MASK                GENMASK_ULL(60, 57)
+#define TWSI_SW_EIA            GENMASK_ULL(61)
+#define TWSI_SW_SLONLY         BIT_ULL(62)
+#define TWSI_SW_V              BIT_ULL(63)
+
+#define TWSI_INT_SDA_OVR       BIT_ULL(8)
+#define TWSI_INT_SCL_OVR       BIT_ULL(9)
+#define TWSI_INT_SDA           BIT_ULL(10)
+#define TWSI_INT_SCL           BIT_ULL(11)
+
+enum {
+       TWSI_OP_WRITE   = 0,
+       TWSI_OP_READ    = 1,
+};
+
+enum {
+       TWSI_EOP_SLAVE_ADDR = 0,
+       TWSI_EOP_CLK_CTL = 3,
+       TWSI_SW_EOP_IA   = 6,
+};
+
+enum {
+       TWSI_SLAVEADD     = 0,
+       TWSI_DATA         = 1,
+       TWSI_CTL          = 2,
+       TWSI_CLKCTL       = 3,
+       TWSI_STAT         = 3,
+       TWSI_SLAVEADD_EXT = 4,
+       TWSI_RST          = 7,
+};
+
+enum {
+       TWSI_CTL_AAK    = BIT(2),
+       TWSI_CTL_IFLG   = BIT(3),
+       TWSI_CTL_STP    = BIT(4),
+       TWSI_CTL_STA    = BIT(5),
+       TWSI_CTL_ENAB   = BIT(6),
+       TWSI_CTL_CE     = BIT(7),
+};
+
+/*
+ * Internal errors. When debugging is enabled, the driver will report the
+ * error number and the user / developer can check the table below for the
+ * detailed error description.
+ */
+enum {
+       /** Bus error */
+       TWSI_STAT_BUS_ERROR             = 0x00,
+       /** Start condition transmitted */
+       TWSI_STAT_START                 = 0x08,
+       /** Repeat start condition transmitted */
+       TWSI_STAT_RSTART                = 0x10,
+       /** Address + write bit transmitted, ACK received */
+       TWSI_STAT_TXADDR_ACK            = 0x18,
+       /** Address + write bit transmitted, /ACK received */
+       TWSI_STAT_TXADDR_NAK            = 0x20,
+       /** Data byte transmitted in master mode, ACK received */
+       TWSI_STAT_TXDATA_ACK            = 0x28,
+       /** Data byte transmitted in master mode, ACK received */
+       TWSI_STAT_TXDATA_NAK            = 0x30,
+       /** Arbitration lost in address or data byte */
+       TWSI_STAT_TX_ARB_LOST           = 0x38,
+       /** Address + read bit transmitted, ACK received */
+       TWSI_STAT_RXADDR_ACK            = 0x40,
+       /** Address + read bit transmitted, /ACK received */
+       TWSI_STAT_RXADDR_NAK            = 0x48,
+       /** Data byte received in master mode, ACK transmitted */
+       TWSI_STAT_RXDATA_ACK_SENT       = 0x50,
+       /** Data byte received, NACK transmitted */
+       TWSI_STAT_RXDATA_NAK_SENT       = 0x58,
+       /** Slave address received, sent ACK */
+       TWSI_STAT_SLAVE_RXADDR_ACK      = 0x60,
+       /**
+        * Arbitration lost in address as master, slave address + write bit
+        * received, ACK transmitted
+        */
+       TWSI_STAT_TX_ACK_ARB_LOST       = 0x68,
+       /** General call address received, ACK transmitted */
+       TWSI_STAT_RX_GEN_ADDR_ACK       = 0x70,
+       /**
+        * Arbitration lost in address as master, general call address
+        * received, ACK transmitted
+        */
+       TWSI_STAT_RX_GEN_ADDR_ARB_LOST  = 0x78,
+       /** Data byte received after slave address received, ACK transmitted */
+       TWSI_STAT_SLAVE_RXDATA_ACK      = 0x80,
+       /** Data byte received after slave address received, /ACK transmitted */
+       TWSI_STAT_SLAVE_RXDATA_NAK      = 0x88,
+       /**
+        * Data byte received after general call address received, ACK
+        * transmitted
+        */
+       TWSI_STAT_GEN_RXADDR_ACK        = 0x90,
+       /**
+        * Data byte received after general call address received, /ACK
+        * transmitted
+        */
+       TWSI_STAT_GEN_RXADDR_NAK        = 0x98,
+       /** STOP or repeated START condition received in slave mode */
+       TWSI_STAT_STOP_MULTI_START      = 0xa0,
+       /** Slave address + read bit received, ACK transmitted */
+       TWSI_STAT_SLAVE_RXADDR2_ACK     = 0xa8,
+       /**
+        * Arbitration lost in address as master, slave address + read bit
+        * received, ACK transmitted
+        */
+       TWSI_STAT_RXDATA_ACK_ARB_LOST   = 0xb0,
+       /** Data byte transmitted in slave mode, ACK received */
+       TWSI_STAT_SLAVE_TXDATA_ACK      = 0xb8,
+       /** Data byte transmitted in slave mode, /ACK received */
+       TWSI_STAT_SLAVE_TXDATA_NAK      = 0xc0,
+       /** Last byte transmitted in slave mode, ACK received */
+       TWSI_STAT_SLAVE_TXDATA_END_ACK  = 0xc8,
+       /** Second address byte + write bit transmitted, ACK received */
+       TWSI_STAT_TXADDR2DATA_ACK       = 0xd0,
+       /** Second address byte + write bit transmitted, /ACK received */
+       TWSI_STAT_TXADDR2DATA_NAK       = 0xd8,
+       /** No relevant status information */
+       TWSI_STAT_IDLE                  = 0xf8
+};
+
+#define CONFIG_SYS_I2C_OCTEON_SLAVE_ADDR       0x77
+
+enum {
+       PROBE_PCI = 0,          /* PCI based probing */
+       PROBE_DT,               /* DT based probing */
+};
+
+enum {
+       CLK_METHOD_OCTEON = 0,
+       CLK_METHOD_OCTEONTX2,
+};
+
+/**
+ * struct octeon_i2c_data - SoC specific data of this driver
+ *
+ * @probe:     Probing of this SoC (DT vs PCI)
+ * @reg_offs:  Register offset
+ * @thp:       THP define for divider calculation
+ * @clk_method:        Clock calculation method
+ */
+struct octeon_i2c_data {
+       int probe;
+       u32 reg_offs;
+       int thp;
+       int clk_method;
+};
+
+/**
+ * struct octeon_twsi - Private data of this driver
+ *
+ * @base:      Base address of i2c registers
+ * @data:      Pointer to SoC specific data struct
+ */
+struct octeon_twsi {
+       void __iomem *base;
+       const struct octeon_i2c_data *data;
+       struct clk clk;
+};
+
+static void twsi_unblock(void *base);
+static int twsi_stop(void *base);
+
+/**
+ * Returns true if we lost arbitration
+ *
+ * @code       status code
+ * @final_read true if this is the final read operation
+ * @return     true if arbitration has been lost, false if it hasn't been lost.
+ */
+static int twsi_i2c_lost_arb(u8 code, int final_read)
+{
+       switch (code) {
+       case TWSI_STAT_TX_ARB_LOST:
+       case TWSI_STAT_TX_ACK_ARB_LOST:
+       case TWSI_STAT_RX_GEN_ADDR_ARB_LOST:
+       case TWSI_STAT_RXDATA_ACK_ARB_LOST:
+               /* Arbitration lost */
+               return -EAGAIN;
+
+       case TWSI_STAT_SLAVE_RXADDR_ACK:
+       case TWSI_STAT_RX_GEN_ADDR_ACK:
+       case TWSI_STAT_GEN_RXADDR_ACK:
+       case TWSI_STAT_GEN_RXADDR_NAK:
+               /* Being addressed as slave, should back off and listen */
+               return -EIO;
+
+       case TWSI_STAT_SLAVE_RXDATA_ACK:
+       case TWSI_STAT_SLAVE_RXDATA_NAK:
+       case TWSI_STAT_STOP_MULTI_START:
+       case TWSI_STAT_SLAVE_RXADDR2_ACK:
+       case TWSI_STAT_SLAVE_TXDATA_ACK:
+       case TWSI_STAT_SLAVE_TXDATA_NAK:
+       case TWSI_STAT_SLAVE_TXDATA_END_ACK:
+               /* Core busy as slave */
+               return  -EIO;
+
+       case TWSI_STAT_RXDATA_ACK_SENT:
+               /* Ack allowed on pre-terminal bytes only */
+               if (!final_read)
+                       return 0;
+               return -EAGAIN;
+
+       case TWSI_STAT_RXDATA_NAK_SENT:
+               /* NAK allowed on terminal byte only */
+               if (!final_read)
+                       return 0;
+               return -EAGAIN;
+
+       case TWSI_STAT_TXDATA_NAK:
+       case TWSI_STAT_TXADDR_NAK:
+       case TWSI_STAT_RXADDR_NAK:
+       case TWSI_STAT_TXADDR2DATA_NAK:
+               return -EAGAIN;
+       }
+
+       return 0;
+}
+
+/**
+ * Writes to the MIO_TWS(0..5)_SW_TWSI register
+ *
+ * @base       Base address of i2c registers
+ * @val                value to write
+ * @return     0 for success, otherwise error
+ */
+static u64 twsi_write_sw(void __iomem *base, u64 val)
+{
+       unsigned long start = get_timer(0);
+
+       val &= ~TWSI_SW_R;
+       val |= TWSI_SW_V;
+
+       debug("%s(%p, 0x%llx)\n", __func__, base, val);
+       writeq(val, base + TWSI_SW_TWSI);
+       do {
+               val = readq(base + TWSI_SW_TWSI);
+       } while ((val & TWSI_SW_V) && (get_timer(start) < 50));
+
+       if (val & TWSI_SW_V)
+               debug("%s: timed out\n", __func__);
+       return val;
+}
+
+/**
+ * Reads the MIO_TWS(0..5)_SW_TWSI register
+ *
+ * @base       Base address of i2c registers
+ * @val                value for eia and op, etc. to read
+ * @return     value of the register
+ */
+static u64 twsi_read_sw(void __iomem *base, u64 val)
+{
+       unsigned long start = get_timer(0);
+
+       val |= TWSI_SW_R | TWSI_SW_V;
+
+       debug("%s(%p, 0x%llx)\n", __func__, base, val);
+       writeq(val, base + TWSI_SW_TWSI);
+
+       do {
+               val = readq(base + TWSI_SW_TWSI);
+       } while ((val & TWSI_SW_V) && (get_timer(start) < 50));
+
+       if (val & TWSI_SW_V)
+               debug("%s: Error writing 0x%llx\n", __func__, val);
+
+       debug("%s: Returning 0x%llx\n", __func__, val);
+       return val;
+}
+
+/**
+ * Write control register
+ *
+ * @base       Base address for i2c registers
+ * @data       data to write
+ */
+static void twsi_write_ctl(void __iomem *base, u8 data)
+{
+       u64 val;
+
+       debug("%s(%p, 0x%x)\n", __func__, base, data);
+       val = data | FIELD_PREP(TWSI_SW_EOP_IA_MASK, TWSI_CTL) |
+               FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA);
+       twsi_write_sw(base, val);
+}
+
+/**
+ * Reads the TWSI Control Register
+ *
+ * @base       Base address for i2c
+ * @return     8-bit TWSI control register
+ */
+static u8 twsi_read_ctl(void __iomem *base)
+{
+       u64 val;
+
+       val = FIELD_PREP(TWSI_SW_EOP_IA_MASK, TWSI_CTL) |
+               FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA);
+       val = twsi_read_sw(base, val);
+
+       debug("%s(%p): 0x%x\n", __func__, base, (u8)val);
+       return (u8)val;
+}
+
+/**
+ * Read i2c status register
+ *
+ * @base       Base address of i2c registers
+ * @return     value of status register
+ */
+static u8 twsi_read_status(void __iomem *base)
+{
+       u64 val;
+
+       val = FIELD_PREP(TWSI_SW_EOP_IA_MASK, TWSI_STAT) |
+               FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA);
+
+       return twsi_read_sw(base, val);
+}
+
+/**
+ * Waits for an i2c operation to complete
+ *
+ * @param      base    Base address of registers
+ * @return     0 for success, 1 if timeout
+ */
+static int twsi_wait(void __iomem *base)
+{
+       unsigned long start = get_timer(0);
+       u8 twsi_ctl;
+
+       debug("%s(%p)\n", __func__, base);
+       do {
+               twsi_ctl = twsi_read_ctl(base);
+               twsi_ctl &= TWSI_CTL_IFLG;
+       } while (!twsi_ctl && get_timer(start) < 50);
+
+       debug("  return: %u\n", !twsi_ctl);
+       return !twsi_ctl;
+}
+
+/**
+ * Unsticks the i2c bus
+ *
+ * @base       base address of registers
+ */
+static int twsi_start_unstick(void __iomem *base)
+{
+       twsi_stop(base);
+       twsi_unblock(base);
+
+       return 0;
+}
+
+/**
+ * Sends an i2c start condition
+ *
+ * @base       base address of registers
+ * @return     0 for success, otherwise error
+ */
+static int twsi_start(void __iomem *base)
+{
+       int ret;
+       u8 stat;
+
+       debug("%s(%p)\n", __func__, base);
+       twsi_write_ctl(base, TWSI_CTL_STA | TWSI_CTL_ENAB);
+       ret = twsi_wait(base);
+       if (ret) {
+               stat = twsi_read_status(base);
+               debug("%s: ret: 0x%x, status: 0x%x\n", __func__, ret, stat);
+               switch (stat) {
+               case TWSI_STAT_START:
+               case TWSI_STAT_RSTART:
+                       return 0;
+               case TWSI_STAT_RXADDR_ACK:
+               default:
+                       return twsi_start_unstick(base);
+               }
+       }
+
+       debug("%s: success\n", __func__);
+       return 0;
+}
+
+/**
+ * Sends an i2c stop condition
+ *
+ * @base       register base address
+ * @return     0 for success, -1 if error
+ */
+static int twsi_stop(void __iomem *base)
+{
+       u8 stat;
+
+       twsi_write_ctl(base, TWSI_CTL_STP | TWSI_CTL_ENAB);
+
+       stat = twsi_read_status(base);
+       if (stat != TWSI_STAT_IDLE) {
+               debug("%s: Bad status on bus@%p\n", __func__, base);
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Writes data to the i2c bus
+ *
+ * @base       register base address
+ * @slave_addr address of slave to write to
+ * @buffer     Pointer to buffer to write
+ * @length     Number of bytes in buffer to write
+ * @return     0 for success, otherwise error
+ */
+static int twsi_write_data(void __iomem *base, u8  slave_addr,
+                          u8 *buffer, unsigned int length)
+{
+       unsigned int curr = 0;
+       u64 val;
+       int ret;
+
+       debug("%s(%p, 0x%x, %p, 0x%x)\n", __func__, base, slave_addr,
+             buffer, length);
+       ret = twsi_start(base);
+       if (ret) {
+               debug("%s: Could not start BUS transaction\n", __func__);
+               return -1;
+       }
+
+       ret = twsi_wait(base);
+       if (ret) {
+               debug("%s: wait failed\n", __func__);
+               return ret;
+       }
+
+       val = (u32)(slave_addr << 1) | TWSI_OP_WRITE |
+               FIELD_PREP(TWSI_SW_EOP_IA_MASK, TWSI_DATA) |
+               FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA);
+       twsi_write_sw(base, val);
+       twsi_write_ctl(base, TWSI_CTL_ENAB);
+
+       debug("%s: Waiting\n", __func__);
+       ret = twsi_wait(base);
+       if (ret) {
+               debug("%s: Timed out writing slave address 0x%x to target\n",
+                     __func__, slave_addr);
+               return ret;
+       }
+
+       ret = twsi_read_status(base);
+       debug("%s: status: 0x%x\n", __func__, ret);
+       if (ret != TWSI_STAT_TXADDR_ACK) {
+               debug("%s: status: 0x%x\n", __func__, ret);
+               twsi_stop(base);
+               return twsi_i2c_lost_arb(ret, 0);
+       }
+
+       while (curr < length) {
+               val = buffer[curr++] |
+                       FIELD_PREP(TWSI_SW_EOP_IA_MASK, TWSI_DATA) |
+                       FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA);
+               twsi_write_sw(base, val);
+               twsi_write_ctl(base, TWSI_CTL_ENAB);
+
+               debug("%s: Writing 0x%llx\n", __func__, val);
+
+               ret = twsi_wait(base);
+               if (ret) {
+                       debug("%s: Timed out writing data to 0x%x\n",
+                             __func__, slave_addr);
+                       return ret;
+               }
+               ret = twsi_read_status(base);
+               debug("%s: status: 0x%x\n", __func__, ret);
+       }
+
+       debug("%s: Stopping\n", __func__);
+       return twsi_stop(base);
+}
+
+/**
+ * Manually clear the I2C bus and send a stop
+ *
+ * @base       register base address
+ */
+static void twsi_unblock(void __iomem *base)
+{
+       int i;
+
+       for (i = 0; i < 9; i++) {
+               writeq(0, base + TWSI_INT);
+               udelay(5);
+               writeq(TWSI_INT_SCL_OVR, base + TWSI_INT);
+               udelay(5);
+       }
+       writeq(TWSI_INT_SCL_OVR | TWSI_INT_SDA_OVR, base + TWSI_INT);
+       udelay(5);
+       writeq(TWSI_INT_SDA_OVR, base + TWSI_INT);
+       udelay(5);
+       writeq(0, base + TWSI_INT);
+       udelay(5);
+}
+
+/**
+ * Performs a read transaction on the i2c bus
+ *
+ * @base       Base address of twsi registers
+ * @slave_addr i2c bus address to read from
+ * @buffer     buffer to read into
+ * @length     number of bytes to read
+ * @return     0 for success, otherwise error
+ */
+static int twsi_read_data(void __iomem *base, u8 slave_addr,
+                         u8 *buffer, unsigned int length)
+{
+       unsigned int curr = 0;
+       u64 val;
+       int ret;
+
+       debug("%s(%p, 0x%x, %p, %u)\n", __func__, base, slave_addr,
+             buffer, length);
+       ret = twsi_start(base);
+       if (ret) {
+               debug("%s: start failed\n", __func__);
+               return ret;
+       }
+
+       ret = twsi_wait(base);
+       if (ret) {
+               debug("%s: wait failed\n", __func__);
+               return ret;
+       }
+
+       val = (u32)(slave_addr << 1) | TWSI_OP_READ |
+               FIELD_PREP(TWSI_SW_EOP_IA_MASK, TWSI_DATA) |
+               FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA);
+       twsi_write_sw(base, val);
+       twsi_write_ctl(base, TWSI_CTL_ENAB);
+
+       ret = twsi_wait(base);
+       if (ret) {
+               debug("%s: waiting for sending addr failed\n", __func__);
+               return ret;
+       }
+
+       ret = twsi_read_status(base);
+       debug("%s: status: 0x%x\n", __func__, ret);
+       if (ret != TWSI_STAT_RXADDR_ACK) {
+               debug("%s: status: 0x%x\n", __func__, ret);
+               twsi_stop(base);
+               return twsi_i2c_lost_arb(ret, 0);
+       }
+
+       while (curr < length) {
+               twsi_write_ctl(base, TWSI_CTL_ENAB |
+                              ((curr < length - 1) ? TWSI_CTL_AAK : 0));
+
+               ret = twsi_wait(base);
+               if (ret) {
+                       debug("%s: waiting for data failed\n", __func__);
+                       return ret;
+               }
+
+               val = twsi_read_sw(base, val);
+               buffer[curr++] = (u8)val;
+       }
+
+       twsi_stop(base);
+
+       return 0;
+}
+
+/**
+ * Calculate the divisor values
+ *
+ * @speed      Speed to set
+ * @m_div      Pointer to M divisor
+ * @n_div      Pointer to N divisor
+ * @return     0 for success, otherwise error
+ */
+static void twsi_calc_div(struct udevice *bus, ulong sclk, unsigned int speed,
+                         int *m_div, int *n_div)
+{
+       struct octeon_twsi *twsi = dev_get_priv(bus);
+       int thp = twsi->data->thp;
+       int tclk, fsamp;
+       int ndiv, mdiv;
+
+       if (twsi->data->clk_method == CLK_METHOD_OCTEON) {
+               tclk = sclk / (2 * (thp + 1));
+       } else {
+               /* Refclk src in mode register defaults to 100MHz clock */
+               sclk = 100000000; /* 100 Mhz */
+               tclk = sclk / (thp + 2);
+       }
+       debug("%s( io_clock %lu tclk %u)\n", __func__, sclk, tclk);
+
+       /*
+        * Compute the clocks M divider:
+        *
+        * TWSI freq = (core freq) / (10 x (M+1) x 2 * (thp+1) x 2^N)
+        * M = ((core freq) / (10 x (TWSI freq) x 2 * (thp+1) x 2^N)) - 1
+        *
+        * For OcteonTX2 -
+        * TWSI freq = (core freq) / (10 x (M+1) x (thp+2) x 2^N)
+        * M = ((core freq) / (10 x (TWSI freq) x (thp+2) x 2^N)) - 1
+        */
+       for (ndiv = 0; ndiv < 8; ndiv++) {
+               fsamp = tclk / (1 << ndiv);
+               mdiv = fsamp / speed / 10;
+               mdiv -= 1;
+               if (mdiv < 16)
+                       break;
+       }
+
+       *m_div = mdiv;
+       *n_div = ndiv;
+}
+
+/**
+ * Init I2C controller
+ *
+ * @base       Base address of twsi registers
+ * @slave_addr I2C slave address to configure this controller to
+ * @return     0 for success, otherwise error
+ */
+static int twsi_init(void __iomem *base, int slaveaddr)
+{
+       u64 val;
+
+       debug("%s (%p, 0x%x)\n", __func__, base, slaveaddr);
+
+       val = slaveaddr << 1 |
+               FIELD_PREP(TWSI_SW_EOP_IA_MASK, 0) |
+               FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA) |
+               TWSI_SW_V;
+       twsi_write_sw(base, val);
+
+       /* Set slave address */
+       val = slaveaddr |
+               FIELD_PREP(TWSI_SW_EOP_IA_MASK, TWSI_EOP_SLAVE_ADDR) |
+               FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA) |
+               TWSI_SW_V;
+       twsi_write_sw(base, val);
+
+       return 0;
+}
+
+/**
+ * Transfers data over the i2c bus
+ *
+ * @bus                i2c bus to transfer data over
+ * @msg                Array of i2c messages
+ * @nmsgs      Number of messages to send/receive
+ * @return     0 for success, otherwise error
+ */
+static int octeon_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+                          int nmsgs)
+{
+       struct octeon_twsi *twsi = dev_get_priv(bus);
+       int ret;
+       int i;
+
+       debug("%s: %d messages\n", __func__, nmsgs);
+       for (i = 0; i < nmsgs; i++, msg++) {
+               debug("%s: chip=0x%x, len=0x%x\n", __func__, msg->addr,
+                     msg->len);
+
+               if (msg->flags & I2C_M_RD) {
+                       debug("%s: Reading data\n", __func__);
+                       ret = twsi_read_data(twsi->base, msg->addr,
+                                            msg->buf, msg->len);
+               } else {
+                       debug("%s: Writing data\n", __func__);
+                       ret = twsi_write_data(twsi->base, msg->addr,
+                                             msg->buf, msg->len);
+               }
+               if (ret) {
+                       debug("%s: error sending\n", __func__);
+                       return -EREMOTEIO;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * Set I2C bus speed
+ *
+ * @bus                i2c bus to transfer data over
+ * @speed      Speed in Hz to set
+ * @return     0 for success, otherwise error
+ */
+static int octeon_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+       struct octeon_twsi *twsi = dev_get_priv(bus);
+       int m_div, n_div;
+       ulong clk_rate;
+       u64 val;
+
+       debug("%s(%p, %u)\n", __func__, bus, speed);
+
+       clk_rate = clk_get_rate(&twsi->clk);
+       if (IS_ERR_VALUE(clk_rate))
+               return -EINVAL;
+
+       twsi_calc_div(bus, clk_rate, speed, &m_div, &n_div);
+       if (m_div >= 16)
+               return -1;
+
+       val = (u32)(((m_div & 0xf) << 3) | ((n_div & 0x7) << 0)) |
+               FIELD_PREP(TWSI_SW_EOP_IA_MASK, TWSI_CLKCTL) |
+               FIELD_PREP(TWSI_SW_OP_MASK, TWSI_SW_EOP_IA) |
+               TWSI_SW_V;
+       /* Only init non-slave ports */
+       writeq(val, twsi->base + TWSI_SW_TWSI);
+
+       debug("%s: Wrote 0x%llx to sw_twsi\n", __func__, val);
+       return 0;
+}
+
+/**
+ * Driver probe function
+ *
+ * @dev                I2C device to probe
+ * @return     0 for success, otherwise error
+ */
+static int octeon_i2c_probe(struct udevice *dev)
+{
+       struct octeon_twsi *twsi = dev_get_priv(dev);
+       u32 i2c_slave_addr;
+       int ret;
+
+       twsi->data = (const struct octeon_i2c_data *)dev_get_driver_data(dev);
+
+       if (twsi->data->probe == PROBE_PCI) {
+               pci_dev_t bdf = dm_pci_get_bdf(dev);
+
+               debug("TWSI PCI device: %x\n", bdf);
+               dev->req_seq = PCI_FUNC(bdf);
+
+               twsi->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
+                                           PCI_REGION_MEM);
+       } else {
+               twsi->base = dev_remap_addr(dev);
+       }
+       twsi->base += twsi->data->reg_offs;
+
+       i2c_slave_addr = dev_read_u32_default(dev, "i2c-sda-hold-time-ns",
+                                             CONFIG_SYS_I2C_OCTEON_SLAVE_ADDR);
+
+       ret = clk_get_by_index(dev, 0, &twsi->clk);
+       if (ret < 0)
+               return ret;
+
+       ret = clk_enable(&twsi->clk);
+       if (ret)
+               return ret;
+
+       debug("TWSI bus %d at %p\n", dev->seq, twsi->base);
+
+       /* Start with standard speed, real speed set via DT or cmd */
+       return twsi_init(twsi->base, i2c_slave_addr);
+}
+
+static const struct dm_i2c_ops octeon_i2c_ops = {
+       .xfer           = octeon_i2c_xfer,
+       .set_bus_speed  = octeon_i2c_set_bus_speed,
+};
+
+static const struct octeon_i2c_data i2c_octeon_data = {
+       .probe = PROBE_DT,
+       .reg_offs = 0x0000,
+       .thp = 3,
+       .clk_method = CLK_METHOD_OCTEON,
+};
+
+static const struct octeon_i2c_data i2c_octeontx_data = {
+       .probe = PROBE_PCI,
+       .reg_offs = 0x8000,
+       .thp = 3,
+       .clk_method = CLK_METHOD_OCTEON,
+};
+
+static const struct octeon_i2c_data i2c_octeontx2_data = {
+       .probe = PROBE_PCI,
+       .reg_offs = 0x8000,
+       .thp = 24,
+       .clk_method = CLK_METHOD_OCTEONTX2,
+};
+
+static const struct udevice_id octeon_i2c_ids[] = {
+       { .compatible = "cavium,octeon-7890-twsi",
+         .data = (ulong)&i2c_octeon_data },
+       { .compatible = "cavium,thunder-8890-twsi",
+         .data = (ulong)&i2c_octeontx_data },
+       { .compatible = "cavium,thunder2-99xx-twsi",
+         .data = (ulong)&i2c_octeontx2_data },
+       { }
+};
+
+U_BOOT_DRIVER(octeon_pci_twsi) = {
+       .name   = "i2c_octeon",
+       .id     = UCLASS_I2C,
+       .of_match = octeon_i2c_ids,
+       .probe  = octeon_i2c_probe,
+       .priv_auto_alloc_size = sizeof(struct octeon_twsi),
+       .ops    = &octeon_i2c_ops,
+};
+
+static struct pci_device_id octeon_twsi_supported[] = {
+       { PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_CAVIUM_TWSI),
+         .driver_data = (ulong)&i2c_octeontx2_data },
+       { },
+};
+
+U_BOOT_PCI_DEVICE(octeon_pci_twsi, octeon_twsi_supported);
index ada8f40..2f60911 100644 (file)
@@ -8,7 +8,9 @@
 #include <dm.h>
 #include <i2c.h>
 #include <log.h>
+#include <regmap.h>
 #include <reset.h>
+#include <syscon.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 
@@ -154,6 +156,7 @@ struct stm32_i2c_spec {
  * @fall_time: Fall time (ns)
  * @dnf: Digital filter coefficient (0-16)
  * @analog_filter: Analog filter delay (On/Off)
+ * @fmp_clr_offset: Fast Mode Plus clear register offset from set register
  */
 struct stm32_i2c_setup {
        u32 speed_freq;
@@ -162,6 +165,7 @@ struct stm32_i2c_setup {
        u32 fall_time;
        u8 dnf;
        bool analog_filter;
+       u32 fmp_clr_offset;
 };
 
 /**
@@ -181,11 +185,26 @@ struct stm32_i2c_timings {
        u8 scll;
 };
 
+/**
+ * struct stm32_i2c_priv - private data of the controller
+ * @regs: I2C registers address
+ * @clk: hw i2c clock
+ * @setup: I2C timing setup parameters
+ * @speed: I2C clock frequency of the controller. Standard, Fast or Fast+
+ * @regmap: holds SYSCFG phandle for Fast Mode Plus bit
+ * @regmap_sreg: register address for setting Fast Mode Plus bits
+ * @regmap_creg: register address for clearing Fast Mode Plus bits
+ * @regmap_mask: mask for Fast Mode Plus bits
+ */
 struct stm32_i2c_priv {
        struct stm32_i2c_regs *regs;
        struct clk clk;
        struct stm32_i2c_setup *setup;
        u32 speed;
+       struct regmap *regmap;
+       u32 regmap_sreg;
+       u32 regmap_creg;
+       u32 regmap_mask;
 };
 
 static const struct stm32_i2c_spec i2c_specs[] = {
@@ -237,6 +256,14 @@ static const struct stm32_i2c_setup stm32f7_setup = {
        .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE,
 };
 
+static const struct stm32_i2c_setup stm32mp15_setup = {
+       .rise_time = STM32_I2C_RISE_TIME_DEFAULT,
+       .fall_time = STM32_I2C_FALL_TIME_DEFAULT,
+       .dnf = STM32_I2C_DNF_DEFAULT,
+       .analog_filter = STM32_I2C_ANALOG_FILTER_ENABLE,
+       .fmp_clr_offset = 0x40,
+};
+
 static int stm32_i2c_check_device_busy(struct stm32_i2c_priv *i2c_priv)
 {
        struct stm32_i2c_regs *regs = i2c_priv->regs;
@@ -761,6 +788,29 @@ static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv,
        return 0;
 }
 
+static int stm32_i2c_write_fm_plus_bits(struct stm32_i2c_priv *i2c_priv)
+{
+       int ret;
+       bool enable = i2c_priv->speed > I2C_SPEED_FAST_RATE;
+
+       /* Optional */
+       if (IS_ERR_OR_NULL(i2c_priv->regmap))
+               return 0;
+
+       if (i2c_priv->regmap_sreg == i2c_priv->regmap_creg)
+               ret = regmap_update_bits(i2c_priv->regmap,
+                                        i2c_priv->regmap_sreg,
+                                        i2c_priv->regmap_mask,
+                                        enable ? i2c_priv->regmap_mask : 0);
+       else
+               ret = regmap_write(i2c_priv->regmap,
+                                  enable ? i2c_priv->regmap_sreg :
+                                           i2c_priv->regmap_creg,
+                                  i2c_priv->regmap_mask);
+
+       return ret;
+}
+
 static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv)
 {
        struct stm32_i2c_regs *regs = i2c_priv->regs;
@@ -775,6 +825,11 @@ static int stm32_i2c_hw_config(struct stm32_i2c_priv *i2c_priv)
        /* Disable I2C */
        clrbits_le32(&regs->cr1, STM32_I2C_CR1_PE);
 
+       /* Setup Fast mode plus if necessary */
+       ret = stm32_i2c_write_fm_plus_bits(i2c_priv);
+       if (ret)
+               return ret;
+
        /* Timing settings */
        timing |= STM32_I2C_TIMINGR_PRESC(t.presc);
        timing |= STM32_I2C_TIMINGR_SCLDEL(t.scldel);
@@ -850,6 +905,7 @@ static int stm32_ofdata_to_platdata(struct udevice *dev)
 {
        struct stm32_i2c_priv *i2c_priv = dev_get_priv(dev);
        u32 rise_time, fall_time;
+       int ret;
 
        i2c_priv->setup = (struct stm32_i2c_setup *)dev_get_driver_data(dev);
        if (!i2c_priv->setup)
@@ -863,6 +919,22 @@ static int stm32_ofdata_to_platdata(struct udevice *dev)
        if (fall_time)
                i2c_priv->setup->fall_time = fall_time;
 
+       /* Optional */
+       i2c_priv->regmap = syscon_regmap_lookup_by_phandle(dev,
+                                                          "st,syscfg-fmp");
+       if (!IS_ERR(i2c_priv->regmap)) {
+               u32 fmp[3];
+
+               ret = dev_read_u32_array(dev, "st,syscfg-fmp", fmp, 3);
+               if (ret)
+                       return ret;
+
+               i2c_priv->regmap_sreg = fmp[1];
+               i2c_priv->regmap_creg = fmp[1] +
+                                       i2c_priv->setup->fmp_clr_offset;
+               i2c_priv->regmap_mask = fmp[2];
+       }
+
        return 0;
 }
 
@@ -873,6 +945,7 @@ static const struct dm_i2c_ops stm32_i2c_ops = {
 
 static const struct udevice_id stm32_i2c_of_match[] = {
        { .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_setup },
+       { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32mp15_setup },
        {}
 };
 
index 19b9375..a5747a2 100644 (file)
@@ -1263,6 +1263,7 @@ struct buffer_location {
  * can be enabled at once
  */
 static struct buffer_location buffer_loc;
+static int buffer_loc_init;
 
 /*
  * Page table entries are set to 1MB, or multiples of 1MB
@@ -5247,40 +5248,44 @@ static int mvpp2_base_probe(struct udevice *dev)
         * be active. Make this area DMA-safe by disabling the D-cache
         */
 
-       /* Align buffer area for descs and rx_buffers to 1MiB */
-       bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
-       mmu_set_region_dcache_behaviour((unsigned long)bd_space,
-                                       BD_SPACE, DCACHE_OFF);
-
-       buffer_loc.aggr_tx_descs = (struct mvpp2_tx_desc *)bd_space;
-       size += MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE;
-
-       buffer_loc.tx_descs =
-               (struct mvpp2_tx_desc *)((unsigned long)bd_space + size);
-       size += MVPP2_MAX_TXD * MVPP2_DESC_ALIGNED_SIZE;
+       if (!buffer_loc_init) {
+               /* Align buffer area for descs and rx_buffers to 1MiB */
+               bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
+               mmu_set_region_dcache_behaviour((unsigned long)bd_space,
+                                               BD_SPACE, DCACHE_OFF);
+
+               buffer_loc.aggr_tx_descs = (struct mvpp2_tx_desc *)bd_space;
+               size += MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE;
+
+               buffer_loc.tx_descs =
+                       (struct mvpp2_tx_desc *)((unsigned long)bd_space + size);
+               size += MVPP2_MAX_TXD * MVPP2_DESC_ALIGNED_SIZE;
+
+               buffer_loc.rx_descs =
+                       (struct mvpp2_rx_desc *)((unsigned long)bd_space + size);
+               size += MVPP2_MAX_RXD * MVPP2_DESC_ALIGNED_SIZE;
+
+               for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+                       buffer_loc.bm_pool[i] =
+                               (unsigned long *)((unsigned long)bd_space + size);
+                       if (priv->hw_version == MVPP21)
+                               size += MVPP2_BM_POOL_SIZE_MAX * 2 * sizeof(u32);
+                       else
+                               size += MVPP2_BM_POOL_SIZE_MAX * 2 * sizeof(u64);
+               }
 
-       buffer_loc.rx_descs =
-               (struct mvpp2_rx_desc *)((unsigned long)bd_space + size);
-       size += MVPP2_MAX_RXD * MVPP2_DESC_ALIGNED_SIZE;
+               for (i = 0; i < MVPP2_BM_LONG_BUF_NUM; i++) {
+                       buffer_loc.rx_buffer[i] =
+                               (unsigned long *)((unsigned long)bd_space + size);
+                       size += RX_BUFFER_SIZE;
+               }
 
-       for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
-               buffer_loc.bm_pool[i] =
-                       (unsigned long *)((unsigned long)bd_space + size);
-               if (priv->hw_version == MVPP21)
-                       size += MVPP2_BM_POOL_SIZE_MAX * 2 * sizeof(u32);
-               else
-                       size += MVPP2_BM_POOL_SIZE_MAX * 2 * sizeof(u64);
-       }
+               /* Clear the complete area so that all descriptors are cleared */
+               memset(bd_space, 0, size);
 
-       for (i = 0; i < MVPP2_BM_LONG_BUF_NUM; i++) {
-               buffer_loc.rx_buffer[i] =
-                       (unsigned long *)((unsigned long)bd_space + size);
-               size += RX_BUFFER_SIZE;
+               buffer_loc_init = 1;
        }
 
-       /* Clear the complete area so that all descriptors are cleared */
-       memset(bd_space, 0, size);
-
        /* Save base addresses for later use */
        priv->base = (void *)devfdt_get_addr_index(dev, 0);
        if (IS_ERR(priv->base))
index edb3f0f..61eb468 100644 (file)
@@ -47,6 +47,12 @@ config PWM_SANDBOX
          useful. The PWM can be enabled but is not connected to any outputs
          so this is not very useful.
 
+config PWM_SIFIVE
+       bool "Enable support for SiFive PWM"
+       depends on DM_PWM
+       help
+         This PWM is found SiFive's FU540 and other SoCs.
+
 config PWM_TEGRA
        bool "Enable support for the Tegra PWM"
        depends on DM_PWM
index 2c3a069..0f4e84b 100644 (file)
@@ -15,5 +15,6 @@ obj-$(CONFIG_PWM_IMX)         += pwm-imx.o pwm-imx-util.o
 obj-$(CONFIG_PWM_MTK)          += pwm-mtk.o
 obj-$(CONFIG_PWM_ROCKCHIP)     += rk_pwm.o
 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
diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c
new file mode 100644 (file)
index 0000000..77bc659
--- /dev/null
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 SiFive, Inc
+ * For SiFive's PWM IP block documentation please refer Chapter 14 of
+ * Reference Manual : https://static.dev.sifive.com/FU540-C000-v1.0.pdf
+ *
+ * Limitations:
+ * - When changing both duty cycle and period, we cannot prevent in
+ *   software that the output might produce a period with mixed
+ *   settings (new period length and old duty cycle).
+ * - The hardware cannot generate a 100% duty cycle.
+ * - The hardware generates only inverted output.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <div64.h>
+#include <dm.h>
+#include <pwm.h>
+#include <regmap.h>
+#include <linux/io.h>
+#include <linux/log2.h>
+#include <linux/bitfield.h>
+
+/* PWMCFG fields */
+#define PWM_SIFIVE_PWMCFG_SCALE         GENMASK(3, 0)
+#define PWM_SIFIVE_PWMCFG_STICKY        BIT(8)
+#define PWM_SIFIVE_PWMCFG_ZERO_CMP      BIT(9)
+#define PWM_SIFIVE_PWMCFG_DEGLITCH      BIT(10)
+#define PWM_SIFIVE_PWMCFG_EN_ALWAYS     BIT(12)
+#define PWM_SIFIVE_PWMCFG_EN_ONCE       BIT(13)
+#define PWM_SIFIVE_PWMCFG_CENTER        BIT(16)
+#define PWM_SIFIVE_PWMCFG_GANG          BIT(24)
+#define PWM_SIFIVE_PWMCFG_IP            BIT(28)
+
+/* PWM_SIFIVE_SIZE_PWMCMP is used to calculate offset for pwmcmpX registers */
+#define PWM_SIFIVE_SIZE_PWMCMP          4
+#define PWM_SIFIVE_CMPWIDTH             16
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct pwm_sifive_regs {
+       unsigned long cfg;
+       unsigned long cnt;
+       unsigned long pwms;
+       unsigned long cmp0;
+};
+
+struct pwm_sifive_data {
+       struct pwm_sifive_regs regs;
+};
+
+struct pwm_sifive_priv {
+       void __iomem *base;
+       ulong freq;
+       const struct pwm_sifive_data *data;
+};
+
+static int pwm_sifive_set_config(struct udevice *dev, uint channel,
+                                uint period_ns, uint duty_ns)
+{
+       struct pwm_sifive_priv *priv = dev_get_priv(dev);
+       const struct pwm_sifive_regs *regs = &priv->data->regs;
+       unsigned long scale_pow;
+       unsigned long long num;
+       u32 scale, val = 0, frac;
+
+       debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns);
+
+       /*
+        * The PWM unit is used with pwmzerocmp=0, so the only way to modify the
+        * period length is using pwmscale which provides the number of bits the
+        * counter is shifted before being feed to the comparators. A period
+        * lasts (1 << (PWM_SIFIVE_CMPWIDTH + pwmscale)) clock ticks.
+        * (1 << (PWM_SIFIVE_CMPWIDTH + scale)) * 10^9/rate = period
+        */
+       scale_pow = lldiv((uint64_t)priv->freq * period_ns, 1000000000);
+       scale = clamp(ilog2(scale_pow) - PWM_SIFIVE_CMPWIDTH, 0, 0xf);
+       val |= FIELD_PREP(PWM_SIFIVE_PWMCFG_SCALE, scale);
+
+       /*
+        * The problem of output producing mixed setting as mentioned at top,
+        * occurs here. To minimize the window for this problem, we are
+        * calculating the register values first and then writing them
+        * consecutively
+        */
+       num = (u64)duty_ns * (1U << PWM_SIFIVE_CMPWIDTH);
+       frac = DIV_ROUND_CLOSEST_ULL(num, period_ns);
+       frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1);
+
+       writel(val, priv->base + regs->cfg);
+       writel(frac, priv->base + regs->cmp0 + channel *
+              PWM_SIFIVE_SIZE_PWMCMP);
+
+       return 0;
+}
+
+static int pwm_sifive_set_enable(struct udevice *dev, uint channel, bool enable)
+{
+       struct pwm_sifive_priv *priv = dev_get_priv(dev);
+       const struct pwm_sifive_regs *regs = &priv->data->regs;
+       u32 val;
+
+       debug("%s: Enable '%s'\n", __func__, dev->name);
+
+       if (enable) {
+               val = readl(priv->base + regs->cfg);
+               val |= PWM_SIFIVE_PWMCFG_EN_ALWAYS;
+               writel(val, priv->base + regs->cfg);
+       } else {
+               writel(0, priv->base + regs->cmp0 + channel *
+                      PWM_SIFIVE_SIZE_PWMCMP);
+       }
+
+       return 0;
+}
+
+static int pwm_sifive_ofdata_to_platdata(struct udevice *dev)
+{
+       struct pwm_sifive_priv *priv = dev_get_priv(dev);
+
+       priv->base = dev_read_addr_ptr(dev);
+
+       return 0;
+}
+
+static int pwm_sifive_probe(struct udevice *dev)
+{
+       struct pwm_sifive_priv *priv = dev_get_priv(dev);
+       struct clk clk;
+       int ret = 0;
+
+       ret = clk_get_by_index(dev, 0, &clk);
+       if (ret < 0) {
+               debug("%s get clock fail!\n", __func__);
+               return -EINVAL;
+       }
+
+       priv->freq = clk_get_rate(&clk);
+       priv->data = (struct pwm_sifive_data *)dev_get_driver_data(dev);
+
+       return 0;
+}
+
+static const struct pwm_ops pwm_sifive_ops = {
+       .set_config     = pwm_sifive_set_config,
+       .set_enable     = pwm_sifive_set_enable,
+};
+
+static const struct pwm_sifive_data pwm_data = {
+       .regs = {
+               .cfg = 0x00,
+               .cnt = 0x08,
+               .pwms = 0x10,
+               .cmp0 = 0x20,
+       },
+};
+
+static const struct udevice_id pwm_sifive_ids[] = {
+       { .compatible = "sifive,pwm0", .data = (ulong)&pwm_data},
+       { }
+};
+
+U_BOOT_DRIVER(pwm_sifive) = {
+       .name   = "pwm_sifive",
+       .id     = UCLASS_PWM,
+       .of_match = pwm_sifive_ids,
+       .ops    = &pwm_sifive_ops,
+       .ofdata_to_platdata     = pwm_sifive_ofdata_to_platdata,
+       .probe          = pwm_sifive_probe,
+       .priv_auto_alloc_size   = sizeof(struct pwm_sifive_priv),
+};
index a010af4..7f78ff8 100644 (file)
@@ -197,7 +197,8 @@ static int sandbox_i2c_rtc_xfer(struct udevice *emul, struct i2c_msg *msg,
 
                        /* Write the register */
                        memcpy(plat->reg + offset, ptr, len);
-                       if (offset == REG_RESET)
+                       /* If the reset register was written to, do reset. */
+                       if (offset <= REG_RESET && REG_RESET < offset + len)
                                reset_time(emul);
                }
        }
index c423960..88ff8c5 100644 (file)
@@ -23,8 +23,7 @@
 #define PCF2127_REG_MO         0x08
 #define PCF2127_REG_YR         0x09
 
-static int pcf2127_read_reg(struct udevice *dev, uint offset,
-                           u8 *buffer, int len)
+static int pcf2127_rtc_read(struct udevice *dev, uint offset, u8 *buffer, uint len)
 {
        struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
        struct i2c_msg msg;
@@ -44,6 +43,12 @@ static int pcf2127_read_reg(struct udevice *dev, uint offset,
        return dm_i2c_xfer(dev, &msg, 1);
 }
 
+static int pcf2127_rtc_write(struct udevice *dev, uint offset,
+                            const u8 *buffer, uint len)
+{
+       return dm_i2c_write(dev, offset, buffer, len);
+}
+
 static int pcf2127_rtc_set(struct udevice *dev, const struct rtc_time *tm)
 {
        uchar buf[7] = {0};
@@ -73,7 +78,7 @@ static int pcf2127_rtc_get(struct udevice *dev, struct rtc_time *tm)
        int ret = 0;
        uchar buf[10] = { PCF2127_REG_CTRL1 };
 
-       ret = pcf2127_read_reg(dev, PCF2127_REG_CTRL1, buf, sizeof(buf));
+       ret = pcf2127_rtc_read(dev, PCF2127_REG_CTRL1, buf, sizeof(buf));
        if (ret < 0)
                return ret;
 
@@ -110,6 +115,8 @@ static const struct rtc_ops pcf2127_rtc_ops = {
        .get = pcf2127_rtc_get,
        .set = pcf2127_rtc_set,
        .reset = pcf2127_rtc_reset,
+       .read = pcf2127_rtc_read,
+       .write = pcf2127_rtc_write,
 };
 
 static const struct udevice_id pcf2127_rtc_ids[] = {
index 926cca2..8035f7f 100644 (file)
@@ -40,24 +40,75 @@ int dm_rtc_reset(struct udevice *dev)
        return ops->reset(dev);
 }
 
-int rtc_read8(struct udevice *dev, unsigned int reg)
+int dm_rtc_read(struct udevice *dev, unsigned int reg, u8 *buf, unsigned int len)
 {
        struct rtc_ops *ops = rtc_get_ops(dev);
 
        assert(ops);
+       if (ops->read)
+               return ops->read(dev, reg, buf, len);
        if (!ops->read8)
                return -ENOSYS;
-       return ops->read8(dev, reg);
+       while (len--) {
+               int ret = ops->read8(dev, reg++);
+
+               if (ret < 0)
+                       return ret;
+               *buf++ = ret;
+       }
+       return 0;
 }
 
-int rtc_write8(struct udevice *dev, unsigned int reg, int val)
+int dm_rtc_write(struct udevice *dev, unsigned int reg,
+                const u8 *buf, unsigned int len)
 {
        struct rtc_ops *ops = rtc_get_ops(dev);
 
        assert(ops);
+       if (ops->write)
+               return ops->write(dev, reg, buf, len);
        if (!ops->write8)
                return -ENOSYS;
-       return ops->write8(dev, reg, val);
+       while (len--) {
+               int ret = ops->write8(dev, reg++, *buf++);
+
+               if (ret < 0)
+                       return ret;
+       }
+       return 0;
+}
+
+int rtc_read8(struct udevice *dev, unsigned int reg)
+{
+       struct rtc_ops *ops = rtc_get_ops(dev);
+
+       assert(ops);
+       if (ops->read8)
+               return ops->read8(dev, reg);
+       if (ops->read) {
+               u8 buf[1];
+               int ret = ops->read(dev, reg, buf, 1);
+
+               if (ret < 0)
+                       return ret;
+               return buf[0];
+       }
+       return -ENOSYS;
+}
+
+int rtc_write8(struct udevice *dev, unsigned int reg, int val)
+{
+       struct rtc_ops *ops = rtc_get_ops(dev);
+
+       assert(ops);
+       if (ops->write8)
+               return ops->write8(dev, reg, val);
+       if (ops->write) {
+               u8 buf[1] = { val };
+
+               return ops->write(dev, reg, buf, 1);
+       }
+       return -ENOSYS;
 }
 
 int rtc_read16(struct udevice *dev, unsigned int reg, u16 *valuep)
index b08d758..77065e4 100644 (file)
 
 static int sandbox_rtc_get(struct udevice *dev, struct rtc_time *time)
 {
-       time->tm_sec = dm_i2c_reg_read(dev, REG_SEC);
-       if (time->tm_sec < 0)
-               return time->tm_sec;
-       time->tm_min = dm_i2c_reg_read(dev, REG_MIN);
-       if (time->tm_min < 0)
-               return time->tm_min;
-       time->tm_hour = dm_i2c_reg_read(dev, REG_HOUR);
-       if (time->tm_hour < 0)
-               return time->tm_hour;
-       time->tm_mday = dm_i2c_reg_read(dev, REG_MDAY);
-       if (time->tm_mday < 0)
-               return time->tm_mday;
-       time->tm_mon = dm_i2c_reg_read(dev, REG_MON);
-       if (time->tm_mon < 0)
-               return time->tm_mon;
-       time->tm_year = dm_i2c_reg_read(dev, REG_YEAR);
-       if (time->tm_year < 0)
-               return time->tm_year;
-       time->tm_year += 1900;
-       time->tm_wday = dm_i2c_reg_read(dev, REG_WDAY);
-       if (time->tm_wday < 0)
-               return time->tm_wday;
+       u8 buf[7];
+       int ret;
+
+       ret = dm_i2c_read(dev, REG_SEC, buf, sizeof(buf));
+       if (ret < 0)
+               return ret;
+
+       time->tm_sec  = buf[REG_SEC - REG_SEC];
+       time->tm_min  = buf[REG_MIN - REG_SEC];
+       time->tm_hour = buf[REG_HOUR - REG_SEC];
+       time->tm_mday = buf[REG_MDAY - REG_SEC];
+       time->tm_mon  = buf[REG_MON - REG_SEC];
+       time->tm_year = buf[REG_YEAR - REG_SEC] + 1900;
+       time->tm_wday = buf[REG_WDAY - REG_SEC];
 
        return 0;
 }
 
 static int sandbox_rtc_set(struct udevice *dev, const struct rtc_time *time)
 {
+       u8 buf[7];
        int ret;
 
-       ret = dm_i2c_reg_write(dev, REG_SEC, time->tm_sec);
-       if (ret < 0)
-               return ret;
-       ret = dm_i2c_reg_write(dev, REG_MIN, time->tm_min);
-       if (ret < 0)
-               return ret;
-       ret = dm_i2c_reg_write(dev, REG_HOUR, time->tm_hour);
-       if (ret < 0)
-               return ret;
-       ret = dm_i2c_reg_write(dev, REG_MDAY, time->tm_mday);
-       if (ret < 0)
-               return ret;
-       ret = dm_i2c_reg_write(dev, REG_MON, time->tm_mon);
-       if (ret < 0)
-               return ret;
-       ret = dm_i2c_reg_write(dev, REG_YEAR, time->tm_year - 1900);
-       if (ret < 0)
-               return ret;
-       ret = dm_i2c_reg_write(dev, REG_WDAY, time->tm_wday);
+       buf[REG_SEC - REG_SEC]  = time->tm_sec;
+       buf[REG_MIN - REG_SEC]  = time->tm_min;
+       buf[REG_HOUR - REG_SEC] = time->tm_hour;
+       buf[REG_MDAY - REG_SEC] = time->tm_mday;
+       buf[REG_MON  - REG_SEC] = time->tm_mon;
+       buf[REG_YEAR - REG_SEC] = time->tm_year - 1900;
+       buf[REG_WDAY - REG_SEC] = time->tm_wday;
+
+       ret = dm_i2c_write(dev, REG_SEC, buf, sizeof(buf));
        if (ret < 0)
                return ret;
 
index 31e2e78..2f4b670 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _CONFIG_HELIOS4_H
 #define _CONFIG_HELIOS4_H
 
-#include <linux/sizes.h>
 #include <linux/stringify.h>
 
 /*
 
 #define CONFIG_ENV_MIN_ENTRIES         128
 
+/* Environment in MMC */
+#define CONFIG_SYS_MMC_ENV_DEV         0
 /*
- * SATA/SCSI/AHCI configuration
+ * For SD - reserve 1 LBA for MBR + 1M for u-boot image. The MMC/eMMC
+ * boot image starts @ LBA-0.
+ * As result in MMC/eMMC case it will be a 1 sector gap between u-boot
+ * image and environment
  */
-#define CONFIG_SCSI_AHCI_PLAT
-#define CONFIG_SYS_SCSI_MAX_SCSI_ID     2
-#define CONFIG_SYS_SCSI_MAX_LUN         2
-#define CONFIG_SYS_SCSI_MAX_DEVICE      (CONFIG_SYS_SCSI_MAX_SCSI_ID * \
-                                       CONFIG_SYS_SCSI_MAX_LUN)
 
-#ifdef CONFIG_MVEBU_SPL_BOOT_DEVICE_SPI
-/* Environment in SPI NOR flash */
-#endif
+#define PHY_ANEG_TIMEOUT       8000    /* PHY needs a longer aneg time */
 
-#ifdef CONFIG_MVEBU_SPL_BOOT_DEVICE_MMC
-/* Environment in MMC */
-#define CONFIG_SYS_MMC_ENV_DEV         0
-/* stay within first 1M */
+/* PCIe support */
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_PCI_SCAN_SHOW
 #endif
 
-#define PHY_ANEG_TIMEOUT       8000    /* PHY needs a longer aneg time */
+/* SATA support */
+#ifdef CONFIG_SCSI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID    1
+#define CONFIG_SYS_SCSI_MAX_LUN                1
+#define CONFIG_SYS_SCSI_MAX_DEVICE     (CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+                                       CONFIG_SYS_SCSI_MAX_LUN)
+#endif
 
 /* Keep device tree and initrd in lower memory so the kernel can access them */
 #define RELOCATION_LIMITS_ENV_SETTINGS \
        "initrd_high=0x10000000\0"
 
 /* SPL */
-/*
- * Select the boot device here
- *
- * Currently supported are:
- * SPL_BOOT_SPI_NOR_FLASH      - Booting via SPI NOR flash
- * SPL_BOOT_SDIO_MMC_CARD      - Booting via SDIO/MMC card (partition 1)
- */
-#define SPL_BOOT_SPI_NOR_FLASH         1
-#define SPL_BOOT_SDIO_MMC_CARD         2
-
-#ifdef CONFIG_MVEBU_SPL_BOOT_DEVICE_SPI
-#define CONFIG_SPL_BOOT_DEVICE         SPL_BOOT_SPI_NOR_FLASH
-#endif
-#ifdef CONFIG_MVEBU_SPL_BOOT_DEVICE_MMC
-#define CONFIG_SPL_BOOT_DEVICE         SPL_BOOT_SDIO_MMC_CARD
-#endif
 
 /* Defines for SPL */
 #define CONFIG_SPL_SIZE                        (140 << 10)
 #define CONFIG_SPL_STACK               (0x40000000 + ((192 - 16) << 10))
 #define CONFIG_SPL_BOOTROM_SAVE                (CONFIG_SPL_STACK + 4)
 
-#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SPI_NOR_FLASH
+#if defined(CONFIG_MVEBU_SPL_BOOT_DEVICE_SPI)
+/* SPL related SPI defines */
 #define CONFIG_SYS_U_BOOT_OFFS         CONFIG_SYS_SPI_U_BOOT_OFFS
-#endif
-
-#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SDIO_MMC_CARD
+#elif defined(CONFIG_MVEBU_SPL_BOOT_DEVICE_MMC) || defined(CONFIG_MVEBU_SPL_BOOT_DEVICE_SATA)
 /* SPL related MMC defines */
 #define CONFIG_SYS_MMC_U_BOOT_OFFS             (160 << 10)
 #define CONFIG_SYS_U_BOOT_OFFS                 CONFIG_SYS_MMC_U_BOOT_OFFS
 #define CONFIG_FIXED_SDHCI_ALIGNED_BUFFER      0x00180000      /* in SDRAM */
 #endif
 #endif
+
 /*
  * mv-common.h should be defined after CMD configs since it used them
  * to enable certain macros
 #define BOOT_TARGET_DEVICES_USB(func)
 #endif
 
-#ifdef CONFIG_SATA
-#define BOOT_TARGET_DEVICES_SATA(func) func(SATA, sata, 0)
+#ifndef CONFIG_SCSI
+#define BOOT_TARGET_DEVICES_SCSI_BUS0(func)
+#define BOOT_TARGET_DEVICES_SCSI_BUS1(func)
+#define BOOT_TARGET_DEVICES_SCSI_BUS2(func)
+#else
+/*
+ * With SCSI enabled, M.2 SATA is always located on bus 0
+ */
+#define BOOT_TARGET_DEVICES_SCSI_BUS0(func) func(SCSI, scsi, 0)
+
+/*
+ * Either one or both mPCIe slots may be configured as mSATA interfaces. The
+ * SCSI bus ids are assigned based on sequence of hardware present, not always
+ * tied to hardware slot ids. As such, use second SCSI bus if either slot is
+ * set for SATA, and only use third SCSI bus if both slots are SATA enabled.
+ */
+#if defined (CONFIG_HELIOS4_CON2_SATA) || defined (CONFIG_HELIOS4_CON3_SATA)
+#define BOOT_TARGET_DEVICES_SCSI_BUS1(func) func(SCSI, scsi, 1)
+#else
+#define BOOT_TARGET_DEVICES_SCSI_BUS1(func)
+#endif
+
+#if defined (CONFIG_HELIOS4_CON2_SATA) && defined (CONFIG_HELIOS4_CON3_SATA)
+#define BOOT_TARGET_DEVICES_SCSI_BUS2(func) func(SCSI, scsi, 2)
 #else
-#define BOOT_TARGET_DEVICES_SATA(func)
+#define BOOT_TARGET_DEVICES_SCSI_BUS2(func)
 #endif
 
+#endif /* CONFIG_SCSI */
+
+/*
+ * The SCSI buses are attempted in increasing bus order, there is no current
+ * mechanism to alter the default bus priority order for booting.
+ */
 #define BOOT_TARGET_DEVICES(func) \
        BOOT_TARGET_DEVICES_MMC(func) \
        BOOT_TARGET_DEVICES_USB(func) \
-       BOOT_TARGET_DEVICES_SATA(func) \
+       BOOT_TARGET_DEVICES_SCSI_BUS0(func) \
+       BOOT_TARGET_DEVICES_SCSI_BUS1(func) \
+       BOOT_TARGET_DEVICES_SCSI_BUS2(func) \
        func(PXE, pxe, na) \
        func(DHCP, dhcp, na)
 
index 5bb0255..031bc99 100644 (file)
 /*
  * SATA Driver configuration
  */
-#ifdef CONFIG_MVSATA_IDE
-#define CONFIG_SYS_ATA_IDE0_OFFSET      MV_SATA_PORT0_OFFSET
+
+#ifdef CONFIG_SATA
+#define CONFIG_SYS_64BIT_LBA
+#define CONFIG_LBA48
 #if defined(CONFIG_NETSPACE_MAX_V2) || defined(CONFIG_D2NET_V2) || \
        defined(CONFIG_NET2BIG_V2)
-#define CONFIG_SYS_ATA_IDE1_OFFSET      MV_SATA_PORT1_OFFSET
-#define CONFIG_SYS_IDE_MAXBUS           2
-#define CONFIG_SYS_IDE_MAXDEVICE        2
+#define CONFIG_SYS_SATA_MAX_DEVICE     2
 #else
-#define CONFIG_SYS_IDE_MAXBUS           1
-#define CONFIG_SYS_IDE_MAXDEVICE        1
+#define CONFIG_SYS_SATA_MAX_DEVICE     1
 #endif
-#endif /* CONFIG_MVSATA_IDE */
+#endif /* CONFIG_SATA */
 
 /*
  * Enable GPI0 support
                "set stdin $stdin,nc; "                         \
                "set stdout $stdout,nc; "                       \
                "set stderr $stderr,nc;\0"                      \
-       "diskload=ide reset && "                                \
-               "ext2load ide 0:1 $loadaddr /boot/$bootfile\0"  \
+       "diskload=sata init && "                                \
+               "ext2load sata 0:1 $loadaddr /boot/$bootfile\0" \
        "usbload=usb start && "                                 \
                "fatload usb 0:1 $loadaddr /boot/$bootfile\0"
 
index 8aabfc1..1efc0db 100644 (file)
@@ -56,6 +56,30 @@ struct rtc_ops {
        int (*reset)(struct udevice *dev);
 
        /**
+        * read() - Read multiple 8-bit registers
+        *
+        * @dev:        Device to read from
+        * @reg:        First register to read
+        * @buf:        Output buffer
+        * @len:        Number of registers to read
+        * @return 0 if OK, -ve on error
+        */
+       int (*read)(struct udevice *dev, unsigned int reg,
+                   u8 *buf, unsigned int len);
+
+       /**
+        * write() - Write multiple 8-bit registers
+        *
+        * @dev:        Device to write to
+        * @reg:        First register to write
+        * @buf:        Input buffer
+        * @len:        Number of registers to write
+        * @return 0 if OK, -ve on error
+        */
+       int (*write)(struct udevice *dev, unsigned int reg,
+                    const u8 *buf, unsigned int len);
+
+       /**
         * read8() - Read an 8-bit register
         *
         * @dev:        Device to read from
@@ -110,6 +134,29 @@ int dm_rtc_set(struct udevice *dev, struct rtc_time *time);
 int dm_rtc_reset(struct udevice *dev);
 
 /**
+ * dm_rtc_read() - Read multiple 8-bit registers
+ *
+ * @dev:       Device to read from
+ * @reg:       First register to read
+ * @buf:       Output buffer
+ * @len:       Number of registers to read
+ * @return 0 if OK, -ve on error
+ */
+int dm_rtc_read(struct udevice *dev, unsigned int reg, u8 *buf, unsigned int len);
+
+/**
+ * dm_rtc_write() - Write multiple 8-bit registers
+ *
+ * @dev:       Device to write to
+ * @reg:       First register to write
+ * @buf:       Input buffer
+ * @len:       Number of registers to write
+ * @return 0 if OK, -ve on error
+ */
+int dm_rtc_write(struct udevice *dev, unsigned int reg,
+                const u8 *buf, unsigned int len);
+
+/**
  * rtc_read8() - Read an 8-bit register
  *
  * @dev:       Device to read from
index 88f8658..dd037a6 100644 (file)
@@ -5,11 +5,13 @@
  */
 
 #include <common.h>
+#include <console.h>
 #include <dm.h>
 #include <i2c.h>
 #include <log.h>
 #include <rtc.h>
 #include <asm/io.h>
+#include <asm/rtc.h>
 #include <asm/test.h>
 #include <dm/test.h>
 #include <test/ut.h>
@@ -70,7 +72,20 @@ static int dm_test_rtc_set_get(struct unit_test_state *uts)
        old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1);
 
        memset(&time, '\0', sizeof(time));
-       time.tm_mday = 25;
+       time.tm_mday = 3;
+       time.tm_mon = 6;
+       time.tm_year = 2004;
+       time.tm_sec = 0;
+       time.tm_min = 18;
+       time.tm_hour = 18;
+       ut_assertok(dm_rtc_set(dev, &time));
+
+       memset(&cmp, '\0', sizeof(cmp));
+       ut_assertok(dm_rtc_get(dev, &cmp));
+       ut_assertok(cmp_times(&time, &cmp, true));
+
+       memset(&time, '\0', sizeof(time));
+       time.tm_mday = 31;
        time.tm_mon = 8;
        time.tm_year = 2004;
        time.tm_sec = 0;
@@ -117,6 +132,107 @@ static int dm_test_rtc_set_get(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_rtc_set_get, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
+static int dm_test_rtc_read_write(struct unit_test_state *uts)
+{
+       struct rtc_time time;
+       struct udevice *dev, *emul;
+       long old_offset;
+       u8 buf[4], reg;
+
+       ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
+
+       memcpy(buf, "car", 4);
+       ut_assertok(dm_rtc_write(dev, REG_AUX0, buf, 4));
+       memset(buf, '\0', sizeof(buf));
+       ut_assertok(dm_rtc_read(dev, REG_AUX0, buf, 4));
+       ut_asserteq(memcmp(buf, "car", 4), 0);
+
+       reg = 'b';
+       ut_assertok(dm_rtc_write(dev, REG_AUX0, &reg, 1));
+       memset(buf, '\0', sizeof(buf));
+       ut_assertok(dm_rtc_read(dev, REG_AUX0, buf, 4));
+       ut_asserteq(memcmp(buf, "bar", 4), 0);
+
+       reg = 't';
+       ut_assertok(dm_rtc_write(dev, REG_AUX2, &reg, 1));
+       memset(buf, '\0', sizeof(buf));
+       ut_assertok(dm_rtc_read(dev, REG_AUX1, buf, 3));
+       ut_asserteq(memcmp(buf, "at", 3), 0);
+
+       ut_assertok(i2c_emul_find(dev, &emul));
+       ut_assert(emul != NULL);
+
+       old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0);
+       ut_assertok(dm_rtc_get(dev, &time));
+
+       ut_assertok(dm_rtc_read(dev, REG_SEC, &reg, 1));
+       ut_asserteq(time.tm_sec, reg);
+       ut_assertok(dm_rtc_read(dev, REG_MDAY, &reg, 1));
+       ut_asserteq(time.tm_mday, reg);
+
+       sandbox_i2c_rtc_set_offset(emul, true, old_offset);
+
+       return 0;
+}
+DM_TEST(dm_test_rtc_read_write, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test 'rtc list' command */
+static int dm_test_rtc_cmd_list(struct unit_test_state *uts)
+{
+       console_record_reset();
+
+       run_command("rtc list", 0);
+       ut_assert_nextline("RTC #0 - rtc@43");
+       ut_assert_nextline("RTC #1 - rtc@61");
+       ut_assert_console_end();
+
+       return 0;
+}
+DM_TEST(dm_test_rtc_cmd_list, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test 'rtc read' and 'rtc write' commands */
+static int dm_test_rtc_cmd_rw(struct unit_test_state *uts)
+{
+       console_record_reset();
+
+       run_command("rtc dev 0", 0);
+       ut_assert_nextline("RTC #0 - rtc@43");
+       ut_assert_console_end();
+
+       run_command("rtc write 0x30 aabb", 0);
+       ut_assert_console_end();
+
+       run_command("rtc read 0x30 2", 0);
+       ut_assert_nextline("00000030: aa bb                                              ..");
+       ut_assert_console_end();
+
+       run_command("rtc dev 1", 0);
+       ut_assert_nextline("RTC #1 - rtc@61");
+       ut_assert_console_end();
+
+       run_command("rtc write 0x30 ccdd", 0);
+       ut_assert_console_end();
+
+       run_command("rtc read 0x30 2", 0);
+       ut_assert_nextline("00000030: cc dd                                              ..");
+       ut_assert_console_end();
+
+       /*
+        * Switch back to device #0, check that its aux registers
+        * still have the same values.
+        */
+       run_command("rtc dev 0", 0);
+       ut_assert_nextline("RTC #0 - rtc@43");
+       ut_assert_console_end();
+
+       run_command("rtc read 0x30 2", 0);
+       ut_assert_nextline("00000030: aa bb                                              ..");
+       ut_assert_console_end();
+
+       return 0;
+}
+DM_TEST(dm_test_rtc_cmd_rw, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 /* Reset the time */
 static int dm_test_rtc_reset(struct unit_test_state *uts)
 {