summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/boards/black-swift/include/board/board_pbl_start.h2
-rw-r--r--arch/mips/boards/tplink-mr3020/include/board/board_pbl_start.h2
-rw-r--r--arch/mips/lib/csrc-r4k.c24
-rw-r--r--arch/mips/mach-ath79/include/mach/ar71xx_regs.h14
-rw-r--r--arch/mips/mach-ath79/include/mach/pbl_macros.h63
-rw-r--r--drivers/of/base.c86
-rw-r--r--include/of.h10
7 files changed, 199 insertions, 2 deletions
diff --git a/arch/mips/boards/black-swift/include/board/board_pbl_start.h b/arch/mips/boards/black-swift/include/board/board_pbl_start.h
index ee21a85ac9..4c2ab2ef0f 100644
--- a/arch/mips/boards/black-swift/include/board/board_pbl_start.h
+++ b/arch/mips/boards/black-swift/include/board/board_pbl_start.h
@@ -26,6 +26,8 @@
mips_barebox_10h
+ pbl_ar9331_wmac_enable
+
hornet_mips24k_cp0_setup
pbl_blt 0xbf000000 skip_pll_ram_config t8
diff --git a/arch/mips/boards/tplink-mr3020/include/board/board_pbl_start.h b/arch/mips/boards/tplink-mr3020/include/board/board_pbl_start.h
index ef0d36dc38..3a7b560a05 100644
--- a/arch/mips/boards/tplink-mr3020/include/board/board_pbl_start.h
+++ b/arch/mips/boards/tplink-mr3020/include/board/board_pbl_start.h
@@ -26,6 +26,8 @@
mips_barebox_10h
+ pbl_ar9331_wmac_enable
+
hornet_mips24k_cp0_setup
pbl_blt 0xbf000000 skip_pll_ram_config t8
diff --git a/arch/mips/lib/csrc-r4k.c b/arch/mips/lib/csrc-r4k.c
index 5c3f18ff24..6f6e18c8e8 100644
--- a/arch/mips/lib/csrc-r4k.c
+++ b/arch/mips/lib/csrc-r4k.c
@@ -21,6 +21,8 @@
*/
#include <init.h>
+#include <of.h>
+#include <linux/clk.h>
#include <clock.h>
#include <io.h>
#include <asm/mipsregs.h>
@@ -37,8 +39,26 @@ static struct clocksource cs = {
static int clocksource_init(void)
{
- cs.mult = clocksource_hz2mult(100000000, cs.shift);
+ unsigned int mips_hpt_frequency;
+ struct device_node *np;
+ struct clk *clk;
+
+ /* default rate: 100 MHz */
+ mips_hpt_frequency = 100000000;
+
+ if (IS_ENABLED(CONFIG_OFTREE)) {
+ np = of_get_cpu_node(0, NULL);
+ if (np) {
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk)) {
+ mips_hpt_frequency = clk_get_rate(clk) / 2;
+ }
+ }
+ }
+
+ clocks_calc_mult_shift(&cs.mult, &cs.shift,
+ mips_hpt_frequency, NSEC_PER_SEC, 10);
return init_clock(&cs);
}
-core_initcall(clocksource_init);
+postcore_initcall(clocksource_init);
diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
index 4cbe94a487..de96c565a6 100644
--- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
+++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
@@ -31,11 +31,25 @@
#define AR71XX_PLL_SIZE 0x100
#define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000)
#define AR71XX_RESET_SIZE 0x100
+#define AR71XX_RTC_BASE (AR71XX_APB_BASE + 0x00107000)
+#define AR71XX_RTC_SIZE 0x100
#define AR933X_UART_BASE (AR71XX_APB_BASE + 0x00020000)
#define AR933X_UART_SIZE 0x14
/*
+ * RTC block
+ */
+#define AR933X_RTC_REG_RESET 0x40
+#define AR933X_RTC_REG_STATUS 0x44
+#define AR933X_RTC_REG_DERIVED 0x48
+#define AR933X_RTC_REG_FORCE_WAKE 0x4c
+#define AR933X_RTC_REG_INT_CAUSE 0x50
+#define AR933X_RTC_REG_CAUSE_CLR 0x50
+#define AR933X_RTC_REG_INT_ENABLE 0x54
+#define AR933X_RTC_REG_INT_MASKE 0x58
+
+/*
* DDR_CTRL block
*/
#define AR933X_DDR_CONFIG 0x00
diff --git a/arch/mips/mach-ath79/include/mach/pbl_macros.h b/arch/mips/mach-ath79/include/mach/pbl_macros.h
index 8f4d09aec4..680fcbb867 100644
--- a/arch/mips/mach-ath79/include/mach/pbl_macros.h
+++ b/arch/mips/mach-ath79/include/mach/pbl_macros.h
@@ -274,4 +274,67 @@ normal_path:
.set pop
.endm
+.macro pbl_ar9331_wmac_enable
+ .set push
+ .set noreorder
+
+ /* These three WLAN_RESET will avoid original issue */
+ li t3, 0x03
+1:
+ li t0, CKSEG1ADDR(AR71XX_RESET_BASE)
+ lw t1, AR933X_RESET_REG_RESET_MODULE(t0)
+ ori t1, t1, 0x0800
+ sw t1, AR933X_RESET_REG_RESET_MODULE(t0)
+ nop
+ lw t1, AR933X_RESET_REG_RESET_MODULE(t0)
+ li t2, 0xfffff7ff
+ and t1, t1, t2
+ sw t1, AR933X_RESET_REG_RESET_MODULE(t0)
+ nop
+ addi t3, t3, -1
+ bnez t3, 1b
+ nop
+
+ li t2, 0x20
+2:
+ beqz t2, 1b
+ nop
+ addi t2, t2, -1
+ lw t5, AR933X_RESET_REG_BOOTSTRAP(t0)
+ andi t1, t5, 0x10
+ bnez t1, 2b
+ nop
+
+ li t1, 0x02110E
+ sw t1, AR933X_RESET_REG_BOOTSTRAP(t0)
+ nop
+
+ /* RTC Force Wake */
+ li t0, CKSEG1ADDR(AR71XX_RTC_BASE)
+ li t1, 0x03
+ sw t1, AR933X_RTC_REG_FORCE_WAKE(t0)
+ nop
+ nop
+
+ /* RTC Reset */
+ li t1, 0x00
+ sw t1, AR933X_RTC_REG_RESET(t0)
+ nop
+ nop
+
+ li t1, 0x01
+ sw t1, AR933X_RTC_REG_RESET(t0)
+ nop
+ nop
+
+ /* Wait for RTC in on state */
+1:
+ lw t1, AR933X_RTC_REG_STATUS(t0)
+ andi t1, t1, 0x02
+ beqz t1, 1b
+ nop
+
+ .set pop
+.endm
+
#endif /* __ASM_MACH_ATH79_PBL_MACROS_H */
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3099c91579..1e6c33dbf2 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -380,6 +380,92 @@ const void *of_get_property(const struct device_node *np, const char *name,
}
EXPORT_SYMBOL(of_get_property);
+/*
+ * arch_match_cpu_phys_id - Match the given logical CPU and physical id
+ *
+ * @cpu: logical cpu index of a core/thread
+ * @phys_id: physical identifier of a core/thread
+ *
+ * Returns true if the physical identifier and the logical cpu index
+ * correspond to the same core/thread, false otherwise.
+ */
+static bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
+{
+ return (u32)phys_id == cpu;
+}
+
+/**
+ * Checks if the given "prop_name" property holds the physical id of the
+ * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
+ * NULL, local thread number within the core is returned in it.
+ */
+static bool __of_find_n_match_cpu_property(struct device_node *cpun,
+ const char *prop_name, int cpu, unsigned int *thread)
+{
+ const __be32 *cell;
+ int ac, prop_len, tid;
+ u64 hwid;
+
+ ac = of_n_addr_cells(cpun);
+ cell = of_get_property(cpun, prop_name, &prop_len);
+ if (!cell || !ac)
+ return false;
+ prop_len /= sizeof(*cell) * ac;
+ for (tid = 0; tid < prop_len; tid++) {
+ hwid = of_read_number(cell, ac);
+ if (arch_match_cpu_phys_id(cpu, hwid)) {
+ if (thread)
+ *thread = tid;
+ return true;
+ }
+ cell += ac;
+ }
+ return false;
+}
+
+/*
+ * arch_find_n_match_cpu_physical_id - See if the given device node is
+ * for the cpu corresponding to logical cpu 'cpu'. Return true if so,
+ * else false. If 'thread' is non-NULL, the local thread number within the
+ * core is returned in it.
+ */
+static bool arch_find_n_match_cpu_physical_id(struct device_node *cpun,
+ int cpu, unsigned int *thread)
+{
+ return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread);
+}
+
+/**
+ * of_get_cpu_node - Get device node associated with the given logical CPU
+ *
+ * @cpu: CPU number(logical index) for which device node is required
+ * @thread: if not NULL, local thread number within the physical core is
+ * returned
+ *
+ * The main purpose of this function is to retrieve the device node for the
+ * given logical CPU index. It should be used to initialize the of_node in
+ * cpu device. Once of_node in cpu device is populated, all the further
+ * references can use that instead.
+ *
+ * CPU logical to physical index mapping is architecture specific and is built
+ * before booting secondary cores. This function uses arch_match_cpu_phys_id
+ * which can be overridden by architecture specific implementation.
+ *
+ * Returns a node pointer for the logical cpu with refcount incremented, use
+ * of_node_put() on it when done. Returns NULL if not found.
+ */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
+{
+ struct device_node *cpun;
+
+ for_each_node_by_type(cpun, "cpu") {
+ if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))
+ return cpun;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(of_get_cpu_node);
+
/** Checks if the given "compat" string matches one of the strings in
* the device's "compatible" property
*/
diff --git a/include/of.h b/include/of.h
index 8c8f57a7cc..ed6e870473 100644
--- a/include/of.h
+++ b/include/of.h
@@ -111,6 +111,7 @@ extern struct property *of_find_property(const struct device_node *np,
const char *name, int *lenp);
extern const void *of_get_property(const struct device_node *np,
const char *name, int *lenp);
+extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
extern int of_set_property(struct device_node *node, const char *p,
const void *val, int len, int create);
@@ -347,6 +348,12 @@ static inline const void *of_get_property(const struct device_node *np,
return NULL;
}
+static inline struct device_node *of_get_cpu_node(int cpu,
+ unsigned int *thread)
+{
+ return NULL;
+}
+
static inline int of_set_property(struct device_node *node, const char *p,
const void *val, int len, int create)
{
@@ -639,6 +646,9 @@ static inline struct device_node *of_find_node_by_path_or_alias(
#define for_each_node_by_name(dn, name) \
for (dn = of_find_node_by_name(NULL, name); dn; \
dn = of_find_node_by_name(dn, name))
+#define for_each_node_by_type(dn, type) \
+ for (dn = of_find_node_by_type(NULL, type); dn; \
+ dn = of_find_node_by_type(dn, type))
#define for_each_node_by_name_from(dn, root, name) \
for (dn = of_find_node_by_name(root, name); dn; \
dn = of_find_node_by_name(dn, name))