Merge branch 'u-boot-ti/master' into 'u-boot-arm/master'
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>
Mon, 24 Feb 2014 09:29:59 +0000 (10:29 +0100)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Mon, 24 Feb 2014 09:29:59 +0000 (10:29 +0100)
29 files changed:
arch/arm/cpu/armv7/Makefile
arch/arm/cpu/armv7/bcm281xx/Makefile [new file with mode: 0644]
arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c [new file with mode: 0644]
arch/arm/cpu/armv7/bcm281xx/clk-bsc.c [new file with mode: 0644]
arch/arm/cpu/armv7/bcm281xx/clk-core.c [new file with mode: 0644]
arch/arm/cpu/armv7/bcm281xx/clk-core.h [new file with mode: 0644]
arch/arm/cpu/armv7/bcm281xx/clk-sdio.c [new file with mode: 0644]
arch/arm/cpu/armv7/bcm281xx/reset.c [new file with mode: 0644]
arch/arm/cpu/armv7/kona-common/Makefile [new file with mode: 0644]
arch/arm/cpu/armv7/kona-common/clk-stubs.c [new file with mode: 0644]
arch/arm/cpu/armv7/kona-common/hwinit-common.c [new file with mode: 0644]
arch/arm/cpu/armv7/kona-common/s_init.c [new file with mode: 0644]
arch/arm/include/asm/arch-bcm281xx/gpio.h [new file with mode: 0644]
arch/arm/include/asm/arch-bcm281xx/sysmap.h [new file with mode: 0644]
arch/arm/include/asm/kona-common/clk.h [new file with mode: 0644]
arch/arm/include/asm/kona-common/kona_sdhci.h [new file with mode: 0644]
board/broadcom/bcm28155_ap/Makefile [new file with mode: 0644]
board/broadcom/bcm28155_ap/bcm28155_ap.c [new file with mode: 0644]
boards.cfg
common/cmd_pxe.c
drivers/gpio/Makefile
drivers/gpio/kona_gpio.c [new file with mode: 0644]
drivers/i2c/Makefile
drivers/i2c/kona_i2c.c [new file with mode: 0644]
drivers/mmc/Makefile
drivers/mmc/kona_sdhci.c [new file with mode: 0644]
include/bitfield.h [new file with mode: 0644]
include/configs/bcm28155_ap.h [new file with mode: 0644]
include/configs/rpi_b.h

index 0467d00..119ebb3 100644 (file)
@@ -23,6 +23,7 @@ obj-y += nonsec_virt.o
 obj-y  += virt-v7.o
 endif
 
+obj-$(CONFIG_KONA) += kona-common/
 obj-$(CONFIG_OMAP_COMMON) += omap-common/
 obj-$(CONFIG_TEGRA) += tegra-common/
 
