All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] sunxi: Tune H3 DRAM PLL to improve lock time
@ 2016-08-19 11:40 Jens Kuske
  2016-08-24 22:50 ` Heather Gibson
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jens Kuske @ 2016-08-19 11:40 UTC (permalink / raw)
  To: u-boot

The H3 PLL5 used for DRAM barely manages to lock to the required
frequency before DRAM controller starts, sometimes leading to wrong
delay-line calibration results.
This patch changes the PLL tuning parameters to the same values as
boot0 used, which speeds up the locking and fixes the problem.

Signed-off-by: Jens Kuske <jenskuske@gmail.com>

---

Hi all,

this might fix some of the DRAM reliability problems seen on H3 boards,
but I could only test it on one board myself, where it only improves
results for dram clocks above 648 MHz. But my board didn't suffer
from reliability problems at 672 MHz, so maybe it helps on boards
where 672 isn't stable.
Even if there are no visible effects on reliability, this is what
boot0 does, and it definitely fixes something, see table below:

DRAM clock	delay steps
		without patch	with patch

552 MHz:	36		36
576 MHz:	35		35
600 MHz:	34		34
624 MHz:	32		32
648 MHz:	31		31
672 MHz:	31		30
696 MHz:	31		29
720 MHz:	31		28
744 MHz:	31		27
768 MHz:	31		26

Looks like the clock only reached ~648 MHz when calibration is run,
leading to increasing error for higher clocks.
If someone wants to reproduce this test, the delays are from the
DXnLCDL1 registers (0x01c63308 + 0..3 * 0x80) and are responsible
for phase-shifting DQS signals by 90deg relative to DQ.

Best Regards,
Jens

---
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 9 ++++++++-
 arch/arm/mach-sunxi/clock_sun6i.c             | 6 ++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index d4dff1e..be9fcfd 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -116,7 +116,9 @@ struct sunxi_ccm_reg {
 	u32 mipi_bias_cfg;	/* 0x240 MIPI Bias config */
 	u32 pll9_bias_cfg;	/* 0x244 PLL9 Bias config */
 	u32 pll10_bias_cfg;	/* 0x248 PLL10 Bias config */
-	u32 reserved21[13];
+	u32 reserved21[5];
+	u32 pll5_tuning_cfg;	/* 0x260 PLL5 Tuning config */
+	u32 reserved21_5[7];
 	u32 pll1_pattern_cfg;	/* 0x280 PLL1 Pattern config */
 	u32 pll2_pattern_cfg;	/* 0x284 PLL2 Pattern config */
 	u32 pll3_pattern_cfg;	/* 0x288 PLL3 Pattern config */
@@ -223,6 +225,11 @@ struct sunxi_ccm_reg {
 #define CCM_PLL11_CTRL_UPD		(0x1 << 30)
 #define CCM_PLL11_CTRL_EN		(0x1 << 31)
 
+#define CCM_PLL5_TUN_LOCK_TIME(x)	(((x) & 0x7) << 24)
+#define CCM_PLL5_TUN_LOCK_TIME_MASK	CCM_PLL5_TUN_LOCK_TIME(0x7)
+#define CCM_PLL5_TUN_INIT_FREQ(x)	(((x) & 0x7f) << 16)
+#define CCM_PLL5_TUN_INIT_FREQ_MASK	CCM_PLL5_TUN_INIT_FREQ(0x7f)
+
 #if defined(CONFIG_MACH_SUN50I)
 /* AHB1=100MHz failsafe setup from the FEL mode, usable with PMIC defaults */
 #define AHB1_ABP1_DIV_DEFAULT		0x00003190 /* AHB1=PLL6/6,APB1=AHB1/2 */
diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
index 15272c9..ed8cd9b 100644
--- a/arch/arm/mach-sunxi/clock_sun6i.c
+++ b/arch/arm/mach-sunxi/clock_sun6i.c
@@ -148,6 +148,12 @@ void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
 	const int max_n = 32;
 	int k = 1, m = 2;
 
+#ifdef CONFIG_MACH_SUN8I_H3
+	clrsetbits_le32(&ccm->pll5_tuning_cfg, CCM_PLL5_TUN_LOCK_TIME_MASK |
+			CCM_PLL5_TUN_INIT_FREQ_MASK,
+			CCM_PLL5_TUN_LOCK_TIME(2) | CCM_PLL5_TUN_INIT_FREQ(16));
+#endif
+
 	if (sigma_delta_enable)
 		writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
 
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] sunxi: Tune H3 DRAM PLL to improve lock time
  2016-08-19 11:40 [U-Boot] [PATCH] sunxi: Tune H3 DRAM PLL to improve lock time Jens Kuske
@ 2016-08-24 22:50 ` Heather Gibson
  2016-08-25 16:03 ` Thomas Kaiser
  2016-08-26 14:58 ` [U-Boot] [linux-sunxi] " Hans de Goede
  2 siblings, 0 replies; 4+ messages in thread
