Explorar el Código

Merge tag 'arc-fixes-for-2020.07-rc1' of https://gitlab.denx.de/u-boot/custodians/u-boot-arc

This is pretty minor set of changes mostly touching HSDK board:

 * Enable on-chip reset controller on HSDK
 * Add possibility to turn-on & off L2$ on more
   recent ARC HS processors.
 * AXI tunnel clock calculation on HSDK
Tom Rini hace 4 años
padre
commit
0f238dab6d
Se han modificado 5 ficheros con 126 adiciones y 10 borrados
  1. 7 0
      arch/arc/dts/hsdk.dts
  2. 7 0
      arch/arc/include/asm/cache.h
  3. 109 9
      arch/arc/lib/cache.c
  4. 1 0
      configs/hsdk_defconfig
  5. 2 1
      drivers/clk/clk-hsdk-cgu.c

+ 7 - 0
arch/arc/dts/hsdk.dts

@@ -6,6 +6,7 @@
 
 #include "skeleton.dtsi"
 #include "dt-bindings/clock/snps,hsdk-cgu.h"
+#include "dt-bindings/reset/snps,hsdk-reset.h"
 
 / {
 	model = "snps,hsdk";
@@ -62,6 +63,12 @@
 		#clock-cells = <1>;
 	};
 
+	cgu_rst: reset-controller@f00008a0 {
+		compatible = "snps,hsdk-reset";
+		#reset-cells = <1>;
+		reg = <0xf00008a0 0x4>, <0xf0000ff0 0x4>;
+	};
+
 	uart0: serial0@f0005000 {
 		compatible = "snps,dw-apb-uart";
 		reg = <0xf0005000 0x1000>;

+ 7 - 0
arch/arc/include/asm/cache.h

@@ -40,6 +40,13 @@ static const inline int is_ioc_enabled(void)
 	return IS_ENABLED(CONFIG_ARC_DBG_IOC_ENABLE);
 }
 