diff --git a/arch/arm/cpu/armv7/bcm281xx/Makefile b/arch/arm/cpu/armv7/bcm281xx/Makefile
new file mode 100644 (file)
index 0000000..98f5aa5
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Copyright 2013 Broadcom Corporation.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  += reset.o
+obj-y  += clk-core.o
+obj-y  += clk-bcm281xx.o
+obj-y  += clk-sdio.o
+obj-y  += clk-bsc.o
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c b/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c
new file mode 100644 (file)
index 0000000..bc8a170
--- /dev/null
@@ -0,0 +1,523 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+/*
+ *
+ * bcm281xx-specific clock tables
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define CLOCK_1K               1000
+#define CLOCK_1M               (CLOCK_1K * 1000)
+
+/* declare a reference clock */
+#define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \
+static struct refclk clk_name = { \
+       .clk    =       { \
+               .name   =       #clk_name, \
+               .parent =       clk_parent, \
+               .rate   =       clk_rate, \
+               .div    =       clk_div, \
+               .ops    =       &ref_clk_ops, \
+       }, \
+}
+
+/*
+ * Reference clocks
+ */
+
+/* Declare a list of reference clocks */
+DECLARE_REF_CLK(ref_crystal,   0,              26  * CLOCK_1M, 1);
+DECLARE_REF_CLK(var_96m,       0,              96  * CLOCK_1M, 1);
+DECLARE_REF_CLK(ref_96m,       0,              96  * CLOCK_1M, 1);
+DECLARE_REF_CLK(ref_312m,      0,              312 * CLOCK_1M, 0);
+DECLARE_REF_CLK(ref_104m,      &ref_312m.clk,  104 * CLOCK_1M, 3);
+DECLARE_REF_CLK(ref_52m,       &ref_104m.clk,  52  * CLOCK_1M, 2);
+DECLARE_REF_CLK(ref_13m,       &ref_52m.clk,   13  * CLOCK_1M, 4);
+DECLARE_REF_CLK(var_312m,      0,              312 * CLOCK_1M, 0);
+DECLARE_REF_CLK(var_104m,      &var_312m.clk,  104 * CLOCK_1M, 3);
+DECLARE_REF_CLK(var_52m,       &var_104m.clk,  52  * CLOCK_1M, 2);
+DECLARE_REF_CLK(var_13m,       &var_52m.clk,   13  * CLOCK_1M, 4);
+
+struct refclk_lkup {
+       struct refclk *procclk;
+       const char *name;
+};
+
+/* Lookup table for string to clk tranlation */
+#define MKSTR(x) {&x, #x}
+static struct refclk_lkup refclk_str_tbl[] = {
+       MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m),
+       MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m),
+       MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m),
+       MKSTR(var_52m), MKSTR(var_13m),
+};
+
+int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]);
+
+/* convert ref clock string to clock structure pointer */
+struct refclk *refclk_str_to_clk(const char *name)
+{
+       int i;
+       struct refclk_lkup *tblp = refclk_str_tbl;
+       for (i = 0; i < refclk_entries; i++, tblp++) {
+               if (!(strcmp(name, tblp->name)))
+                       return tblp->procclk;
+       }
+       return NULL;
+}
+
+/* frequency tables indexed by freq_id */
+unsigned long master_axi_freq_tbl[8] = {
+       26 * CLOCK_1M,
+       52 * CLOCK_1M,
+       104 * CLOCK_1M,
+       156 * CLOCK_1M,
+       156 * CLOCK_1M,
+       208 * CLOCK_1M,
+       312 * CLOCK_1M,
+       312 * CLOCK_1M
+};
+
+unsigned long master_ahb_freq_tbl[8] = {
+       26 * CLOCK_1M,
+       52 * CLOCK_1M,
+       52 * CLOCK_1M,
+       52 * CLOCK_1M,
+       78 * CLOCK_1M,
+       104 * CLOCK_1M,
+       104 * CLOCK_1M,
+       156 * CLOCK_1M
+};
+
+unsigned long slave_axi_freq_tbl[8] = {
+       26 * CLOCK_1M,
+       52 * CLOCK_1M,
+       78 * CLOCK_1M,
+       104 * CLOCK_1M,
+       156 * CLOCK_1M,
+       156 * CLOCK_1M
+};
+
+unsigned long slave_apb_freq_tbl[8] = {
+       26 * CLOCK_1M,
+       26 * CLOCK_1M,
+       39 * CLOCK_1M,
+       52 * CLOCK_1M,
+       52 * CLOCK_1M,
+       78 * CLOCK_1M
+};
+
+static struct bus_clk_data bsc1_apb_data = {
+       .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
+};
+
+static struct bus_clk_data bsc2_apb_data = {
+       .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
+};
+
+static struct bus_clk_data bsc3_apb_data = {
+       .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
+};
+
+/* * Master CCU clocks */
+static struct peri_clk_data sdio1_data = {
+       .gate           = HW_SW_GATE(0x0358, 18, 2, 3),
+       .clocks         = CLOCKS("ref_crystal",
+                                "var_52m",
+                                "ref_52m",
+                                "var_96m",
+                                "ref_96m"),
+       .sel            = SELECTOR(0x0a28, 0, 3),
+       .div            = DIVIDER(0x0a28, 4, 14),
+       .trig           = TRIGGER(0x0afc, 9),
+};
+
+static struct peri_clk_data sdio2_data = {
+       .gate           = HW_SW_GATE(0x035c, 18, 2, 3),
+       .clocks         = CLOCKS("ref_crystal",
+                                "var_52m",
+                                "ref_52m",
+                                "var_96m",
+                                "ref_96m"),
+       .sel            = SELECTOR(0x0a2c, 0, 3),
+       .div            = DIVIDER(0x0a2c, 4, 14),
+       .trig           = TRIGGER(0x0afc, 10),
+};
+
+static struct peri_clk_data sdio3_data = {
+       .gate           = HW_SW_GATE(0x0364, 18, 2, 3),
+       .clocks         = CLOCKS("ref_crystal",
+                                "var_52m",
+                                "ref_52m",
+                                "var_96m",
+                                "ref_96m"),
+       .sel            = SELECTOR(0x0a34, 0, 3),
+       .div            = DIVIDER(0x0a34, 4, 14),
+       .trig           = TRIGGER(0x0afc, 12),
+};
+
+static struct peri_clk_data sdio4_data = {
+       .gate           = HW_SW_GATE(0x0360, 18, 2, 3),
+       .clocks         = CLOCKS("ref_crystal",
+                                "var_52m",
+                                "ref_52m",
+                                "var_96m",
+                                "ref_96m"),
+       .sel            = SELECTOR(0x0a30, 0, 3),
+       .div            = DIVIDER(0x0a30, 4, 14),
+       .trig           = TRIGGER(0x0afc, 11),
+};
+
+static struct peri_clk_data sdio1_sleep_data = {
+       .clocks         = CLOCKS("ref_32k"),
+       .gate           = SW_ONLY_GATE(0x0358, 20, 4),
+};
+
+static struct peri_clk_data sdio2_sleep_data = {
+       .clocks         = CLOCKS("ref_32k"),
+       .gate           = SW_ONLY_GATE(0x035c, 20, 4),
+};
+
+static struct peri_clk_data sdio3_sleep_data = {
+       .clocks         = CLOCKS("ref_32k"),
+       .gate           = SW_ONLY_GATE(0x0364, 20, 4),
+};
+
+static struct peri_clk_data sdio4_sleep_data = {
+       .clocks         = CLOCKS("ref_32k"),
+       .gate           = SW_ONLY_GATE(0x0360, 20, 4),
+};
+
+static struct bus_clk_data sdio1_ahb_data = {
+       .gate           = HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio2_ahb_data = {
+       .gate           = HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio3_ahb_data = {
+       .gate           = HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
+};
+
+static struct bus_clk_data sdio4_ahb_data = {
+       .gate           = HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
+};
+
+/* * Slave CCU clocks */
+static struct peri_clk_data bsc1_data = {
+       .gate           = HW_SW_GATE(0x0458, 18, 2, 3),
+       .clocks         = CLOCKS("ref_crystal",
+                                "var_104m",
+                                "ref_104m",
+                                "var_13m",
+                                "ref_13m"),
+       .sel            = SELECTOR(0x0a64, 0, 3),
+       .trig           = TRIGGER(0x0afc, 23),
+};
+
+static struct peri_clk_data bsc2_data = {
+       .gate           = HW_SW_GATE(0x045c, 18, 2, 3),
+       .clocks         = CLOCKS("ref_crystal",
+                                "var_104m",
+                                "ref_104m",
+                                "var_13m",
+                                "ref_13m"),
+       .sel            = SELECTOR(0x0a68, 0, 3),
+       .trig           = TRIGGER(0x0afc, 24),
+};
+
+static struct peri_clk_data bsc3_data = {
+       .gate           = HW_SW_GATE(0x0484, 18, 2, 3),
+       .clocks         = CLOCKS("ref_crystal",
+                                "var_104m",
+                                "ref_104m",
+                                "var_13m",
+                                "ref_13m"),
+       .sel            = SELECTOR(0x0a84, 0, 3),
+       .trig           = TRIGGER(0x0b00, 2),
+};
+
+/*
+ * CCU clocks
+ */
+
+static struct ccu_clock kpm_ccu_clk = {
+       .clk = {
+               .name = "kpm_ccu_clk",
+               .ops = &ccu_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .num_policy_masks = 1,
+       .policy_freq_offset = 0x00000008,
+       .freq_bit_shift = 8,
+       .policy_ctl_offset = 0x0000000c,
+       .policy0_mask_offset = 0x00000010,
+       .policy1_mask_offset = 0x00000014,
+       .policy2_mask_offset = 0x00000018,
+       .policy3_mask_offset = 0x0000001c,
+       .lvm_en_offset = 0x00000034,
+       .freq_id = 2,
+       .freq_tbl = master_axi_freq_tbl,
+};
+
+static struct ccu_clock kps_ccu_clk = {
+       .clk = {
+               .name = "kps_ccu_clk",
+               .ops = &ccu_clk_ops,
+               .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+       },
+       .num_policy_masks = 2,
+       .policy_freq_offset = 0x00000008,
+       .freq_bit_shift = 8,
+       .policy_ctl_offset = 0x0000000c,
+       .policy0_mask_offset = 0x00000010,
+       .policy1_mask_offset = 0x00000014,
+       .policy2_mask_offset = 0x00000018,
+       .policy3_mask_offset = 0x0000001c,
+       .policy0_mask2_offset = 0x00000048,
+       .policy1_mask2_offset = 0x0000004c,
+       .policy2_mask2_offset = 0x00000050,
+       .policy3_mask2_offset = 0x00000054,
+       .lvm_en_offset = 0x00000034,
+       .freq_id = 2,
+       .freq_tbl = slave_axi_freq_tbl,
+};
+
+/*
+ * Bus clocks
+ */
+
+/* KPM bus clocks */
+static struct bus_clock sdio1_ahb_clk = {
+       .clk = {
+               .name = "sdio1_ahb_clk",
+               .parent = &kpm_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .freq_tbl = master_ahb_freq_tbl,
+       .data = &sdio1_ahb_data,
+};
+
+static struct bus_clock sdio2_ahb_clk = {
+       .clk = {
+               .name = "sdio2_ahb_clk",
+               .parent = &kpm_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .freq_tbl = master_ahb_freq_tbl,
+       .data = &sdio2_ahb_data,
+};
+
+static struct bus_clock sdio3_ahb_clk = {
+       .clk = {
+               .name = "sdio3_ahb_clk",
+               .parent = &kpm_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .freq_tbl = master_ahb_freq_tbl,
+       .data = &sdio3_ahb_data,
+};
+
+static struct bus_clock sdio4_ahb_clk = {
+       .clk = {
+               .name = "sdio4_ahb_clk",
+               .parent = &kpm_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .freq_tbl = master_ahb_freq_tbl,
+       .data = &sdio4_ahb_data,
+};
+
+static struct bus_clock bsc1_apb_clk = {
+       .clk = {
+               .name = "bsc1_apb_clk",
+               .parent = &kps_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+       },
+       .freq_tbl = slave_apb_freq_tbl,
+       .data = &bsc1_apb_data,
+};
+
+static struct bus_clock bsc2_apb_clk = {
+       .clk = {
+               .name = "bsc2_apb_clk",
+               .parent = &kps_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+               },
+       .freq_tbl = slave_apb_freq_tbl,
+       .data = &bsc2_apb_data,
+};
+
+static struct bus_clock bsc3_apb_clk = {
+       .clk = {
+               .name = "bsc3_apb_clk",
+               .parent = &kps_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+               },
+       .freq_tbl = slave_apb_freq_tbl,
+       .data = &bsc3_apb_data,
+};
+
+/* KPM peripheral */
+static struct peri_clock sdio1_clk = {
+       .clk = {
+               .name = "sdio1_clk",
+               .parent = &ref_52m.clk,
+               .ops = &peri_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .data = &sdio1_data,
+};
+
+static struct peri_clock sdio2_clk = {
+       .clk = {
+               .name = "sdio2_clk",
+               .parent = &ref_52m.clk,
+               .ops = &peri_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .data = &sdio2_data,
+};
+
+static struct peri_clock sdio3_clk = {
+       .clk = {
+               .name = "sdio3_clk",
+               .parent = &ref_52m.clk,
+               .ops = &peri_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .data = &sdio3_data,
+};
+
+static struct peri_clock sdio4_clk = {
+       .clk = {
+               .name = "sdio4_clk",
+               .parent = &ref_52m.clk,
+               .ops = &peri_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .data = &sdio4_data,
+};
+
+static struct peri_clock sdio1_sleep_clk = {
+       .clk = {
+               .name = "sdio1_sleep_clk",
+               .parent = &kpm_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .data = &sdio1_sleep_data,
+};
+
+static struct peri_clock sdio2_sleep_clk = {
+       .clk = {
+               .name = "sdio2_sleep_clk",
+               .parent = &kpm_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .data = &sdio2_sleep_data,
+};
+
+static struct peri_clock sdio3_sleep_clk = {
+       .clk = {
+               .name = "sdio3_sleep_clk",
+               .parent = &kpm_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .data = &sdio3_sleep_data,
+};
+
+static struct peri_clock sdio4_sleep_clk = {
+       .clk = {
+               .name = "sdio4_sleep_clk",
+               .parent = &kpm_ccu_clk.clk,
+               .ops = &bus_clk_ops,
+               .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
+       },
+       .data = &sdio4_sleep_data,
+};
+
+/* KPS peripheral clock */
+static struct peri_clock bsc1_clk = {
+       .clk = {
+               .name = "bsc1_clk",
+               .parent = &ref_13m.clk,
+               .rate = 13 * CLOCK_1M,
+               .div = 1,
+               .ops = &peri_clk_ops,
+               .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+       },
+       .data = &bsc1_data,
+};
+
+static struct peri_clock bsc2_clk = {
+       .clk = {
+               .name = "bsc2_clk",
+               .parent = &ref_13m.clk,
+               .rate = 13 * CLOCK_1M,
+               .div = 1,
+               .ops = &peri_clk_ops,
+               .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+       },
+       .data = &bsc2_data,
+};
+
+static struct peri_clock bsc3_clk = {
+       .clk = {
+               .name = "bsc3_clk",
+               .parent = &ref_13m.clk,
+               .rate = 13 * CLOCK_1M,
+               .div = 1,
+               .ops = &peri_clk_ops,
+               .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
+       },
+       .data = &bsc3_data,
+};
+
+/* public table for registering clocks */
+struct clk_lookup arch_clk_tbl[] = {
+       /* Peripheral clocks */
+       CLK_LK(sdio1),
+       CLK_LK(sdio2),
+       CLK_LK(sdio3),
+       CLK_LK(sdio4),
+       CLK_LK(sdio1_sleep),
+       CLK_LK(sdio2_sleep),
+       CLK_LK(sdio3_sleep),
+       CLK_LK(sdio4_sleep),
+       CLK_LK(bsc1),
+       CLK_LK(bsc2),
+       CLK_LK(bsc3),
+       /* Bus clocks */
+       CLK_LK(sdio1_ahb),
+       CLK_LK(sdio2_ahb),
+       CLK_LK(sdio3_ahb),
+       CLK_LK(sdio4_ahb),
+       CLK_LK(bsc1_apb),
+       CLK_LK(bsc2_apb),
+       CLK_LK(bsc3_apb),
+};
+
+/* public array size */
+unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c b/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c
new file mode 100644 (file)
index 0000000..ba55d0a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+/* Enable appropriate clocks for a BSC/I2C port */
+int clk_bsc_enable(void *base)
+{
+       int ret;
+       char *bscstr, *apbstr;
+
+       switch ((u32) base) {
+       case PMU_BSC_BASE_ADDR:
+               /* PMU clock is always enabled */
+               return 0;
+       case BSC1_BASE_ADDR:
+               bscstr = "bsc1_clk";
+               apbstr = "bsc1_apb_clk";
+               break;
+       case BSC2_BASE_ADDR:
+               bscstr = "bsc2_clk";
+               apbstr = "bsc2_apb_clk";
+               break;
+       case BSC3_BASE_ADDR:
+               bscstr = "bsc3_clk";
+               apbstr = "bsc3_apb_clk";
+               break;
+       default:
+               printf("%s: base 0x%p not found\n", __func__, base);
+               return -EINVAL;
+       }
+
+       /* Note that the bus clock must be enabled first */
+
+       ret = clk_get_and_enable(apbstr);
+       if (ret)
+               return ret;
+
+       ret = clk_get_and_enable(bscstr);
+       if (ret)
+               return ret;
+
+       return 0;
+}
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-core.c b/arch/arm/cpu/armv7/bcm281xx/clk-core.c
new file mode 100644 (file)
index 0000000..d442583
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+/*
+ *
+ * bcm281xx architecture clock framework
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <bitfield.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define CLK_WR_ACCESS_PASSWORD 0x00a5a501
+#define WR_ACCESS_OFFSET       0       /* common to all clock blocks */
+#define POLICY_CTL_GO          1       /* Load and refresh policy masks */
+#define POLICY_CTL_GO_ATL      4       /* Active Load */
+
+/* Helper function */
+int clk_get_and_enable(char *clkstr)
+{
+       int ret = 0;
+       struct clk *c;
+
+       debug("%s: %s\n", __func__, clkstr);
+
+       c = clk_get(clkstr);
+       if (c) {
+               ret = clk_enable(c);
+               if (ret)
+                       return ret;
+       } else {
+               printf("%s: Couldn't find %s\n", __func__, clkstr);
+               return -EINVAL;
+       }
+       return ret;
+}
+
+/*
+ * Poll a register in a CCU's address space, returning when the
+ * specified bit in that register's value is set (or clear).  Delay
+ * a microsecond after each read of the register.  Returns true if
+ * successful, or false if we gave up trying.
+ *
+ * Caller must ensure the CCU lock is held.
+ */
+#define CLK_GATE_DELAY_USEC 2000
+static inline int wait_bit(void *base, u32 offset, u32 bit, bool want)
+{
+       unsigned int tries;
+       u32 bit_mask = 1 << bit;
+
+       for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) {
+               u32 val;
+               bool bit_val;
+
+               val = readl(base + offset);
+               bit_val = (val & bit_mask) ? 1 : 0;
+               if (bit_val == want)
+                       return 0;       /* success */
+               udelay(1);
+       }
+
+       debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n",
+             __func__, base + offset, bit, want);
+
+       return -ETIMEDOUT;
+}
+
+/* Enable a peripheral clock */
+static int peri_clk_enable(struct clk *c, int enable)
+{
+       int ret = 0;
+       u32 reg;
+       struct peri_clock *peri_clk = to_peri_clk(c);
+       struct peri_clk_data *cd = peri_clk->data;
+       struct bcm_clk_gate *gate = &cd->gate;
+       void *base = (void *)c->ccu_clk_mgr_base;
+
+
+       debug("%s: %s\n", __func__, c->name);
+
+       clk_get_rate(c);        /* Make sure rate and sel are filled in */
+
+       /* enable access */
+       writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+       if (enable) {
+               debug("%s %s set rate %lu div %lu sel %d parent %lu\n",
+                     __func__, c->name, c->rate, c->div, c->sel,
+                     c->parent->rate);
+
+               /*
+                * clkgate - only software controllable gates are
+                * supported by u-boot which includes all clocks
+                * that matter. This avoids bringing in a lot of extra
+                * complexity as done in the kernel framework.
+                */
+               if (gate_exists(gate)) {
+                       reg = readl(base + cd->gate.offset);
+                       reg |= (1 << cd->gate.en_bit);
+                       writel(reg, base + cd->gate.offset);
+               }
+
+               /* div and pll select */
+               if (divider_exists(&cd->div)) {
+                       reg = readl(base + cd->div.offset);
+                       bitfield_replace(reg, cd->div.shift, cd->div.width,
+                                        c->div - 1);
+                       writel(reg, base + cd->div.offset);
+               }
+
+               /* frequency selector */
+               if (selector_exists(&cd->sel)) {
+                       reg = readl(base + cd->sel.offset);
+                       bitfield_replace(reg, cd->sel.shift, cd->sel.width,
+                                        c->sel);
+                       writel(reg, base + cd->sel.offset);
+               }
+
+               /* trigger */
+               if (trigger_exists(&cd->trig)) {
+                       writel((1 << cd->trig.bit), base + cd->trig.offset);
+
+                       /* wait for trigger status bit to go to 0 */
+                       ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0);
+                       if (ret)
+                               return ret;
+               }
+
+               /* wait for running (status_bit = 1) */
+               ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1);
+               if (ret)
+                       return ret;
+       } else {
+               debug("%s disable clock %s\n", __func__, c->name);
+
+               /* clkgate */
+               reg = readl(base + cd->gate.offset);
+               reg &= ~(1 << cd->gate.en_bit);
+               writel(reg, base + cd->gate.offset);
+
+               /* wait for stop (status_bit = 0) */
+               ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0);
+       }
+
+       /* disable access */
+       writel(0, base + WR_ACCESS_OFFSET);
+
+       return ret;
+}
+
+/* Set the rate of a peripheral clock */
+static int peri_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret = 0;
+       int i;
+       unsigned long diff;
+       unsigned long new_rate = 0, div = 1;
+       struct peri_clock *peri_clk = to_peri_clk(c);
+       struct peri_clk_data *cd = peri_clk->data;
+       const char **clock;
+
+       debug("%s: %s\n", __func__, c->name);
+       diff = rate;
+
+       i = 0;
+       for (clock = cd->clocks; *clock; clock++, i++) {
+               struct refclk *ref = refclk_str_to_clk(*clock);
+               if (!ref) {
+                       printf("%s: Lookup of %s failed\n", __func__, *clock);
+                       return -EINVAL;
+               }
+
+               /* round to the new rate */
+               div = ref->clk.rate / rate;
+               if (div == 0)
+                       div = 1;
+
+               new_rate = ref->clk.rate / div;
+
+               /* get the min diff */
+               if (abs(new_rate - rate) < diff) {
+                       diff = abs(new_rate - rate);
+                       c->sel = i;
+                       c->parent = &ref->clk;
+                       c->rate = new_rate;
+                       c->div = div;
+               }
+       }
+
+       debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__,
+             c->name, c->rate, c->div, c->sel, c->parent->rate);
+       return ret;
+}
+
+/* Get the rate of a peripheral clock */
+static unsigned long peri_clk_get_rate(struct clk *c)
+{
+       struct peri_clock *peri_clk = to_peri_clk(c);
+       struct peri_clk_data *cd = peri_clk->data;
+       void *base = (void *)c->ccu_clk_mgr_base;
+       int div = 1;
+       const char **clock;
+       struct refclk *ref;
+       u32 reg;
+
+       debug("%s: %s\n", __func__, c->name);
+       if (selector_exists(&cd->sel)) {
+               reg = readl(base + cd->sel.offset);
+               c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width);
+       } else {
+               /*
+                * For peri clocks that don't have a selector, the single
+                * reference clock will always exist at index 0.
+                */
+               c->sel = 0;
+       }
+
+       if (divider_exists(&cd->div)) {
+               reg = readl(base + cd->div.offset);
+               div = bitfield_extract(reg, cd->div.shift, cd->div.width);
+               div += 1;
+       }
+
+       clock = cd->clocks;
+       ref = refclk_str_to_clk(clock[c->sel]);
+       if (!ref) {
+               printf("%s: Can't lookup %s\n", __func__, clock[c->sel]);
+               return 0;
+       }
+
+       c->parent = &ref->clk;
+       c->div = div;
+       c->rate = c->parent->rate / c->div;
+       debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__,
+             c->parent->rate, div, c->sel, c->rate);
+
+       return c->rate;
+}
+
+/* Peripheral clock operations */
+struct clk_ops peri_clk_ops = {
+       .enable = peri_clk_enable,
+       .set_rate = peri_clk_set_rate,
+       .get_rate = peri_clk_get_rate,
+};
+
+/* Enable a CCU clock */
+static int ccu_clk_enable(struct clk *c, int enable)
+{
+       struct ccu_clock *ccu_clk = to_ccu_clk(c);
+       void *base = (void *)c->ccu_clk_mgr_base;
+       int ret = 0;
+       u32 reg;
+
+       debug("%s: %s\n", __func__, c->name);
+       if (!enable)
+               return -EINVAL; /* CCU clock cannot shutdown */
+
+       /* enable access */
+       writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+       /* config enable for policy engine */
+       writel(1, base + ccu_clk->lvm_en_offset);
+
+       /* wait for bit to go to 0 */
+       ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0);
+       if (ret)
+               return ret;
+
+       /* freq ID */
+       if (!ccu_clk->freq_bit_shift)
+               ccu_clk->freq_bit_shift = 8;
+
+       /* Set frequency id for each of the 4 policies */
+       reg = ccu_clk->freq_id |
+           (ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) |
+           (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) |
+           (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3));
+       writel(reg, base + ccu_clk->policy_freq_offset);
+
+       /* enable all clock mask */
+       writel(0x7fffffff, base + ccu_clk->policy0_mask_offset);
+       writel(0x7fffffff, base + ccu_clk->policy1_mask_offset);
+       writel(0x7fffffff, base + ccu_clk->policy2_mask_offset);
+       writel(0x7fffffff, base + ccu_clk->policy3_mask_offset);
+
+       if (ccu_clk->num_policy_masks == 2) {
+               writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset);
+               writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset);
+               writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset);
+               writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset);
+       }
+
+       /* start policy engine */
+       reg = readl(base + ccu_clk->policy_ctl_offset);
+       reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL);
+       writel(reg, base + ccu_clk->policy_ctl_offset);
+
+       /* wait till started */
+       ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0);
+       if (ret)
+               return ret;
+
+       /* disable access */
+       writel(0, base + WR_ACCESS_OFFSET);
+
+       return ret;
+}
+
+/* Get the CCU clock rate */
+static unsigned long ccu_clk_get_rate(struct clk *c)
+{
+       struct ccu_clock *ccu_clk = to_ccu_clk(c);
+       debug("%s: %s\n", __func__, c->name);
+       c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id];
+       return c->rate;
+}
+
+/* CCU clock operations */
+struct clk_ops ccu_clk_ops = {
+       .enable = ccu_clk_enable,
+       .get_rate = ccu_clk_get_rate,
+};
+
+/* Enable a bus clock */
+static int bus_clk_enable(struct clk *c, int enable)
+{
+       struct bus_clock *bus_clk = to_bus_clk(c);
+       struct bus_clk_data *cd = bus_clk->data;
+       void *base = (void *)c->ccu_clk_mgr_base;
+       int ret = 0;
+       u32 reg;
+
+       debug("%s: %s\n", __func__, c->name);
+       /* enable access */
+       writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
+
+       /* enable gating */
+       reg = readl(base + cd->gate.offset);
+       if (!!(reg & (1 << cd->gate.status_bit)) == !!enable)
+               debug("%s already %s\n", c->name,
+                     enable ? "enabled" : "disabled");
+       else {
+               int want = (enable) ? 1 : 0;
+               reg |= (1 << cd->gate.hw_sw_sel_bit);
+
+               if (enable)
+                       reg |= (1 << cd->gate.en_bit);
+               else
+                       reg &= ~(1 << cd->gate.en_bit);
+
+               writel(reg, base + cd->gate.offset);
+               ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit,
+                              want);
+               if (ret)
+                       return ret;
+       }
+
+       /* disable access */
+       writel(0, base + WR_ACCESS_OFFSET);
+
+       return ret;
+}
+
+/* Get the rate of a bus clock */
+static unsigned long bus_clk_get_rate(struct clk *c)
+{
+       struct bus_clock *bus_clk = to_bus_clk(c);
+       struct ccu_clock *ccu_clk;
+
+       debug("%s: %s\n", __func__, c->name);
+       ccu_clk = to_ccu_clk(c->parent);
+
+       c->rate = bus_clk->freq_tbl[ccu_clk->freq_id];
+       c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate;
+       return c->rate;
+}
+
+/* Bus clock operations */
+struct clk_ops bus_clk_ops = {
+       .enable = bus_clk_enable,
+       .get_rate = bus_clk_get_rate,
+};
+
+/* Enable a reference clock */
+static int ref_clk_enable(struct clk *c, int enable)
+{
+       debug("%s: %s\n", __func__, c->name);
+       return 0;
+}
+
+/* Reference clock operations */
+struct clk_ops ref_clk_ops = {
+       .enable = ref_clk_enable,
+};
+
+/*
+ * clk.h implementation follows
+ */
+
+/* Initialize the clock framework */
+int clk_init(void)
+{
+       debug("%s:\n", __func__);
+       return 0;
+}
+
+/* Get a clock handle, give a name string */
+struct clk *clk_get(const char *con_id)
+{
+       int i;
+       struct clk_lookup *clk_tblp;
+
+       debug("%s: %s\n", __func__, con_id);
+
+       clk_tblp = arch_clk_tbl;
+       for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) {
+               if (clk_tblp->con_id) {
+                       if (!con_id || strcmp(clk_tblp->con_id, con_id))
+                               continue;
+                       return clk_tblp->clk;
+               }
+       }
+       return NULL;
+}
+
+/* Enable a clock */
+int clk_enable(struct clk *c)
+{
+       int ret = 0;
+
+       debug("%s: %s\n", __func__, c->name);
+       if (!c->ops || !c->ops->enable)
+               return -1;
+
+       /* enable parent clock first */
+       if (c->parent)
+               ret = clk_enable(c->parent);
+
+       if (ret)
+               return ret;
+
+       if (!c->use_cnt) {
+               c->use_cnt++;
+               ret = c->ops->enable(c, 1);
+       }
+
+       return ret;
+}
+
+/* Disable a clock */
+void clk_disable(struct clk *c)
+{
+       debug("%s: %s\n", __func__, c->name);
+       if (!c->ops || !c->ops->enable)
+               return;
+
+       if (c->use_cnt) {
+               c->use_cnt--;
+               c->ops->enable(c, 0);
+       }
+
+       /* disable parent */
+       if (c->parent)
+               clk_disable(c->parent);
+}
+
+/* Get the clock rate */
+unsigned long clk_get_rate(struct clk *c)
+{
+       unsigned long rate;
+
+       debug("%s: %s\n", __func__, c->name);
+       if (!c || !c->ops || !c->ops->get_rate)
+               return 0;
+
+       rate = c->ops->get_rate(c);
+       debug("%s: rate = %ld\n", __func__, rate);
+       return rate;
+}
+
+/* Set the clock rate */
+int clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret;
+
+       debug("%s: %s rate=%ld\n", __func__, c->name, rate);
+       if (!c || !c->ops || !c->ops->set_rate)
+               return -EINVAL;
+
+       if (c->use_cnt)
+               return -EINVAL;
+
+       ret = c->ops->set_rate(c, rate);
+
+       return ret;
+}
+
+/* Not required for this arch */
+/*
+long clk_round_rate(struct clk *clk, unsigned long rate);
+int clk_set_parent(struct clk *clk, struct clk *parent);
+struct clk *clk_get_parent(struct clk *clk);
+*/
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-core.h b/arch/arm/cpu/armv7/bcm281xx/clk-core.h
new file mode 100644 (file)
index 0000000..882a297
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <linux/stddef.h>
+
+#ifdef CONFIG_CLK_DEBUG
+#undef writel
+#undef readl
+static inline void writel(u32 val, void *addr)
+{
+       printf("Write [0x%p] = 0x%08x\n", addr, val);
+       *(u32 *)addr = val;
+}
+
+static inline u32 readl(void *addr)
+{
+       u32 val = *(u32 *)addr;
+       printf("Read  [0x%p] = 0x%08x\n", addr, val);
+       return val;
+}
+#endif
+
+struct clk;
+
+struct clk_lookup {
+       const char *dev_id;
+       const char *con_id;
+       struct clk *clk;
+};
+
+extern struct clk_lookup arch_clk_tbl[];
+extern unsigned int arch_clk_tbl_array_size;
+
+/**
+ * struct clk_ops - standard clock operations
+ * @enable: enable/disable clock, see clk_enable() and clk_disable()
+ * @set_rate: set the clock rate, see clk_set_rate().
+ * @get_rate: get the clock rate, see clk_get_rate().
+ * @round_rate: round a given clock rate, see clk_round_rate().
+ * @set_parent: set the clock's parent, see clk_set_parent().
+ *
+ * Group the common clock implementations together so that we
+ * don't have to keep setting the same fiels again. We leave
+ * enable in struct clk.
+ *
+ */
+struct clk_ops {
+       int (*enable) (struct clk *c, int enable);
+       int (*set_rate) (struct clk *c, unsigned long rate);
+       unsigned long (*get_rate) (struct clk *c);
+       unsigned long (*round_rate) (struct clk *c, unsigned long rate);
+       int (*set_parent) (struct clk *c, struct clk *parent);
+};
+
+struct clk {
+       struct clk *parent;
+       const char *name;
+       int use_cnt;
+       unsigned long rate;     /* in HZ */
+
+       /* programmable divider. 0 means fixed ratio to parent clock */
+       unsigned long div;
+
+       struct clk_src *src;
+       struct clk_ops *ops;
+
+       unsigned long ccu_clk_mgr_base;
+       int sel;
+};
+
+struct refclk *refclk_str_to_clk(const char *name);
+
+#define U8_MAX ((u8)~0U)
+#define U32_MAX        ((u32)~0U)
+#define U64_MAX        ((u64)~0U)
+
+/* The common clock framework uses u8 to represent a parent index */
+#define PARENT_COUNT_MAX       ((u32)U8_MAX)
+
+#define BAD_CLK_INDEX          U8_MAX  /* Can't ever be valid */
+#define BAD_CLK_NAME           ((const char *)-1)
+
+#define BAD_SCALED_DIV_VALUE   U64_MAX
+
+/*
+ * Utility macros for object flag management.  If possible, flags
+ * should be defined such that 0 is the desired default value.
+ */
+#define FLAG(type, flag)               BCM_CLK_ ## type ## _FLAGS_ ## flag
+#define FLAG_SET(obj, type, flag)      ((obj)->flags |= FLAG(type, flag))
+#define FLAG_CLEAR(obj, type, flag)    ((obj)->flags &= ~(FLAG(type, flag)))
+#define FLAG_FLIP(obj, type, flag)     ((obj)->flags ^= FLAG(type, flag))
+#define FLAG_TEST(obj, type, flag)     (!!((obj)->flags & FLAG(type, flag)))
+
+/* Clock field state tests */
+
+#define gate_exists(gate)              FLAG_TEST(gate, GATE, EXISTS)
+#define gate_is_enabled(gate)          FLAG_TEST(gate, GATE, ENABLED)
+#define gate_is_hw_controllable(gate)  FLAG_TEST(gate, GATE, HW)
+#define gate_is_sw_controllable(gate)  FLAG_TEST(gate, GATE, SW)
+#define gate_is_sw_managed(gate)       FLAG_TEST(gate, GATE, SW_MANAGED)
+#define gate_is_no_disable(gate)       FLAG_TEST(gate, GATE, NO_DISABLE)
+
+#define gate_flip_enabled(gate)                FLAG_FLIP(gate, GATE, ENABLED)
+
+#define divider_exists(div)            FLAG_TEST(div, DIV, EXISTS)
+#define divider_is_fixed(div)          FLAG_TEST(div, DIV, FIXED)
+#define divider_has_fraction(div)      (!divider_is_fixed(div) && \
+                                               (div)->frac_width > 0)
+
+#define selector_exists(sel)           ((sel)->width != 0)
+#define trigger_exists(trig)           FLAG_TEST(trig, TRIG, EXISTS)
+
+/* Clock type, used to tell common block what it's part of */
+enum bcm_clk_type {
+       bcm_clk_none,           /* undefined clock type */
+       bcm_clk_bus,
+       bcm_clk_core,
+       bcm_clk_peri
+};
+
+/*
+ * Gating control and status is managed by a 32-bit gate register.
+ *
+ * There are several types of gating available:
+ * - (no gate)
+ *     A clock with no gate is assumed to be always enabled.
+ * - hardware-only gating (auto-gating)
+ *     Enabling or disabling clocks with this type of gate is
+ *     managed automatically by the hardware.  Such clocks can be
+ *     considered by the software to be enabled.  The current status
+ *     of auto-gated clocks can be read from the gate status bit.
+ * - software-only gating
+ *     Auto-gating is not available for this type of clock.
+ *     Instead, software manages whether it's enabled by setting or
+ *     clearing the enable bit.  The current gate status of a gate
+ *     under software control can be read from the gate status bit.
+ *     To ensure a change to the gating status is complete, the
+ *     status bit can be polled to verify that the gate has entered
+ *     the desired state.
+ * - selectable hardware or software gating
+ *     Gating for this type of clock can be configured to be either
+ *     under software or hardware control.  Which type is in use is
+ *     determined by the hw_sw_sel bit of the gate register.
+ */
+struct bcm_clk_gate {
+       u32 offset;             /* gate register offset */
+       u32 status_bit;         /* 0: gate is disabled; 0: gatge is enabled */
+       u32 en_bit;             /* 0: disable; 1: enable */
+       u32 hw_sw_sel_bit;      /* 0: hardware gating; 1: software gating */
+       u32 flags;              /* BCM_CLK_GATE_FLAGS_* below */
+};
+
+/*
+ * Gate flags:
+ *   HW         means this gate can be auto-gated
+ *   SW         means the state of this gate can be software controlled
+ *   NO_DISABLE means this gate is (only) enabled if under software control
+ *   SW_MANAGED means the status of this gate is under software control
+ *   ENABLED    means this software-managed gate is *supposed* to be enabled
+ */
+#define BCM_CLK_GATE_FLAGS_EXISTS      ((u32)1 << 0)   /* Gate is valid */
+#define BCM_CLK_GATE_FLAGS_HW          ((u32)1 << 1)   /* Can auto-gate */
+#define BCM_CLK_GATE_FLAGS_SW          ((u32)1 << 2)   /* Software control */
+#define BCM_CLK_GATE_FLAGS_NO_DISABLE  ((u32)1 << 3)   /* HW or enabled */
+#define BCM_CLK_GATE_FLAGS_SW_MANAGED  ((u32)1 << 4)   /* SW now in control */
+#define BCM_CLK_GATE_FLAGS_ENABLED     ((u32)1 << 5)   /* If SW_MANAGED */
+
+/*
+ * Gate initialization macros.
+ *
+ * Any gate initially under software control will be enabled.
+ */
+
+/* A hardware/software gate initially under software control */
+#define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit)      \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .status_bit = (_status_bit),                            \
+               .en_bit = (_en_bit),                                    \
+               .hw_sw_sel_bit = (_hw_sw_sel_bit),                      \
+               .flags = FLAG(GATE, HW)|FLAG(GATE, SW)|                 \
+                       FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)|     \
+                       FLAG(GATE, EXISTS),                             \
+       }
+
+/* A hardware/software gate initially under hardware control */
+#define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .status_bit = (_status_bit),                            \
+               .en_bit = (_en_bit),                                    \
+               .hw_sw_sel_bit = (_hw_sw_sel_bit),                      \
+               .flags = FLAG(GATE, HW)|FLAG(GATE, SW)|                 \
+                       FLAG(GATE, EXISTS),                             \
+       }
+
+/* A hardware-or-enabled gate (enabled if not under hardware control) */
+#define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit)  \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .status_bit = (_status_bit),                            \
+               .en_bit = (_en_bit),                                    \
+               .hw_sw_sel_bit = (_hw_sw_sel_bit),                      \
+               .flags = FLAG(GATE, HW)|FLAG(GATE, SW)|                 \
+                       FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS),      \
+       }
+
+/* A software-only gate */
+#define SW_ONLY_GATE(_offset, _status_bit, _en_bit)                    \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .status_bit = (_status_bit),                            \
+               .en_bit = (_en_bit),                                    \
+               .flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)|         \
+                       FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS),         \
+       }
+
+/* A hardware-only gate */
+#define HW_ONLY_GATE(_offset, _status_bit)                             \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .status_bit = (_status_bit),                            \
+               .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS),             \
+       }
+
+/*
+ * Each clock can have zero, one, or two dividers which change the
+ * output rate of the clock.  Each divider can be either fixed or
+ * variable.  If there are two dividers, they are the "pre-divider"
+ * and the "regular" or "downstream" divider.  If there is only one,
+ * there is no pre-divider.
+ *
+ * A fixed divider is any non-zero (positive) value, and it
+ * indicates how the input rate is affected by the divider.
+ *
+ * The value of a variable divider is maintained in a sub-field of a
+ * 32-bit divider register.  The position of the field in the
+ * register is defined by its offset and width.  The value recorded
+ * in this field is always 1 less than the value it represents.
+ *
+ * In addition, a variable divider can indicate that some subset
+ * of its bits represent a "fractional" part of the divider.  Such
+ * bits comprise the low-order portion of the divider field, and can
+ * be viewed as representing the portion of the divider that lies to
+ * the right of the decimal point.  Most variable dividers have zero
+ * fractional bits.  Variable dividers with non-zero fraction width
+ * still record a value 1 less than the value they represent; the
+ * added 1 does *not* affect the low-order bit in this case, it
+ * affects the bits above the fractional part only.  (Often in this
+ * code a divider field value is distinguished from the value it
+ * represents by referring to the latter as a "divisor".)
+ *
+ * In order to avoid dealing with fractions, divider arithmetic is
+ * performed using "scaled" values.  A scaled value is one that's
+ * been left-shifted by the fractional width of a divider.  Dividing
+ * a scaled value by a scaled divisor produces the desired quotient
+ * without loss of precision and without any other special handling
+ * for fractions.
+ *
+ * The recorded value of a variable divider can be modified.  To
+ * modify either divider (or both), a clock must be enabled (i.e.,
+ * using its gate).  In addition, a trigger register (described
+ * below) must be used to commit the change, and polled to verify
+ * the change is complete.
+ */
+struct bcm_clk_div {
+       union {
+               struct {        /* variable divider */
+                       u32 offset;     /* divider register offset */
+                       u32 shift;      /* field shift */
+                       u32 width;      /* field width */
+                       u32 frac_width; /* field fraction width */
+
+                       u64 scaled_div; /* scaled divider value */
+               };
+               u32 fixed;      /* non-zero fixed divider value */
+       };
+       u32 flags;              /* BCM_CLK_DIV_FLAGS_* below */
+};
+
+/*
+ * Divider flags:
+ *   EXISTS means this divider exists
+ *   FIXED means it is a fixed-rate divider
+ */
+#define BCM_CLK_DIV_FLAGS_EXISTS       ((u32)1 << 0)   /* Divider is valid */
+#define BCM_CLK_DIV_FLAGS_FIXED                ((u32)1 << 1)   /* Fixed-value */
+
+/* Divider initialization macros */
+
+/* A fixed (non-zero) divider */
+#define FIXED_DIVIDER(_value)                                          \
+       {                                                               \
+               .fixed = (_value),                                      \
+               .flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED),            \
+       }
+
+/* A divider with an integral divisor */
+#define DIVIDER(_offset, _shift, _width)                               \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .shift = (_shift),                                      \
+               .width = (_width),                                      \
+               .scaled_div = BAD_SCALED_DIV_VALUE,                     \
+               .flags = FLAG(DIV, EXISTS),                             \
+       }
+
+/* A divider whose divisor has an integer and fractional part */
+#define FRAC_DIVIDER(_offset, _shift, _width, _frac_width)             \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .shift = (_shift),                                      \
+               .width = (_width),                                      \
+               .frac_width = (_frac_width),                            \
+               .scaled_div = BAD_SCALED_DIV_VALUE,                     \
+               .flags = FLAG(DIV, EXISTS),                             \
+       }
+
+/*
+ * Clocks may have multiple "parent" clocks.  If there is more than
+ * one, a selector must be specified to define which of the parent
+ * clocks is currently in use.  The selected clock is indicated in a
+ * sub-field of a 32-bit selector register.  The range of
+ * representable selector values typically exceeds the number of
+ * available parent clocks.  Occasionally the reset value of a
+ * selector field is explicitly set to a (specific) value that does
+ * not correspond to a defined input clock.
+ *
+ * We register all known parent clocks with the common clock code
+ * using a packed array (i.e., no empty slots) of (parent) clock
+ * names, and refer to them later using indexes into that array.
+ * We maintain an array of selector values indexed by common clock
+ * index values in order to map between these common clock indexes
+ * and the selector values used by the hardware.
+ *
+ * Like dividers, a selector can be modified, but to do so a clock
+ * must be enabled, and a trigger must be used to commit the change.
+ */
+struct bcm_clk_sel {
+       u32 offset;             /* selector register offset */
+       u32 shift;              /* field shift */
+       u32 width;              /* field width */
+
+       u32 parent_count;       /* number of entries in parent_sel[] */
+       u32 *parent_sel;        /* array of parent selector values */
+       u8 clk_index;           /* current selected index in parent_sel[] */
+};
+
+/* Selector initialization macro */
+#define SELECTOR(_offset, _shift, _width)                              \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .shift = (_shift),                                      \
+               .width = (_width),                                      \
+               .clk_index = BAD_CLK_INDEX,                             \
+       }
+
+/*
+ * Making changes to a variable divider or a selector for a clock
+ * requires the use of a trigger.  A trigger is defined by a single
+ * bit within a register.  To signal a change, a 1 is written into
+ * that bit.  To determine when the change has been completed, that
+ * trigger bit is polled; the read value will be 1 while the change
+ * is in progress, and 0 when it is complete.
+ *
+ * Occasionally a clock will have more than one trigger.  In this
+ * case, the "pre-trigger" will be used when changing a clock's
+ * selector and/or its pre-divider.
+ */
+struct bcm_clk_trig {
+       u32 offset;             /* trigger register offset */
+       u32 bit;                /* trigger bit */
+       u32 flags;              /* BCM_CLK_TRIG_FLAGS_* below */
+};
+
+/*
+ * Trigger flags:
+ *   EXISTS means this trigger exists
+ */
+#define BCM_CLK_TRIG_FLAGS_EXISTS      ((u32)1 << 0)   /* Trigger is valid */
+
+/* Trigger initialization macro */
+#define TRIGGER(_offset, _bit)                                         \
+       {                                                               \
+               .offset = (_offset),                                    \
+               .bit = (_bit),                                          \
+               .flags = FLAG(TRIG, EXISTS),                            \
+       }
+
+struct bus_clk_data {
+       struct bcm_clk_gate gate;
+};
+
+struct core_clk_data {
+       struct bcm_clk_gate gate;
+};
+
+struct peri_clk_data {
+       struct bcm_clk_gate gate;
+       struct bcm_clk_trig pre_trig;
+       struct bcm_clk_div pre_div;
+       struct bcm_clk_trig trig;
+       struct bcm_clk_div div;
+       struct bcm_clk_sel sel;
+       const char *clocks[];   /* must be last; use CLOCKS() to declare */
+};
+#define CLOCKS(...)    { __VA_ARGS__, NULL, }
+#define NO_CLOCKS      { NULL, }       /* Must use of no parent clocks */
+
+struct refclk {
+       struct clk clk;
+};
+
+struct peri_clock {
+       struct clk clk;
+       struct peri_clk_data *data;
+};
+
+struct ccu_clock {
+       struct clk clk;
+
+       int num_policy_masks;
+       unsigned long policy_freq_offset;
+       int freq_bit_shift;     /* 8 for most CCUs */
+       unsigned long policy_ctl_offset;
+       unsigned long policy0_mask_offset;
+       unsigned long policy1_mask_offset;
+       unsigned long policy2_mask_offset;
+       unsigned long policy3_mask_offset;
+       unsigned long policy0_mask2_offset;
+       unsigned long policy1_mask2_offset;
+       unsigned long policy2_mask2_offset;
+       unsigned long policy3_mask2_offset;
+       unsigned long lvm_en_offset;
+
+       int freq_id;
+       unsigned long *freq_tbl;
+};
+
+struct bus_clock {
+       struct clk clk;
+       struct bus_clk_data *data;
+       unsigned long *freq_tbl;
+};
+
+struct ref_clock {
+       struct clk clk;
+};
+
+static inline int is_same_clock(struct clk *a, struct clk *b)
+{
+       return (a == b);
+}
+
+#define to_clk(p) (&((p)->clk))
+#define name_to_clk(name) (&((name##_clk).clk))
+/* declare a struct clk_lookup */
+#define CLK_LK(name) \
+{.con_id = __stringify(name##_clk), .clk = name_to_clk(name),}
+
+static inline struct refclk *to_refclk(struct clk *clock)
+{
+       return container_of(clock, struct refclk, clk);
+}
+
+static inline struct peri_clock *to_peri_clk(struct clk *clock)
+{
+       return container_of(clock, struct peri_clock, clk);
+}
+
+static inline struct ccu_clock *to_ccu_clk(struct clk *clock)
+{
+       return container_of(clock, struct ccu_clock, clk);
+}
+
+static inline struct bus_clock *to_bus_clk(struct clk *clock)
+{
+       return container_of(clock, struct bus_clock, clk);
+}
+
+static inline struct ref_clock *to_ref_clk(struct clk *clock)
+{
+       return container_of(clock, struct ref_clock, clk);
+}
+
+extern struct clk_ops peri_clk_ops;
+extern struct clk_ops ccu_clk_ops;
+extern struct clk_ops bus_clk_ops;
+extern struct clk_ops ref_clk_ops;
+
+extern int clk_get_and_enable(char *clkstr);
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c b/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c
new file mode 100644 (file)
index 0000000..49badcb
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+/* Enable appropriate clocks for an SDIO port */
+int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep)
+{
+       int ret;
+       struct clk *c;
+
+       char *clkstr;
+       char *slpstr;
+       char *ahbstr;
+
+       switch ((u32) base) {
+       case CONFIG_SYS_SDIO_BASE0:
+               clkstr = CONFIG_SYS_SDIO0 "_clk";
+               ahbstr = CONFIG_SYS_SDIO0 "_ahb_clk";
+               slpstr = CONFIG_SYS_SDIO0 "_sleep_clk";
+               break;
+       case CONFIG_SYS_SDIO_BASE1:
+               clkstr = CONFIG_SYS_SDIO1 "_clk";
+               ahbstr = CONFIG_SYS_SDIO1 "_ahb_clk";
+               slpstr = CONFIG_SYS_SDIO1 "_sleep_clk";
+               break;
+       case CONFIG_SYS_SDIO_BASE2:
+               clkstr = CONFIG_SYS_SDIO2 "_clk";
+               ahbstr = CONFIG_SYS_SDIO2 "_ahb_clk";
+               slpstr = CONFIG_SYS_SDIO2 "_sleep_clk";
+               break;
+       case CONFIG_SYS_SDIO_BASE3:
+               clkstr = CONFIG_SYS_SDIO3 "_clk";
+               ahbstr = CONFIG_SYS_SDIO3 "_ahb_clk";
+               slpstr = CONFIG_SYS_SDIO3 "_sleep_clk";
+               break;
+       default:
+               printf("%s: base 0x%p not found\n", __func__, base);
+               return -EINVAL;
+       }
+
+       ret = clk_get_and_enable(ahbstr);
+       if (ret)
+               return ret;
+
+       ret = clk_get_and_enable(slpstr);
+       if (ret)
+               return ret;
+
+       c = clk_get(clkstr);
+       if (c) {
+               ret = clk_set_rate(c, rate);
+               if (ret)
+                       return ret;
+
+               ret = clk_enable(c);
+               if (ret)
+                       return ret;
+       } else {
+               printf("%s: Couldn't find %s\n", __func__, clkstr);
+               return -EINVAL;
+       }
+       *actual_ratep = rate;
+       return 0;
+}
diff --git a/arch/arm/cpu/armv7/bcm281xx/reset.c b/arch/arm/cpu/armv7/bcm281xx/reset.c
new file mode 100644 (file)
index 0000000..3beb0ed
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sysmap.h>
+
+#define EN_MASK                0x08000000      /* Enable timer */
+#define SRSTEN_MASK    0x04000000      /* Enable soft reset */
+#define CLKS_SHIFT     20              /* Clock period shift */
+#define LD_SHIFT       0               /* Reload value shift */
+
+void reset_cpu(ulong ignored)
+{
+       /*
+        * Set WD enable, RST enable,
+        * 3.9 msec clock period (8), reload value (8*3.9ms)
+        */
+       u32 reg = EN_MASK + SRSTEN_MASK + (8 << CLKS_SHIFT) + (8 << LD_SHIFT);
+       writel(reg, SECWD2_BASE_ADDR);
+
+       while (1)
+               ;       /* loop forever till reset */
+}
diff --git a/arch/arm/cpu/armv7/kona-common/Makefile b/arch/arm/cpu/armv7/kona-common/Makefile
new file mode 100644 (file)
index 0000000..da225cb
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Copyright 2013 Broadcom Corporation.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  += s_init.o
+obj-y  += hwinit-common.o
+obj-y  += clk-stubs.o
diff --git a/arch/arm/cpu/armv7/kona-common/clk-stubs.c b/arch/arm/cpu/armv7/kona-common/clk-stubs.c
new file mode 100644 (file)
index 0000000..338e0e4
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+
+/*
+ * These weak functions are available to kona architectures that don't
+ * require clock enables from the driver code.
+ */
+int __weak clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep)
+{
+       return 0;
+}
+
+int __weak clk_bsc_enable(void *base, u32 rate, u32 *actual_ratep)
+{
+       return 0;
+}
diff --git a/arch/arm/cpu/armv7/kona-common/hwinit-common.c b/arch/arm/cpu/armv7/kona-common/hwinit-common.c
new file mode 100644 (file)
index 0000000..f8b1e06
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/sizes.h>
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+       /* Enable D-cache. I-cache is already enabled in start.S */
+       dcache_enable();
+}
+#endif
diff --git a/arch/arm/cpu/armv7/kona-common/s_init.c b/arch/arm/cpu/armv7/kona-common/s_init.c
new file mode 100644 (file)
index 0000000..6066a73
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/*
+ * Early system init. Currently empty.
+ */
+void s_init(void)
+{
+}
diff --git a/arch/arm/include/asm/arch-bcm281xx/gpio.h b/arch/arm/include/asm/arch-bcm281xx/gpio.h
new file mode 100644 (file)
index 0000000..1b40a96
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#ifndef __ARCH_BCM281XX_GPIO_H
+#define __ARCH_BCM281XX_GPIO_H
+
+/*
+ * Empty file - cmd_gpio.c requires this. The implementation
+ * is in drivers/gpio/kona_gpio.c instead of inlined here.
+ */
+
+#endif
diff --git a/arch/arm/include/asm/arch-bcm281xx/sysmap.h b/arch/arm/include/asm/arch-bcm281xx/sysmap.h
new file mode 100644 (file)
index 0000000..880b4e0
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#ifndef __ARCH_BCM281XX_SYSMAP_H
+
+#define BSC1_BASE_ADDR         0x3e016000
+#define BSC2_BASE_ADDR         0x3e017000
+#define BSC3_BASE_ADDR         0x3e018000
+#define GPIO2_BASE_ADDR                0x35003000
+#define KONA_MST_CLK_BASE_ADDR 0x3f001000
+#define KONA_SLV_CLK_BASE_ADDR 0x3e011000
+#define PMU_BSC_BASE_ADDR      0x3500d000
+#define PWRMGR_BASE_ADDR       0x35010000
+#define SDIO1_BASE_ADDR                0x3f180000
+#define SDIO2_BASE_ADDR                0x3f190000
+#define SDIO3_BASE_ADDR                0x3f1a0000
+#define SDIO4_BASE_ADDR                0x3f1b0000
+#define SECWD_BASE_ADDR                0x3500c000
+#define SECWD2_BASE_ADDR       0x35002f40
+#define TIMER_BASE_ADDR                0x3e00d000
+
+#endif
diff --git a/arch/arm/include/asm/kona-common/clk.h b/arch/arm/include/asm/kona-common/clk.h
new file mode 100644 (file)
index 0000000..2c7e829
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+/* This API file is loosely based on u-boot/drivers/video/ipu.h and linux */
+
+#ifndef __KONA_COMMON_CLK_H
+#define __KONA_COMMON_CLK_H
+
+#include <linux/types.h>
+
+struct clk;
+
+/* Only implement required functions for your specific architecture */
+int clk_init(void);
+struct clk *clk_get(const char *id);
+int clk_enable(struct clk *clk);
+void clk_disable(struct clk *clk);
+unsigned long clk_get_rate(struct clk *clk);
+long clk_round_rate(struct clk *clk, unsigned long rate);
+int clk_set_rate(struct clk *clk, unsigned long rate);
+int clk_set_parent(struct clk *clk, struct clk *parent);
+struct clk *clk_get_parent(struct clk *clk);
+int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep);
+int clk_bsc_enable(void *base);
+
+#endif
diff --git a/arch/arm/include/asm/kona-common/kona_sdhci.h b/arch/arm/include/asm/kona-common/kona_sdhci.h
new file mode 100644 (file)
index 0000000..1ff0e55
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#ifndef __KONA_SDHCI_H
+#define __KONA_SDHCI_H
+
+int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks);
+
+#endif
diff --git a/board/broadcom/bcm28155_ap/Makefile b/board/broadcom/bcm28155_ap/Makefile
new file mode 100644 (file)
index 0000000..b18785a
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright 2013 Broadcom Corporation.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  += $(BOARD).o
diff --git a/board/broadcom/bcm28155_ap/bcm28155_ap.c b/board/broadcom/bcm28155_ap/bcm28155_ap.c
new file mode 100644 (file)
index 0000000..940a1c2
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <mmc.h>
+#include <asm/kona-common/kona_sdhci.h>
+#include <asm/kona-common/clk.h>
+#include <asm/arch/sysmap.h>
+
+#define SECWATCHDOG_SDOGCR_OFFSET      0x00000000
+#define SECWATCHDOG_SDOGCR_EN_SHIFT    27
+#define SECWATCHDOG_SDOGCR_SRSTEN_SHIFT        26
+#define SECWATCHDOG_SDOGCR_CLKS_SHIFT  20
+#define SECWATCHDOG_SDOGCR_LD_SHIFT    0
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * board_init - early hardware init
+ */
+int board_init(void)
+{
+       printf("Relocation Offset is: %08lx\n", gd->reloc_off);
+
+       /* adress of boot parameters */
+       gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+       clk_init();
+
+       return 0;
+}
+
+/*
+ * misc_init_r - miscellaneous platform dependent initializations
+ */
+int misc_init_r(void)
+{
+       /* Disable watchdog reset - watchdog unused */
+       writel((0 << SECWATCHDOG_SDOGCR_EN_SHIFT) |
+              (0 << SECWATCHDOG_SDOGCR_SRSTEN_SHIFT) |
+              (4 << SECWATCHDOG_SDOGCR_CLKS_SHIFT) |
+              (0x5a0 << SECWATCHDOG_SDOGCR_LD_SHIFT),
+              (SECWD_BASE_ADDR + SECWATCHDOG_SDOGCR_OFFSET));
+
+       return 0;
+}
+
+/*
+ * dram_init - sets uboots idea of sdram size
+ */
+int dram_init(void)
+{
+       gd->ram_size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
+                                   CONFIG_SYS_SDRAM_SIZE);
+       return 0;
+}
+
+/* This is called after dram_init() so use get_ram_size result */
+void dram_init_banksize(void)
+{
+       gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+       gd->bd->bi_dram[0].size = gd->ram_size;
+}
+
+#ifdef CONFIG_KONA_SDHCI
+/*
+ * mmc_init - Initializes mmc
+ */
+int board_mmc_init(bd_t *bis)
+{
+       int ret = 0;
+
+       /* Register eMMC - SDIO2 */
+       ret = kona_sdhci_init(1, 400000, 0);
+       if (ret)
+               return ret;
+
+       /* Register SD Card - SDIO4 kona_mmc_init assumes 0 based index */
+       ret = kona_sdhci_init(3, 400000, 0);
+       return ret;
+}
+#endif
index 462e35b..872cb09 100644 (file)
@@ -278,6 +278,7 @@ Active  arm         armv7          am33xx      ti              ti816x
 Active  arm         armv7          at91        atmel           sama5d3xek          sama5d3xek_mmc                       sama5d3xek:SAMA5D3,SYS_USE_MMC                                                                                                    Bo Shen <voice.shen@atmel.com>
 Active  arm         armv7          at91        atmel           sama5d3xek          sama5d3xek_nandflash                 sama5d3xek:SAMA5D3,SYS_USE_NANDFLASH                                                                                              Bo Shen <voice.shen@atmel.com>
 Active  arm         armv7          at91        atmel           sama5d3xek          sama5d3xek_spiflash                  sama5d3xek:SAMA5D3,SYS_USE_SERIALFLASH                                                                                            Bo Shen <voice.shen@atmel.com>