From: Heather Gibson @ 2016-08-24 22:50 UTC (permalink / raw)
  To: u-boot




On Friday, August 19, 2016 at 7:40:54 AM UTC-4, Jens Kuske wrote:
>
> The H3 PLL5 used for DRAM barely manages to lock to the required 
> frequency before DRAM controller starts, sometimes leading to wrong 
> delay-line calibration results. 
> This patch changes the PLL tuning parameters to the same values as 
> boot0 used, which speeds up the locking and fixes the problem. 
>
> Signed-off-by: Jens Kuske <jens...@gmail.com <javascript:>> 
>
> --- 
>
> Hi all, 
>
> this might fix some of the DRAM reliability problems seen on H3 boards, 
> but I could only test it on one board myself, where it only improves 
> results for dram clocks above 648 MHz. But my board didn't suffer 
> from reliability problems at 672 MHz, so maybe it helps on boards 
> where 672 isn't stable. 
> Even if there are no visible effects on reliability, this is what 
> boot0 does, and it definitely fixes something, see table below: 
>
> DRAM clock        delay steps 
>                 without patch        with patch 
>
> 552 MHz:        36                36 
> 576 MHz:        35                35 
> 600 MHz:        34                34 
> 624 MHz:        32                32 
> 648 MHz:        31                31 
> 672 MHz:        31                30 
> 696 MHz:        31                29 
> 720 MHz:        31                28 
> 744 MHz:        31                27 
> 768 MHz:        31                26 
>
> Looks like the clock only reached ~648 MHz when calibration is run, 
> leading to increasing error for higher clocks. 
> If someone wants to reproduce this test, the delays are from the 
> DXnLCDL1 registers (0x01c63308 + 0..3 * 0x80) and are responsible 
> for phase-shifting DQS signals by 90deg relative to DQ. 
>
> Best Regards, 
> Jens 
>
> --- 
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 9 ++++++++- 
>  arch/arm/mach-sunxi/clock_sun6i.c             | 6 ++++++ 
>  2 files changed, 14 insertions(+), 1 deletion(-) 
>
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h 
> b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h 
> index d4dff1e..be9fcfd 100644 
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h 
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h 
> @@ -116,7 +116,9 @@ struct sunxi_ccm_reg { 
>          u32 mipi_bias_cfg;        /* 0x240 MIPI Bias config */ 
>          u32 pll9_bias_cfg;        /* 0x244 PLL9 Bias config */ 
>          u32 pll10_bias_cfg;        /* 0x248 PLL10 Bias config */ 
> -        u32 reserved21[13]; 
> +        u32 reserved21[5]; 
> +        u32 pll5_tuning_cfg;        /* 0x260 PLL5 Tuning config */ 
> +        u32 reserved21_5[7]; 
>          u32 pll1_pattern_cfg;        /* 0x280 PLL1 Pattern config */ 
>          u32 pll2_pattern_cfg;        /* 0x284 PLL2 Pattern config */ 
>          u32 pll3_pattern_cfg;        /* 0x288 PLL3 Pattern config */ 
> @@ -223,6 +225,11 @@ struct sunxi_ccm_reg { 
>  #define CCM_PLL11_CTRL_UPD                (0x1 << 30) 
>  #define CCM_PLL11_CTRL_EN                (0x1 << 31) 
>   
> +#define CCM_PLL5_TUN_LOCK_TIME(x)        (((x) & 0x7) << 24) 
> +#define CCM_PLL5_TUN_LOCK_TIME_MASK        CCM_PLL5_TUN_LOCK_TIME(0x7) 
> +#define CCM_PLL5_TUN_INIT_FREQ(x)        (((x) & 0x7f) << 16) 
> +#define CCM_PLL5_TUN_INIT_FREQ_MASK        CCM_PLL5_TUN_INIT_FREQ(0x7f) 
> + 
>  #if defined(CONFIG_MACH_SUN50I) 
>  /* AHB1=100MHz failsafe setup from the FEL mode, usable with PMIC 
> defaults */ 
>  #define AHB1_ABP1_DIV_DEFAULT                0x00003190 /* 
> AHB1=PLL6/6,APB1=AHB1/2 */ 
> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c 
> b/arch/arm/mach-sunxi/clock_sun6i.c 
> index 15272c9..ed8cd9b 100644 
> --- a/arch/arm/mach-sunxi/clock_sun6i.c 
> +++ b/arch/arm/mach-sunxi/clock_sun6i.c 
> @@ -148,6 +148,12 @@ void clock_set_pll5(unsigned int clk, bool 
> sigma_delta_enable) 
>          const int max_n = 32; 
>          int k = 1, m = 2; 
>   
> +#ifdef CONFIG_MACH_SUN8I_H3 
> +        clrsetbits_le32(&ccm->pll5_tuning_cfg, 
> CCM_PLL5_TUN_LOCK_TIME_MASK | 
> +                        CCM_PLL5_TUN_INIT_FREQ_MASK, 
> +                        CCM_PLL5_TUN_LOCK_TIME(2) | 
> CCM_PLL5_TUN_INIT_FREQ(16)); 
> +#endif 
> + 
>          if (sigma_delta_enable) 
>                  writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg); 
>   
> -- 
> 2.9.3 
>
>
On Friday, August 19, 2016 at 7:40:54 AM UTC-4, Jens Kuske wrote:
>
> The H3 PLL5 used for DRAM barely manages to lock to the required 
> frequency before DRAM controller starts, sometimes leading to wrong 
> delay-line calibration results. 
> This patch changes the PLL tuning parameters to the same values as 
> boot0 used, which speeds up the locking and fixes the problem. 
>
> Signed-off-by: Jens Kuske <jens...@gmail.com <javascript:>> 
>
> --- 
>
> Hi all, 
>
> this might fix some of the DRAM reliability problems seen on H3 boards, 
> but I could only test it on one board myself, where it only improves 
> results for dram clocks above 648 MHz. But my board didn't suffer 
> from reliability problems at 672 MHz, so maybe it helps on boards 
> where 672 isn't stable. 
> Even if there are no visible effects on reliability, this is what 
> boot0 does, and it definitely fixes something, see table below: 
>
> DRAM clock        delay steps 
>                 without patch        with patch 
>
> 552 MHz:        36                36 
> 576 MHz:        35                35 
> 600 MHz:        34                34 
> 624 MHz:        32                32 
> 648 MHz:        31                31 
> 672 MHz:        31                30 
> 696 MHz:        31                29 
> 720 MHz:        31                28 
> 744 MHz:        31                27 
> 768 MHz:        31                26 
>
> Looks like the clock only reached ~648 MHz when calibration is run, 
> leading to increasing error for higher clocks. 
> If someone wants to reproduce this test, the delays are from the 
> DXnLCDL1 registers (0x01c63308 + 0..3 * 0x80) and are responsible 
> for phase-shifting DQS signals by 90deg relative to DQ. 
>
> Best Regards, 
> Jens 
>
> --- 
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 9 ++++++++- 
>  arch/arm/mach-sunxi/clock_sun6i.c             | 6 ++++++ 
>  2 files changed, 14 insertions(+), 1 deletion(-) 
>
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h 
> b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h 
> index d4dff1e..be9fcfd 100644 
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h 
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h 
> @@ -116,7 +116,9 @@ struct sunxi_ccm_reg { 
>          u32 mipi_bias_cfg;        /* 0x240 MIPI Bias config */ 
>          u32 pll9_bias_cfg;        /* 0x244 PLL9 Bias config */ 
>          u32 pll10_bias_cfg;        /* 0x248 PLL10 Bias config */ 
> -        u32 reserved21[13]; 
> +        u32 reserved21[5]; 
> +        u32 pll5_tuning_cfg;        /* 0x260 PLL5 Tuning config */ 
> +        u32 reserved21_5[7]; 
>          u32 pll1_pattern_cfg;        /* 0x280 PLL1 Pattern config */ 
>          u32 pll2_pattern_cfg;        /* 0x284 PLL2 Pattern config */ 
>          u32 pll3_pattern_cfg;        /* 0x288 PLL3 Pattern config */ 
> @@ -223,6 +225,11 @@ struct sunxi_ccm_reg { 
>  #define CCM_PLL11_CTRL_UPD                (0x1 << 30) 
>  #define CCM_PLL11_CTRL_EN                (0x1 << 31) 
>   
> +#define CCM_PLL5_TUN_LOCK_TIME(x)        (((x) & 0x7) << 24) 
> +#define CCM_PLL5_TUN_LOCK_TIME_MASK        CCM_PLL5_TUN_LOCK_TIME(0x7) 
> +#define CCM_PLL5_TUN_INIT_FREQ(x)        (((x) & 0x7f) << 16) 
> +#define CCM_PLL5_TUN_INIT_FREQ_MASK        CCM_PLL5_TUN_INIT_FREQ(0x7f) 
> + 
>  #if defined(CONFIG_MACH_SUN50I) 
>  /* AHB1=100MHz failsafe setup from the FEL mode, usable with PMIC 
> defaults */ 
>  #define AHB1_ABP1_DIV_DEFAULT                0x00003190 /* 
> AHB1=PLL6/6,APB1=AHB1/2 */ 
> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c 
> b/arch/arm/mach-sunxi/clock_sun6i.c 
> index 15272c9..ed8cd9b 100644 
> --- a/arch/arm/mach-sunxi/clock_sun6i.c 
> +++ b/arch/arm/mach-sunxi/clock_sun6i.c 
> @@ -148,6 +148,12 @@ void clock_set_pll5(unsigned int clk, bool 
> sigma_delta_enable) 
>          const int max_n = 32; 
>          int k = 1, m = 2; 
>   
> +#ifdef CONFIG_MACH_SUN8I_H3 
> +        clrsetbits_le32(&ccm->pll5_tuning_cfg, 
> CCM_PLL5_TUN_LOCK_TIME_MASK | 
> +                        CCM_PLL5_TUN_INIT_FREQ_MASK, 
> +                        CCM_PLL5_TUN_LOCK_TIME(2) | 
> CCM_PLL5_TUN_INIT_FREQ(16)); 
> +#endif 
> + 
>          if (sigma_delta_enable) 
>                  writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg); 
>   
> -- 
> 2.9.3 
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] sunxi: Tune H3 DRAM PLL to improve lock time
  2016-08-19 11:40 [U-Boot] [PATCH] sunxi: Tune H3 DRAM PLL to improve lock time Jens Kuske
  2016-08-24 22:50 ` Heather Gibson
@ 2016-08-25 16:03 ` Thomas Kaiser
  2016-08-26 14:58 ` [U-Boot] [linux-sunxi] " Hans de Goede
  2 siblings, 0 replies; 4+ messages in thread
From: Thomas Kaiser @ 2016-08-25 16:03 UTC (permalink / raw)
  To: u-boot

Jens Kuske wrote:

> The H3 PLL5 used for DRAM barely manages to lock to the required 
> frequency before DRAM controller starts, sometimes leading to wrong 
> delay-line calibration results. 
> This patch changes the PLL tuning parameters to the same values as 
> boot0 used, which speeds up the locking and fixes the problem.
>

Just FYI: I prepared an archive with u-boot packages (for Debian/Ubuntu 
based distros -- target audience are Armbian users) including your patch 
and covering 624-768 MHz DRAM clockspeed:

    http://kaiser-edv.de/tmp/4U4tkD/linux-u-boot-sun8i-624-768.tar.bz2

Will now ask in Armbian forum for volunteers willing to test. 

Thx,

Thomas

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [linux-sunxi] [PATCH] sunxi: Tune H3 DRAM PLL to improve lock time
  2016-08-19 11:40 [U-Boot] [PATCH] sunxi: Tune H3 DRAM PLL to improve lock time Jens Kuske
  2016-08-24 22:50 ` Heather Gibson
  2016-08-25 16:03 ` Thomas Kaiser
@ 2016-08-26 14:58 ` Hans de Goede
  2 siblings, 0 replies; 4+ messages in thread
From: Hans de Goede @ 2016-08-26 14:58 UTC (permalink / raw)
  To: u-boot

Hi,

On 19-08-16 13:40, Jens Kuske wrote:
> The H3 PLL5 used for DRAM barely manages to lock to the required
> frequency before DRAM controller starts, sometimes leading to wrong
> delay-line calibration results.
> This patch changes the PLL tuning parameters to the same values as
> boot0 used, which speeds up the locking and fixes the problem.
>
> Signed-off-by: Jens Kuske <jenskuske@gmail.com>

Thanks, I've added this to my local tree. I'm currently running
some tests, once those are done I plan to submit a pull-req
for v2016.09 which will include this patch.

Regards,

Hans



>
> ---
>
> Hi all,
>
> this might fix some of the DRAM reliability problems seen on H3 boards,
> but I could only test it on one board myself, where it only improves
> results for dram clocks above 648 MHz. But my board didn't suffer
> from reliability problems at 672 MHz, so maybe it helps on boards
> where 672 isn't stable.
> Even if there are no visible effects on reliability, this is what
> boot0 does, and it definitely fixes something, see table below:
>
> DRAM clock	delay steps
> 		without patch	with patch
>
> 552 MHz:	36		36
> 576 MHz:	35		35
> 600 MHz:	34		34
> 624 MHz:	32		32
> 648 MHz:	31		31
> 672 MHz:	31		30
> 696 MHz:	31		29
> 720 MHz:	31		28
> 744 MHz:	31		27
> 768 MHz:	31		26
>
> Looks like the clock only reached ~648 MHz when calibration is run,
> leading to increasing error for higher clocks.
> If someone wants to reproduce this test, the delays are from the
> DXnLCDL1 registers (0x01c63308 + 0..3 * 0x80) and are responsible
> for phase-shifting DQS signals by 90deg relative to DQ.
>
> Best Regards,
> Jens
>
> ---
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 9 ++++++++-
>  arch/arm/mach-sunxi/clock_sun6i.c             | 6 ++++++
>  2 files changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index d4dff1e..be9fcfd 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -116,7 +116,9 @@ struct sunxi_ccm_reg {
>  	u32 mipi_bias_cfg;	/* 0x240 MIPI Bias config */
>  	u32 pll9_bias_cfg;	/* 0x244 PLL9 Bias config */
>  	u32 pll10_bias_cfg;	/* 0x248 PLL10 Bias config */
> -	u32 reserved21[13];
> +	u32 reserved21[5];
> +	u32 pll5_tuning_cfg;	/* 0x260 PLL5 Tuning config */
> +	u32 reserved21_5[7];
>  	u32 pll1_pattern_cfg;	/* 0x280 PLL1 Pattern config */
>  	u32 pll2_pattern_cfg;	/* 0x284 PLL2 Pattern config */
>  	u32 pll3_pattern_cfg;	/* 0x288 PLL3 Pattern config */
> @@ -223,6 +225,11 @@ struct sunxi_ccm_reg {
>  #define CCM_PLL11_CTRL_UPD		(0x1 << 30)
>  #define CCM_PLL11_CTRL_EN		(0x1 << 31)
>
> +#define CCM_PLL5_TUN_LOCK_TIME(x)	(((x) & 0x7) << 24)
> +#define CCM_PLL5_TUN_LOCK_TIME_MASK	CCM_PLL5_TUN_LOCK_TIME(0x7)
> +#define CCM_PLL5_TUN_INIT_FREQ(x)	(((x) & 0x7f) << 16)
> +#define CCM_PLL5_TUN_INIT_FREQ_MASK	CCM_PLL5_TUN_INIT_FREQ(0x7f)
> +
>  #if defined(CONFIG_MACH_SUN50I)
>  /* AHB1=100MHz failsafe setup from the FEL mode, usable with PMIC defaults */
>  #define AHB1_ABP1_DIV_DEFAULT		0x00003190 /* AHB1=PLL6/6,APB1=AHB1/2 */
> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
> index 15272c9..ed8cd9b 100644
> --- a/arch/arm/mach-sunxi/clock_sun6i.c
> +++ b/arch/arm/mach-sunxi/clock_sun6i.c
> @@ -148,6 +148,12 @@ void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
>  	const int max_n = 32;
>  	int k = 1, m = 2;
>
> +#ifdef CONFIG_MACH_SUN8I_H3
> +	clrsetbits_le32(&ccm->pll5_tuning_cfg, CCM_PLL5_TUN_LOCK_TIME_MASK |
> +			CCM_PLL5_TUN_INIT_FREQ_MASK,
> +			CCM_PLL5_TUN_LOCK_TIME(2) | CCM_PLL5_TUN_INIT_FREQ(16));
> +#endif
> +
>  	if (sigma_delta_enable)
>  		writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-08-26 14:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-19 11:40 [U-Boot] [PATCH] sunxi: Tune H3 DRAM PLL to improve lock time Jens Kuske
2016-08-24 22:50 ` Heather Gibson
2016-08-25 16:03 ` Thomas Kaiser
2016-08-26 14:58 ` [U-Boot] [linux-sunxi] " Hans de Goede

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.