+/*
+ * We export SLC control functions to use them in platform configuration code.
+ * They maust not be used in any generic code!
+ */
+void slc_enable(void);
+void slc_disable(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_ARC_CACHE_H */

+ 109 - 9
arch/arc/lib/cache.c

@@ -89,8 +89,7 @@
  *
  * [ NOTE 2 ]:
  * As of today we only support the following cache configurations on ARC.
- * Other configurations may exist in HW (for example, since version 3.0 HS
- * supports SL$ (L2 system level cache) disable) but we don't support it in SW.
+ * Other configurations may exist in HW but we don't support it in SW.
  * Configuration 1:
  *        ______________________
  *       |                      |
@@ -120,7 +119,8 @@
  *       |                      |
  *       |   L2 (SL$)           |
  *       |______________________|
- *          always must be on
+ *          always on (ARCv2, HS <  3.0)
+ *          on/off    (ARCv2, HS >= 3.0)
  *        ___|______________|____
  *       |                      |
  *       |   main memory        |
@@ -178,6 +178,8 @@ DECLARE_GLOBAL_DATA_PTR;
 
 static inlined_cachefunc void __ic_entire_invalidate(void);
 static inlined_cachefunc void __dc_entire_op(const int cacheop);
+static inlined_cachefunc void __slc_entire_op(const int op);
+static inlined_cachefunc bool ioc_enabled(void);
 
 static inline bool pae_exists(void)
 {
@@ -238,6 +240,70 @@ static inlined_cachefunc bool slc_exists(void)
 	return false;
 }
 
+enum slc_dis_status {
+	ST_SLC_MISSING = 0,
+	ST_SLC_NO_DISABLE_CTRL,
+	ST_SLC_DISABLE_CTRL
+};
+
+/*
+ * ARCv1                                     -> ST_SLC_MISSING
+ * ARCv2 && SLC absent                       -> ST_SLC_MISSING
+ * ARCv2 && SLC exists && SLC version <= 2   -> ST_SLC_NO_DISABLE_CTRL
+ * ARCv2 && SLC exists && SLC version > 2    -> ST_SLC_DISABLE_CTRL
+ */
+static inlined_cachefunc enum slc_dis_status slc_disable_supported(void)
+{
+	if (is_isa_arcv2()) {
+		union bcr_generic sbcr;
+
+		sbcr.word = read_aux_reg(ARC_BCR_SLC);
+		if (sbcr.fields.ver == 0)
+			return ST_SLC_MISSING;
+		else if (sbcr.fields.ver <= 2)
+			return ST_SLC_NO_DISABLE_CTRL;
+		else
+			return ST_SLC_DISABLE_CTRL;
+	}
+
+	return ST_SLC_MISSING;
+}
+
+static inlined_cachefunc bool __slc_enabled(void)
+{
+	return !(read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_DIS);
+}
+
+static inlined_cachefunc void __slc_enable(void)
+{
+	unsigned int ctrl;
+
+	ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
+	ctrl &= ~SLC_CTRL_DIS;
+	write_aux_reg(ARC_AUX_SLC_CTRL, ctrl);
+}
+
+static inlined_cachefunc void __slc_disable(void)
+{
+	unsigned int ctrl;
+
+	ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
+	ctrl |= SLC_CTRL_DIS;
+	write_aux_reg(ARC_AUX_SLC_CTRL, ctrl);
+}
+
+static inlined_cachefunc bool slc_enabled(void)
+{
+	enum slc_dis_status slc_status = slc_disable_supported();
+
+	if (slc_status == ST_SLC_MISSING)
+		return false;
+	else if (slc_status == ST_SLC_NO_DISABLE_CTRL)
+		return true;
+	else
+		return __slc_enabled();
+}
+
 static inlined_cachefunc bool slc_data_bypass(void)
 {
 	/*
@@ -247,7 +313,40 @@ static inlined_cachefunc bool slc_data_bypass(void)
 	return !dcache_enabled();
 }
 
-static inline bool ioc_exists(void)
+void slc_enable(void)
+{
+	if (slc_disable_supported() != ST_SLC_DISABLE_CTRL)
+		return;
+
+	if (__slc_enabled())
+		return;
+
+	__slc_enable();
+}
+
+/* TODO: warn if we are not able to disable SLC */
+void slc_disable(void)
+{
+	if (slc_disable_supported() != ST_SLC_DISABLE_CTRL)
+		return;
+
+	/* we don't support SLC disabling if we use IOC */
+	if (ioc_enabled())
+		return;
+
+	if (!__slc_enabled())
+		return;
+
+	/*
+	 * We need to flush L1D$ to guarantee that we won't have any
+	 * writeback operations during SLC disabling.
+	 */
+	__dc_entire_op(OP_FLUSH);
+	__slc_entire_op(OP_FLUSH_N_INV);
+	__slc_disable();
+}
+
+static inlined_cachefunc bool ioc_exists(void)
 {
 	if (is_isa_arcv2()) {
 		union bcr_clust_cfg cbcr;
@@ -259,7 +358,7 @@ static inline bool ioc_exists(void)
 	return false;
 }
 
-static inline bool ioc_enabled(void)
+static inlined_cachefunc bool ioc_enabled(void)
 {
 	/*
 	 * We check only CONFIG option instead of IOC HW state check as IOC
@@ -275,7 +374,7 @@ static inlined_cachefunc void __slc_entire_op(const int op)
 {
 	unsigned int ctrl;
 
-	if (!slc_exists())
+	if (!slc_enabled())
 		return;
 
 	ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
@@ -324,7 +423,7 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op)
 	unsigned int ctrl;
 	unsigned long end;
 
-	if (!slc_exists())
+	if (!slc_enabled())
 		return;
 
 	/*
@@ -382,6 +481,9 @@ static void arc_ioc_setup(void)
 	if (!slc_exists())
 		panic("Try to enable IOC but SLC is not present");
 
+	if (!slc_enabled())
+		panic("Try to enable IOC but SLC is disabled");
+
 	/* Unsupported configuration. See [ NOTE 2 ] for more details. */
 	if (!dcache_enabled())
 		panic("Try to enable IOC but L1 D$ is disabled");
@@ -517,8 +619,6 @@ void invalidate_icache_all(void)
 	/*
 	 * If SL$ is bypassed for data it is used only for instructions,
 	 * so we need to invalidate it too.
-	 * TODO: HS 3.0 supports SLC disable so we need to check slc
-	 * enable/disable status here.
 	 */
 	if (is_isa_arcv2() && slc_data_bypass())
 		__slc_entire_op(OP_INV);

+ 1 - 0
configs/hsdk_defconfig

@@ -47,6 +47,7 @@ CONFIG_SPI_FLASH_SST=y
 CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
+CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_DEBUG_UART_ANNOUNCE=y

+ 2 - 1
drivers/clk/clk-hsdk-cgu.c

@@ -144,7 +144,7 @@ struct hsdk_tun_clk_cfg {
 
 static const struct hsdk_tun_clk_cfg tun_clk_cfg = {
 	{ 25000000,  50000000,  75000000,  100000000, 125000000, 150000000 },
-	{ 600000000, 600000000, 600000000, 600000000, 700000000, 600000000 }, {
+	{ 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, {
 	{ CGU_TUN_IDIV_TUN,	{ 24,	12,	8,	6,	6,	4 } },
 	{ CGU_TUN_IDIV_ROM,	{ 4,	4,	4,	4,	5,	4 } },
 	{ CGU_TUN_IDIV_PWM,	{ 8,	8,	8,	8,	10,	8 } }
@@ -205,6 +205,7 @@ static const struct hsdk_pll_cfg asdt_pll_cfg[] = {
 	{ 500000000,  0, 14, 1, 0 },
 	{ 600000000,  0, 17, 1, 0 },
 	{ 700000000,  0, 20, 1, 0 },
+	{ 750000000,  1, 44, 1, 0 },
 	{ 800000000,  0, 23, 1, 0 },
 	{ 900000000,  1, 26, 0, 0 },
 	{ 1000000000, 1, 29, 0, 0 },