+Active  arm         armv7          bcm281xx    broadcom        bcm28155_ap         bcm28155_ap                          bcm28155_ap                                                                                                                       Tim Kryger <tim.kryger@linaro.org>
 Active  arm         armv7          exynos      samsung         arndale             arndale                              -                                                                                                                                 Inderpal Singh <inderpal.singh@linaro.org>
 Active  arm         armv7          exynos      samsung         origen              origen                               -                                                                                                                                 Chander Kashyap <k.chander@samsung.com>
 Active  arm         armv7          exynos      samsung         smdk5250            smdk5250                             -                                                                                                                                 Chander Kashyap <k.chander@samsung.com>
index 29e48db..3d13268 100644 (file)
@@ -45,6 +45,7 @@ static char *from_env(const char *envvar)
        return ret;
 }
 
+#ifdef CONFIG_CMD_NET
 /*
  * Convert an ethaddr from the environment to the format used by pxelinux
  * filenames based on mac addresses. Convert's ':' to '-', and adds "01-" to
@@ -75,6 +76,7 @@ static int format_mac_pxe(char *outbuf, size_t outbuf_len)
 
        return 1;
 }
+#endif
 
 /*
  * Returns the directory the file specified in the bootfile env variable is
@@ -120,6 +122,7 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path,
 
 static int (*do_getfile)(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr);
 
+#ifdef CONFIG_CMD_NET
 static int do_get_tftp(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
 {
        char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
@@ -132,6 +135,7 @@ static int do_get_tftp(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
 
        return 1;
 }
+#endif
 
 static char *fs_argv[5];
 
@@ -249,6 +253,8 @@ static int get_pxe_file(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr
        return 1;
 }
 
+#ifdef CONFIG_CMD_NET
+
 #define PXELINUX_DIR "pxelinux.cfg/"
 
 /*
@@ -397,6 +403,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        return 1;
 }
+#endif
 
 /*
  * Wrapper to make it easier to store the file at file_path in the location
@@ -647,6 +654,7 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
                len += strlen(ip_str);
        }
 
+#ifdef CONFIG_CMD_NET
        if (label->ipappend & 0x2) {
                int err;
                strcpy(mac_str, " BOOTIF=");
@@ -655,6 +663,7 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
                        mac_str[0] = '\0';
                len += strlen(mac_str);
        }
+#endif
 
        if (label->append)
                len += strlen(label->append);
@@ -1500,6 +1509,7 @@ static void handle_pxe_menu(cmd_tbl_t *cmdtp, struct pxe_menu *cfg)
        boot_unattempted_labels(cmdtp, cfg);
 }
 
+#ifdef CONFIG_CMD_NET
 /*
  * Boots a system using a pxe file
  *
@@ -1576,6 +1586,7 @@ U_BOOT_CMD(
        "get - try to retrieve a pxe file using tftp\npxe "
        "boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n"
 );
+#endif
 
 /*
  * Boots a system using a local disk syslinux/extlinux file
index b903c45..ed2c0c7 100644 (file)
@@ -8,6 +8,7 @@
 obj-$(CONFIG_AT91_GPIO)        += at91_gpio.o
 obj-$(CONFIG_INTEL_ICH6_GPIO)  += intel_ich6_gpio.o
 obj-$(CONFIG_KIRKWOOD_GPIO)    += kw_gpio.o
+obj-$(CONFIG_KONA_GPIO)        += kona_gpio.o
 obj-$(CONFIG_MARVELL_GPIO)     += mvgpio.o
 obj-$(CONFIG_MARVELL_MFP)      += mvmfp.o
 obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o
diff --git a/drivers/gpio/kona_gpio.c b/drivers/gpio/kona_gpio.c
new file mode 100644 (file)
index 0000000..6511743
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sysmap.h>
+
+#define GPIO_BASE                              (void *)GPIO2_BASE_ADDR
+
+#define GPIO_PASSWD                            0x00a5a501
+#define GPIO_PER_BANK                          32
+#define GPIO_MAX_BANK_NUM                      8
+
+#define GPIO_BANK(gpio)                                ((gpio) >> 5)
+#define GPIO_BITMASK(gpio)     \
+       (1UL << ((gpio) & (GPIO_PER_BANK - 1)))
+
+#define GPIO_OUT_STATUS(bank)                  (0x00000000 + ((bank) << 2))
+#define GPIO_IN_STATUS(bank)                   (0x00000020 + ((bank) << 2))
+#define GPIO_OUT_SET(bank)                     (0x00000040 + ((bank) << 2))
+#define GPIO_OUT_CLEAR(bank)                   (0x00000060 + ((bank) << 2))
+#define GPIO_INT_STATUS(bank)                  (0x00000080 + ((bank) << 2))
+#define GPIO_INT_MASK(bank)                    (0x000000a0 + ((bank) << 2))
+#define GPIO_INT_MSKCLR(bank)                  (0x000000c0 + ((bank) << 2))
+#define GPIO_CONTROL(bank)                     (0x00000100 + ((bank) << 2))
+#define GPIO_PWD_STATUS(bank)                  (0x00000500 + ((bank) << 2))
+
+#define GPIO_GPPWR_OFFSET                      0x00000520
+
+#define GPIO_GPCTR0_DBR_SHIFT                  5
+#define GPIO_GPCTR0_DBR_MASK                   0x000001e0
+
+#define GPIO_GPCTR0_ITR_SHIFT                  3
+#define GPIO_GPCTR0_ITR_MASK                   0x00000018
+#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE                0x00000001
+#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE       0x00000002
+#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE          0x00000003
+
+#define GPIO_GPCTR0_IOTR_MASK                  0x00000001
+#define GPIO_GPCTR0_IOTR_CMD_0UTPUT            0x00000000
+#define GPIO_GPCTR0_IOTR_CMD_INPUT             0x00000001
+
+int gpio_request(unsigned gpio, const char *label)
+{
+       unsigned int value, off;
+
+       writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
+       off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
+       value = readl(GPIO_BASE + off) & ~GPIO_BITMASK(gpio);
+       writel(value, GPIO_BASE + off);
+
+       return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+       unsigned int value, off;
+
+       writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
+       off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
+       value = readl(GPIO_BASE + off) | GPIO_BITMASK(gpio);
+       writel(value, GPIO_BASE + off);
+
+       return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+       u32 val;
+
+       val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+       val &= ~GPIO_GPCTR0_IOTR_MASK;
+       val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
+       writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
+
+       return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+       int bank_id = GPIO_BANK(gpio);
+       int bitmask = GPIO_BITMASK(gpio);
+       u32 val, off;
+
+       val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+       val &= ~GPIO_GPCTR0_IOTR_MASK;
+       val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
+       writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
+       off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+       val = readl(GPIO_BASE + off);
+       val |= bitmask;
+       writel(val, GPIO_BASE + off);
+
+       return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+       int bank_id = GPIO_BANK(gpio);
+       int bitmask = GPIO_BITMASK(gpio);
+       u32 val, off;
+
+       /* determine the GPIO pin direction */
+       val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+       val &= GPIO_GPCTR0_IOTR_MASK;
+
+       /* read the GPIO bank status */
+       off = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
+           GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
+       val = readl(GPIO_BASE + off);
+
+       /* return the specified bit status */
+       return !!(val & bitmask);
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+       int bank_id = GPIO_BANK(gpio);
+       int bitmask = GPIO_BITMASK(gpio);
+       u32 val, off;
+
+       /* determine the GPIO pin direction */
+       val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+       val &= GPIO_GPCTR0_IOTR_MASK;
+
+       /* this function only applies to output pin */
+       if (GPIO_GPCTR0_IOTR_CMD_INPUT == val) {
+               printf("%s: Cannot set an input pin %d\n", __func__, gpio);
+               return;
+       }
+
+       off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+       val = readl(GPIO_BASE + off);
+       val |= bitmask;
+       writel(val, GPIO_BASE + off);
+}
index fa3a875..36d5e5f 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
 obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
 obj-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o
+obj-$(CONFIG_SYS_I2C_KONA) += kona_i2c.o
 obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
 obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
 obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o
diff --git a/drivers/i2c/kona_i2c.c b/drivers/i2c/kona_i2c.c
new file mode 100644 (file)
index 0000000..0b1715a
--- /dev/null
@@ -0,0 +1,730 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include <i2c.h>
+
+/* Hardware register offsets and field defintions */
+#define CS_OFFSET                              0x00000020
+#define CS_ACK_SHIFT                           3
+#define CS_ACK_MASK                            0x00000008
+#define CS_ACK_CMD_GEN_START                   0x00000000
+#define CS_ACK_CMD_GEN_RESTART                 0x00000001
+#define CS_CMD_SHIFT                           1
+#define CS_CMD_CMD_NO_ACTION                   0x00000000
+#define CS_CMD_CMD_START_RESTART               0x00000001
+#define CS_CMD_CMD_STOP                                0x00000002
+#define CS_EN_SHIFT                            0
+#define CS_EN_CMD_ENABLE_BSC                   0x00000001
+
+#define TIM_OFFSET                             0x00000024
+#define TIM_PRESCALE_SHIFT                     6
+#define TIM_P_SHIFT                            3
+#define TIM_NO_DIV_SHIFT                       2
+#define TIM_DIV_SHIFT                          0
+
+#define DAT_OFFSET                             0x00000028
+
+#define TOUT_OFFSET                            0x0000002c
+
+#define TXFCR_OFFSET                           0x0000003c
+#define TXFCR_FIFO_FLUSH_MASK                  0x00000080
+#define TXFCR_FIFO_EN_MASK                     0x00000040
+
+#define IER_OFFSET                             0x00000044
+#define IER_READ_COMPLETE_INT_MASK             0x00000010
+#define IER_I2C_INT_EN_MASK                    0x00000008
+#define IER_FIFO_INT_EN_MASK                   0x00000002
+#define IER_NOACK_EN_MASK                      0x00000001
+
+#define ISR_OFFSET                             0x00000048
+#define ISR_RESERVED_MASK                      0xffffff60
+#define ISR_CMDBUSY_MASK                       0x00000080
+#define ISR_READ_COMPLETE_MASK                 0x00000010
+#define ISR_SES_DONE_MASK                      0x00000008
+#define ISR_ERR_MASK                           0x00000004
+#define ISR_TXFIFOEMPTY_MASK                   0x00000002
+#define ISR_NOACK_MASK                         0x00000001
+
+#define CLKEN_OFFSET                           0x0000004c
+#define CLKEN_AUTOSENSE_OFF_MASK               0x00000080
+#define CLKEN_M_SHIFT                          4
+#define CLKEN_N_SHIFT                          1
+#define CLKEN_CLKEN_MASK                       0x00000001
+
+#define FIFO_STATUS_OFFSET                     0x00000054
+#define FIFO_STATUS_RXFIFO_EMPTY_MASK          0x00000004
+#define FIFO_STATUS_TXFIFO_EMPTY_MASK          0x00000010
+
+#define HSTIM_OFFSET                           0x00000058
+#define HSTIM_HS_MODE_MASK                     0x00008000
+#define HSTIM_HS_HOLD_SHIFT                    10
+#define HSTIM_HS_HIGH_PHASE_SHIFT              5
+#define HSTIM_HS_SETUP_SHIFT                   0
+
+#define PADCTL_OFFSET                          0x0000005c
+#define PADCTL_PAD_OUT_EN_MASK                 0x00000004
+
+#define RXFCR_OFFSET                           0x00000068
+#define RXFCR_NACK_EN_SHIFT                    7
+#define RXFCR_READ_COUNT_SHIFT                 0
+#define RXFIFORDOUT_OFFSET                     0x0000006c
+
+/* Locally used constants */
+#define MAX_RX_FIFO_SIZE               64U     /* bytes */
+#define MAX_TX_FIFO_SIZE               64U     /* bytes */
+
+#define I2C_TIMEOUT                    100000  /* usecs */
+
+#define WAIT_INT_CHK                   100     /* usecs */
+#if I2C_TIMEOUT % WAIT_INT_CHK
+#error I2C_TIMEOUT must be a multiple of WAIT_INT_CHK
+#endif
+
+/* Operations that can be commanded to the controller */
+enum bcm_kona_cmd_t {
+       BCM_CMD_NOACTION = 0,
+       BCM_CMD_START,
+       BCM_CMD_RESTART,
+       BCM_CMD_STOP,
+};
+
+enum bus_speed_index {
+       BCM_SPD_100K = 0,
+       BCM_SPD_400K,
+       BCM_SPD_1MHZ,
+};
+
+/* Internal divider settings for standard mode, fast mode and fast mode plus */
+struct bus_speed_cfg {
+       uint8_t time_m;         /* Number of cycles for setup time */
+       uint8_t time_n;         /* Number of cycles for hold time */
+       uint8_t prescale;       /* Prescale divider */
+       uint8_t time_p;         /* Timing coefficient */
+       uint8_t no_div;         /* Disable clock divider */
+       uint8_t time_div;       /* Post-prescale divider */
+};
+
+static const struct bus_speed_cfg std_cfg_table[] = {
+       [BCM_SPD_100K] = {0x01, 0x01, 0x03, 0x06, 0x00, 0x02},
+       [BCM_SPD_400K] = {0x05, 0x01, 0x03, 0x05, 0x01, 0x02},
+       [BCM_SPD_1MHZ] = {0x01, 0x01, 0x03, 0x01, 0x01, 0x03},
+};
+
+struct bcm_kona_i2c_dev {
+       void *base;
+       uint speed;
+       const struct bus_speed_cfg *std_cfg;
+};
+
+/* Keep these two defines in sync */
+#define DEF_SPD 100000
+#define DEF_SPD_ENUM BCM_SPD_100K
+
+#define DEF_DEVICE(num) \
+{(void *)CONFIG_SYS_I2C_BASE##num, DEF_SPD, &std_cfg_table[DEF_SPD_ENUM]}
+
+static struct bcm_kona_i2c_dev g_i2c_devs[CONFIG_SYS_MAX_I2C_BUS] = {
+#ifdef CONFIG_SYS_I2C_BASE0
+       DEF_DEVICE(0),
+#endif
+#ifdef CONFIG_SYS_I2C_BASE1
+       DEF_DEVICE(1),
+#endif
+#ifdef CONFIG_SYS_I2C_BASE2
+       DEF_DEVICE(2),
+#endif
+#ifdef CONFIG_SYS_I2C_BASE3
+       DEF_DEVICE(3),
+#endif
+#ifdef CONFIG_SYS_I2C_BASE4
+       DEF_DEVICE(4),
+#endif
+#ifdef CONFIG_SYS_I2C_BASE5
+       DEF_DEVICE(5),
+#endif
+};
+
+#define I2C_M_TEN      0x0010  /* ten bit address */
+#define I2C_M_RD       0x0001  /* read data */
+#define I2C_M_NOSTART  0x4000  /* no restart between msgs */
+
+struct i2c_msg {
+       uint16_t addr;
+       uint16_t flags;
+       uint16_t len;
+       uint8_t *buf;
+};
+
+static void bcm_kona_i2c_send_cmd_to_ctrl(struct bcm_kona_i2c_dev *dev,
+                                         enum bcm_kona_cmd_t cmd)
+{
+       debug("%s, %d\n", __func__, cmd);
+
+       switch (cmd) {
+       case BCM_CMD_NOACTION:
+               writel((CS_CMD_CMD_NO_ACTION << CS_CMD_SHIFT) |
+                      (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
+                      dev->base + CS_OFFSET);
+               break;
+
+       case BCM_CMD_START:
+               writel((CS_ACK_CMD_GEN_START << CS_ACK_SHIFT) |
+                      (CS_CMD_CMD_START_RESTART << CS_CMD_SHIFT) |
+                      (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
+                      dev->base + CS_OFFSET);
+               break;
+
+       case BCM_CMD_RESTART:
+               writel((CS_ACK_CMD_GEN_RESTART << CS_ACK_SHIFT) |
+                      (CS_CMD_CMD_START_RESTART << CS_CMD_SHIFT) |
+                      (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
+                      dev->base + CS_OFFSET);
+               break;
+
+       case BCM_CMD_STOP:
+               writel((CS_CMD_CMD_STOP << CS_CMD_SHIFT) |
+                      (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT),
+                      dev->base + CS_OFFSET);
+               break;
+
+       default:
+               printf("Unknown command %d\n", cmd);
+       }
+}
+
+static void bcm_kona_i2c_enable_clock(struct bcm_kona_i2c_dev *dev)
+{
+       writel(readl(dev->base + CLKEN_OFFSET) | CLKEN_CLKEN_MASK,
+              dev->base + CLKEN_OFFSET);
+}
+
+static void bcm_kona_i2c_disable_clock(struct bcm_kona_i2c_dev *dev)
+{
+       writel(readl(dev->base + CLKEN_OFFSET) & ~CLKEN_CLKEN_MASK,
+              dev->base + CLKEN_OFFSET);
+}
+
+/* Wait until at least one of the mask bit(s) are set */
+static unsigned long wait_for_int_timeout(struct bcm_kona_i2c_dev *dev,
+                                         unsigned long time_left,
+                                         uint32_t mask)
+{
+       uint32_t status;
+
+       while (time_left) {
+               status = readl(dev->base + ISR_OFFSET);
+
+               if ((status & ~ISR_RESERVED_MASK) == 0) {
+                       debug("Bogus I2C interrupt 0x%x\n", status);
+                       continue;
+               }
+
+               /* Must flush the TX FIFO when NAK detected */
+               if (status & ISR_NOACK_MASK)
+                       writel(TXFCR_FIFO_FLUSH_MASK | TXFCR_FIFO_EN_MASK,
+                              dev->base + TXFCR_OFFSET);
+
+               writel(status & ~ISR_RESERVED_MASK, dev->base + ISR_OFFSET);
+
+               if (status & mask) {
+                       /* We are done since one of the mask bits are set */
+                       return time_left;
+               }
+               udelay(WAIT_INT_CHK);
+               time_left -= WAIT_INT_CHK;
+       }
+       return 0;
+}
+
+/* Send command to I2C bus */
+static int bcm_kona_send_i2c_cmd(struct bcm_kona_i2c_dev *dev,
+                                enum bcm_kona_cmd_t cmd)
+{
+       int rc = 0;
+       unsigned long time_left = I2C_TIMEOUT;
+
+       /* Send the command */
+       bcm_kona_i2c_send_cmd_to_ctrl(dev, cmd);
+
+       /* Wait for transaction to finish or timeout */
+       time_left = wait_for_int_timeout(dev, time_left, IER_I2C_INT_EN_MASK);
+
+       if (!time_left) {
+               printf("controller timed out\n");
+               rc = -ETIMEDOUT;
+       }
+
+       /* Clear command */
+       bcm_kona_i2c_send_cmd_to_ctrl(dev, BCM_CMD_NOACTION);
+
+       return rc;
+}
+
+/* Read a single RX FIFO worth of data from the i2c bus */
+static int bcm_kona_i2c_read_fifo_single(struct bcm_kona_i2c_dev *dev,
+                                        uint8_t *buf, unsigned int len,
+                                        unsigned int last_byte_nak)
+{
+       unsigned long time_left = I2C_TIMEOUT;
+
+       /* Start the RX FIFO */
+       writel((last_byte_nak << RXFCR_NACK_EN_SHIFT) |
+              (len << RXFCR_READ_COUNT_SHIFT), dev->base + RXFCR_OFFSET);
+
+       /* Wait for FIFO read to complete */
+       time_left =
+           wait_for_int_timeout(dev, time_left, IER_READ_COMPLETE_INT_MASK);
+
+       if (!time_left) {
+               printf("RX FIFO time out\n");
+               return -EREMOTEIO;
+       }
+
+       /* Read data from FIFO */
+       for (; len > 0; len--, buf++)
+               *buf = readl(dev->base + RXFIFORDOUT_OFFSET);
+
+       return 0;
+}
+
+/* Read any amount of data using the RX FIFO from the i2c bus */
+static int bcm_kona_i2c_read_fifo(struct bcm_kona_i2c_dev *dev,
+                                 struct i2c_msg *msg)
+{
+       unsigned int bytes_to_read = MAX_RX_FIFO_SIZE;
+       unsigned int last_byte_nak = 0;
+       unsigned int bytes_read = 0;
+       int rc;
+
+       uint8_t *tmp_buf = msg->buf;
+
+       while (bytes_read < msg->len) {
+               if (msg->len - bytes_read <= MAX_RX_FIFO_SIZE) {
+                       last_byte_nak = 1;      /* NAK last byte of transfer */
+                       bytes_to_read = msg->len - bytes_read;
+               }
+
+               rc = bcm_kona_i2c_read_fifo_single(dev, tmp_buf, bytes_to_read,
+                                                  last_byte_nak);
+               if (rc < 0)
+                       return -EREMOTEIO;
+
+               bytes_read += bytes_to_read;
+               tmp_buf += bytes_to_read;
+       }
+
+       return 0;
+}
+
+/* Write a single byte of data to the i2c bus */
+static int bcm_kona_i2c_write_byte(struct bcm_kona_i2c_dev *dev, uint8_t data,
+                                  unsigned int nak_expected)
+{
+       unsigned long time_left = I2C_TIMEOUT;
+       unsigned int nak_received;
+
+       /* Clear pending session done interrupt */
+       writel(ISR_SES_DONE_MASK, dev->base + ISR_OFFSET);
+
+       /* Send one byte of data */
+       writel(data, dev->base + DAT_OFFSET);
+
+       time_left = wait_for_int_timeout(dev, time_left, IER_I2C_INT_EN_MASK);
+
+       if (!time_left) {
+               debug("controller timed out\n");
+               return -ETIMEDOUT;
+       }
+
+       nak_received = readl(dev->base + CS_OFFSET) & CS_ACK_MASK ? 1 : 0;
+
+       if (nak_received ^ nak_expected) {
+               debug("unexpected NAK/ACK\n");
+               return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+/* Write a single TX FIFO worth of data to the i2c bus */
+static int bcm_kona_i2c_write_fifo_single(struct bcm_kona_i2c_dev *dev,
+                                         uint8_t *buf, unsigned int len)
+{
+       int k;
+       unsigned long time_left = I2C_TIMEOUT;
+       unsigned int fifo_status;
+
+       /* Write data into FIFO */
+       for (k = 0; k < len; k++)
+               writel(buf[k], (dev->base + DAT_OFFSET));
+
+       /* Wait for FIFO to empty */
+       do {
+               time_left =
+                   wait_for_int_timeout(dev, time_left,
+                                        (IER_FIFO_INT_EN_MASK |
+                                         IER_NOACK_EN_MASK));
+               fifo_status = readl(dev->base + FIFO_STATUS_OFFSET);
+       } while (time_left && !(fifo_status & FIFO_STATUS_TXFIFO_EMPTY_MASK));
+
+       /* Check if there was a NAK */
+       if (readl(dev->base + CS_OFFSET) & CS_ACK_MASK) {
+               printf("unexpected NAK\n");
+               return -EREMOTEIO;
+       }
+
+       /* Check if a timeout occured */
+       if (!time_left) {
+               printf("completion timed out\n");
+               return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+/* Write any amount of data using TX FIFO to the i2c bus */
+static int bcm_kona_i2c_write_fifo(struct bcm_kona_i2c_dev *dev,
+                                  struct i2c_msg *msg)
+{
+       unsigned int bytes_to_write = MAX_TX_FIFO_SIZE;
+       unsigned int bytes_written = 0;
+       int rc;
+
+       uint8_t *tmp_buf = msg->buf;
+
+       while (bytes_written < msg->len) {
+               if (msg->len - bytes_written <= MAX_TX_FIFO_SIZE)
+                       bytes_to_write = msg->len - bytes_written;
+
+               rc = bcm_kona_i2c_write_fifo_single(dev, tmp_buf,
+                                                   bytes_to_write);
+               if (rc < 0)
+                       return -EREMOTEIO;
+
+               bytes_written += bytes_to_write;
+               tmp_buf += bytes_to_write;
+       }
+
+       return 0;
+}
+
+/* Send i2c address */
+static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev,
+                               struct i2c_msg *msg)
+{
+       unsigned char addr;
+
+       if (msg->flags & I2C_M_TEN) {
+               /* First byte is 11110XX0 where XX is upper 2 bits */
+               addr = 0xf0 | ((msg->addr & 0x300) >> 7);
+               if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
+                       return -EREMOTEIO;
+
+               /* Second byte is the remaining 8 bits */
+               addr = msg->addr & 0xff;
+               if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
+                       return -EREMOTEIO;
+
+               if (msg->flags & I2C_M_RD) {
+                       /* For read, send restart command */
+                       if (bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART) < 0)
+                               return -EREMOTEIO;
+
+                       /* Then re-send the first byte with the read bit set */
+                       addr = 0xf0 | ((msg->addr & 0x300) >> 7) | 0x01;
+                       if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
+                               return -EREMOTEIO;
+               }
+       } else {
+               addr = msg->addr << 1;
+
+               if (msg->flags & I2C_M_RD)
+                       addr |= 1;
+
+               if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
+                       return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+static void bcm_kona_i2c_enable_autosense(struct bcm_kona_i2c_dev *dev)
+{
+       writel(readl(dev->base + CLKEN_OFFSET) & ~CLKEN_AUTOSENSE_OFF_MASK,
+              dev->base + CLKEN_OFFSET);
+}
+
+static void bcm_kona_i2c_config_timing(struct bcm_kona_i2c_dev *dev)
+{
+       writel(readl(dev->base + HSTIM_OFFSET) & ~HSTIM_HS_MODE_MASK,
+              dev->base + HSTIM_OFFSET);
+
+       writel((dev->std_cfg->prescale << TIM_PRESCALE_SHIFT) |
+              (dev->std_cfg->time_p << TIM_P_SHIFT) |
+              (dev->std_cfg->no_div << TIM_NO_DIV_SHIFT) |
+              (dev->std_cfg->time_div << TIM_DIV_SHIFT),
+              dev->base + TIM_OFFSET);
+
+       writel((dev->std_cfg->time_m << CLKEN_M_SHIFT) |
+              (dev->std_cfg->time_n << CLKEN_N_SHIFT) |
+              CLKEN_CLKEN_MASK, dev->base + CLKEN_OFFSET);
+}
+
+/* Master transfer function */
+static int bcm_kona_i2c_xfer(struct bcm_kona_i2c_dev *dev,
+                            struct i2c_msg msgs[], int num)
+{
+       struct i2c_msg *pmsg;
+       int rc = 0;
+       int i;
+
+       /* Enable pad output */
+       writel(0, dev->base + PADCTL_OFFSET);
+
+       /* Enable internal clocks */
+       bcm_kona_i2c_enable_clock(dev);
+
+       /* Send start command */
+       rc = bcm_kona_send_i2c_cmd(dev, BCM_CMD_START);
+       if (rc < 0) {
+               printf("Start command failed rc = %d\n", rc);
+               goto xfer_disable_pad;
+       }
+
+       /* Loop through all messages */
+       for (i = 0; i < num; i++) {
+               pmsg = &msgs[i];
+
+               /* Send restart for subsequent messages */
+               if ((i != 0) && ((pmsg->flags & I2C_M_NOSTART) == 0)) {
+                       rc = bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART);
+                       if (rc < 0) {
+                               printf("restart cmd failed rc = %d\n", rc);
+                               goto xfer_send_stop;
+                       }
+               }
+
+               /* Send slave address */
+               if (!(pmsg->flags & I2C_M_NOSTART)) {
+                       rc = bcm_kona_i2c_do_addr(dev, pmsg);
+                       if (rc < 0) {
+                               debug("NAK from addr %2.2x msg#%d rc = %d\n",
+                                     pmsg->addr, i, rc);
+                               goto xfer_send_stop;
+                       }
+               }
+
+               /* Perform data transfer */
+               if (pmsg->flags & I2C_M_RD) {
+                       rc = bcm_kona_i2c_read_fifo(dev, pmsg);
+                       if (rc < 0) {
+                               printf("read failure\n");
+                               goto xfer_send_stop;
+                       }
+               } else {
+                       rc = bcm_kona_i2c_write_fifo(dev, pmsg);
+                       if (rc < 0) {
+                               printf("write failure");
+                               goto xfer_send_stop;
+                       }
+               }
+       }
+
+       rc = num;
+
+xfer_send_stop:
+       /* Send a STOP command */
+       bcm_kona_send_i2c_cmd(dev, BCM_CMD_STOP);
+
+xfer_disable_pad:
+       /* Disable pad output */
+       writel(PADCTL_PAD_OUT_EN_MASK, dev->base + PADCTL_OFFSET);
+
+       /* Stop internal clock */
+       bcm_kona_i2c_disable_clock(dev);
+
+       return rc;
+}
+
+static uint bcm_kona_i2c_assign_bus_speed(struct bcm_kona_i2c_dev *dev,
+                                         uint speed)
+{
+       switch (speed) {
+       case 100000:
+               dev->std_cfg = &std_cfg_table[BCM_SPD_100K];
+               break;
+       case 400000:
+               dev->std_cfg = &std_cfg_table[BCM_SPD_400K];
+               break;
+       case 1000000:
+               dev->std_cfg = &std_cfg_table[BCM_SPD_1MHZ];
+               break;
+       default:
+               printf("%d hz bus speed not supported\n", speed);
+               return -EINVAL;
+       }
+       dev->speed = speed;
+       return 0;
+}
+
+static void bcm_kona_i2c_init(struct bcm_kona_i2c_dev *dev)
+{
+       /* Parse bus speed */
+       bcm_kona_i2c_assign_bus_speed(dev, dev->speed);
+
+       /* Enable internal clocks */
+       bcm_kona_i2c_enable_clock(dev);
+
+       /* Configure internal dividers */
+       bcm_kona_i2c_config_timing(dev);
+
+       /* Disable timeout */
+       writel(0, dev->base + TOUT_OFFSET);
+
+       /* Enable autosense */
+       bcm_kona_i2c_enable_autosense(dev);
+
+       /* Enable TX FIFO */
+       writel(TXFCR_FIFO_FLUSH_MASK | TXFCR_FIFO_EN_MASK,
+              dev->base + TXFCR_OFFSET);
+
+       /* Mask all interrupts */
+       writel(0, dev->base + IER_OFFSET);
+
+       /* Clear all pending interrupts */
+       writel(ISR_CMDBUSY_MASK |
+              ISR_READ_COMPLETE_MASK |
+              ISR_SES_DONE_MASK |
+              ISR_ERR_MASK |
+              ISR_TXFIFOEMPTY_MASK | ISR_NOACK_MASK, dev->base + ISR_OFFSET);
+
+       /* Enable the controller but leave it idle */
+       bcm_kona_i2c_send_cmd_to_ctrl(dev, BCM_CMD_NOACTION);
+
+       /* Disable pad output */
+       writel(PADCTL_PAD_OUT_EN_MASK, dev->base + PADCTL_OFFSET);
+}
+
+/*
+ * uboot layer
+ */
+struct bcm_kona_i2c_dev *kona_get_dev(struct i2c_adapter *adap)
+{
+       return &g_i2c_devs[adap->hwadapnr];
+}
+
+static void kona_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
+{
+       struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
+
+       if (clk_bsc_enable(dev->base))
+               return;
+
+       bcm_kona_i2c_init(dev);
+}
+
+static int kona_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
+                        int alen, uchar *buffer, int len)
+{
+       /* msg[0] writes the addr, msg[1] reads the data */
+       struct i2c_msg msg[2];
+       unsigned char msgbuf0[64];
+       struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
+
+       msg[0].addr = chip;
+       msg[0].flags = 0;
+       msg[0].len = 1;
+       msg[0].buf = msgbuf0;   /* msgbuf0 contains incrementing reg addr */
+
+       msg[1].addr = chip;
+       msg[1].flags = I2C_M_RD;
+       /* msg[1].buf dest ptr increments each read */
+
+       msgbuf0[0] = (unsigned char)addr;
+       msg[1].buf = buffer;
+       msg[1].len = len;
+       if (bcm_kona_i2c_xfer(dev, msg, 2) < 0) {
+               /* Sending 2 i2c messages */
+               kona_i2c_init(adap, adap->speed, adap->slaveaddr);
+               debug("I2C read: I/O error\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+static int kona_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
+                         int alen, uchar *buffer, int len)
+{
+       struct i2c_msg msg[0];
+       unsigned char msgbuf0[64];
+       unsigned int i;
+       struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
+
+       msg[0].addr = chip;
+       msg[0].flags = 0;
+       msg[0].len = 2;         /* addr byte plus data */
+       msg[0].buf = msgbuf0;
+
+       for (i = 0; i < len; i++) {
+               msgbuf0[0] = addr++;
+               msgbuf0[1] = buffer[i];
+               if (bcm_kona_i2c_xfer(dev, msg, 1) < 0) {
+                       kona_i2c_init(adap, adap->speed, adap->slaveaddr);
+                       debug("I2C write: I/O error\n");
+                       return -EIO;
+               }
+       }
+       return 0;
+}
+
+static int kona_i2c_probe(struct i2c_adapter *adap, uchar chip)
+{
+       uchar tmp;
+
+       /*
+        * read addr 0x0 of the given chip.
+        */
+       return kona_i2c_read(adap, chip, 0x0, 1, &tmp, 1);
+}
+
+static uint kona_i2c_set_bus_speed(struct i2c_adapter *adap, uint speed)
+{
+       struct bcm_kona_i2c_dev *dev = kona_get_dev(adap);
+       return bcm_kona_i2c_assign_bus_speed(dev, speed);
+}
+
+/*
+ * Register kona i2c adapters. Keep the order below so
+ * that the bus number matches the adapter number.
+ */
+#define DEF_ADAPTER(num) \
+U_BOOT_I2C_ADAP_COMPLETE(kona##num, kona_i2c_init, kona_i2c_probe, \
+                        kona_i2c_read, kona_i2c_write, \
+                        kona_i2c_set_bus_speed, DEF_SPD, 0x00, num)
+
+#ifdef CONFIG_SYS_I2C_BASE0
+       DEF_ADAPTER(0)
+#endif
+#ifdef CONFIG_SYS_I2C_BASE1
+       DEF_ADAPTER(1)
+#endif
+#ifdef CONFIG_SYS_I2C_BASE2
+       DEF_ADAPTER(2)
+#endif
+#ifdef CONFIG_SYS_I2C_BASE3
+       DEF_ADAPTER(3)
+#endif
+#ifdef CONFIG_SYS_I2C_BASE4
+       DEF_ADAPTER(4)
+#endif
+#ifdef CONFIG_SYS_I2C_BASE5
+       DEF_ADAPTER(5)
+#endif
index e793ed9..931922b 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
 obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
 obj-$(CONFIG_SDHCI) += sdhci.o
 obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o
+obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o
 obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
 obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o
diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c
new file mode 100644 (file)
index 0000000..77e42c8
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <sdhci.h>
+#include <asm/errno.h>
+#include <asm/kona-common/clk.h>
+
+#define SDHCI_CORECTRL_OFFSET          0x00008000
+#define SDHCI_CORECTRL_EN              0x01
+#define SDHCI_CORECTRL_RESET           0x02
+
+#define SDHCI_CORESTAT_OFFSET          0x00008004
+#define SDHCI_CORESTAT_CD_SW           0x01
+
+#define SDHCI_COREIMR_OFFSET           0x00008008
+#define SDHCI_COREIMR_IP               0x01
+
+static int init_kona_mmc_core(struct sdhci_host *host)
+{
+       unsigned int mask;
+       unsigned int timeout;
+
+       if (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) {
+               printf("%s: sd host controller reset error\n", __func__);
+               return 1;
+       }
+
+       /* For kona a hardware reset before anything else. */
+       mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET) | SDHCI_CORECTRL_RESET;
+       sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);
+
+       /* Wait max 100 ms */
+       timeout = 1000;
+       do {
+               if (timeout == 0) {
+                       printf("%s: reset timeout error\n", __func__);
+                       return 1;
+               }
+               timeout--;
+               udelay(100);
+       } while (0 ==
+                (sdhci_readl(host, SDHCI_CORECTRL_OFFSET) &
+                 SDHCI_CORECTRL_RESET));
+
+       /* Clear the reset bit. */
+       mask = mask & ~SDHCI_CORECTRL_RESET;
+       sdhci_writel(host, mask, SDHCI_CORECTRL_OFFSET);
+
+       /* Enable AHB clock */
+       mask = sdhci_readl(host, SDHCI_CORECTRL_OFFSET);
+       sdhci_writel(host, mask | SDHCI_CORECTRL_EN, SDHCI_CORECTRL_OFFSET);
+
+       /* Enable interrupts */
+       sdhci_writel(host, SDHCI_COREIMR_IP, SDHCI_COREIMR_OFFSET);
+
+       /* Make sure Card is detected in controller */
+       mask = sdhci_readl(host, SDHCI_CORESTAT_OFFSET);
+       sdhci_writel(host, mask | SDHCI_CORESTAT_CD_SW, SDHCI_CORESTAT_OFFSET);
+
+       /* Wait max 100 ms */
+       timeout = 1000;
+       while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
+               if (timeout == 0) {
+                       printf("%s: CARD DETECT timeout error\n", __func__);
+                       return 1;
+               }
+               timeout--;
+               udelay(100);
+       }
+       return 0;
+}
+
+int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks)
+{
+       int ret = 0;
+       u32 max_clk;
+       void *reg_base;
+       struct sdhci_host *host = NULL;
+
+       host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
+       if (!host) {
+               printf("%s: sdhci host malloc fail!\n", __func__);
+               return -ENOMEM;
+       }
+       switch (dev_index) {
+       case 0:
+               reg_base = (void *)CONFIG_SYS_SDIO_BASE0;
+               ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO0_MAX_CLK,
+                                     &max_clk);
+               break;
+       case 1:
+               reg_base = (void *)CONFIG_SYS_SDIO_BASE1;
+               ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO1_MAX_CLK,
+                                     &max_clk);
+               break;
+       case 2:
+               reg_base = (void *)CONFIG_SYS_SDIO_BASE2;
+               ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO2_MAX_CLK,
+                                     &max_clk);
+               break;
+       case 3:
+               reg_base = (void *)CONFIG_SYS_SDIO_BASE3;
+               ret = clk_sdio_enable(reg_base, CONFIG_SYS_SDIO3_MAX_CLK,
+                                     &max_clk);
+               break;
+       default:
+               printf("%s: sdio dev index %d not supported\n",
+                      __func__, dev_index);
+               ret = -EINVAL;
+       }
+       if (ret)
+               return ret;
+
+       host->name = "kona-sdhci";
+       host->ioaddr = reg_base;
+       host->quirks = quirks;
+       host->host_caps = MMC_MODE_HC;
+
+       if (init_kona_mmc_core(host))
+               return -EINVAL;
+
+       if (quirks & SDHCI_QUIRK_REG32_RW)
+               host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
+       else
+               host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+
+       add_sdhci(host, max_clk, min_clk);
+       return ret;
+}
diff --git a/include/bitfield.h b/include/bitfield.h
new file mode 100644 (file)
index 0000000..ec4815c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+/*
+ * Bitfield operations
+ *
+ * These are generic bitfield operations which allow manipulation of variable
+ * width bitfields within a word. One use of this would be to use data tables
+ * to determine how to reprogram fields within R/W hardware registers.
+ *
+ * Example:
+ *
+ *            old_reg_val
+ * +--------+----+---+--+-----+----------+
+ * |        |    |   |  | old |          |
+ * +--------+----+---+--+-----+----------+
+ *
+ *            new_reg_val
+ * +--------+----+---+--+-----+----------+
+ * |        |    |   |  | new |          |
+ * +--------+----+---+--+-----+----------+
+ *
+ * mask = bitfield_mask(10, 5);
+ * old = bitfield_extract(old_reg_val, 10, 5);
+ * new_reg_val = bitfield_replace(old_reg_val, 10, 5, new);
+ *
+ * The numbers 10 and 5 could for example come from data
+ * tables which describe all bitfields in all registers.
+ */
+
+#include <linux/types.h>
+
+/* Produces a mask of set bits covering a range of a uint value */
+static inline uint bitfield_mask(uint shift, uint width)
+{
+       return ((1 << width) - 1) << shift;
+}
+
+/* Extract the value of a bitfield found within a given register value */
+static inline uint bitfield_extract(uint reg_val, uint shift, uint width)
+{
+       return (reg_val & bitfield_mask(shift, width)) >> shift;
+}
+
+/*
+ * Replace the value of a bitfield found within a given register value
+ * Returns the newly modified uint value with the replaced field.
+ */
+static inline uint bitfield_replace(uint reg_val, uint shift, uint width,
+                                   uint bitfield_val)
+{
+       uint mask = bitfield_mask(shift, width);
+
+       return (reg_val & ~mask) | (bitfield_val << shift);
+}
diff --git a/include/configs/bcm28155_ap.h b/include/configs/bcm28155_ap.h
new file mode 100644 (file)
index 0000000..8e1c81f
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#ifndef __BCM28155_AP_H
+#define __BCM28155_AP_H
+
+#include <asm/sizes.h>
+#include <asm/arch/sysmap.h>
+
+/* Architecture, CPU, chip, mach, etc */
+#define CONFIG_ARMV7
+#define CONFIG_KONA
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+/*
+ * Memory configuration
+ */
+#define CONFIG_SYS_TEXT_BASE           0xae000000
+
+#define CONFIG_SYS_SDRAM_BASE          0x80000000
+#define CONFIG_SYS_SDRAM_SIZE          0x80000000
+#define CONFIG_NR_DRAM_BANKS           1
+
+#define CONFIG_SYS_MALLOC_LEN          SZ_4M   /* see armv7/start.S. */
+#define CONFIG_STACKSIZE               SZ_256K
+
+/* GPIO Driver */
+#define CONFIG_KONA_GPIO
+
+/* MMC/SD Driver */
+#define CONFIG_SDHCI
+#define CONFIG_MMC_SDMA
+#define CONFIG_KONA_SDHCI
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+
+#define CONFIG_SYS_SDIO_BASE0 SDIO1_BASE_ADDR
+#define CONFIG_SYS_SDIO_BASE1 SDIO2_BASE_ADDR
+#define CONFIG_SYS_SDIO_BASE2 SDIO3_BASE_ADDR
+#define CONFIG_SYS_SDIO_BASE3 SDIO4_BASE_ADDR
+#define CONFIG_SYS_SDIO0_MAX_CLK 48000000
+#define CONFIG_SYS_SDIO1_MAX_CLK 48000000
+#define CONFIG_SYS_SDIO2_MAX_CLK 48000000
+#define CONFIG_SYS_SDIO3_MAX_CLK 48000000
+#define CONFIG_SYS_SDIO0 "sdio1"
+#define CONFIG_SYS_SDIO1 "sdio2"
+#define CONFIG_SYS_SDIO2 "sdio3"
+#define CONFIG_SYS_SDIO3 "sdio4"
+
+/* I2C Driver */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_KONA
+#define CONFIG_SYS_SPD_BUS_NUM 3       /* Start with PMU bus */
+#define CONFIG_SYS_MAX_I2C_BUS 4
+#define CONFIG_SYS_I2C_BASE0   BSC1_BASE_ADDR
+#define CONFIG_SYS_I2C_BASE1   BSC2_BASE_ADDR
+#define CONFIG_SYS_I2C_BASE2   BSC3_BASE_ADDR
+#define CONFIG_SYS_I2C_BASE3   PMU_BSC_BASE_ADDR
+
+/* Timer Driver */
+#define CONFIG_SYS_TIMER_RATE          32000
+#define CONFIG_SYS_TIMER_COUNTER       (TIMER_BASE_ADDR + 4) /* STCLO offset */
+
+/* Init functions */
+#define CONFIG_MISC_INIT_R     /* board's misc_init_r function */
+
+/* Some commands use this as the default load address */
+#define CONFIG_SYS_LOAD_ADDR           CONFIG_SYS_SDRAM_BASE
+
+/* No mtest functions as recommended */
+#undef CONFIG_CMD_MEMORY
+
+/*
+ * This is the initial SP which is used only briefly for relocating the u-boot
+ * image to the top of SDRAM. After relocation u-boot moves the stack to the
+ * proper place.
+ */
+#define CONFIG_SYS_INIT_SP_ADDR                CONFIG_SYS_TEXT_BASE
+
+/* Serial Info */
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+/* Post pad 3 bytes after each reg addr */
+#define CONFIG_SYS_NS16550_REG_SIZE    (-4)
+#define CONFIG_SYS_NS16550_CLK         13000000
+#define CONFIG_CONS_INDEX              1
+#define CONFIG_SYS_NS16550_COM1                0x3e000000
+
+#define CONFIG_BAUDRATE                        115200
+
+#define CONFIG_ENV_SIZE                        0x10000
+#define CONFIG_ENV_IS_NOWHERE
+
+#define CONFIG_SYS_NO_FLASH    /* Not using NAND/NOR unmanaged flash */
+
+/* console configuration */
+#define CONFIG_SYS_CBSIZE              1024    /* Console buffer size */
+#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE + \
+                       sizeof(CONFIG_SYS_PROMPT) + 16) /* Printbuffer size */
+#define CONFIG_SYS_MAXARGS             64
+#define CONFIG_SYS_BARGSIZE            CONFIG_SYS_CBSIZE
+
+/*
+ * One partition type must be defined for part.c
+ * This is necessary for the fatls command to work on an SD card
+ * for example.
+ */
+#define CONFIG_DOS_PARTITION
+
+/* version string, parser, etc */
+#define CONFIG_VERSION_VARIABLE
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
+
+#define CONFIG_CRC32_VERIFY
+#define CONFIG_MX_CYCLIC
+
+/* Initial upstream - boot to cmd prompt only */
+#define CONFIG_BOOTCOMMAND             ""
+
+/* Commands */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_BOOTZ
+#define CONFIG_FAT_WRITE
+
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_NFS
+
+#endif /* __BCM28155_AP_H */
index 976ceaa..6306d61 100644 (file)
 #define CONFIG_SYS_LOAD_ADDR           0x1000000
 #define CONFIG_CONSOLE_MUX
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_PREBOOT \
+       "if load mmc 0:1 ${loadaddr} /uEnv.txt; then " \
+               "env import -t ${loadaddr} ${filesize}; " \
+       "fi"
+
+#define ENV_DEVICE_SETTINGS \
+       "stdin=serial,lcd\0" \
+       "stdout=serial,lcd\0" \
+       "stderr=serial,lcd\0"
+
 /*
  * Memory layout for where various images get loaded by boot scripts:
  *
  * scriptaddr can be pretty much anywhere that doesn't conflict with something
  *   else. Put it low in memory to avoid conflicts.
  *
+ * pxefile_addr_r can be pretty much anywhere that doesn't conflict with
+ *   something else. Put it low in memory to avoid conflicts.
+ *
  * kernel_addr_r must be within the first 128M of RAM in order for the
  *   kernel's CONFIG_AUTO_ZRELADDR option to work. Since the kernel will
  *   decompress itself to 0x8000 after the start of RAM, kernel_addr_r
  * ramdisk_addr_r simply shouldn't overlap anything else. Choosing 33M allows
  *   for the FDT/DTB to be up to 1M, which is hopefully plenty.
  */
-#define CONFIG_EXTRA_ENV_SETTINGS \
-       "stdin=serial\0" \
-       "stderr=serial,lcd\0" \
-       "stdout=serial,lcd\0" \
+#define ENV_MEM_LAYOUT_SETTINGS \
        "scriptaddr=0x00000000\0" \
+       "pxefile_addr_r=0x00100000\0" \
        "kernel_addr_r=0x01000000\0" \
        "fdt_addr_r=0x02000000\0" \
        "fdtfile=bcm2835-rpi-b.dtb\0" \
        "ramdisk_addr_r=0x02100000\0" \
-       "boot_targets=mmc0\0" \
-       \
-       "script_boot=" \
-               "if fatload ${devtype} ${devnum}:1 " \
-                                       "${scriptaddr} boot.scr.uimg; then " \
-                       "source ${scriptaddr}; " \
-               "fi;\0" \
-       \
+
+#define BOOTCMDS_MMC \
        "mmc_boot=" \
                "setenv devtype mmc; " \
                "if mmc dev ${devnum}; then " \
-                       "run script_boot; " \
+                       "run scan_boot; " \
                "fi\0" \
+       "bootcmd_mmc0=setenv devnum 0; run mmc_boot;\0"
+#define BOOT_TARGETS_MMC "mmc0"
+
+#define BOOTCMDS_COMMON \
+       "rootpart=1\0" \
+       \
+       "do_script_boot="                                                 \
+               "load ${devtype} ${devnum}:${rootpart} "                  \
+                       "${scriptaddr} ${prefix}${script}; "              \
+               "source ${scriptaddr}\0"                                  \
+       \
+       "script_boot="                                                    \
+               "for script in ${boot_scripts}; do "                      \
+                       "if test -e ${devtype} ${devnum}:${rootpart} "    \
+                                       "${prefix}${script}; then "       \
+                               "echo Found ${prefix}${script}; "         \
+                               "run do_script_boot; "                    \
+                               "echo SCRIPT FAILED: continuing...; "     \
+                       "fi; "                                            \
+               "done\0"                                                  \
+       \
+       "do_sysboot_boot="                                                \
+               "sysboot ${devtype} ${devnum}:${rootpart} any "           \
+                       "${scriptaddr} ${prefix}extlinux/extlinux.conf\0" \
+       \
+       "sysboot_boot="                                                   \
+               "if test -e ${devtype} ${devnum}:${rootpart} "            \
+                               "${prefix}extlinux/extlinux.conf; then "  \
+                       "echo Found ${prefix}extlinux/extlinux.conf; "    \
+                       "run do_sysboot_boot; "                           \
+                       "echo SCRIPT FAILED: continuing...; "             \
+               "fi\0"                                                    \
+       \
+       "scan_boot="                                                      \
+               "echo Scanning ${devtype} ${devnum}...; "                 \
+               "for prefix in ${boot_prefixes}; do "                     \
+                       "run sysboot_boot; "                              \
+                       "run script_boot; "                               \
+               "done\0"                                                  \
+       \
+       "boot_targets=" \
+               BOOT_TARGETS_MMC " " \
+               "\0" \
+       \
+       "boot_prefixes=/\0" \
+       \
+       "boot_scripts=boot.scr.uimg\0" \
        \
-       "bootcmd_mmc0=setenv devnum 0; run mmc_boot\0" \
+       BOOTCMDS_MMC
 
 #define CONFIG_BOOTCOMMAND \
        "for target in ${boot_targets}; do run bootcmd_${target}; done"
 
-#define CONFIG_BOOTDELAY               2
+#define CONFIG_BOOTCOMMAND \
+       "for target in ${boot_targets}; do run bootcmd_${target}; done"
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+       ENV_DEVICE_SETTINGS \
+       ENV_MEM_LAYOUT_SETTINGS \
+       BOOTCMDS_COMMON
+
+#define CONFIG_BOOTDELAY 2
 
 /* Shell */
-#define CONFIG_SYS_HUSH_PARSER
 #define CONFIG_SYS_MAXARGS             8
 #define CONFIG_SYS_PROMPT              "U-Boot> "
-#define CONFIG_SYS_LONGHELP
-#define CONFIG_CMDLINE_EDITING
 #define CONFIG_COMMAND_HISTORY
-#define CONFIG_AUTO_COMPLETE
 
 /* Commands */
 #include <config_cmd_default.h>
-#define CONFIG_CMD_BOOTZ
 #define CONFIG_CMD_GPIO
 #define CONFIG_CMD_MMC
-#define CONFIG_DOS_PARTITION
 #define CONFIG_PARTITION_UUIDS
 #define CONFIG_CMD_PART
-#define CONFIG_CMD_FS_GENERIC
-#define CONFIG_CMD_FAT
-#define CONFIG_CMD_EXT
-/* Some things don't make sense on this HW or yet */
-#undef CONFIG_CMD_FPGA
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
-#undef CONFIG_CMD_SAVEENV
 
-/* Device tree support for bootm/bootz */
-#define CONFIG_OF_LIBFDT
+/* Device tree support */
 #define CONFIG_OF_BOARD_SETUP
 /* ATAGs support for bootm/bootz */
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_INITRD_TAG
 
+#include <config_distro_defaults.h>
+
+/* Some things don't make sense on this HW or yet */
+#undef CONFIG_CMD_FPGA
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_NFS
+#undef CONFIG_CMD_SAVEENV
+#undef CONFIG_CMD_DHCP
+#undef CONFIG_CMD_MII
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_PING
+
 #endif