The *Full* Cubox-i series
Subsystems (40)
cover The *Full* Cubox-i series
So that people can see what kind of a patch nightmare I'm in, and hopefully start being more co-operative towards getting patches into mainline, here is the *full* patch set for CuBox-i support that I'm presently sitting on.
Anything that can be done to make this easier would be very helpful, so I'm not spending lots of time tweaking some random patch and then having to remerge all these different sub-series.
.../DocBook/media/v4l/pixfmt-packed-rgb.xml | 39 + .../devicetree/bindings/leds/leds-pwm.txt | 2 + Documentation/devicetree/bindings/mmc/mmc.txt | 11 + .../bindings/staging/imx-drm/fsl-imx-drm.txt | 3 +- arch/arm/Kconfig | 51 - arch/arm/boot/dts/imx6dl-hummingboard.dts | 28 + arch/arm/boot/dts/imx6q-cubox-i.dts | 4 + arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 79 +- arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi | 22 +- arch/arm/boot/dts/imx6qdl-microsom.dtsi | 98 ++ arch/arm/boot/dts/imx6qdl.dtsi | 2 + arch/arm/boot/dts/imx6sl.dtsi | 2 + arch/arm/boot/dts/marco.dtsi | 2 +- arch/arm/boot/dts/prima2.dtsi | 2 +- arch/arm/configs/imx_v6_v7_defconfig | 1 + arch/arm/include/asm/hardware/cache-l2x0.h | 104 +- arch/arm/include/asm/outercache.h | 67 +- arch/arm/mach-berlin/berlin.c | 2 +- arch/arm/mach-cns3xxx/core.c | 10 +- arch/arm/mach-exynos/common.h | 1 - arch/arm/mach-exynos/exynos.c | 15 +- arch/arm/mach-exynos/sleep.S | 30 +- arch/arm/mach-highbank/highbank.c | 18 +- arch/arm/mach-imx/clk-imx6q.c | 29 +- arch/arm/mach-imx/clk-pllv3.c | 27 +- arch/arm/mach-imx/mach-vf610.c | 2 +- arch/arm/mach-imx/suspend-imx6.S | 24 +- arch/arm/mach-imx/system.c | 8 +- arch/arm/mach-mvebu/board-v7.c | 2 +- arch/arm/mach-nomadik/cpu-8815.c | 2 +- arch/arm/mach-omap2/Kconfig | 1 + arch/arm/mach-omap2/common.h | 1 + arch/arm/mach-omap2/io.c | 2 + arch/arm/mach-omap2/omap-mpuss-lowpower.c | 16 +- arch/arm/mach-omap2/omap4-common.c | 86 +- arch/arm/mach-prima2/l2x0.c | 34 +- arch/arm/mach-prima2/pm.c | 1 - arch/arm/mach-realview/realview_eb.c | 9 +- arch/arm/mach-realview/realview_pb1176.c | 8 +- arch/arm/mach-realview/realview_pb11mp.c | 9 +- arch/arm/mach-realview/realview_pbx.c | 4 +- arch/arm/mach-rockchip/rockchip.c | 2 +- .../board-armadillo800eva-reference.c | 4 +- arch/arm/mach-shmobile/board-armadillo800eva.c | 4 +- arch/arm/mach-shmobile/board-kzm9g-reference.c | 4 +- arch/arm/mach-shmobile/board-kzm9g.c | 4 +- arch/arm/mach-shmobile/setup-r8a7778.c | 4 +- arch/arm/mach-shmobile/setup-r8a7779.c | 4 +- arch/arm/mach-socfpga/socfpga.c | 2 +- arch/arm/mach-spear/platsmp.c | 19 +- arch/arm/mach-spear/spear13xx.c | 8 +- arch/arm/mach-sti/board-dt.c | 12 +- arch/arm/mach-tegra/pm.h | 2 - arch/arm/mach-tegra/reset-handler.S | 11 +- arch/arm/mach-tegra/sleep.h | 31 - arch/arm/mach-tegra/tegra.c | 22 +- arch/arm/mach-ux500/cache-l2x0.c | 32 +- arch/arm/mach-vexpress/ct-ca9x4.c | 28 +- arch/arm/mach-zynq/common.c | 2 +- arch/arm/mm/Kconfig | 51 + arch/arm/mm/Makefile | 3 +- arch/arm/mm/cache-feroceon-l2.c | 1 - arch/arm/mm/cache-l2x0.c | 1564 +++++++++++++------- arch/arm/mm/l2c-common.c | 20 + arch/arm/mm/l2c-l2x0-resume.S | 58 + arch/arm/plat-samsung/s5p-sleep.S | 1 - drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/ata/ahci_imx.c | 184 ++- drivers/cec/Kconfig | 14 + drivers/cec/Makefile | 1 + drivers/cec/cec-dev.c | 384 +++++ drivers/gpu/drm/drm_crtc_helper.c | 6 - drivers/leds/leds-pwm.c | 144 +- drivers/mmc/core/core.c | 42 + drivers/mmc/core/host.c | 68 + drivers/mmc/core/sdio_irq.c | 41 +- drivers/mmc/host/Kconfig | 63 +- drivers/mmc/host/dw_mmc.c | 2 + drivers/mmc/host/sdhci-acpi.c | 8 + drivers/mmc/host/sdhci-bcm-kona.c | 4 + drivers/mmc/host/sdhci-bcm2835.c | 4 + drivers/mmc/host/sdhci-cns3xxx.c | 13 +- drivers/mmc/host/sdhci-dove.c | 4 + drivers/mmc/host/sdhci-esdhc-imx.c | 82 +- drivers/mmc/host/sdhci-esdhc.h | 4 +- drivers/mmc/host/sdhci-of-arasan.c | 4 + drivers/mmc/host/sdhci-of-esdhc.c | 70 +- drivers/mmc/host/sdhci-of-hlwd.c | 4 + drivers/mmc/host/sdhci-pci.c | 9 +- drivers/mmc/host/sdhci-pltfm.c | 4 + drivers/mmc/host/sdhci-pxav2.c | 14 +- drivers/mmc/host/sdhci-pxav3.c | 13 +- drivers/mmc/host/sdhci-s3c.c | 36 +- drivers/mmc/host/sdhci-sirf.c | 4 + drivers/mmc/host/sdhci-spear.c | 5 +- drivers/mmc/host/sdhci-tegra.c | 27 +- drivers/mmc/host/sdhci.c | 728 +++++---- drivers/mmc/host/sdhci.h | 20 +- drivers/net/ethernet/freescale/fec.h | 62 +- drivers/net/ethernet/freescale/fec_main.c | 1414 +++++++++++------- drivers/regulator/anatop-regulator.c | 1 + drivers/regulator/core.c | 2 +- drivers/regulator/dummy.c | 1 + drivers/regulator/fixed.c | 4 +- drivers/staging/imx-drm/Kconfig | 18 + drivers/staging/imx-drm/Makefile | 3 + drivers/staging/imx-drm/drm-ddc-connector.c | 92 ++ drivers/staging/imx-drm/drm-ddc-connector.h | 26 + drivers/staging/imx-drm/dw-hdmi-audio.c | 654 ++++++++ drivers/staging/imx-drm/dw-hdmi-audio.h | 15 + drivers/staging/imx-drm/dw-hdmi-cec.c | 205 +++ drivers/staging/imx-drm/dw-hdmi-cec.h | 16 + drivers/staging/imx-drm/imx-drm-core.c | 7 +- drivers/staging/imx-drm/imx-hdmi.c | 178 ++- drivers/staging/imx-drm/imx-ldb.c | 21 + drivers/staging/imx-drm/imx-tve.c | 63 +- drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h | 5 + drivers/staging/imx-drm/ipu-v3/ipu-common.c | 41 +- drivers/staging/imx-drm/ipu-v3/ipu-dc.c | 94 +- drivers/staging/imx-drm/ipu-v3/ipu-di.c | 2 +- drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c | 25 +- drivers/staging/imx-drm/ipu-v3/ipu-dp.c | 71 +- drivers/staging/imx-drm/ipu-v3/ipu-prv.h | 3 + drivers/staging/imx-drm/ipuv3-crtc.c | 16 +- drivers/staging/imx-drm/ipuv3-plane.c | 4 + drivers/staging/imx-drm/parallel-display.c | 2 + include/linux/cec-dev.h | 69 + include/linux/mmc/host.h | 8 + include/linux/mmc/sdhci.h | 15 +- include/uapi/linux/cec-dev.h | 34 + include/uapi/linux/videodev2.h | 1 + sound/soc/fsl/imx-pcm-dma.c | 2 +- 133 files changed, 5598 insertions(+), 2336 deletions(-)
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 1/222 ARM: l2c: remove outer_inv_all() method
No one ever calls this function anywhere in the kernel, so let's completely remove it from the outer cache API and turn it into an internal-only thing.
--- arch/arm/include/asm/outercache.h | 8 -------- arch/arm/mm/cache-feroceon-l2.c | 1 - arch/arm/mm/cache-l2x0.c | 5 ----- 3 files changed, 14 deletions(-)
arch/arm/include/asm/outercache.h +0 -8
@@ -28,7 +28,6 @@ struct outer_cache_fns {void (*clean_range)(unsigned long ,unsigned long );void (*flush_range)(unsigned long ,unsigned long );void (*flush_all)(void ); -void (*inv_all)(void );void (*disable)(void );#ifdef CONFIG_OUTER_CACHE_SYNC void (*sync)(void );
@@ -63,12 +62,6 @@ static inline void outer_flush_all(void) outer_cache.flush_all (); } -static inline void outer_inv_all (void ) -{ -if (outer_cache.inv_all) - outer_cache.inv_all (); -} -static inline void outer_disable (void ) {if (outer_cache.disable)
@@ -90,7 +83,6 @@ static inline void outer_clean_range(phys_addr_t start, phys_addr_t end)static inline void outer_flush_range (phys_addr_t start,phys_addr_t end) { }static inline void outer_flush_all (void ) { } -static inline void outer_inv_all (void ) { }static inline void outer_disable (void ) { }static inline void outer_resume (void ) { }
arch/arm/mm/cache-feroceon-l2.c +0 -1
@@ -350,7 +350,6 @@ void __init feroceon_l2_init(int __l2_wt_override) outer_cache.inv_range = feroceon_l2_inv_range; outer_cache.clean_range = feroceon_l2_clean_range; outer_cache.flush_range = feroceon_l2_flush_range; - outer_cache.inv_all = l2_inv_all;enable_l2 ();
arch/arm/mm/cache-l2x0.c +0 -5
@@ -414,7 +414,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) outer_cache.flush_range = l2x0_flush_range; outer_cache.sync = l2x0_cache_sync; outer_cache.flush_all = l2x0_flush_all; - outer_cache.inv_all = l2x0_inv_all; outer_cache.disable = l2x0_disable; }
@@ -884,7 +883,6 @@ static const struct l2x0_of_data pl310_data = { .flush_range = l2x0_flush_range, .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, - .inv_all = l2x0_inv_all, .disable = l2x0_disable, }, };
@@ -899,7 +897,6 @@ static const struct l2x0_of_data l2x0_data = { .flush_range = l2x0_flush_range, .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, - .inv_all = l2x0_inv_all, .disable = l2x0_disable, }, };
@@ -914,7 +911,6 @@ static const struct l2x0_of_data aurora_with_outer_data = { .flush_range = aurora_flush_range, .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, - .inv_all = l2x0_inv_all, .disable = l2x0_disable, }, };
@@ -946,7 +942,6 @@ static const struct l2x0_of_data bcm_l2x0_data = { .flush_range = bcm_flush_range, .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, - .inv_all = l2x0_inv_all, .disable = l2x0_disable, }, };
Signature · 1 line
1.8.3.1
PATCH 2/222 ARM: l2c: remove unnecessary call to outer_flush_all()
In reply to Russell King - ARM Linuxouter_disable() is defined to safely turn the L2 cache off without data
loss: this means that outer_flush_all() should never be called unless you need to implement some special L2 cache disabling, and even then only from your replacement L2 cache disable function.
--- arch/arm/mach-prima2/pm.c | 1 - 1 file changed, 1 deletion(-)
arch/arm/mach-prima2/pm.c +0 -1
@@ -71,7 +71,6 @@ static int sirfsoc_pm_enter(suspend_state_t state)case PM_SUSPEND_MEM :sirfsoc_pre_suspend_power_off (); -outer_flush_all ();outer_disable ();/* go zzz */ cpu_suspend (0 , sirfsoc_finish_suspend);
Signature · 1 line
1.8.3.1
PATCH 3/222 ARM: l2c: avoid calling outer_flush_all() unnecessarily (Spear)
In reply to Russell King - ARM LinuxSpear calls outer_flush_all() from it's SMP bringup function. This is potentially dangerous as the L2C set/way operations which implement this don't take kindly to concurrent operations. Besides, there's better solutions to this, as implemented on other platforms.
--- arch/arm/mach-spear/platsmp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
arch/arm/mach-spear/platsmp.c +14 -5
@@ -20,6 +20,18 @@#include <mach/spear.h> #include "generic.h" +/* +* Write pen_release in a way that is guaranteed to be visible to all +* observers, irrespective of whether they're taking part in coherency +* or not. This is necessary for the hotplug code to work reliably. +*/ +static void write_pen_release (int val) +{ + pen_release = val; +smp_wmb (); +sync_cache_w (&pen_release); +} +static DEFINE_SPINLOCK (boot_lock);static void __iomem *scu_base =IOMEM (VA_SCU_BASE );
@@ -30,8 +42,7 @@ static void spear13xx_secondary_init(unsigned int cpu)* let the primary processor know we're out of the * pen, then head off into the C entry point */ - pen_release =-1 ; -smp_wmb (); +write_pen_release (-1 );/* * Synchronise with the boot thread.
@@ -58,9 +69,7 @@ static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)* Note that "pen_release" is the hardware CPU ID, whereas * "cpu" is Linux's internal ID. */ - pen_release = cpu; -flush_cache_all (); -outer_flush_all (); +write_pen_release (cpu); timeout = jiffies + (1 *HZ );while (time_before (jiffies, timeout)) {
Signature · 1 line
1.8.3.1
PATCH 4/222 ARM: l2c: omap2: remove ES1.0 support
In reply to Russell King - ARM LinuxSantosh says:
Quoted 4 lines
But we should kill all of that since we long back decided to remove ES1.0 related code. The mach-omap code alreasy has removed the ES1.0 compatibility so feel free to remove any specific ES1.0 related stuff. That silicon is long dead.
--- arch/arm/mach-omap2/omap4-common.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-)
arch/arm/mach-omap2/omap4-common.c +8 -17
@@ -182,7 +182,7 @@ static void omap4_l2x0_set_debug(unsigned long val)static int __init omap_l2_cache_init (void ) { -u32 aux_ctrl =0 ; +u32 aux_ctrl;/* * To avoid code running on other OMAPs in
@@ -196,27 +196,18 @@ static int __init omap_l2_cache_init(void)if (WARN_ON (!l2cache_base))return -ENOMEM ; -/* -* 16-way associativity, parity disabled -* Way size - 32KB (es1.0) -* Way size - 64KB (es2.0 +) -*/ - aux_ctrl = ((1 <<L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT ) | +/* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ + aux_ctrl = (1 <<L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT ) | (0x1 <<25 ) | (0x1 <<L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT ) | - (0x1 <<L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT )); - -if (omap_rev () ==OMAP4430_REV_ES1_0 ) { - aux_ctrl |=0x2 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ; - }else { - aux_ctrl |= ((0x3 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ) | + (0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT)) | + (0x3 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ) | (1 <<L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT ) | (1 <<L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT ) | (1 <<L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT ) | - (1 <<L2X0_AUX_CTRL_EARLY_BRESP_SHIFT )); - } -if (omap_rev () !=OMAP4430_REV_ES1_0 ) -omap_smc1 (0x109 , aux_ctrl); + (1 <<L2X0_AUX_CTRL_EARLY_BRESP_SHIFT ); + +omap_smc1 (0x109 , aux_ctrl);/* Enable PL310 L2 Cache controller */ omap_smc1 (0x102 ,0x1 );
Signature · 1 line
1.8.3.1
PATCH 5/222 ARM: l2c: remove unnecessary UL-suffix to mask values
In reply to Russell King - ARM LinuxThey're u32, they're not unsigned long. The UL suffix is not required here.
--- arch/arm/mach-highbank/highbank.c | 2 +- arch/arm/mach-imx/mach-vf610.c | 2 +- arch/arm/mach-imx/system.c | 2 +- arch/arm/mach-mvebu/board-v7.c | 2 +- arch/arm/mach-rockchip/rockchip.c | 2 +- arch/arm/mach-socfpga/socfpga.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
arch/arm/mach-highbank/highbank.c +1 -1
@@ -69,7 +69,7 @@ static void __init highbank_init_irq(void)if (IS_ENABLED (CONFIG_CACHE_L2X0 ) &&of_find_compatible_node (NULL ,NULL ,"arm,pl310-cache" )) {highbank_smc1 (0x102 ,0x1 ); -l2x0_of_init (0 , ~0UL ); +l2x0_of_init (0 , ~0 ); outer_cache.disable = highbank_l2x0_disable; } }
arch/arm/mach-imx/mach-vf610.c +1 -1
@@ -22,7 +22,7 @@ static void __init vf610_init_machine(void)static void __init vf610_init_irq (void ) { -l2x0_of_init (0 , ~0UL ); +l2x0_of_init (0 , ~0 );irqchip_init (); }
arch/arm/mach-imx/system.c +1 -1
@@ -145,6 +145,6 @@ void __init imx_init_l2cache(void)of_node_put (np); out: - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); }#endif
arch/arm/mach-mvebu/board-v7.c +1 -1
@@ -60,7 +60,7 @@ static void __init mvebu_timer_and_clk_init(void)coherency_init ();BUG_ON (mvebu_mbus_dt_init ());#ifdef CONFIG_CACHE_L2X0 -l2x0_of_init (0 , ~0UL ); +l2x0_of_init (0 , ~0 );#endif if (of_machine_is_compatible ("marvell,armada375" ))
arch/arm/mach-rockchip/rockchip.c +1 -1
@@ -26,7 +26,7 @@static void __init rockchip_dt_init (void ) { -l2x0_of_init (0 , ~0UL ); +l2x0_of_init (0 , ~0 );of_platform_populate (NULL , of_default_bus_match_table,NULL ,NULL ); }
arch/arm/mach-socfpga/socfpga.c +1 -1
@@ -100,7 +100,7 @@ static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd)static void __init socfpga_cyclone5_init (void ) { -l2x0_of_init (0 , ~0UL ); +l2x0_of_init (0 , ~0 );of_platform_populate (NULL , of_default_bus_match_table,NULL ,NULL ); }
Signature · 1 line
1.8.3.1
PATCH 6/222 ARM: outer cache: add documentation of outer cache functions
In reply to Russell King - ARM LinuxAdd some documentation to cover the outer cache functions so that their requirements can be better understood. Of particular note are the flush_all() and disable() methods which must not be called except in very specific circumstances.
--- arch/arm/include/asm/outercache.h | 48 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-)
arch/arm/include/asm/outercache.h +47 -1
@@ -39,35 +39,75 @@ struct outer_cache_fns {extern struct outer_cache_fns outer_cache;#ifdef CONFIG_OUTER_CACHE - +/** +* outer_inv_range - invalidate range of outer cache lines +* @start: starting physical address, inclusive +* @end: end physical address, exclusive +*/ static inline void outer_inv_range (phys_addr_t start,phys_addr_t end) {if (outer_cache.inv_range) outer_cache.inv_range (start, end); } + +/** +* outer_clean_range - clean dirty outer cache lines +* @start: starting physical address, inclusive +* @end: end physical address, exclusive +*/ static inline void outer_clean_range (phys_addr_t start,phys_addr_t end) {if (outer_cache.clean_range) outer_cache.clean_range (start, end); } + +/** +* outer_flush_range - clean and invalidate outer cache lines +* @start: starting physical address, inclusive +* @end: end physical address, exclusive +*/ static inline void outer_flush_range (phys_addr_t start,phys_addr_t end) {if (outer_cache.flush_range) outer_cache.flush_range (start, end); } +/** +* outer_flush_all - clean and invalidate all cache lines in the outer cache +* +* Note: depending on implementation, this may not be atomic - it must +* only be called with interrupts disabled and no other active outer +* cache masters. +* +* It is intended that this function is only used by implementations +* needing to override the outer_cache.disable() method due to security. +* (Some implementations perform this as a clean followed by an invalidate.) +*/ static inline void outer_flush_all (void ) {if (outer_cache.flush_all) outer_cache.flush_all (); } +/** +* outer_disable - clean, invalidate and disable the outer cache +* +* Disable the outer cache, ensuring that any data contained in the outer +* cache is pushed out to lower levels of system memory. The note and +* conditions above concerning outer_flush_all() applies here. +*/ static inline void outer_disable (void ) {if (outer_cache.disable) outer_cache.disable (); } +/** +* outer_resume - restore the cache configuration and re-enable outer cache +* +* Restore any configuration that the cache had when previously enabled, +* and re-enable the outer cache. +*/ static inline void outer_resume (void ) {if (outer_cache.resume)
@@ -89,6 +129,12 @@ static inline void outer_resume(void) { }#endif #ifdef CONFIG_OUTER_CACHE_SYNC +/** +* outer_sync - perform a sync point for outer cache +* +* Ensure that all outer cache operations are complete and any store +* buffers are drained. +*/ static inline void outer_sync (void ) {if (outer_cache.sync)
Signature · 1 line
1.8.3.1
PATCH 7/222 ARM: outer cache: add WARN_ON() to outer_disable()
In reply to Russell King - ARM LinuxAdd WARN_ON() conditions to outer_disable() to ensure that its requirements aren't violated.
--- arch/arm/include/asm/outercache.h | 7 ++----- arch/arm/mm/Makefile | 1 + arch/arm/mm/l2c-common.c | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mm/l2c-common.c
arch/arm/include/asm/outercache.h +2 -5
@@ -21,6 +21,7 @@#ifndef __ASM_OUTERCACHE_H#define __ASM_OUTERCACHE_H +#include <linux/bug.h> #include <linux/types.h> struct outer_cache_fns {
@@ -96,11 +97,7 @@ static inline void outer_flush_all(void)* cache is pushed out to lower levels of system memory. The note and * conditions above concerning outer_flush_all() applies here. */ -static inline void outer_disable (void ) -{ -if (outer_cache.disable) - outer_cache.disable (); -} +extern void outer_disable (void );/** * outer_resume - restore the cache configuration and re-enable outer cache
arch/arm/mm/Makefile +1 -0
@@ -95,6 +95,7 @@ obj-$(CONFIG_CPU_V7M) += proc-v7m.o AFLAGS_proc-v6.o :=-Wa,-march=armv6 AFLAGS_proc-v7.o :=-Wa,-march=armv7-a +obj-$(CONFIG_OUTER_CACHE) += l2c-common.o obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o
arch/arm/mm/l2c-common.c new file +20 -0
@@ -0,0 +1,20 @@ +/* +* Copyright (C) 2010 ARM Ltd. +* Written by Catalin Marinas <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ +#include <linux/bug.h> +#include <linux/smp.h> +#include <asm/outercache.h> + +void outer_disable (void ) +{ +WARN_ON (!irqs_disabled ()); +WARN_ON (num_online_cpus () >1 ); + +if (outer_cache.disable) + outer_cache.disable (); +}
Signature · 1 line
1.8.3.1
PATCH 8/222 ARM: l2c: add helper for L2 cache controller DT IDs
In reply to Russell King - ARM LinuxMake it easier to declare L2 cache controller DT IDs by using a macro.
--- arch/arm/mm/cache-l2x0.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
arch/arm/mm/cache-l2x0.c +10 -13
@@ -946,20 +946,17 @@ static const struct l2x0_of_data bcm_l2x0_data = { }, }; +#define L2C_ID (name, fns) { .compatible = name, .data = (void *)&fns }static const struct of_device_id l2x0_ids[]__initconst = { - { .compatible ="arm,l210-cache" , .data = (void *)&l2x0_data }, - { .compatible ="arm,l220-cache" , .data = (void *)&l2x0_data }, - { .compatible ="arm,pl310-cache" , .data = (void *)&pl310_data }, - { .compatible ="bcm,bcm11351-a2-pl310-cache" ,/* deprecated name */ - .data = (void *)&bcm_l2x0_data}, - { .compatible ="brcm,bcm11351-a2-pl310-cache" , - .data = (void *)&bcm_l2x0_data}, - { .compatible ="marvell,aurora-outer-cache" , - .data = (void *)&aurora_with_outer_data}, - { .compatible ="marvell,aurora-system-cache" , - .data = (void *)&aurora_no_outer_data}, - { .compatible ="marvell,tauros3-cache" , - .data = (void *)&tauros3_data }, +L2C_ID ("arm,l210-cache" , l2x0_data), +L2C_ID ("arm,l220-cache" , l2x0_data), +L2C_ID ("arm,pl310-cache" , pl310_data), +L2C_ID ("brcm,bcm11351-a2-pl310-cache" , bcm_l2x0_data), +L2C_ID ("marvell,aurora-outer-cache" , aurora_with_outer_data), +L2C_ID ("marvell,aurora-system-cache" , aurora_no_outer_data), +L2C_ID ("marvell,tauros3-cache" , tauros3_data), +/* Deprecated IDs */ +L2C_ID ("bcm,bcm11351-a2-pl310-cache" , bcm_l2x0_data), {} };
Signature · 1 line
1.8.3.1
PATCH 9/222 ARM: l2c: tidy up l2x0_of_data declarations
In reply to Russell King - ARM LinuxRemove NULL initialisers, make these all __initconst structures, and order their members in the same order as the structure declaration.
--- arch/arm/mm/cache-l2x0.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)
arch/arm/mm/cache-l2x0.c +14 -16
@@ -873,49 +873,48 @@ static void __init aurora_of_setup(const struct device_node *np, *aux_mask &= ~mask; } -static const struct l2x0_of_data pl310_data = { +static const struct l2x0_of_data pl310_data__initconst = { .setup = pl310_of_setup, .save = pl310_save, .outer_cache = { - .resume = pl310_resume, .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, .flush_range = l2x0_flush_range, - .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = pl310_resume, }, }; -static const struct l2x0_of_data l2x0_data = { +static const struct l2x0_of_data l2x0_data__initconst = { .setup = l2x0_of_setup, - .save =NULL , .outer_cache = { - .resume = l2x0_resume, .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, .flush_range = l2x0_flush_range, - .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = l2x0_resume, }, }; -static const struct l2x0_of_data aurora_with_outer_data = { +static const struct l2x0_of_data aurora_with_outer_data__initconst = { .setup = aurora_of_setup, .save = aurora_save, .outer_cache = { - .resume = aurora_resume, .inv_range = aurora_inv_range, .clean_range = aurora_clean_range, .flush_range = aurora_flush_range, - .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = aurora_resume, }, }; -static const struct l2x0_of_data aurora_no_outer_data = { +static const struct l2x0_of_data aurora_no_outer_data__initconst = { .setup = aurora_of_setup, .save = aurora_save, .outer_cache = {
@@ -923,8 +922,7 @@ static const struct l2x0_of_data aurora_no_outer_data = { }, }; -static const struct l2x0_of_data tauros3_data = { - .setup =NULL , +static const struct l2x0_of_data tauros3_data__initconst = { .save = tauros3_save,/* Tauros3 broadcasts L1 cache operations to L2 */ .outer_cache = {
@@ -932,17 +930,17 @@ static const struct l2x0_of_data tauros3_data = { }, }; -static const struct l2x0_of_data bcm_l2x0_data = { +static const struct l2x0_of_data bcm_l2x0_data__initconst = { .setup = pl310_of_setup, .save = pl310_save, .outer_cache = { - .resume = pl310_resume, .inv_range = bcm_inv_range, .clean_range = bcm_clean_range, .flush_range = bcm_flush_range, - .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = pl310_resume, }, };
Signature · 1 line
1.8.3.1
PATCH 10/222 ARM: l2c: rename OF specific things, making l2x0_of_data available to all
In reply to Russell King - ARM LinuxRename a few things to help distinguish their function(s):
l2x0_of_data -> l2c_init_data
setup -> of_parse
add of_ prefix to OF specific data
--- arch/arm/mm/cache-l2x0.c | 64 ++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 32 deletions(-)
arch/arm/mm/cache-l2x0.c +32 -32
@@ -28,6 +28,12 @@#include "cache-tauros3.h" #include "cache-aurora-l2.h" +struct l2c_init_data { +void (*of_parse)(const struct device_node *,u32 *,u32 *); +void (*save)(void ); +struct outer_cache_fns outer_cache; +}; +#define CACHE_LINE_SIZE 32static void __iomem *l2x0_base;
@@ -42,12 +48,6 @@ static u32 cache_id_part_number_from_dt;struct l2x0_regs l2x0_saved_regs; -struct l2x0_of_data { -void (*setup)(const struct device_node *,u32 *,u32 *); -void (*save)(void ); -struct outer_cache_fns outer_cache; -}; -static bool of_init = false;static inline void cache_wait_way (void __iomem *reg,unsigned long mask)
@@ -664,7 +664,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end) new_end); } -static void __init l2x0_of_setup (const struct device_node *np, +static void __init l2x0_of_parse (const struct device_node *np,u32 *aux_val,u32 *aux_mask) {u32 data[2 ] = {0 ,0 };
@@ -698,7 +698,7 @@ static void __init l2x0_of_setup(const struct device_node *np, *aux_mask &= ~mask; } -static void __init pl310_of_setup (const struct device_node *np, +static void __init pl310_of_parse (const struct device_node *np,u32 *aux_val,u32 *aux_mask) {u32 data[3 ] = {0 ,0 ,0 };
@@ -851,7 +851,7 @@ static void __init aurora_broadcast_l2_commands(void)isb (); } -static void __init aurora_of_setup (const struct device_node *np, +static void __init aurora_of_parse (const struct device_node *np,u32 *aux_val,u32 *aux_mask) {u32 val =AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU ;
@@ -873,8 +873,8 @@ static void __init aurora_of_setup(const struct device_node *np, *aux_mask &= ~mask; } -static const struct l2x0_of_data pl310_data__initconst = { - .setup = pl310_of_setup, +static const struct l2c_init_data of_pl310_data__initconst = { + .of_parse = pl310_of_parse, .save = pl310_save, .outer_cache = { .inv_range = l2x0_inv_range,
@@ -887,8 +887,8 @@ static const struct l2x0_of_data pl310_data __initconst = { }, }; -static const struct l2x0_of_data l2x0_data__initconst = { - .setup = l2x0_of_setup, +static const struct l2c_init_data of_l2x0_data__initconst = { + .of_parse = l2x0_of_parse, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range,
@@ -900,8 +900,8 @@ static const struct l2x0_of_data l2x0_data __initconst = { }, }; -static const struct l2x0_of_data aurora_with_outer_data__initconst = { - .setup = aurora_of_setup, +static const struct l2c_init_data of_aurora_with_outer_data__initconst = { + .of_parse = aurora_of_parse, .save = aurora_save, .outer_cache = { .inv_range = aurora_inv_range,
@@ -914,15 +914,15 @@ static const struct l2x0_of_data aurora_with_outer_data __initconst = { }, }; -static const struct l2x0_of_data aurora_no_outer_data__initconst = { - .setup = aurora_of_setup, +static const struct l2c_init_data of_aurora_no_outer_data__initconst = { + .of_parse = aurora_of_parse, .save = aurora_save, .outer_cache = { .resume = aurora_resume, }, }; -static const struct l2x0_of_data tauros3_data__initconst = { +static const struct l2c_init_data of_tauros3_data__initconst = { .save = tauros3_save,/* Tauros3 broadcasts L1 cache operations to L2 */ .outer_cache = {
@@ -930,8 +930,8 @@ static const struct l2x0_of_data tauros3_data __initconst = { }, }; -static const struct l2x0_of_data bcm_l2x0_data__initconst = { - .setup = pl310_of_setup, +static const struct l2c_init_data of_bcm_l2x0_data__initconst = { + .of_parse = pl310_of_parse, .save = pl310_save, .outer_cache = { .inv_range = bcm_inv_range,
@@ -946,22 +946,22 @@ static const struct l2x0_of_data bcm_l2x0_data __initconst = {#define L2C_ID (name, fns) { .compatible = name, .data = (void *)&fns }static const struct of_device_id l2x0_ids[]__initconst = { -L2C_ID ("arm,l210-cache" , l2x0_data), -L2C_ID ("arm,l220-cache" , l2x0_data), -L2C_ID ("arm,pl310-cache" , pl310_data), -L2C_ID ("brcm,bcm11351-a2-pl310-cache" , bcm_l2x0_data), -L2C_ID ("marvell,aurora-outer-cache" , aurora_with_outer_data), -L2C_ID ("marvell,aurora-system-cache" , aurora_no_outer_data), -L2C_ID ("marvell,tauros3-cache" , tauros3_data), +L2C_ID ("arm,l210-cache" , of_l2x0_data), +L2C_ID ("arm,l220-cache" , of_l2x0_data), +L2C_ID ("arm,pl310-cache" , of_pl310_data), +L2C_ID ("brcm,bcm11351-a2-pl310-cache" , of_bcm_l2x0_data), +L2C_ID ("marvell,aurora-outer-cache" , of_aurora_with_outer_data), +L2C_ID ("marvell,aurora-system-cache" , of_aurora_no_outer_data), +L2C_ID ("marvell,tauros3-cache" , of_tauros3_data),/* Deprecated IDs */ -L2C_ID ("bcm,bcm11351-a2-pl310-cache" , bcm_l2x0_data), +L2C_ID ("bcm,bcm11351-a2-pl310-cache" , of_bcm_l2x0_data), {} };int __init l2x0_of_init (u32 aux_val,u32 aux_mask) { +const struct l2c_init_data *data;struct device_node *np; -const struct l2x0_of_data *data;struct resource res; np =of_find_matching_node (NULL , l2x0_ids);
@@ -981,12 +981,12 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)/* L2 configuration can only be changed if the cache is disabled */ if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -if (data->setup) - data->setup (np, &aux_val, &aux_mask); +if (data->of_parse) + data->of_parse (np, &aux_val, &aux_mask);/* For aurora cache in no outer mode select the * correct mode using the coprocessor*/ -if (data == &aurora_no_outer_data) +if (data == &of_aurora_no_outer_data)aurora_broadcast_l2_commands (); }
Signature · 1 line
1.8.3.1
PATCH 11/222 ARM: l2c: provide generic function for calling set_debug method
In reply to Russell King - ARM LinuxProvide a generic function which always calls the set_debug method. This will be used later in the series as some work-arounds require that the debug register be written.
--- arch/arm/mm/cache-l2x0.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
arch/arm/mm/cache-l2x0.c +11 -1
@@ -57,6 +57,16 @@ static inline void cache_wait_way(void __iomem *reg, unsigned long mask)cpu_relax (); } +/* +* This should only be called when we have a requirement that the +* register be written due to a work-around, as platforms running +* in non-secure mode may not be able to access this register. +*/ +static inline void l2c_set_debug (void __iomem *base,unsigned long val) +{ + outer_cache.set_debug (val); +} +#ifdef CONFIG_CACHE_PL310 static inline void cache_wait (void __iomem *reg,unsigned long mask) {
@@ -92,7 +102,7 @@ static inline void l2x0_inv_line(unsigned long addr)static inline void debug_writel (unsigned long val) {if (outer_cache.set_debug) - outer_cache.set_debug (val); +l2c_set_debug (l2x0_base, val); }static void pl310_set_debug (unsigned long val)
Signature · 1 line
1.8.3.1
PATCH 12/222 ARM: l2c: split out cache unlock code
In reply to Russell King - ARM LinuxSplit the cache unlock code out of l2x0_unlock(). We want to be able to re-use this functionality later.
--- arch/arm/mm/cache-l2x0.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
arch/arm/mm/cache-l2x0.c +16 -7
@@ -50,6 +50,9 @@ struct l2x0_regs l2x0_saved_regs;static bool of_init = false; +/* +* Common code for all cache controllers. +*/ static inline void cache_wait_way (void __iomem *reg,unsigned long mask) {/* wait for cache operation by line or way to complete */
@@ -67,6 +70,18 @@ static inline void l2c_set_debug(void __iomem *base, unsigned long val) outer_cache.set_debug (val); } +static inline void l2c_unlock (void __iomem *base,unsigned num) +{ +unsigned i; + +for (i =0 ; i < num; i++) { +writel_relaxed (0 , base +L2X0_LOCKDOWN_WAY_D_BASE + + i *L2X0_LOCKDOWN_STRIDE ); +writel_relaxed (0 , base +L2X0_LOCKDOWN_WAY_I_BASE + + i *L2X0_LOCKDOWN_STRIDE ); + } +} +#ifdef CONFIG_CACHE_PL310 static inline void cache_wait (void __iomem *reg,unsigned long mask) {
@@ -308,7 +323,6 @@ static void l2x0_disable(void)static void l2x0_unlock (u32 cache_id) {int lockregs; -int i;switch (cache_id &L2X0_CACHE_ID_PART_MASK ) {case L2X0_CACHE_ID_PART_L310 :
@@ -323,12 +337,7 @@ static void l2x0_unlock(u32 cache_id)break ; } -for (i =0 ; i < lockregs; i++) { -writel_relaxed (0x0 , l2x0_base +L2X0_LOCKDOWN_WAY_D_BASE + - i *L2X0_LOCKDOWN_STRIDE ); -writel_relaxed (0x0 , l2x0_base +L2X0_LOCKDOWN_WAY_I_BASE + - i *L2X0_LOCKDOWN_STRIDE ); - } +l2c_unlock (l2x0_base, lockregs); }void __init l2x0_init (void __iomem *base,u32 aux_val,u32 aux_mask)
Signature · 1 line
1.8.3.1
PATCH 13/222 ARM: l2c: provide generic helper for way-based operations
In reply to Russell King - ARM LinuxProvide a generic helper function for way based operations. These are always background operations, and thus have to be waited for before a new operation is commenced. This helper extracts that requirement from several locations in the code.
--- arch/arm/mm/cache-l2x0.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
arch/arm/mm/cache-l2x0.c +9 -6
@@ -70,6 +70,12 @@ static inline void l2c_set_debug(void __iomem *base, unsigned long val) outer_cache.set_debug (val); } +static void __l2c_op_way (void __iomem *reg) +{ +writel_relaxed (l2x0_way_mask, reg); +cache_wait_way (reg, l2x0_way_mask); +} +static inline void l2c_unlock (void __iomem *base,unsigned num) {unsigned i;
@@ -166,8 +172,7 @@ static void l2x0_cache_sync(void)static void __l2x0_flush_all (void ) {debug_writel (0x03 ); -writel_relaxed (l2x0_way_mask, l2x0_base +L2X0_CLEAN_INV_WAY ); -cache_wait_way (l2x0_base +L2X0_CLEAN_INV_WAY , l2x0_way_mask); +__l2c_op_way (l2x0_base +L2X0_CLEAN_INV_WAY );cache_sync ();debug_writel (0x00 ); }
@@ -188,8 +193,7 @@ static void l2x0_clean_all(void)/* clean all ways */ raw_spin_lock_irqsave (&l2x0_lock, flags); -writel_relaxed (l2x0_way_mask, l2x0_base +L2X0_CLEAN_WAY ); -cache_wait_way (l2x0_base +L2X0_CLEAN_WAY , l2x0_way_mask); +__l2c_op_way (l2x0_base +L2X0_CLEAN_WAY );cache_sync ();raw_spin_unlock_irqrestore (&l2x0_lock, flags); }
@@ -202,8 +206,7 @@ static void l2x0_inv_all(void)raw_spin_lock_irqsave (&l2x0_lock, flags);/* Invalidating when L2 is enabled is a nono */ BUG_ON (readl (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN ); -writel_relaxed (l2x0_way_mask, l2x0_base +L2X0_INV_WAY ); -cache_wait_way (l2x0_base +L2X0_INV_WAY , l2x0_way_mask); +__l2c_op_way (l2x0_base +L2X0_INV_WAY );cache_sync ();raw_spin_unlock_irqrestore (&l2x0_lock, flags); }
Signature · 1 line
1.8.3.1
PATCH 14/222 ARM: l2c: rename cache_wait_way()
In reply to Russell King - ARM Linuxcache_wait_way() is actually used to wait for a particular mask to report clear; it's not really got much to do with cache ways at all. Indeed, it gets used to wait for the C bit to clear on older caches. Rename this with a more generic function name which better reflects its purpose: l2c_wait_mask().
--- arch/arm/mm/cache-l2x0.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm/mm/cache-l2x0.c +3 -3
@@ -53,7 +53,7 @@ static bool of_init = false;/* * Common code for all cache controllers. */ -static inline void cache_wait_way (void __iomem *reg,unsigned long mask) +static inline void l2c_wait_mask (void __iomem *reg,unsigned long mask) {/* wait for cache operation by line or way to complete */ while (readl_relaxed (reg) & mask)
@@ -73,7 +73,7 @@ static inline void l2c_set_debug(void __iomem *base, unsigned long val)static void __l2c_op_way (void __iomem *reg) {writel_relaxed (l2x0_way_mask, reg); -cache_wait_way (reg, l2x0_way_mask); +l2c_wait_mask (reg, l2x0_way_mask); }static inline void l2c_unlock (void __iomem *base,unsigned num)
@@ -94,7 +94,7 @@ static inline void cache_wait(void __iomem *reg, unsigned long mask) /* cache operations by line are atomic on PL310 */ }#else -#define cache_wait cache_wait_way +#define cache_wait l2c_wait_mask#endif static inline void cache_sync (void )
Signature · 1 line
1.8.3.1
PATCH 15/222 ARM: l2c: add and use L2C revision constants
In reply to Russell King - ARM LinuxThe revision namespace is specific to the L2 cache part, so don't name these with generic identifiers, use a part specific identifier.
--- arch/arm/include/asm/hardware/cache-l2x0.h | 22 ++++++++++++++++------ arch/arm/mm/cache-l2x0.c | 10 +++++----- 2 files changed, 21 insertions(+), 11 deletions(-)
arch/arm/include/asm/hardware/cache-l2x0.h +16 -6
@@ -68,14 +68,24 @@/* Registers shifts and masks */ #define L2X0_CACHE_ID_PART_MASK (0xf << 6)#define L2X0_CACHE_ID_PART_L210 (1 << 6) +#define L2X0_CACHE_ID_PART_L220 (2 << 6)#define L2X0_CACHE_ID_PART_L310 (3 << 6)#define L2X0_CACHE_ID_RTL_MASK 0x3f -#define L2X0_CACHE_ID_RTL_R0P0 0x0 -#define L2X0_CACHE_ID_RTL_R1P0 0x2 -#define L2X0_CACHE_ID_RTL_R2P0 0x4 -#define L2X0_CACHE_ID_RTL_R3P0 0x5 -#define L2X0_CACHE_ID_RTL_R3P1 0x6 -#define L2X0_CACHE_ID_RTL_R3P2 0x8 +#define L210_CACHE_ID_RTL_R0P2_02 0x00 +#define L210_CACHE_ID_RTL_R0P1 0x01 +#define L210_CACHE_ID_RTL_R0P2_01 0x02 +#define L210_CACHE_ID_RTL_R0P3 0x03 +#define L210_CACHE_ID_RTL_R0P4 0x0b +#define L210_CACHE_ID_RTL_R0P5 0x0f +#define L220_CACHE_ID_RTL_R1P7_01REL0 0x06 +#define L310_CACHE_ID_RTL_R0P0 0x00 +#define L310_CACHE_ID_RTL_R1P0 0x02 +#define L310_CACHE_ID_RTL_R2P0 0x04 +#define L310_CACHE_ID_RTL_R3P0 0x05 +#define L310_CACHE_ID_RTL_R3P1 0x06 +#define L310_CACHE_ID_RTL_R3P1_50REL0 0x07 +#define L310_CACHE_ID_RTL_R3P2 0x08 +#define L310_CACHE_ID_RTL_R3P3 0x09#define L2X0_AUX_CTRL_MASK 0xc0000fff#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0
arch/arm/mm/cache-l2x0.c +5 -5
@@ -374,7 +374,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)/* Unmapped register. */ sync_reg_offset =L2X0_DUMMY_REG ;#endif -if ((cache_id &L2X0_CACHE_ID_RTL_MASK ) <=L2X0_CACHE_ID_RTL_R3P0 ) +if ((cache_id &L2X0_CACHE_ID_RTL_MASK ) <=L310_CACHE_ID_RTL_R3P0 ) outer_cache.set_debug = pl310_set_debug;break ;case L2X0_CACHE_ID_PART_L210 :
@@ -768,7 +768,7 @@ static void __init pl310_save(void) l2x0_saved_regs.filter_start =readl_relaxed (l2x0_base +L2X0_ADDR_FILTER_START ); -if (l2x0_revision >=L2X0_CACHE_ID_RTL_R2P0 ) { +if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) {/* * From r2p0, there is Prefetch offset/control register */
@@ -777,7 +777,7 @@ static void __init pl310_save(void)/* * From r3p0, there is Power control register */ -if (l2x0_revision >=L2X0_CACHE_ID_RTL_R3P0 ) +if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) l2x0_saved_regs.pwr_ctrl =readl_relaxed (l2x0_base +L2X0_POWER_CTRL ); }
@@ -830,10 +830,10 @@ static void pl310_resume(void) l2x0_revision =readl_relaxed (l2x0_base +L2X0_CACHE_ID ) &L2X0_CACHE_ID_RTL_MASK ; -if (l2x0_revision >=L2X0_CACHE_ID_RTL_R2P0 ) { +if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) {writel_relaxed (l2x0_saved_regs.prefetch_ctrl, l2x0_base +L2X0_PREFETCH_CTRL ); -if (l2x0_revision >=L2X0_CACHE_ID_RTL_R3P0 ) +if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 )writel_relaxed (l2x0_saved_regs.pwr_ctrl, l2x0_base +L2X0_POWER_CTRL ); }
Signature · 1 line
1.8.3.1
PATCH 16/222 ARM: l2c: clean up OF initialisation a bit
In reply to Russell King - ARM LinuxRather than having a boolean and other tricks to disable some bits of l2x0_init(), split this function into two parts: a common part shared between OF and non-OF, and the non-OF part.
The common part can take a block of function pointers, and the cache ID (to cope with Aurora's DT specified ID.) Eliminate the redundant setting of l2x0_base in the OF case, moving it to the non-OF init function.
This allows us to localise the OF-specific initialisation handling from the non-OF handling.
--- arch/arm/mm/cache-l2x0.c | 66 +++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 26 deletions(-)
arch/arm/mm/cache-l2x0.c +40 -26
@@ -42,14 +42,8 @@ static u32 l2x0_way_mask; /* Bitmask of active ways */static u32 l2x0_size;static unsigned long sync_reg_offset =L2X0_CACHE_SYNC ; -/* Aurora don't have the cache ID register available, so we have to -* pass it though the device tree */ -static u32 cache_id_part_number_from_dt; -struct l2x0_regs l2x0_saved_regs; -static bool of_init = false; -/* * Common code for all cache controllers. */
@@ -343,20 +337,26 @@ static void l2x0_unlock(u32 cache_id)l2c_unlock (l2x0_base, lockregs); } -void __init l2x0_init (void __iomem *base,u32 aux_val,u32 aux_mask) +static const struct l2c_init_data l2x0_init_fns__initconst = { + .outer_cache = { + .inv_range = l2x0_inv_range, + .clean_range = l2x0_clean_range, + .flush_range = l2x0_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + }, +}; + +static void __init __l2c_init (const struct l2c_init_data *data, +u32 aux_val,u32 aux_mask,u32 cache_id) {u32 aux; -u32 cache_id;u32 way_size =0 ;int ways;int way_size_shift =L2X0_WAY_SIZE_SHIFT ;const char *type; - l2x0_base = base; -if (cache_id_part_number_from_dt) - cache_id = cache_id_part_number_from_dt; -else - cache_id =readl_relaxed (l2x0_base +L2X0_CACHE_ID ); aux =readl_relaxed (l2x0_base +L2X0_AUX_CTRL ); aux &= aux_mask;
@@ -374,8 +374,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)/* Unmapped register. */ sync_reg_offset =L2X0_DUMMY_REG ;#endif -if ((cache_id &L2X0_CACHE_ID_RTL_MASK ) <=L310_CACHE_ID_RTL_R3P0 ) - outer_cache.set_debug = pl310_set_debug;break ;case L2X0_CACHE_ID_PART_L210 : ways = (aux >>13 ) &0xf ;
@@ -430,23 +428,35 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)/* Save the value for resuming. */ l2x0_saved_regs.aux_ctrl = aux; -if (!of_init) { - outer_cache.inv_range = l2x0_inv_range; - outer_cache.clean_range = l2x0_clean_range; - outer_cache.flush_range = l2x0_flush_range; - outer_cache.sync = l2x0_cache_sync; - outer_cache.flush_all = l2x0_flush_all; - outer_cache.disable = l2x0_disable; - } + outer_cache = data->outer_cache; + +if ((cache_id &L2X0_CACHE_ID_PART_MASK ) ==L2X0_CACHE_ID_PART_L310 && + (cache_id &L2X0_CACHE_ID_RTL_MASK ) <=L310_CACHE_ID_RTL_R3P0 ) + outer_cache.set_debug = pl310_set_debug;pr_info ("%s cache controller enabled\n" , type);pr_info ("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n" , ways, cache_id, aux, l2x0_size >>10 ); } +void __init l2x0_init (void __iomem *base,u32 aux_val,u32 aux_mask) +{ +u32 cache_id; + + l2x0_base = base; + + cache_id =readl_relaxed (base +L2X0_CACHE_ID ); + +__l2c_init (&l2x0_init_fns, aux_val, aux_mask, cache_id); +} +#ifdef CONFIG_OF static int l2_wt_override; +/* Aurora don't have the cache ID register available, so we have to +* pass it though the device tree */ +static u32 cache_id_part_number_from_dt; +/* * Note that the end addresses passed to Linux primitives are * noninclusive, while the hardware cache range operations use
@@ -985,6 +995,7 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)const struct l2c_init_data *data;struct device_node *np;struct resource res; +u32 cache_id; np =of_find_matching_node (NULL , l2x0_ids);if (!np)
@@ -1015,9 +1026,12 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)if (data->save) data->save (); - of_init = true; -memcpy (&outer_cache, &data->outer_cache,sizeof (outer_cache)); -l2x0_init (l2x0_base, aux_val, aux_mask); +if (cache_id_part_number_from_dt) + cache_id = cache_id_part_number_from_dt; +else + cache_id =readl_relaxed (l2x0_base +L2X0_CACHE_ID ); + +__l2c_init (data, aux_val, aux_mask, cache_id);return 0 ; }
Signature · 1 line
1.8.3.1
PATCH 17/222 ARM: l2c: pass iomem address into data->save function
In reply to Russell King - ARM LinuxPass the iomem address into this function so we don't have to keep accessing it from a global.
--- arch/arm/mm/cache-l2x0.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
arch/arm/mm/cache-l2x0.c +16 -16
@@ -30,7 +30,7 @@struct l2c_init_data {void (*of_parse)(const struct device_node *,u32 *,u32 *); -void (*save)(void ); +void (*save)(void __iomem *);struct outer_cache_fns outer_cache; };
@@ -764,47 +764,47 @@ static void __init pl310_of_parse(const struct device_node *np, } } -static void __init pl310_save (void ) +static void __init pl310_save (void __iomem *base) { -u32 l2x0_revision =readl_relaxed (l2x0_base +L2X0_CACHE_ID ) & +u32 l2x0_revision =readl_relaxed (base +L2X0_CACHE_ID ) &L2X0_CACHE_ID_RTL_MASK ; - l2x0_saved_regs.tag_latency =readl_relaxed (l2x0_base + + l2x0_saved_regs.tag_latency =readl_relaxed (base +L2X0_TAG_LATENCY_CTRL ); - l2x0_saved_regs.data_latency =readl_relaxed (l2x0_base + + l2x0_saved_regs.data_latency =readl_relaxed (base +L2X0_DATA_LATENCY_CTRL ); - l2x0_saved_regs.filter_end =readl_relaxed (l2x0_base + + l2x0_saved_regs.filter_end =readl_relaxed (base +L2X0_ADDR_FILTER_END ); - l2x0_saved_regs.filter_start =readl_relaxed (l2x0_base + + l2x0_saved_regs.filter_start =readl_relaxed (base +L2X0_ADDR_FILTER_START );if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) {/* * From r2p0, there is Prefetch offset/control register */ - l2x0_saved_regs.prefetch_ctrl =readl_relaxed (l2x0_base + + l2x0_saved_regs.prefetch_ctrl =readl_relaxed (base +L2X0_PREFETCH_CTRL );/* * From r3p0, there is Power control register */ if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) - l2x0_saved_regs.pwr_ctrl =readl_relaxed (l2x0_base + + l2x0_saved_regs.pwr_ctrl =readl_relaxed (base +L2X0_POWER_CTRL ); } } -static void aurora_save (void ) +static void aurora_save (void __iomem *base) { - l2x0_saved_regs.ctrl =readl_relaxed (l2x0_base +L2X0_CTRL ); - l2x0_saved_regs.aux_ctrl =readl_relaxed (l2x0_base +L2X0_AUX_CTRL ); + l2x0_saved_regs.ctrl =readl_relaxed (base +L2X0_CTRL ); + l2x0_saved_regs.aux_ctrl =readl_relaxed (base +L2X0_AUX_CTRL ); } -static void __init tauros3_save (void ) +static void __init tauros3_save (void __iomem *base) { l2x0_saved_regs.aux2_ctrl = -readl_relaxed (l2x0_base +TAUROS3_AUX2_CTRL ); +readl_relaxed (base +TAUROS3_AUX2_CTRL ); l2x0_saved_regs.prefetch_ctrl = -readl_relaxed (l2x0_base +L2X0_PREFETCH_CTRL ); +readl_relaxed (base +L2X0_PREFETCH_CTRL ); }static void l2x0_resume (void )
@@ -1024,7 +1024,7 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) }if (data->save) - data->save (); + data->save (l2x0_base);if (cache_id_part_number_from_dt) cache_id = cache_id_part_number_from_dt;
Signature · 1 line
1.8.3.1
PATCH 18/222 ARM: l2c: move l2c save function to __l2c_init()
In reply to Russell King - ARM LinuxThere's no reason this functionality should be specific to DT, so move it into the common initialisation function.
--- arch/arm/mm/cache-l2x0.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
arch/arm/mm/cache-l2x0.c +7 -3
@@ -357,6 +357,13 @@ static void __init __l2c_init(const struct l2c_init_data *data,int way_size_shift =L2X0_WAY_SIZE_SHIFT ;const char *type; +/* +* It is strange to save the register state before initialisation, +* but hey, this is what the DT implementations decided to do. +*/ +if (data->save) + data->save (l2x0_base); + aux =readl_relaxed (l2x0_base +L2X0_AUX_CTRL ); aux &= aux_mask;
@@ -1023,9 +1030,6 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)aurora_broadcast_l2_commands (); } -if (data->save) - data->save (l2x0_base); -if (cache_id_part_number_from_dt) cache_id = cache_id_part_number_from_dt;else
Signature · 1 line
1.8.3.1
PATCH 19/222 ARM: l2c: group implementation specific code together
In reply to Russell King - ARM LinuxBack in the mists of time, someone decided that it would be a good idea to group like functions together - so all the save functions in one place, all the resume functions in another, all the OF parsing functions some place else.
This makes it difficult to get an overview on what a particular implementation is doing - grouping an implementations specific functions together makes more sense, because you can see what it's doing without the clutter of other implementations.
Organise it according to implementation.
--- arch/arm/mm/cache-l2x0.c | 502 +++++++++++++++++++++++------------------------ 1 file changed, 251 insertions(+), 251 deletions(-)
arch/arm/mm/cache-l2x0.c +251 -251
@@ -464,6 +464,175 @@ static int l2_wt_override;* pass it though the device tree */ static u32 cache_id_part_number_from_dt; +static void __init l2x0_of_parse (const struct device_node *np, +u32 *aux_val,u32 *aux_mask) +{ +u32 data[2 ] = {0 ,0 }; +u32 tag =0 ; +u32 dirty =0 ; +u32 val =0 , mask =0 ; + +of_property_read_u32 (np,"arm,tag-latency" , &tag); +if (tag) { + mask |=L2X0_AUX_CTRL_TAG_LATENCY_MASK ; + val |= (tag -1 ) <<L2X0_AUX_CTRL_TAG_LATENCY_SHIFT ; + } + +of_property_read_u32_array (np,"arm,data-latency" , + data,ARRAY_SIZE (data)); +if (data[0 ] && data[1 ]) { + mask |=L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK | +L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK ; + val |= ((data[0 ] -1 ) <<L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT ) | + ((data[1 ] -1 ) <<L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT ); + } + +of_property_read_u32 (np,"arm,dirty-latency" , &dirty); +if (dirty) { + mask |=L2X0_AUX_CTRL_DIRTY_LATENCY_MASK ; + val |= (dirty -1 ) <<L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT ; + } + + *aux_val &= ~mask; + *aux_val |= val; + *aux_mask &= ~mask; +} + +static void l2x0_resume (void ) +{ +if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +/* restore aux ctrl and enable l2 */ +l2x0_unlock (readl_relaxed (l2x0_base +L2X0_CACHE_ID )); + +writel_relaxed (l2x0_saved_regs.aux_ctrl, l2x0_base + +L2X0_AUX_CTRL ); + +l2x0_inv_all (); + +writel_relaxed (L2X0_CTRL_EN , l2x0_base +L2X0_CTRL ); + } +} + +static const struct l2c_init_data of_l2x0_data__initconst = { + .of_parse = l2x0_of_parse, + .outer_cache = { + .inv_range = l2x0_inv_range, + .clean_range = l2x0_clean_range, + .flush_range = l2x0_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = l2x0_resume, + }, +}; + +static void __init pl310_of_parse (const struct device_node *np, +u32 *aux_val,u32 *aux_mask) +{ +u32 data[3 ] = {0 ,0 ,0 }; +u32 tag[3 ] = {0 ,0 ,0 }; +u32 filter[2 ] = {0 ,0 }; + +of_property_read_u32_array (np,"arm,tag-latency" , tag,ARRAY_SIZE (tag)); +if (tag[0 ] && tag[1 ] && tag[2 ]) +writel_relaxed ( + ((tag[0 ] -1 ) <<L2X0_LATENCY_CTRL_RD_SHIFT ) | + ((tag[1 ] -1 ) <<L2X0_LATENCY_CTRL_WR_SHIFT ) | + ((tag[2 ] -1 ) <<L2X0_LATENCY_CTRL_SETUP_SHIFT ), + l2x0_base +L2X0_TAG_LATENCY_CTRL ); + +of_property_read_u32_array (np,"arm,data-latency" , + data,ARRAY_SIZE (data)); +if (data[0 ] && data[1 ] && data[2 ]) +writel_relaxed ( + ((data[0 ] -1 ) <<L2X0_LATENCY_CTRL_RD_SHIFT ) | + ((data[1 ] -1 ) <<L2X0_LATENCY_CTRL_WR_SHIFT ) | + ((data[2 ] -1 ) <<L2X0_LATENCY_CTRL_SETUP_SHIFT ), + l2x0_base +L2X0_DATA_LATENCY_CTRL ); + +of_property_read_u32_array (np,"arm,filter-ranges" , + filter,ARRAY_SIZE (filter)); +if (filter[1 ]) { +writel_relaxed (ALIGN (filter[0 ] + filter[1 ],SZ_1M ), + l2x0_base +L2X0_ADDR_FILTER_END ); +writel_relaxed ((filter[0 ] & ~(SZ_1M -1 )) |L2X0_ADDR_FILTER_EN , + l2x0_base +L2X0_ADDR_FILTER_START ); + } +} + +static void __init pl310_save (void __iomem *base) +{ +u32 l2x0_revision =readl_relaxed (base +L2X0_CACHE_ID ) & +L2X0_CACHE_ID_RTL_MASK ; + + l2x0_saved_regs.tag_latency =readl_relaxed (base + +L2X0_TAG_LATENCY_CTRL ); + l2x0_saved_regs.data_latency =readl_relaxed (base + +L2X0_DATA_LATENCY_CTRL ); + l2x0_saved_regs.filter_end =readl_relaxed (base + +L2X0_ADDR_FILTER_END ); + l2x0_saved_regs.filter_start =readl_relaxed (base + +L2X0_ADDR_FILTER_START ); + +if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { +/* +* From r2p0, there is Prefetch offset/control register +*/ + l2x0_saved_regs.prefetch_ctrl =readl_relaxed (base + +L2X0_PREFETCH_CTRL ); +/* +* From r3p0, there is Power control register +*/ +if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) + l2x0_saved_regs.pwr_ctrl =readl_relaxed (base + +L2X0_POWER_CTRL ); + } +} + +static void pl310_resume (void ) +{ +u32 l2x0_revision; + +if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +/* restore pl310 setup */ +writel_relaxed (l2x0_saved_regs.tag_latency, + l2x0_base +L2X0_TAG_LATENCY_CTRL ); +writel_relaxed (l2x0_saved_regs.data_latency, + l2x0_base +L2X0_DATA_LATENCY_CTRL ); +writel_relaxed (l2x0_saved_regs.filter_end, + l2x0_base +L2X0_ADDR_FILTER_END ); +writel_relaxed (l2x0_saved_regs.filter_start, + l2x0_base +L2X0_ADDR_FILTER_START ); + + l2x0_revision =readl_relaxed (l2x0_base +L2X0_CACHE_ID ) & +L2X0_CACHE_ID_RTL_MASK ; + +if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { +writel_relaxed (l2x0_saved_regs.prefetch_ctrl, + l2x0_base +L2X0_PREFETCH_CTRL ); +if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) +writel_relaxed (l2x0_saved_regs.pwr_ctrl, + l2x0_base +L2X0_POWER_CTRL ); + } + } + +l2x0_resume (); +} + +static const struct l2c_init_data of_pl310_data__initconst = { + .of_parse = pl310_of_parse, + .save = pl310_save, + .outer_cache = { + .inv_range = l2x0_inv_range, + .clean_range = l2x0_clean_range, + .flush_range = l2x0_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = pl310_resume, + }, +}; +/* * Note that the end addresses passed to Linux primitives are * noninclusive, while the hardware cache range operations use
@@ -562,6 +731,75 @@ static void aurora_flush_range(unsigned long start, unsigned long end) } } +static void aurora_save (void __iomem *base) +{ + l2x0_saved_regs.ctrl =readl_relaxed (base +L2X0_CTRL ); + l2x0_saved_regs.aux_ctrl =readl_relaxed (base +L2X0_AUX_CTRL ); +} + +static void aurora_resume (void ) +{ +if (!(readl (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +writel_relaxed (l2x0_saved_regs.aux_ctrl, + l2x0_base +L2X0_AUX_CTRL ); +writel_relaxed (l2x0_saved_regs.ctrl, l2x0_base +L2X0_CTRL ); + } +} + +static void __init aurora_broadcast_l2_commands (void ) +{ +__u32 u; +/* Enable Broadcasting of cache commands to L2*/ + __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" :"=r" (u)); + u |=AURORA_CTRL_FW ;/* Set the FW bit */ + __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : :"r" (u)); +isb (); +} + +static void __init aurora_of_parse (const struct device_node *np, +u32 *aux_val,u32 *aux_mask) +{ +u32 val =AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU ; +u32 mask =AURORA_ACR_REPLACEMENT_MASK ; + +of_property_read_u32 (np,"cache-id-part" , + &cache_id_part_number_from_dt); + +/* Determine and save the write policy */ + l2_wt_override =of_property_read_bool (np,"wt-override" ); + +if (l2_wt_override) { + val |=AURORA_ACR_FORCE_WRITE_THRO_POLICY ; + mask |=AURORA_ACR_FORCE_WRITE_POLICY_MASK ; + } + + *aux_val &= ~mask; + *aux_val |= val; + *aux_mask &= ~mask; +} + +static const struct l2c_init_data of_aurora_with_outer_data__initconst = { + .of_parse = aurora_of_parse, + .save = aurora_save, + .outer_cache = { + .inv_range = aurora_inv_range, + .clean_range = aurora_clean_range, + .flush_range = aurora_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = aurora_resume, + }, +}; + +static const struct l2c_init_data of_aurora_no_outer_data__initconst = { + .of_parse = aurora_of_parse, + .save = aurora_save, + .outer_cache = { + .resume = aurora_resume, + }, +}; +/* * For certain Broadcom SoCs, depending on the address range, different offsets * need to be added to the address before passing it to L2 for
@@ -703,108 +941,19 @@ static void bcm_flush_range(unsigned long start, unsigned long end) new_end); } -static void __init l2x0_of_parse (const struct device_node *np, -u32 *aux_val,u32 *aux_mask) -{ -u32 data[2 ] = {0 ,0 }; -u32 tag =0 ; -u32 dirty =0 ; -u32 val =0 , mask =0 ; - -of_property_read_u32 (np,"arm,tag-latency" , &tag); -if (tag) { - mask |=L2X0_AUX_CTRL_TAG_LATENCY_MASK ; - val |= (tag -1 ) <<L2X0_AUX_CTRL_TAG_LATENCY_SHIFT ; - } - -of_property_read_u32_array (np,"arm,data-latency" , - data,ARRAY_SIZE (data)); -if (data[0 ] && data[1 ]) { - mask |=L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK | -L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK ; - val |= ((data[0 ] -1 ) <<L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT ) | - ((data[1 ] -1 ) <<L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT ); - } - -of_property_read_u32 (np,"arm,dirty-latency" , &dirty); -if (dirty) { - mask |=L2X0_AUX_CTRL_DIRTY_LATENCY_MASK ; - val |= (dirty -1 ) <<L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT ; - } - - *aux_val &= ~mask; - *aux_val |= val; - *aux_mask &= ~mask; -} - -static void __init pl310_of_parse (const struct device_node *np, -u32 *aux_val,u32 *aux_mask) -{ -u32 data[3 ] = {0 ,0 ,0 }; -u32 tag[3 ] = {0 ,0 ,0 }; -u32 filter[2 ] = {0 ,0 }; - -of_property_read_u32_array (np,"arm,tag-latency" , tag,ARRAY_SIZE (tag)); -if (tag[0 ] && tag[1 ] && tag[2 ]) -writel_relaxed ( - ((tag[0 ] -1 ) <<L2X0_LATENCY_CTRL_RD_SHIFT ) | - ((tag[1 ] -1 ) <<L2X0_LATENCY_CTRL_WR_SHIFT ) | - ((tag[2 ] -1 ) <<L2X0_LATENCY_CTRL_SETUP_SHIFT ), - l2x0_base +L2X0_TAG_LATENCY_CTRL ); - -of_property_read_u32_array (np,"arm,data-latency" , - data,ARRAY_SIZE (data)); -if (data[0 ] && data[1 ] && data[2 ]) -writel_relaxed ( - ((data[0 ] -1 ) <<L2X0_LATENCY_CTRL_RD_SHIFT ) | - ((data[1 ] -1 ) <<L2X0_LATENCY_CTRL_WR_SHIFT ) | - ((data[2 ] -1 ) <<L2X0_LATENCY_CTRL_SETUP_SHIFT ), - l2x0_base +L2X0_DATA_LATENCY_CTRL ); - -of_property_read_u32_array (np,"arm,filter-ranges" , - filter,ARRAY_SIZE (filter)); -if (filter[1 ]) { -writel_relaxed (ALIGN (filter[0 ] + filter[1 ],SZ_1M ), - l2x0_base +L2X0_ADDR_FILTER_END ); -writel_relaxed ((filter[0 ] & ~(SZ_1M -1 )) |L2X0_ADDR_FILTER_EN , - l2x0_base +L2X0_ADDR_FILTER_START ); - } -} - -static void __init pl310_save (void __iomem *base) -{ -u32 l2x0_revision =readl_relaxed (base +L2X0_CACHE_ID ) & -L2X0_CACHE_ID_RTL_MASK ; - - l2x0_saved_regs.tag_latency =readl_relaxed (base + -L2X0_TAG_LATENCY_CTRL ); - l2x0_saved_regs.data_latency =readl_relaxed (base + -L2X0_DATA_LATENCY_CTRL ); - l2x0_saved_regs.filter_end =readl_relaxed (base + -L2X0_ADDR_FILTER_END ); - l2x0_saved_regs.filter_start =readl_relaxed (base + -L2X0_ADDR_FILTER_START ); - -if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { -/* -* From r2p0, there is Prefetch offset/control register -*/ - l2x0_saved_regs.prefetch_ctrl =readl_relaxed (base + -L2X0_PREFETCH_CTRL ); -/* -* From r3p0, there is Power control register -*/ -if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) - l2x0_saved_regs.pwr_ctrl =readl_relaxed (base + -L2X0_POWER_CTRL ); - } -} - -static void aurora_save (void __iomem *base) -{ - l2x0_saved_regs.ctrl =readl_relaxed (base +L2X0_CTRL ); - l2x0_saved_regs.aux_ctrl =readl_relaxed (base +L2X0_AUX_CTRL ); -} +static const struct l2c_init_data of_bcm_l2x0_data__initconst = { + .of_parse = pl310_of_parse, + .save = pl310_save, + .outer_cache = { + .inv_range = bcm_inv_range, + .clean_range = bcm_clean_range, + .flush_range = bcm_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = pl310_resume, + }, +};static void __init tauros3_save (void __iomem *base) {
@@ -814,60 +963,6 @@ static void __init tauros3_save(void __iomem *base)readl_relaxed (base +L2X0_PREFETCH_CTRL ); } -static void l2x0_resume (void ) -{ -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -/* restore aux ctrl and enable l2 */ -l2x0_unlock (readl_relaxed (l2x0_base +L2X0_CACHE_ID )); - -writel_relaxed (l2x0_saved_regs.aux_ctrl, l2x0_base + -L2X0_AUX_CTRL ); - -l2x0_inv_all (); - -writel_relaxed (L2X0_CTRL_EN , l2x0_base +L2X0_CTRL ); - } -} - -static void pl310_resume (void ) -{ -u32 l2x0_revision; - -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -/* restore pl310 setup */ -writel_relaxed (l2x0_saved_regs.tag_latency, - l2x0_base +L2X0_TAG_LATENCY_CTRL ); -writel_relaxed (l2x0_saved_regs.data_latency, - l2x0_base +L2X0_DATA_LATENCY_CTRL ); -writel_relaxed (l2x0_saved_regs.filter_end, - l2x0_base +L2X0_ADDR_FILTER_END ); -writel_relaxed (l2x0_saved_regs.filter_start, - l2x0_base +L2X0_ADDR_FILTER_START ); - - l2x0_revision =readl_relaxed (l2x0_base +L2X0_CACHE_ID ) & -L2X0_CACHE_ID_RTL_MASK ; - -if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { -writel_relaxed (l2x0_saved_regs.prefetch_ctrl, - l2x0_base +L2X0_PREFETCH_CTRL ); -if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) -writel_relaxed (l2x0_saved_regs.pwr_ctrl, - l2x0_base +L2X0_POWER_CTRL ); - } - } - -l2x0_resume (); -} - -static void aurora_resume (void ) -{ -if (!(readl (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -writel_relaxed (l2x0_saved_regs.aux_ctrl, - l2x0_base +L2X0_AUX_CTRL ); -writel_relaxed (l2x0_saved_regs.ctrl, l2x0_base +L2X0_CTRL ); - } -} -static void tauros3_resume (void ) {if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) {
@@ -880,87 +975,6 @@ static void tauros3_resume(void)l2x0_resume (); } -static void __init aurora_broadcast_l2_commands (void ) -{ -__u32 u; -/* Enable Broadcasting of cache commands to L2*/ - __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" :"=r" (u)); - u |=AURORA_CTRL_FW ;/* Set the FW bit */ - __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : :"r" (u)); -isb (); -} - -static void __init aurora_of_parse (const struct device_node *np, -u32 *aux_val,u32 *aux_mask) -{ -u32 val =AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU ; -u32 mask =AURORA_ACR_REPLACEMENT_MASK ; - -of_property_read_u32 (np,"cache-id-part" , - &cache_id_part_number_from_dt); - -/* Determine and save the write policy */ - l2_wt_override =of_property_read_bool (np,"wt-override" ); - -if (l2_wt_override) { - val |=AURORA_ACR_FORCE_WRITE_THRO_POLICY ; - mask |=AURORA_ACR_FORCE_WRITE_POLICY_MASK ; - } - - *aux_val &= ~mask; - *aux_val |= val; - *aux_mask &= ~mask; -} - -static const struct l2c_init_data of_pl310_data__initconst = { - .of_parse = pl310_of_parse, - .save = pl310_save, - .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = pl310_resume, - }, -}; - -static const struct l2c_init_data of_l2x0_data__initconst = { - .of_parse = l2x0_of_parse, - .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = l2x0_resume, - }, -}; - -static const struct l2c_init_data of_aurora_with_outer_data__initconst = { - .of_parse = aurora_of_parse, - .save = aurora_save, - .outer_cache = { - .inv_range = aurora_inv_range, - .clean_range = aurora_clean_range, - .flush_range = aurora_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = aurora_resume, - }, -}; - -static const struct l2c_init_data of_aurora_no_outer_data__initconst = { - .of_parse = aurora_of_parse, - .save = aurora_save, - .outer_cache = { - .resume = aurora_resume, - }, -}; -static const struct l2c_init_data of_tauros3_data__initconst = { .save = tauros3_save,/* Tauros3 broadcasts L1 cache operations to L2 */
@@ -969,20 +983,6 @@ static const struct l2c_init_data of_tauros3_data __initconst = { }, }; -static const struct l2c_init_data of_bcm_l2x0_data__initconst = { - .of_parse = pl310_of_parse, - .save = pl310_save, - .outer_cache = { - .inv_range = bcm_inv_range, - .clean_range = bcm_clean_range, - .flush_range = bcm_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = pl310_resume, - }, -}; -#define L2C_ID (name, fns) { .compatible = name, .data = (void *)&fns }static const struct of_device_id l2x0_ids[]__initconst = {L2C_ID ("arm,l210-cache" , of_l2x0_data),
Signature · 1 line
1.8.3.1
PATCH 20/222 ARM: l2c: provide enable method
In reply to Russell King - ARM LinuxProviding an enable method gives L2 cache controllers a chance to do special handling at enable time. This allows us to remove a hack in l2x0_unlock() for Marvell Aurora L2 caches.
--- arch/arm/mm/cache-l2x0.c | 80 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 18 deletions(-)
arch/arm/mm/cache-l2x0.c +62 -18
@@ -29,7 +29,9 @@#include "cache-aurora-l2.h" struct l2c_init_data { +unsigned num_lock;void (*of_parse)(const struct device_node *,u32 *,u32 *); +void (*enable)(void __iomem *,u32 ,unsigned );void (*save)(void __iomem *);struct outer_cache_fns outer_cache; };
@@ -82,6 +84,36 @@ static inline void l2c_unlock(void __iomem *base, unsigned num) } } +/* +* Enable the L2 cache controller. This function must only be +* called when the cache controller is known to be disabled. +*/ +static void l2c_enable (void __iomem *base,u32 aux,unsigned num_lock) +{ +unsigned long flags; + +l2c_unlock (base, num_lock); + +writel_relaxed (aux, base +L2X0_AUX_CTRL ); + +local_irq_save (flags); +__l2c_op_way (base +L2X0_INV_WAY ); +writel_relaxed (0 , base + sync_reg_offset); +l2c_wait_mask (base + sync_reg_offset,1 ); +local_irq_restore (flags); + +writel_relaxed (L2X0_CTRL_EN , base +L2X0_CTRL ); +} + +static void l2c_disable (void ) +{ +void __iomem *base = l2x0_base; + + outer_cache.flush_all (); +writel_relaxed (0 , base +L2X0_CTRL ); +dsb (st); +} +#ifdef CONFIG_CACHE_PL310 static inline void cache_wait (void __iomem *reg,unsigned long mask) {
@@ -325,9 +357,6 @@ static void l2x0_unlock(u32 cache_id)case L2X0_CACHE_ID_PART_L310 : lockregs =8 ;break ; -case AURORA_CACHE_ID : - lockregs =4 ; -break ;default :/* L210 and unknown types */ lockregs =1 ;
@@ -337,7 +366,22 @@ static void l2x0_unlock(u32 cache_id)l2c_unlock (l2x0_base, lockregs); } +static void l2x0_enable (void __iomem *base,u32 aux,unsigned num_lock) +{ +/* Make sure that I&D is not locked down when starting */ +l2x0_unlock (readl_relaxed (base +L2X0_CACHE_ID )); + +/* l2x0 controller is disabled */ +writel_relaxed (aux, base +L2X0_AUX_CTRL ); + +l2x0_inv_all (); + +/* enable L2X0 */ +writel_relaxed (L2X0_CTRL_EN , base +L2X0_CTRL ); +} +static const struct l2c_init_data l2x0_init_fns__initconst = { + .enable = l2x0_enable, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range,
@@ -412,22 +456,11 @@ static void __init __l2c_init(const struct l2c_init_data *data, l2x0_size = ways * way_size *SZ_1K ;/* -* Check if l2x0 controller is already enabled. -* If you are booting from non-secure mode -* accessing the below registers will fault. +* Check if l2x0 controller is already enabled. If we are booting +* in non-secure mode accessing the below registers will fault. */ -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -/* Make sure that I&D is not locked down when starting */ -l2x0_unlock (cache_id); - -/* l2x0 controller is disabled */ -writel_relaxed (aux, l2x0_base +L2X0_AUX_CTRL ); - -l2x0_inv_all (); - -/* enable L2X0 */ -writel_relaxed (L2X0_CTRL_EN , l2x0_base +L2X0_CTRL ); - } +if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) + data->enable (l2x0_base, aux, data->num_lock);/* Re-read it in case some bits are reserved. */ aux =readl_relaxed (l2x0_base +L2X0_AUX_CTRL );
@@ -515,6 +548,7 @@ static void l2x0_resume(void)static const struct l2c_init_data of_l2x0_data__initconst = { .of_parse = l2x0_of_parse, + .enable = l2x0_enable, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range,
@@ -620,7 +654,9 @@ static void pl310_resume(void) }static const struct l2c_init_data of_pl310_data__initconst = { + .num_lock =8 , .of_parse = pl310_of_parse, + .enable = l2c_enable, .save = pl310_save, .outer_cache = { .inv_range = l2x0_inv_range,
@@ -779,7 +815,9 @@ static void __init aurora_of_parse(const struct device_node *np, }static const struct l2c_init_data of_aurora_with_outer_data__initconst = { + .num_lock =4 , .of_parse = aurora_of_parse, + .enable = l2c_enable, .save = aurora_save, .outer_cache = { .inv_range = aurora_inv_range,
@@ -793,7 +831,9 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { };static const struct l2c_init_data of_aurora_no_outer_data__initconst = { + .num_lock =4 , .of_parse = aurora_of_parse, + .enable = l2c_enable, .save = aurora_save, .outer_cache = { .resume = aurora_resume,
@@ -942,7 +982,9 @@ static void bcm_flush_range(unsigned long start, unsigned long end) }static const struct l2c_init_data of_bcm_l2x0_data__initconst = { + .num_lock =8 , .of_parse = pl310_of_parse, + .enable = l2c_enable, .save = pl310_save, .outer_cache = { .inv_range = bcm_inv_range,
@@ -976,6 +1018,8 @@ static void tauros3_resume(void) }static const struct l2c_init_data of_tauros3_data__initconst = { + .num_lock =8 , + .enable = l2c_enable, .save = tauros3_save,/* Tauros3 broadcasts L1 cache operations to L2 */ .outer_cache = {
Signature · 1 line
1.8.3.1
PATCH 21/222 ARM: l2c: write auxctrl register before unlocking
In reply to Russell King - ARM LinuxWe should write the auxillary control register before unlocking: the write may be necessary to enable non-secure access to the lock registers.
--- arch/arm/mm/cache-l2x0.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
arch/arm/mm/cache-l2x0.c +5 -5
@@ -92,10 +92,10 @@ static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) {unsigned long flags; -l2c_unlock (base, num_lock); -writel_relaxed (aux, base +L2X0_AUX_CTRL ); +l2c_unlock (base, num_lock); +local_irq_save (flags);__l2c_op_way (base +L2X0_INV_WAY );writel_relaxed (0 , base + sync_reg_offset);
@@ -368,12 +368,12 @@ static void l2x0_unlock(u32 cache_id)static void l2x0_enable (void __iomem *base,u32 aux,unsigned num_lock) { -/* Make sure that I&D is not locked down when starting */ -l2x0_unlock (readl_relaxed (base +L2X0_CACHE_ID )); -/* l2x0 controller is disabled */ writel_relaxed (aux, base +L2X0_AUX_CTRL ); +/* Make sure that I&D is not locked down when starting */ +l2x0_unlock (readl_relaxed (base +L2X0_CACHE_ID )); +l2x0_inv_all ();/* enable L2X0 */
Signature · 1 line
1.8.3.1
PATCH 22/222 ARM: l2c: only write the auxiliary control register if required
In reply to Russell King - ARM LinuxAvoid unnecessary writes to the auxiliary control register if the register already contains the required value. This allows us to avoid invoking the platforms secure monitor code unnecessarily.
--- arch/arm/mm/cache-l2x0.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm/mm/cache-l2x0.c +3 -1
@@ -92,7 +92,9 @@ static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) {unsigned long flags; -writel_relaxed (aux, base +L2X0_AUX_CTRL ); +/* Only write the aux register if it needs changing */ +if (readl_relaxed (base +L2X0_AUX_CTRL ) != aux) +writel_relaxed (aux, base +L2X0_AUX_CTRL );l2c_unlock (base, num_lock);
Signature · 1 line
1.8.3.1
PATCH 23/222 ARM: l2c: move aurora broadcast setup to enable function
In reply to Russell King - ARM LinuxRather than having this hacked into the OF initialiation function, we can handle this via the enable function instead. While here, clean up that code and comments a little.
--- arch/arm/mm/cache-l2x0.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
arch/arm/mm/cache-l2x0.c +15 -13
@@ -784,14 +784,22 @@ static void aurora_resume(void) } } -static void __init aurora_broadcast_l2_commands (void ) +/* +* For Aurora cache in no outer mode, enable via the CP15 coprocessor +* broadcasting of cache commands to L2. +*/ +static void __init aurora_enable_no_outer (void __iomem *base,u32 aux, +unsigned num_lock) { -__u32 u; -/* Enable Broadcasting of cache commands to L2*/ - __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" :"=r" (u)); +u32 u; + + asmvolatile ("mrc p15, 1, %0, c15, c2, 0" :"=r" (u)); u |=AURORA_CTRL_FW ;/* Set the FW bit */ - __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : :"r" (u)); + asmvolatile ("mcr p15, 1, %0, c15, c2, 0" : :"r" (u)); +isb (); + +l2c_enable (base, aux, num_lock); } static void __init aurora_of_parse(const struct device_node *np,
@@ -835,7 +843,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = {static const struct l2c_init_data of_aurora_no_outer_data__initconst = { .num_lock =4 , .of_parse = aurora_of_parse, - .enable = l2c_enable, + .enable = aurora_enable_no_outer, .save = aurora_save, .outer_cache = { .resume = aurora_resume,
@@ -1066,16 +1074,10 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) data =of_match_node (l2x0_ids, np)->data;/* L2 configuration can only be changed if the cache is disabled */ -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN ))if (data->of_parse) data->of_parse (np, &aux_val, &aux_mask); -/* For aurora cache in no outer mode select the -* correct mode using the coprocessor*/ -if (data == &of_aurora_no_outer_data) -aurora_broadcast_l2_commands (); - } -if (cache_id_part_number_from_dt) cache_id = cache_id_part_number_from_dt;else
Signature · 1 line
1.8.3.1
PATCH 24/222 ARM: l2c: implement fixups for L2 cache controller quirks/errata
In reply to Russell King - ARM LinuxRather than putting quirk handling in __l2c_init(), move it out to a separate function which individual implementations can specify. This helps to localise the quirks to those implementations which require them.
--- arch/arm/mm/cache-l2x0.c | 112 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 11 deletions(-)
arch/arm/mm/cache-l2x0.c +101 -11
@@ -32,6 +32,7 @@ struct l2c_init_data {unsigned num_lock;void (*of_parse)(const struct device_node *,u32 *,u32 *);void (*enable)(void __iomem *,u32 ,unsigned ); +void (*fixup)(void __iomem *,u32 ,struct outer_cache_fns *);void (*save)(void __iomem *);struct outer_cache_fns outer_cache; };
@@ -394,9 +395,80 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { }, }; +/* +* L2C-310 specific code. +* +* Errata: +* 588369: PL310 R0P0->R1P0, fixed R2P0. +* Affects: all clean+invalidate operations +* clean and invalidate skips the invalidate step, so we need to issue +* separate operations. We also require the above debug workaround +* enclosing this code fragment on affected parts. On unaffected parts, +* we must not use this workaround without the debug register writes +* to avoid exposing a problem similar to 727915. +* +* 727915: PL310 R2P0->R3P0, fixed R3P1. +* Affects: clean+invalidate by way +* clean and invalidate by way runs in the background, and a store can +* hit the line between the clean operation and invalidate operation, +* resulting in the store being lost. +* +* 753970: PL310 R3P0, fixed R3P1. +* Affects: sync +* prevents merging writes after the sync operation, until another L2C +* operation is performed (or a number of other conditions.) +* +* 769419: PL310 R0P0->R3P1, fixed R3P2. +* Affects: store buffer +* store buffer is not automatically drained. +*/ +static void __init l2c310_fixup (void __iomem *base,u32 cache_id, +struct outer_cache_fns *fns) +{ +unsigned revision = cache_id &L2X0_CACHE_ID_RTL_MASK ; +const char *errata[4 ]; +unsigned n =0 ; + +if (revision <=L310_CACHE_ID_RTL_R3P0 ) + fns->set_debug = pl310_set_debug; + +if (IS_ENABLED (CONFIG_PL310_ERRATA_753970 ) && + revision ==L310_CACHE_ID_RTL_R3P0 ) { + sync_reg_offset =L2X0_DUMMY_REG ; + errata[n++] ="753970" ; + } + +if (IS_ENABLED (CONFIG_PL310_ERRATA_769419 )) + errata[n++] ="769419" ; + +if (n) { +unsigned i; + +pr_info ("L2C-310 errat%s" , n >1 ?"a" :"um" ); +for (i =0 ; i < n; i++) +pr_cont (" %s" , errata[i]); +pr_cont (" enabled\n" ); + } +} + +static const struct l2c_init_data l2c310_init_fns__initconst = { + .num_lock =8 , + .enable = l2c_enable, + .fixup = l2c310_fixup, + .outer_cache = { + .inv_range = l2x0_inv_range, + .clean_range = l2x0_clean_range, + .flush_range = l2x0_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + }, +}; +static void __init __l2c_init (const struct l2c_init_data *data,u32 aux_val,u32 aux_mask,u32 cache_id) { +struct outer_cache_fns fns;u32 aux;u32 way_size =0 ;int ways;
@@ -423,23 +495,20 @@ static void __init __l2c_init(const struct l2c_init_data *data,else ways =8 ; type ="L310" ; -#ifdef CONFIG_PL310_ERRATA_753970 -/* Unmapped register. */ - sync_reg_offset =L2X0_DUMMY_REG ; -#endif break ; +case L2X0_CACHE_ID_PART_L210 : ways = (aux >>13 ) &0xf ; type ="L210" ;break ;case AURORA_CACHE_ID : - sync_reg_offset =AURORA_SYNC_REG ; ways = (aux >>13 ) &0xf ; ways =2 << ((ways +1 ) >>2 ); way_size_shift =AURORA_WAY_SIZE_SHIFT ; type ="Aurora" ;break ; +default :/* Assume unknown chips have 8 ways */ ways =8 ;
@@ -457,6 +526,10 @@ static void __init __l2c_init(const struct l2c_init_data *data, l2x0_size = ways * way_size *SZ_1K ; + fns = data->outer_cache; +if (data->fixup) + data->fixup (l2x0_base, cache_id, &fns); +/* * Check if l2x0 controller is already enabled. If we are booting * in non-secure mode accessing the below registers will fault.
@@ -470,11 +543,7 @@ static void __init __l2c_init(const struct l2c_init_data *data,/* Save the value for resuming. */ l2x0_saved_regs.aux_ctrl = aux; - outer_cache = data->outer_cache; - -if ((cache_id &L2X0_CACHE_ID_PART_MASK ) ==L2X0_CACHE_ID_PART_L310 && - (cache_id &L2X0_CACHE_ID_RTL_MASK ) <=L310_CACHE_ID_RTL_R3P0 ) - outer_cache.set_debug = pl310_set_debug; + outer_cache = fns;pr_info ("%s cache controller enabled\n" , type); pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n",
@@ -483,13 +552,24 @@ static void __init __l2c_init(const struct l2c_init_data *data,void __init l2x0_init (void __iomem *base,u32 aux_val,u32 aux_mask) { +const struct l2c_init_data *data;u32 cache_id; l2x0_base = base; cache_id =readl_relaxed (base +L2X0_CACHE_ID ); -__l2c_init (&l2x0_init_fns, aux_val, aux_mask, cache_id); +switch (cache_id &L2X0_CACHE_ID_PART_MASK ) { +default : + data = &l2x0_init_fns; +break ; + +case L2X0_CACHE_ID_PART_L310 : + data = &l2c310_init_fns; +break ; + } + +__l2c_init (data, aux_val, aux_mask, cache_id); }#ifdef CONFIG_OF
@@ -659,6 +739,7 @@ static const struct l2c_init_data of_pl310_data __initconst = { .num_lock = 8, .of_parse = pl310_of_parse, .enable = l2c_enable, + .fixup = l2c310_fixup, .save = pl310_save, .outer_cache = { .inv_range = l2x0_inv_range,
@@ -802,6 +883,12 @@ static void __init aurora_enable_no_outer(void __iomem *base, u32 aux,l2c_enable (base, aux, num_lock); } +static void __init aurora_fixup (void __iomem *base,u32 cache_id, +struct outer_cache_fns *fns) +{ + sync_reg_offset =AURORA_SYNC_REG ; +} +static void __init aurora_of_parse (const struct device_node *np,u32 *aux_val,u32 *aux_mask) {
@@ -828,6 +915,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { .num_lock = 4, .of_parse = aurora_of_parse, .enable = l2c_enable, + .fixup = aurora_fixup, .save = aurora_save, .outer_cache = { .inv_range = aurora_inv_range,
@@ -844,6 +932,7 @@ static const struct l2c_init_data of_aurora_no_outer_data __initconst = { .num_lock = 4, .of_parse = aurora_of_parse, .enable = aurora_enable_no_outer, + .fixup = aurora_fixup, .save = aurora_save, .outer_cache = { .resume = aurora_resume,
@@ -995,6 +1084,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .num_lock = 8, .of_parse = pl310_of_parse, .enable = l2c_enable, + .fixup = l2c310_fixup, .save = pl310_save, .outer_cache = { .inv_range = bcm_inv_range,
Signature · 1 line
1.8.3.1
PATCH 25/222 ARM: l2c: clean up L2 cache initialisation messages
In reply to Russell King - ARM LinuxMake one of them purely "English", and the other purely technical.
--- arch/arm/mm/cache-l2x0.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
arch/arm/mm/cache-l2x0.c +4 -3
@@ -545,9 +545,10 @@ static void __init __l2c_init(const struct l2c_init_data *data, outer_cache = fns; -pr_info ("%s cache controller enabled\n" , type); -pr_info ("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n" , - ways, cache_id, aux, l2x0_size >>10 ); +pr_info ("%s cache controller enabled, %d ways, %d kB\n" , + type, ways, l2x0_size >>10 ); +pr_info ("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n" , + type, cache_id, aux); }void __init l2x0_init (void __iomem *base,u32 aux_val,u32 aux_mask)
Signature · 1 line
1.8.3.1
PATCH 26/222 ARM: l2c: move and add ARM L2C-2x0/L2C-310 save/resume code to non-OF
In reply to Russell King - ARM LinuxAdd the save/resume code hooks to the non-OF implementations as well. There's no reason for the non-OF implementations to be any different from the OF implementations.
--- arch/arm/mm/cache-l2x0.c | 151 ++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 74 deletions(-)
arch/arm/mm/cache-l2x0.c +77 -74
@@ -383,6 +383,21 @@ static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock)writel_relaxed (L2X0_CTRL_EN , base +L2X0_CTRL ); } +static void l2x0_resume (void ) +{ +if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +/* restore aux ctrl and enable l2 */ +l2x0_unlock (readl_relaxed (l2x0_base +L2X0_CACHE_ID )); + +writel_relaxed (l2x0_saved_regs.aux_ctrl, l2x0_base + +L2X0_AUX_CTRL ); + +l2x0_inv_all (); + +writel_relaxed (L2X0_CTRL_EN , l2x0_base +L2X0_CTRL ); + } +} +static const struct l2c_init_data l2x0_init_fns__initconst = { .enable = l2x0_enable, .outer_cache = {
@@ -392,6 +407,7 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, + .resume = l2x0_resume, }, };
@@ -422,6 +438,65 @@ static const struct l2c_init_data l2x0_init_fns __initconst = {* Affects: store buffer * store buffer is not automatically drained. */ +static void __init pl310_save (void __iomem *base) +{ +u32 l2x0_revision =readl_relaxed (base +L2X0_CACHE_ID ) & +L2X0_CACHE_ID_RTL_MASK ; + + l2x0_saved_regs.tag_latency =readl_relaxed (base + +L2X0_TAG_LATENCY_CTRL ); + l2x0_saved_regs.data_latency =readl_relaxed (base + +L2X0_DATA_LATENCY_CTRL ); + l2x0_saved_regs.filter_end =readl_relaxed (base + +L2X0_ADDR_FILTER_END ); + l2x0_saved_regs.filter_start =readl_relaxed (base + +L2X0_ADDR_FILTER_START ); + +if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { +/* +* From r2p0, there is Prefetch offset/control register +*/ + l2x0_saved_regs.prefetch_ctrl =readl_relaxed (base + +L2X0_PREFETCH_CTRL ); +/* +* From r3p0, there is Power control register +*/ +if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) + l2x0_saved_regs.pwr_ctrl =readl_relaxed (base + +L2X0_POWER_CTRL ); + } +} + +static void pl310_resume (void ) +{ +u32 l2x0_revision; + +if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +/* restore pl310 setup */ +writel_relaxed (l2x0_saved_regs.tag_latency, + l2x0_base +L2X0_TAG_LATENCY_CTRL ); +writel_relaxed (l2x0_saved_regs.data_latency, + l2x0_base +L2X0_DATA_LATENCY_CTRL ); +writel_relaxed (l2x0_saved_regs.filter_end, + l2x0_base +L2X0_ADDR_FILTER_END ); +writel_relaxed (l2x0_saved_regs.filter_start, + l2x0_base +L2X0_ADDR_FILTER_START ); + + l2x0_revision =readl_relaxed (l2x0_base +L2X0_CACHE_ID ) & +L2X0_CACHE_ID_RTL_MASK ; + +if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { +writel_relaxed (l2x0_saved_regs.prefetch_ctrl, + l2x0_base +L2X0_PREFETCH_CTRL ); +if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) +writel_relaxed (l2x0_saved_regs.pwr_ctrl, + l2x0_base +L2X0_POWER_CTRL ); + } + } + +l2x0_resume (); +} +static void __init l2c310_fixup (void __iomem *base,u32 cache_id,struct outer_cache_fns *fns) {
@@ -455,6 +530,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .num_lock = 8, .enable = l2c_enable, .fixup = l2c310_fixup, + .save = pl310_save, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range,
@@ -462,6 +538,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, + .resume = pl310_resume, }, };
@@ -614,21 +691,6 @@ static void __init l2x0_of_parse(const struct device_node *np, *aux_mask &= ~mask; } -static void l2x0_resume (void ) -{ -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -/* restore aux ctrl and enable l2 */ -l2x0_unlock (readl_relaxed (l2x0_base +L2X0_CACHE_ID )); - -writel_relaxed (l2x0_saved_regs.aux_ctrl, l2x0_base + -L2X0_AUX_CTRL ); - -l2x0_inv_all (); - -writel_relaxed (L2X0_CTRL_EN , l2x0_base +L2X0_CTRL ); - } -} -static const struct l2c_init_data of_l2x0_data__initconst = { .of_parse = l2x0_of_parse, .enable = l2x0_enable,
@@ -677,65 +739,6 @@ static void __init pl310_of_parse(const struct device_node *np, } } -static void __init pl310_save (void __iomem *base) -{ -u32 l2x0_revision =readl_relaxed (base +L2X0_CACHE_ID ) & -L2X0_CACHE_ID_RTL_MASK ; - - l2x0_saved_regs.tag_latency =readl_relaxed (base + -L2X0_TAG_LATENCY_CTRL ); - l2x0_saved_regs.data_latency =readl_relaxed (base + -L2X0_DATA_LATENCY_CTRL ); - l2x0_saved_regs.filter_end =readl_relaxed (base + -L2X0_ADDR_FILTER_END ); - l2x0_saved_regs.filter_start =readl_relaxed (base + -L2X0_ADDR_FILTER_START ); - -if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { -/* -* From r2p0, there is Prefetch offset/control register -*/ - l2x0_saved_regs.prefetch_ctrl =readl_relaxed (base + -L2X0_PREFETCH_CTRL ); -/* -* From r3p0, there is Power control register -*/ -if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) - l2x0_saved_regs.pwr_ctrl =readl_relaxed (base + -L2X0_POWER_CTRL ); - } -} - -static void pl310_resume (void ) -{ -u32 l2x0_revision; - -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -/* restore pl310 setup */ -writel_relaxed (l2x0_saved_regs.tag_latency, - l2x0_base +L2X0_TAG_LATENCY_CTRL ); -writel_relaxed (l2x0_saved_regs.data_latency, - l2x0_base +L2X0_DATA_LATENCY_CTRL ); -writel_relaxed (l2x0_saved_regs.filter_end, - l2x0_base +L2X0_ADDR_FILTER_END ); -writel_relaxed (l2x0_saved_regs.filter_start, - l2x0_base +L2X0_ADDR_FILTER_START ); - - l2x0_revision =readl_relaxed (l2x0_base +L2X0_CACHE_ID ) & -L2X0_CACHE_ID_RTL_MASK ; - -if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { -writel_relaxed (l2x0_saved_regs.prefetch_ctrl, - l2x0_base +L2X0_PREFETCH_CTRL ); -if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) -writel_relaxed (l2x0_saved_regs.pwr_ctrl, - l2x0_base +L2X0_POWER_CTRL ); - } - } - -l2x0_resume (); -} -static const struct l2c_init_data of_pl310_data__initconst = { .num_lock =8 , .of_parse = pl310_of_parse,
Signature · 1 line
1.8.3.1
PATCH 27/222 ARM: l2c: clean up save/resume functions
In reply to Russell King - ARM LinuxRename the pl310 save/resume functions to have a l2c310 prefix - this is it's official name. Use a local cached copy of the l2x0_base virtual address, and also realise that many of the resume function tails are the same as the enable functions, so make a call to the enable function instead of duplicating that code.
--- arch/arm/mm/cache-l2x0.c | 109 ++++++++++++++++++++++------------------------- 1 file changed, 52 insertions(+), 57 deletions(-)
arch/arm/mm/cache-l2x0.c +52 -57
@@ -385,17 +385,10 @@ static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock)static void l2x0_resume (void ) { -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -/* restore aux ctrl and enable l2 */ -l2x0_unlock (readl_relaxed (l2x0_base +L2X0_CACHE_ID )); - -writel_relaxed (l2x0_saved_regs.aux_ctrl, l2x0_base + -L2X0_AUX_CTRL ); - -l2x0_inv_all (); +void __iomem *base = l2x0_base; -writel_relaxed (L2X0_CTRL_EN , l2x0_base +L2X0_CTRL ); - } +if (!(readl_relaxed (base +L2X0_CTRL ) &L2X0_CTRL_EN )) +l2x0_enable (base, l2x0_saved_regs.aux_ctrl,0 ); }static const struct l2c_init_data l2x0_init_fns__initconst = {
@@ -438,10 +431,9 @@ static const struct l2c_init_data l2x0_init_fns __initconst = {* Affects: store buffer * store buffer is not automatically drained. */ -static void __init pl310_save (void __iomem *base) +static void __init l2c310_save (void __iomem *base) { -u32 l2x0_revision =readl_relaxed (base +L2X0_CACHE_ID ) & -L2X0_CACHE_ID_RTL_MASK ; +unsigned revision; l2x0_saved_regs.tag_latency =readl_relaxed (base +L2X0_TAG_LATENCY_CTRL );
@@ -452,49 +444,49 @@ static void __init pl310_save(void __iomem *base) l2x0_saved_regs.filter_start =readl_relaxed (base +L2X0_ADDR_FILTER_START ); -if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { -/* -* From r2p0, there is Prefetch offset/control register -*/ + revision =readl_relaxed (base +L2X0_CACHE_ID ) & +L2X0_CACHE_ID_RTL_MASK ; + +/* From r2p0, there is Prefetch offset/control register */ +if (revision >=L310_CACHE_ID_RTL_R2P0 ) l2x0_saved_regs.prefetch_ctrl =readl_relaxed (base + -L2X0_PREFETCH_CTRL ); -/* -* From r3p0, there is Power control register -*/ -if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) - l2x0_saved_regs.pwr_ctrl =readl_relaxed (base + -L2X0_POWER_CTRL ); - } +L2X0_PREFETCH_CTRL ); + +/* From r3p0, there is Power control register */ +if (revision >=L310_CACHE_ID_RTL_R3P0 ) + l2x0_saved_regs.pwr_ctrl =readl_relaxed (base + +L2X0_POWER_CTRL ); } -static void pl310_resume (void ) +static void l2c310_resume (void ) { -u32 l2x0_revision; +void __iomem *base = l2x0_base; + +if (!(readl_relaxed (base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +unsigned revision; -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) {/* restore pl310 setup */ writel_relaxed (l2x0_saved_regs.tag_latency, - l2x0_base +L2X0_TAG_LATENCY_CTRL ); + base +L2X0_TAG_LATENCY_CTRL );writel_relaxed (l2x0_saved_regs.data_latency, - l2x0_base +L2X0_DATA_LATENCY_CTRL ); + base +L2X0_DATA_LATENCY_CTRL );writel_relaxed (l2x0_saved_regs.filter_end, - l2x0_base +L2X0_ADDR_FILTER_END ); + base +L2X0_ADDR_FILTER_END );writel_relaxed (l2x0_saved_regs.filter_start, - l2x0_base +L2X0_ADDR_FILTER_START ); + base +L2X0_ADDR_FILTER_START ); - l2x0_revision =readl_relaxed (l2x0_base +L2X0_CACHE_ID ) & -L2X0_CACHE_ID_RTL_MASK ; + revision =readl_relaxed (base +L2X0_CACHE_ID ) & +L2X0_CACHE_ID_RTL_MASK ; -if (l2x0_revision >=L310_CACHE_ID_RTL_R2P0 ) { +if (revision >=L310_CACHE_ID_RTL_R2P0 )writel_relaxed (l2x0_saved_regs.prefetch_ctrl, - l2x0_base +L2X0_PREFETCH_CTRL ); -if (l2x0_revision >=L310_CACHE_ID_RTL_R3P0 ) -writel_relaxed (l2x0_saved_regs.pwr_ctrl, - l2x0_base +L2X0_POWER_CTRL ); - } - } + base +L2X0_PREFETCH_CTRL ); +if (revision >=L310_CACHE_ID_RTL_R3P0 ) +writel_relaxed (l2x0_saved_regs.pwr_ctrl, + base +L2X0_POWER_CTRL ); -l2x0_resume (); +l2c_enable (base, l2x0_saved_regs.aux_ctrl,8 ); + } } static void __init l2c310_fixup(void __iomem *base, u32 cache_id,
@@ -530,7 +522,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .num_lock = 8, .enable = l2c_enable, .fixup = l2c310_fixup, - .save = pl310_save, + .save = l2c310_save, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range,
@@ -538,7 +530,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, - .resume = pl310_resume, + .resume = l2c310_resume, }, };
@@ -744,7 +736,7 @@ static const struct l2c_init_data of_pl310_data __initconst = { .of_parse = pl310_of_parse, .enable = l2c_enable, .fixup = l2c310_fixup, - .save = pl310_save, + .save = l2c310_save, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range,
@@ -752,7 +744,7 @@ static const struct l2c_init_data of_pl310_data __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, - .resume = pl310_resume, + .resume = l2c310_resume, }, };
@@ -862,10 +854,11 @@ static void aurora_save(void __iomem *base)static void aurora_resume (void ) { -if (!(readl (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { -writel_relaxed (l2x0_saved_regs.aux_ctrl, - l2x0_base +L2X0_AUX_CTRL ); -writel_relaxed (l2x0_saved_regs.ctrl, l2x0_base +L2X0_CTRL ); +void __iomem *base = l2x0_base; + +if (!(readl (base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +writel_relaxed (l2x0_saved_regs.aux_ctrl, base +L2X0_AUX_CTRL ); +writel_relaxed (l2x0_saved_regs.ctrl, base +L2X0_CTRL ); } }
@@ -1089,7 +1082,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .of_parse = pl310_of_parse, .enable = l2c_enable, .fixup = l2c310_fixup, - .save = pl310_save, + .save = l2c310_save, .outer_cache = { .inv_range = bcm_inv_range, .clean_range = bcm_clean_range,
@@ -1097,7 +1090,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, - .resume = pl310_resume, + .resume = l2c310_resume, }, };
@@ -1111,14 +1104,16 @@ static void __init tauros3_save(void __iomem *base)static void tauros3_resume (void ) { -if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN )) { +void __iomem *base = l2x0_base; + +if (!(readl_relaxed (base +L2X0_CTRL ) &L2X0_CTRL_EN )) {writel_relaxed (l2x0_saved_regs.aux2_ctrl, - l2x0_base +TAUROS3_AUX2_CTRL ); + base +TAUROS3_AUX2_CTRL );writel_relaxed (l2x0_saved_regs.prefetch_ctrl, - l2x0_base +L2X0_PREFETCH_CTRL ); - } + base +L2X0_PREFETCH_CTRL ); -l2x0_resume (); +l2c_enable (base, l2x0_saved_regs.aux_ctrl,8 ); + } }static const struct l2c_init_data of_tauros3_data__initconst = {
Signature · 1 line
1.8.3.1
PATCH 28/222 ARM: l2c: simplify l2x0 unlocking code
In reply to Russell King - ARM LinuxThe l2x0 unlocking code is only called from l2x0_enable() now, so move the logic entirely into that function and simplify it.
--- arch/arm/mm/cache-l2x0.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-)
arch/arm/mm/cache-l2x0.c +8 -17
@@ -352,30 +352,21 @@ static void l2x0_disable(void)raw_spin_unlock_irqrestore (&l2x0_lock, flags); } -static void l2x0_unlock (u32 cache_id) +static void l2x0_enable (void __iomem *base,u32 aux,unsigned num_lock) { -int lockregs; +unsigned id; -switch (cache_id &L2X0_CACHE_ID_PART_MASK ) { -case L2X0_CACHE_ID_PART_L310 : - lockregs =8 ; -break ; -default : -/* L210 and unknown types */ - lockregs =1 ; -break ; - } - -l2c_unlock (l2x0_base, lockregs); -} + id =readl_relaxed (base +L2X0_CACHE_ID ) &L2X0_CACHE_ID_PART_MASK ; +if (id ==L2X0_CACHE_ID_PART_L310 ) + num_lock =8 ; +else + num_lock =1 ; -static void l2x0_enable (void __iomem *base,u32 aux,unsigned num_lock) -{/* l2x0 controller is disabled */ writel_relaxed (aux, base +L2X0_AUX_CTRL );/* Make sure that I&D is not locked down when starting */ -l2x0_unlock (readl_relaxed (base +L2X0_CACHE_ID )); +l2c_unlock (base, num_lock);l2x0_inv_all ();
Signature · 1 line
1.8.3.1
PATCH 29/222 ARM: l2c: move pl310_set_debug() into l2c-310 code
In reply to Russell King - ARM LinuxMove the pl310_set_debug() into the l2c-310 code area, and don't hide it with ifdefs. Rename it to l2c310_set_debug().
--- arch/arm/mm/cache-l2x0.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
arch/arm/mm/cache-l2x0.c +6 -8
@@ -154,18 +154,11 @@ static inline void debug_writel(unsigned long val)if (outer_cache.set_debug) l2c_set_debug(l2x0_base, val); } - -static void pl310_set_debug (unsigned long val) -{ -writel_relaxed (val, l2x0_base +L2X0_DEBUG_CTRL ); -}#else /* Optimised out for non-errata case */ static inline void debug_writel (unsigned long val) { } - -#define pl310_set_debug NULL#endif #ifdef CONFIG_PL310_ERRATA_588369
@@ -422,6 +415,11 @@ static const struct l2c_init_data l2x0_init_fns __initconst = {* Affects: store buffer * store buffer is not automatically drained. */ +static void l2c310_set_debug (unsigned long val) +{ +writel_relaxed (val, l2x0_base +L2X0_DEBUG_CTRL ); +} +static void __init l2c310_save (void __iomem *base) {unsigned revision;
@@ -488,7 +486,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id,unsigned n =0 ;if (revision <=L310_CACHE_ID_RTL_R3P0 ) - fns->set_debug = pl310_set_debug; + fns->set_debug = l2c310_set_debug;if (IS_ENABLED (CONFIG_PL310_ERRATA_753970 ) && revision ==L310_CACHE_ID_RTL_R3P0 ) {
Signature · 1 line
1.8.3.1
PATCH 30/222 ARM: l2c: add L2C-210 specific handlers
In reply to Russell King - ARM LinuxAdd L2C-210 specific cache operation handlers. These are tailored to the requirements of the L2C-210 cache controller, which doesn't require any workarounds. We avoid using the way operations during normal operation, which means we can avoid locking: the only time we use the way operations are during initialisation, and when disabling the cache.
--- arch/arm/mm/cache-l2x0.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-)
arch/arm/mm/cache-l2x0.c +122 -1
@@ -389,6 +389,108 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { };/* +* L2C-210 specific code. +* +* The L2C-2x0 PA, set/way and sync operations are atomic, but we must +* ensure that no background operation is running. The way operations +* are all background tasks. +* +* While a background operation is in progress, any new operation is +* ignored (unspecified whether this causes an error.) Thankfully, not +* used on SMP. +* +* Never has a different sync register other than L2X0_CACHE_SYNC, but +* we use sync_reg_offset here so we can share some of this with L2C-310. +*/ +static void __l2c210_cache_sync (void __iomem *base) +{ +writel_relaxed (0 , base + sync_reg_offset); +} + +static void __l2c210_op_pa_range (void __iomem *reg,unsigned long start, +unsigned long end) +{ +while (start < end) { +writel_relaxed (start, reg); + start +=CACHE_LINE_SIZE ; + } +} + +static void l2c210_inv_range (unsigned long start,unsigned long end) +{ +void __iomem *base = l2x0_base; + +if (start & (CACHE_LINE_SIZE -1 )) { + start &= ~(CACHE_LINE_SIZE -1 ); +writel_relaxed (start, base +L2X0_CLEAN_INV_LINE_PA ); + start +=CACHE_LINE_SIZE ; + } + +if (end & (CACHE_LINE_SIZE -1 )) { + end &= ~(CACHE_LINE_SIZE -1 ); +writel_relaxed (end, base +L2X0_CLEAN_INV_LINE_PA ); + } + +__l2c210_op_pa_range (base +L2X0_INV_LINE_PA , start, end); +__l2c210_cache_sync (base); +} + +static void l2c210_clean_range (unsigned long start,unsigned long end) +{ +void __iomem *base = l2x0_base; + + start &= ~(CACHE_LINE_SIZE -1 ); +__l2c210_op_pa_range (base +L2X0_CLEAN_LINE_PA , start, end); +__l2c210_cache_sync (base); +} + +static void l2c210_flush_range (unsigned long start,unsigned long end) +{ +void __iomem *base = l2x0_base; + + start &= ~(CACHE_LINE_SIZE -1 ); +__l2c210_op_pa_range (base +L2X0_CLEAN_INV_LINE_PA , start, end); +__l2c210_cache_sync (base); +} + +static void l2c210_flush_all (void ) +{ +void __iomem *base = l2x0_base; + +BUG_ON (!irqs_disabled ()); + +__l2c_op_way (base +L2X0_CLEAN_INV_WAY ); +__l2c210_cache_sync (base); +} + +static void l2c210_sync (void ) +{ +__l2c210_cache_sync (l2x0_base); +} + +static void l2c210_resume (void ) +{ +void __iomem *base = l2x0_base; + +if (!(readl_relaxed (base +L2X0_CTRL ) &L2X0_CTRL_EN )) +l2c_enable (base, l2x0_saved_regs.aux_ctrl,1 ); +} + +static const struct l2c_init_data l2c210_data__initconst = { + .num_lock =1 , + .enable = l2c_enable, + .outer_cache = { + .inv_range = l2c210_inv_range, + .clean_range = l2c210_clean_range, + .flush_range = l2c210_flush_range, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, + .resume = l2c210_resume, + }, +}; + +/* * L2C-310 specific code. * * Errata:
@@ -623,6 +725,10 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) data = &l2x0_init_fns;break ; +case L2X0_CACHE_ID_PART_L210 : + data = &l2c210_data; +break ; +case L2X0_CACHE_ID_PART_L310 : data = &l2c310_init_fns;break ;
@@ -672,6 +778,21 @@ static void __init l2x0_of_parse(const struct device_node *np, *aux_mask &= ~mask; } +static const struct l2c_init_data of_l2c210_data__initconst = { + .num_lock =1 , + .of_parse = l2x0_of_parse, + .enable = l2c_enable, + .outer_cache = { + .inv_range = l2c210_inv_range, + .clean_range = l2c210_clean_range, + .flush_range = l2c210_flush_range, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, + .resume = l2c210_resume, + }, +}; +static const struct l2c_init_data of_l2x0_data__initconst = { .of_parse = l2x0_of_parse, .enable = l2x0_enable,
@@ -1117,7 +1238,7 @@ static const struct l2c_init_data of_tauros3_data __initconst = {#define L2C_ID (name, fns) { .compatible = name, .data = (void *)&fns }static const struct of_device_id l2x0_ids[]__initconst = { -L2C_ID ("arm,l210-cache" , of_l2x0_data), +L2C_ID ("arm,l210-cache" , of_l2c210_data),L2C_ID ("arm,l220-cache" , of_l2x0_data),L2C_ID ("arm,pl310-cache" , of_pl310_data),L2C_ID ("brcm,bcm11351-a2-pl310-cache" , of_bcm_l2x0_data),
Signature · 1 line
1.8.3.1
PATCH 31/222 ARM: l2c: implement L2C-310 erratum 727915 as a method override
In reply to Russell King - ARM LinuxImplement L2C-310 erratum 727915 by overriding the flush_all method in the outer_cache operations structure. This allows us to sensibly contain the erratum code in one place without affecting other locations or implementations.
--- arch/arm/mm/cache-l2x0.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
arch/arm/mm/cache-l2x0.c +20 -0
@@ -522,6 +522,19 @@ static void l2c310_set_debug(unsigned long val)writel_relaxed (val, l2x0_base +L2X0_DEBUG_CTRL ); } +static void l2c310_flush_all_erratum (void ) +{ +void __iomem *base = l2x0_base; +unsigned long flags; + +raw_spin_lock_irqsave (&l2x0_lock, flags); +l2c_set_debug (base,0x03 ); +__l2c_op_way (base +L2X0_CLEAN_INV_WAY ); +l2c_set_debug (base,0x00 ); +__l2c210_cache_sync (base); +raw_spin_unlock_irqrestore (&l2x0_lock, flags); +} +static void __init l2c310_save (void __iomem *base) {unsigned revision;
@@ -590,6 +603,13 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id,if (revision <=L310_CACHE_ID_RTL_R3P0 ) fns->set_debug = l2c310_set_debug; +if (IS_ENABLED (CONFIG_PL310_ERRATA_727915 ) && + revision >=L310_CACHE_ID_RTL_R2P0 && + revision <L310_CACHE_ID_RTL_R3P1 ) { + fns->flush_all = l2c310_flush_all_erratum; + errata[n++] ="727915" ; + } +if (IS_ENABLED (CONFIG_PL310_ERRATA_753970 ) && revision ==L310_CACHE_ID_RTL_R3P0 ) { sync_reg_offset =L2X0_DUMMY_REG ;
Signature · 1 line
1.8.3.1
PATCH 32/222 ARM: l2c: implement L2C-310 erratum 588369 as a method override
In reply to Russell King - ARM LinuxImplement L2C-310 erratum 588369 by overriding the invalidate range and flush range methods in the outer_cache operations structure. This allows us to sensibly contain the erratum code in one place without affecting other locations/implemetations.
--- arch/arm/mm/cache-l2x0.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
arch/arm/mm/cache-l2x0.c +69 -0
@@ -522,6 +522,65 @@ static void l2c310_set_debug(unsigned long val)writel_relaxed (val, l2x0_base +L2X0_DEBUG_CTRL ); } +static void l2c310_inv_range_erratum (unsigned long start,unsigned long end) +{ +void __iomem *base = l2x0_base; + +if ((start | end) & (CACHE_LINE_SIZE -1 )) { +unsigned long flags; + +/* Erratum 588369 for both clean+invalidate operations */ +raw_spin_lock_irqsave (&l2x0_lock, flags); +l2c_set_debug (base,0x03 ); + +if (start & (CACHE_LINE_SIZE -1 )) { + start &= ~(CACHE_LINE_SIZE -1 ); +writel_relaxed (start, base +L2X0_CLEAN_LINE_PA ); +writel_relaxed (start, base +L2X0_INV_LINE_PA ); + start +=CACHE_LINE_SIZE ; + } + +if (end & (CACHE_LINE_SIZE -1 )) { + end &= ~(CACHE_LINE_SIZE -1 ); +writel_relaxed (end, base +L2X0_CLEAN_LINE_PA ); +writel_relaxed (end, base +L2X0_INV_LINE_PA ); + } + +l2c_set_debug (base,0x00 ); +raw_spin_unlock_irqrestore (&l2x0_lock, flags); + } + +__l2c210_op_pa_range (base +L2X0_INV_LINE_PA , start, end); +__l2c210_cache_sync (base); +} + +static void l2c310_flush_range_erratum (unsigned long start,unsigned long end) +{ +raw_spinlock_t *lock = &l2x0_lock; +unsigned long flags; +void __iomem *base = l2x0_base; + +raw_spin_lock_irqsave (lock, flags); +while (start < end) { +unsigned long blk_end = start +min (end - start,4096UL ); + +l2c_set_debug (base,0x03 ); +while (start < blk_end) { +writel_relaxed (start, base +L2X0_CLEAN_LINE_PA ); +writel_relaxed (start, base +L2X0_INV_LINE_PA ); + start +=CACHE_LINE_SIZE ; + } +l2c_set_debug (base,0x00 ); + +if (blk_end < end) { +raw_spin_unlock_irqrestore (lock, flags); +raw_spin_lock_irqsave (lock, flags); + } + } +raw_spin_unlock_irqrestore (lock, flags); +__l2c210_cache_sync (base); +} +static void l2c310_flush_all_erratum (void ) {void __iomem *base = l2x0_base;
@@ -600,9 +659,19 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id,const char *errata[4 ];unsigned n =0 ; +/* For compatibility */ if (revision <=L310_CACHE_ID_RTL_R3P0 ) fns->set_debug = l2c310_set_debug; +if (IS_ENABLED (CONFIG_PL310_ERRATA_588369 ) && + revision <L310_CACHE_ID_RTL_R2P0 && +/* For bcm compatibility */ + fns->inv_range == l2x0_inv_range) { + fns->inv_range = l2c310_inv_range_erratum; + fns->flush_range = l2c310_flush_range_erratum; + errata[n++] ="588369" ; + } +if (IS_ENABLED (CONFIG_PL310_ERRATA_727915 ) && revision >=L310_CACHE_ID_RTL_R2P0 && revision <L310_CACHE_ID_RTL_R3P1 ) {
Signature · 1 line
1.8.3.1
PATCH 33/222 ARM: l2c: use L2C-210 handlers for L2C-310 errata-less implementations
In reply to Russell King - ARM LinuxWhere no errata affect the L2C-310 handlers, they are functionally equivalent to L2C-210. Re-use the L2C-210 handlers for the L2C-310 part.
--- arch/arm/mm/cache-l2x0.c | 58 ++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 22 deletions(-)
arch/arm/mm/cache-l2x0.c +36 -22
@@ -493,6 +493,18 @@ static const struct l2c_init_data l2c210_data __initconst = {/* * L2C-310 specific code. * +* Very similar to L2C-210, the PA, set/way and sync operations are atomic, +* and the way operations are all background tasks. However, issuing an +* operation while a background operation is in progress results in a +* SLVERR response. We can reuse: +* +* __l2c210_cache_sync (using sync_reg_offset) +* l2c210_sync +* l2c210_inv_range (if 588369 is not applicable) +* l2c210_clean_range +* l2c210_flush_range (if 588369 is not applicable) +* l2c210_flush_all (if 727915 is not applicable) +* * Errata: * 588369: PL310 R0P0->R1P0, fixed R2P0. * Affects: all clean+invalidate operations
@@ -666,7 +678,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id,if (IS_ENABLED (CONFIG_PL310_ERRATA_588369 ) && revision <L310_CACHE_ID_RTL_R2P0 &&/* For bcm compatibility */ - fns->inv_range == l2x0_inv_range) { + fns->inv_range == l2c210_inv_range) { fns->inv_range = l2c310_inv_range_erratum; fns->flush_range = l2c310_flush_range_erratum; errata[n++] ="588369" ;
@@ -704,12 +716,13 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, + .inv_range = l2c210_inv_range, + .clean_range = l2c210_clean_range, + .flush_range = l2c210_flush_range, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, + .set_debug = l2c310_set_debug, .resume = l2c310_resume, }, };
@@ -896,8 +909,8 @@ static const struct l2c_init_data of_l2x0_data __initconst = { }, }; -static void __init pl310_of_parse (const struct device_node *np, -u32 *aux_val,u32 *aux_mask) +static void __init l2c310_of_parse (const struct device_node *np, +u32 *aux_val,u32 *aux_mask) {u32 data[3 ] = {0 ,0 ,0 };u32 tag[3 ] = {0 ,0 ,0 };
@@ -930,19 +943,20 @@ static void __init pl310_of_parse(const struct device_node *np, } } -static const struct l2c_init_data of_pl310_data__initconst = { +static const struct l2c_init_data of_l2c310_data__initconst = { .num_lock =8 , - .of_parse = pl310_of_parse, + .of_parse = l2c310_of_parse, .enable = l2c_enable, .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, + .inv_range = l2c210_inv_range, + .clean_range = l2c210_clean_range, + .flush_range = l2c210_flush_range, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, + .set_debug = l2c310_set_debug, .resume = l2c310_resume, }, };
@@ -1278,7 +1292,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end)static const struct l2c_init_data of_bcm_l2x0_data__initconst = { .num_lock =8 , - .of_parse = pl310_of_parse, + .of_parse = l2c310_of_parse, .enable = l2c_enable, .fixup = l2c310_fixup, .save = l2c310_save,
@@ -1286,9 +1300,9 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .inv_range = bcm_inv_range, .clean_range = bcm_clean_range, .flush_range = bcm_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, .resume = l2c310_resume, }, };
@@ -1329,7 +1343,7 @@ static const struct l2c_init_data of_tauros3_data __initconst = {static const struct of_device_id l2x0_ids[]__initconst = {L2C_ID ("arm,l210-cache" , of_l2c210_data),L2C_ID ("arm,l220-cache" , of_l2x0_data), -L2C_ID ("arm,pl310-cache" , of_pl310_data), +L2C_ID ("arm,pl310-cache" , of_l2c310_data),L2C_ID ("brcm,bcm11351-a2-pl310-cache" , of_bcm_l2x0_data),L2C_ID ("marvell,aurora-outer-cache" , of_aurora_with_outer_data),L2C_ID ("marvell,aurora-system-cache" , of_aurora_no_outer_data),
Signature · 1 line
1.8.3.1
PATCH 34/222 ARM: l2c: add L2C-220 specific handlers
In reply to Russell King - ARM LinuxThe L2C-220 is different from the L2C-210 and L2C-310 in that every operation is a background operation: this means we have to use spinlocks to protect all operations, and we have to wait for every operation to complete.
Should a second operation be attempted while a previous operation is in progress, the response will be an imprecise abort.
--- arch/arm/mm/cache-l2x0.c | 167 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 157 insertions(+), 10 deletions(-)
arch/arm/mm/cache-l2x0.c +157 -10
@@ -491,6 +491,148 @@ static const struct l2c_init_data l2c210_data __initconst = { };/* +* L2C-220 specific code. +* +* All operations are background operations: they have to be waited for. +* Conflicting requests generate a slave error (which will cause an +* imprecise abort.) Never uses sync_reg_offset, so we hard-code the +* sync register here. +* +* However, we can re-use the l2c210_resume call. +*/ +static inline void __l2c220_cache_sync (void __iomem *base) +{ +writel_relaxed (0 , base +L2X0_CACHE_SYNC ); +l2c_wait_mask (base +L2X0_CACHE_SYNC ,1 ); +} + +static void l2c220_op_way (void __iomem *base,unsigned reg) +{ +unsigned long flags; + +raw_spin_lock_irqsave (&l2x0_lock, flags); +__l2c_op_way (base + reg); +__l2c220_cache_sync (base); +raw_spin_unlock_irqrestore (&l2x0_lock, flags); +} + +static unsigned long l2c220_op_pa_range (void __iomem *reg,unsigned long start, +unsigned long end,unsigned long flags) +{ +raw_spinlock_t *lock = &l2x0_lock; + +while (start < end) { +unsigned long blk_end = start +min (end - start,4096UL ); + +while (start < blk_end) { +l2c_wait_mask (reg,1 ); +writel_relaxed (start, reg); + start +=CACHE_LINE_SIZE ; + } + +if (blk_end < end) { +raw_spin_unlock_irqrestore (lock, flags); +raw_spin_lock_irqsave (lock, flags); + } + } + +return flags; +} + +static void l2c220_inv_range (unsigned long start,unsigned long end) +{ +void __iomem *base = l2x0_base; +unsigned long flags; + +raw_spin_lock_irqsave (&l2x0_lock, flags); +if ((start | end) & (CACHE_LINE_SIZE -1 )) { +if (start & (CACHE_LINE_SIZE -1 )) { + start &= ~(CACHE_LINE_SIZE -1 ); +writel_relaxed (start, base +L2X0_CLEAN_INV_LINE_PA ); + start +=CACHE_LINE_SIZE ; + } + +if (end & (CACHE_LINE_SIZE -1 )) { + end &= ~(CACHE_LINE_SIZE -1 ); +l2c_wait_mask (base +L2X0_CLEAN_INV_LINE_PA ,1 ); +writel_relaxed (end, base +L2X0_CLEAN_INV_LINE_PA ); + } + } + + flags =l2c220_op_pa_range (base +L2X0_INV_LINE_PA , + start, end, flags); +l2c_wait_mask (base +L2X0_INV_LINE_PA ,1 ); +__l2c220_cache_sync (base); +raw_spin_unlock_irqrestore (&l2x0_lock, flags); +} + +static void l2c220_clean_range (unsigned long start,unsigned long end) +{ +void __iomem *base = l2x0_base; +unsigned long flags; + + start &= ~(CACHE_LINE_SIZE -1 ); +if ((end - start) >= l2x0_size) { +l2c220_op_way (base,L2X0_CLEAN_WAY ); +return ; + } + +raw_spin_lock_irqsave (&l2x0_lock, flags); + flags =l2c220_op_pa_range (base +L2X0_CLEAN_LINE_PA , + start, end, flags); +l2c_wait_mask (base +L2X0_CLEAN_INV_LINE_PA ,1 ); +__l2c220_cache_sync (base); +raw_spin_unlock_irqrestore (&l2x0_lock, flags); +} + +static void l2c220_flush_range (unsigned long start,unsigned long end) +{ +void __iomem *base = l2x0_base; +unsigned long flags; + + start &= ~(CACHE_LINE_SIZE -1 ); +if ((end - start) >= l2x0_size) { +l2c220_op_way (base,L2X0_CLEAN_INV_WAY ); +return ; + } + +raw_spin_lock_irqsave (&l2x0_lock, flags); + flags =l2c220_op_pa_range (base +L2X0_CLEAN_INV_LINE_PA , + start, end, flags); +l2c_wait_mask (base +L2X0_CLEAN_INV_LINE_PA ,1 ); +__l2c220_cache_sync (base); +raw_spin_unlock_irqrestore (&l2x0_lock, flags); +} + +static void l2c220_flush_all (void ) +{ +l2c220_op_way (l2x0_base,L2X0_CLEAN_INV_WAY ); +} + +static void l2c220_sync (void ) +{ +unsigned long flags; + +raw_spin_lock_irqsave (&l2x0_lock, flags); +__l2c220_cache_sync (l2x0_base); +raw_spin_unlock_irqrestore (&l2x0_lock, flags); +} + +static const struct l2c_init_data l2c220_data = { + .num_lock =1 , + .enable = l2c_enable, + .outer_cache = { + .inv_range = l2c220_inv_range, + .clean_range = l2c220_clean_range, + .flush_range = l2c220_flush_range, + .flush_all = l2c220_flush_all, + .disable = l2c_disable, + .sync = l2c220_sync, + .resume = l2c210_resume, + }, +}; + +/* * L2C-310 specific code. * * Very similar to L2C-210, the PA, set/way and sync operations are atomic,
@@ -831,6 +973,10 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) data = &l2c210_data;break ; +case L2X0_CACHE_ID_PART_L220 : + data = &l2c220_data; +break ; +case L2X0_CACHE_ID_PART_L310 : data = &l2c310_init_fns;break ;
@@ -895,17 +1041,18 @@ static const struct l2c_init_data of_l2c210_data __initconst = { }, }; -static const struct l2c_init_data of_l2x0_data__initconst = { +static const struct l2c_init_data of_l2c220_data__initconst = { + .num_lock =1 , .of_parse = l2x0_of_parse, - .enable = l2x0_enable, + .enable = l2c_enable, .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = l2x0_resume, + .inv_range = l2c220_inv_range, + .clean_range = l2c220_clean_range, + .flush_range = l2c220_flush_range, + .flush_all = l2c220_flush_all, + .disable = l2c_disable, + .sync = l2c220_sync, + .resume = l2c210_resume, }, };
@@ -1342,7 +1489,7 @@ static const struct l2c_init_data of_tauros3_data __initconst = {#define L2C_ID (name, fns) { .compatible = name, .data = (void *)&fns }static const struct of_device_id l2x0_ids[]__initconst = {L2C_ID ("arm,l210-cache" , of_l2c210_data), -L2C_ID ("arm,l220-cache" , of_l2x0_data), +L2C_ID ("arm,l220-cache" , of_l2c220_data),L2C_ID ("arm,pl310-cache" , of_l2c310_data),L2C_ID ("brcm,bcm11351-a2-pl310-cache" , of_bcm_l2x0_data),L2C_ID ("marvell,aurora-outer-cache" , of_aurora_with_outer_data),
Signature · 1 line
1.8.3.1
PATCH 35/222 ARM: l2c: convert Broadcom L2C-310 to new code
In reply to Russell King - ARM LinuxThe Broadcom L2C-310 devices use ARMs L2C-310 R2P3 or later. These require no errata workarounds, and so we can directly call the l2c210 functions from their methods.
--- arch/arm/mm/cache-l2x0.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-)
arch/arm/mm/cache-l2x0.c +11 -16
@@ -1360,16 +1360,16 @@ static void bcm_inv_range(unsigned long start, unsigned long end)/* normal case, no cross section between start and end */ if (likely (bcm_addr_is_sys_emi (end) || !bcm_addr_is_sys_emi (start))) { -l2x0_inv_range (new_start, new_end); +l2c210_inv_range (new_start, new_end);return ; }/* They cross sections, so it can only be a cross from section * 2 to section 3 */ -l2x0_inv_range (new_start, +l2c210_inv_range (new_start,bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR -1 )); -l2x0_inv_range (bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR ), +l2c210_inv_range (bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR ), new_end); }
@@ -1382,26 +1382,21 @@ static void bcm_clean_range(unsigned long start, unsigned long end)if (unlikely (end <= start))return ; -if ((end - start) >= l2x0_size) { -l2x0_clean_all (); -return ; - } - new_start =bcm_l2_phys_addr (start); new_end =bcm_l2_phys_addr (end);/* normal case, no cross section between start and end */ if (likely (bcm_addr_is_sys_emi (end) || !bcm_addr_is_sys_emi (start))) { -l2x0_clean_range (new_start, new_end); +l2c210_clean_range (new_start, new_end);return ; }/* They cross sections, so it can only be a cross from section * 2 to section 3 */ -l2x0_clean_range (new_start, +l2c210_clean_range (new_start,bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR -1 )); -l2x0_clean_range (bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR ), +l2c210_clean_range (bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR ), new_end); }
@@ -1415,7 +1410,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end)return ;if ((end - start) >= l2x0_size) { -l2x0_flush_all (); + outer_cache.flush_all ();return ; }
@@ -1424,24 +1419,24 @@ static void bcm_flush_range(unsigned long start, unsigned long end)/* normal case, no cross section between start and end */ if (likely (bcm_addr_is_sys_emi (end) || !bcm_addr_is_sys_emi (start))) { -l2x0_flush_range (new_start, new_end); +l2c210_flush_range (new_start, new_end);return ; }/* They cross sections, so it can only be a cross from section * 2 to section 3 */ -l2x0_flush_range (new_start, +l2c210_flush_range (new_start,bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR -1 )); -l2x0_flush_range (bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR ), +l2c210_flush_range (bcm_l2_phys_addr (BCM_VC_EMI_SEC3_START_ADDR ), new_end); } +/* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */ static const struct l2c_init_data of_bcm_l2x0_data__initconst = { .num_lock =8 , .of_parse = l2c310_of_parse, .enable = l2c_enable, - .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = { .inv_range = bcm_inv_range,
Signature · 1 line
1.8.3.1
PATCH 36/222 ARM: l2c: remove obsolete l2x0 ops for non-OF init
In reply to Russell King - ARM Linuxnon-OF initialisation has never been used with any cache controller which isn't an ARM cache controller, so we can safely get rid of the old (and buggy) l2x0_*-based operations structure.
This is also the last reference to:
- l2x0_clean_line()
- l2x0_inv_line()
- l2x0_flush_line()
- l2x0_flush_all()
- l2x0_clean_all()
- l2x0_inv_all()
- l2x0_inv_range()
- l2x0_clean_range()
- l2x0_flush_range()
- l2x0_enable()
- l2x0_resume()
so kill those functions too.
--- arch/arm/mm/cache-l2x0.c | 206 ----------------------------------------------- 1 file changed, 206 deletions(-)
arch/arm/mm/cache-l2x0.c +0 -206
@@ -134,20 +134,6 @@ static inline void cache_sync(void)cache_wait (base +L2X0_CACHE_SYNC ,1 ); } -static inline void l2x0_clean_line (unsigned long addr) -{ -void __iomem *base = l2x0_base; -cache_wait (base +L2X0_CLEAN_LINE_PA ,1 ); -writel_relaxed (addr, base +L2X0_CLEAN_LINE_PA ); -} - -static inline void l2x0_inv_line (unsigned long addr) -{ -void __iomem *base = l2x0_base; -cache_wait (base +L2X0_INV_LINE_PA ,1 ); -writel_relaxed (addr, base +L2X0_INV_LINE_PA ); -} -#if defined(CONFIG_PL310_ERRATA_588369 ) || defined(CONFIG_PL310_ERRATA_727915 )static inline void debug_writel (unsigned long val) {
@@ -161,27 +147,6 @@ static inline void debug_writel(unsigned long val) }#endif -#ifdef CONFIG_PL310_ERRATA_588369 -static inline void l2x0_flush_line (unsigned long addr) -{ -void __iomem *base = l2x0_base; - -/* Clean by PA followed by Invalidate by PA */ -cache_wait (base +L2X0_CLEAN_LINE_PA ,1 ); -writel_relaxed (addr, base +L2X0_CLEAN_LINE_PA ); -cache_wait (base +L2X0_INV_LINE_PA ,1 ); -writel_relaxed (addr, base +L2X0_INV_LINE_PA ); -} -#else - -static inline void l2x0_flush_line (unsigned long addr) -{ -void __iomem *base = l2x0_base; -cache_wait (base +L2X0_CLEAN_INV_LINE_PA ,1 ); -writel_relaxed (addr, base +L2X0_CLEAN_INV_LINE_PA ); -} -#endif -static void l2x0_cache_sync (void ) {unsigned long flags;
@@ -209,131 +174,6 @@ static void l2x0_flush_all(void)raw_spin_unlock_irqrestore (&l2x0_lock, flags); } -static void l2x0_clean_all (void ) -{ -unsigned long flags; - -/* clean all ways */ -raw_spin_lock_irqsave (&l2x0_lock, flags); -__l2c_op_way (l2x0_base +L2X0_CLEAN_WAY ); -cache_sync (); -raw_spin_unlock_irqrestore (&l2x0_lock, flags); -} - -static void l2x0_inv_all (void ) -{ -unsigned long flags; - -/* invalidate all ways */ -raw_spin_lock_irqsave (&l2x0_lock, flags); -/* Invalidating when L2 is enabled is a nono */ -BUG_ON (readl (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN ); -__l2c_op_way (l2x0_base +L2X0_INV_WAY ); -cache_sync (); -raw_spin_unlock_irqrestore (&l2x0_lock, flags); -} - -static void l2x0_inv_range (unsigned long start,unsigned long end) -{ -void __iomem *base = l2x0_base; -unsigned long flags; - -raw_spin_lock_irqsave (&l2x0_lock, flags); -if (start & (CACHE_LINE_SIZE -1 )) { - start &= ~(CACHE_LINE_SIZE -1 ); -debug_writel (0x03 ); -l2x0_flush_line (start); -debug_writel (0x00 ); - start +=CACHE_LINE_SIZE ; - } - -if (end & (CACHE_LINE_SIZE -1 )) { - end &= ~(CACHE_LINE_SIZE -1 ); -debug_writel (0x03 ); -l2x0_flush_line (end); -debug_writel (0x00 ); - } - -while (start < end) { -unsigned long blk_end = start +min (end - start,4096UL ); - -while (start < blk_end) { -l2x0_inv_line (start); - start +=CACHE_LINE_SIZE ; - } - -if (blk_end < end) { -raw_spin_unlock_irqrestore (&l2x0_lock, flags); -raw_spin_lock_irqsave (&l2x0_lock, flags); - } - } -cache_wait (base +L2X0_INV_LINE_PA ,1 ); -cache_sync (); -raw_spin_unlock_irqrestore (&l2x0_lock, flags); -} - -static void l2x0_clean_range (unsigned long start,unsigned long end) -{ -void __iomem *base = l2x0_base; -unsigned long flags; - -if ((end - start) >= l2x0_size) { -l2x0_clean_all (); -return ; - } - -raw_spin_lock_irqsave (&l2x0_lock, flags); - start &= ~(CACHE_LINE_SIZE -1 ); -while (start < end) { -unsigned long blk_end = start +min (end - start,4096UL ); - -while (start < blk_end) { -l2x0_clean_line (start); - start +=CACHE_LINE_SIZE ; - } - -if (blk_end < end) { -raw_spin_unlock_irqrestore (&l2x0_lock, flags); -raw_spin_lock_irqsave (&l2x0_lock, flags); - } - } -cache_wait (base +L2X0_CLEAN_LINE_PA ,1 ); -cache_sync (); -raw_spin_unlock_irqrestore (&l2x0_lock, flags); -} - -static void l2x0_flush_range (unsigned long start,unsigned long end) -{ -void __iomem *base = l2x0_base; -unsigned long flags; - -if ((end - start) >= l2x0_size) { -l2x0_flush_all (); -return ; - } - -raw_spin_lock_irqsave (&l2x0_lock, flags); - start &= ~(CACHE_LINE_SIZE -1 ); -while (start < end) { -unsigned long blk_end = start +min (end - start,4096UL ); - -debug_writel (0x03 ); -while (start < blk_end) { -l2x0_flush_line (start); - start +=CACHE_LINE_SIZE ; - } -debug_writel (0x00 ); - -if (blk_end < end) { -raw_spin_unlock_irqrestore (&l2x0_lock, flags); -raw_spin_lock_irqsave (&l2x0_lock, flags); - } - } -cache_wait (base +L2X0_CLEAN_INV_LINE_PA ,1 ); -cache_sync (); -raw_spin_unlock_irqrestore (&l2x0_lock, flags); -} -static void l2x0_disable (void ) {unsigned long flags;
@@ -345,49 +185,6 @@ static void l2x0_disable(void)raw_spin_unlock_irqrestore (&l2x0_lock, flags); } -static void l2x0_enable (void __iomem *base,u32 aux,unsigned num_lock) -{ -unsigned id; - - id =readl_relaxed (base +L2X0_CACHE_ID ) &L2X0_CACHE_ID_PART_MASK ; -if (id ==L2X0_CACHE_ID_PART_L310 ) - num_lock =8 ; -else - num_lock =1 ; - -/* l2x0 controller is disabled */ -writel_relaxed (aux, base +L2X0_AUX_CTRL ); - -/* Make sure that I&D is not locked down when starting */ -l2c_unlock (base, num_lock); - -l2x0_inv_all (); - -/* enable L2X0 */ -writel_relaxed (L2X0_CTRL_EN , base +L2X0_CTRL ); -} - -static void l2x0_resume (void ) -{ -void __iomem *base = l2x0_base; - -if (!(readl_relaxed (base +L2X0_CTRL ) &L2X0_CTRL_EN )) -l2x0_enable (base, l2x0_saved_regs.aux_ctrl,0 ); -} - -static const struct l2c_init_data l2x0_init_fns__initconst = { - .enable = l2x0_enable, - .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = l2x0_resume, - }, -}; -/* * L2C-210 specific code. *
@@ -966,9 +763,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)switch (cache_id &L2X0_CACHE_ID_PART_MASK ) {default : - data = &l2x0_init_fns; -break ; -case L2X0_CACHE_ID_PART_L210 : data = &l2c210_data;break ;
Signature · 1 line
1.8.3.1
PATCH 37/222 ARM: l2c: move type string into l2c_init_data structure
In reply to Russell King - ARM LinuxRather than decoding this from the ID register, store it in the l2c_init_data structure. This simplifies things some more, and allows us to better provide further details as to how we're driving the cache. We print the cache ID value anyway should we need to precisely identify the cache hardware.
--- arch/arm/mm/cache-l2x0.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
arch/arm/mm/cache-l2x0.c +13 -7
@@ -29,6 +29,7 @@#include "cache-aurora-l2.h" struct l2c_init_data { +const char *type;unsigned num_lock;void (*of_parse)(const struct device_node *,u32 *,u32 *);void (*enable)(void __iomem *,u32 ,unsigned );
@@ -274,6 +275,7 @@ static void l2c210_resume(void) }static const struct l2c_init_data l2c210_data__initconst = { + .type ="L2C-210" , .num_lock =1 , .enable = l2c_enable, .outer_cache = {
@@ -416,6 +418,7 @@ static void l2c220_sync(void) }static const struct l2c_init_data l2c220_data = { + .type ="L2C-220" , .num_lock =1 , .enable = l2c_enable, .outer_cache = {
@@ -650,6 +653,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, }static const struct l2c_init_data l2c310_init_fns__initconst = { + .type ="L2C-310" , .num_lock =8 , .enable = l2c_enable, .fixup = l2c310_fixup,
@@ -674,7 +678,6 @@ static void __init __l2c_init(const struct l2c_init_data *data,u32 way_size =0 ;int ways;int way_size_shift =L2X0_WAY_SIZE_SHIFT ; -const char *type;/* * It is strange to save the register state before initialisation,
@@ -695,25 +698,21 @@ static void __init __l2c_init(const struct l2c_init_data *data, ways =16 ; else ways =8 ; - type ="L310" ;break ;case L2X0_CACHE_ID_PART_L210 : ways = (aux >>13 ) &0xf ; - type ="L210" ;break ;case AURORA_CACHE_ID : ways = (aux >>13 ) &0xf ; ways =2 << ((ways +1 ) >>2 ); way_size_shift =AURORA_WAY_SIZE_SHIFT ; - type ="Aurora" ;break ;default :/* Assume unknown chips have 8 ways */ ways =8 ; - type ="L2x0 series" ;break ; }
@@ -747,9 +746,9 @@ static void __init __l2c_init(const struct l2c_init_data *data, outer_cache = fns;pr_info ("%s cache controller enabled, %d ways, %d kB\n" , - type, ways, l2x0_size >>10 ); + data->type, ways, l2x0_size >>10 );pr_info ("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n" , - type, cache_id, aux); + data->type, cache_id, aux); }void __init l2x0_init (void __iomem *base,u32 aux_val,u32 aux_mask)
@@ -821,6 +820,7 @@ static void __init l2x0_of_parse(const struct device_node *np, }static const struct l2c_init_data of_l2c210_data__initconst = { + .type ="L2C-210" , .num_lock =1 , .of_parse = l2x0_of_parse, .enable = l2c_enable,
@@ -836,6 +836,7 @@ static const struct l2c_init_data of_l2c210_data __initconst = { };static const struct l2c_init_data of_l2c220_data__initconst = { + .type ="L2C-220" , .num_lock =1 , .of_parse = l2x0_of_parse, .enable = l2c_enable,
@@ -885,6 +886,7 @@ static void __init l2c310_of_parse(const struct device_node *np, }static const struct l2c_init_data of_l2c310_data__initconst = { + .type ="L2C-310" , .num_lock =8 , .of_parse = l2c310_of_parse, .enable = l2c_enable,
@@ -1063,6 +1065,7 @@ static void __init aurora_of_parse(const struct device_node *np, }static const struct l2c_init_data of_aurora_with_outer_data__initconst = { + .type ="Aurora" , .num_lock =4 , .of_parse = aurora_of_parse, .enable = l2c_enable,
@@ -1080,6 +1083,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { };static const struct l2c_init_data of_aurora_no_outer_data__initconst = { + .type ="Aurora" , .num_lock =4 , .of_parse = aurora_of_parse, .enable = aurora_enable_no_outer,
@@ -1228,6 +1232,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end)/* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */ static const struct l2c_init_data of_bcm_l2x0_data__initconst = { + .type ="BCM-L2C-310" , .num_lock =8 , .of_parse = l2c310_of_parse, .enable = l2c_enable,
@@ -1266,6 +1271,7 @@ static void tauros3_resume(void) }static const struct l2c_init_data of_tauros3_data__initconst = { + .type ="Tauros3" , .num_lock =8 , .enable = l2c_enable, .save = tauros3_save,
Signature · 1 line
1.8.3.1
PATCH 38/222 ARM: l2c: add decode for L2C-220 cache ways
In reply to Russell King - ARM LinuxRather than assuming these are always 8-way, it can be decoded from the auxillary register in the same manner as L2C-210.
--- arch/arm/mm/cache-l2x0.c | 1 + 1 file changed, 1 insertion(+)
arch/arm/mm/cache-l2x0.c +1 -0
@@ -701,6 +701,7 @@ static void __init __l2c_init(const struct l2c_init_data *data,break ;case L2X0_CACHE_ID_PART_L210 : +case L2X0_CACHE_ID_PART_L220 : ways = (aux >>13 ) &0xf ;break ;
Signature · 1 line
1.8.3.1
PATCH 39/222 ARM: l2c: move way size calculation data into l2c_init_data
In reply to Russell King - ARM LinuxMove the way size calculation data (base of way size) out of the switch statement into the provided initialisation data.
--- arch/arm/mm/cache-l2x0.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-)
arch/arm/mm/cache-l2x0.c +20 -9
@@ -30,6 +30,7 @@struct l2c_init_data {const char *type; +unsigned way_size_0;unsigned num_lock;void (*of_parse)(const struct device_node *,u32 *,u32 *);void (*enable)(void __iomem *,u32 ,unsigned );
@@ -276,6 +277,7 @@ static void l2c210_resume(void)static const struct l2c_init_data l2c210_data__initconst = { .type ="L2C-210" , + .way_size_0 =SZ_8K , .num_lock =1 , .enable = l2c_enable, .outer_cache = {
@@ -419,6 +421,7 @@ static void l2c220_sync(void)static const struct l2c_init_data l2c220_data = { .type ="L2C-220" , + .way_size_0 =SZ_8K , .num_lock =1 , .enable = l2c_enable, .outer_cache = {
@@ -654,6 +657,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id,static const struct l2c_init_data l2c310_init_fns__initconst = { .type ="L2C-310" , + .way_size_0 =SZ_8K , .num_lock =8 , .enable = l2c_enable, .fixup = l2c310_fixup,
@@ -674,10 +678,8 @@ static void __init __l2c_init(const struct l2c_init_data *data, u32 aux_val, u32 aux_mask, u32 cache_id) { struct outer_cache_fns fns; +unsigned way_size_bits, ways;u32 aux; -u32 way_size =0 ; -int ways; -int way_size_shift =L2X0_WAY_SIZE_SHIFT ;/* * It is strange to save the register state before initialisation,
@@ -708,7 +710,6 @@ static void __init __l2c_init(const struct l2c_init_data *data,case AURORA_CACHE_ID : ways = (aux >>13 ) &0xf ; ways =2 << ((ways +1 ) >>2 ); - way_size_shift =AURORA_WAY_SIZE_SHIFT ;break ;default :
@@ -720,12 +721,15 @@ static void __init __l2c_init(const struct l2c_init_data *data, l2x0_way_mask = (1 << ways) -1 ;/* -* L2 cache Size = Way size * Number of ways +* way_size_0 is the size that a way_size value of zero would be +* given the calculation: way_size = way_size_0 << way_size_bits. +* So, if way_size_bits=0 is reserved, but way_size_bits=1 is 16k, +* then way_size_0 would be 8k. +* +* L2 cache size = number of ways * way size. */ - way_size = (aux &L2X0_AUX_CTRL_WAY_SIZE_MASK ) >>17 ; - way_size =1 << (way_size + way_size_shift); - - l2x0_size = ways * way_size *SZ_1K ; + way_size_bits = (aux &L2X0_AUX_CTRL_WAY_SIZE_MASK ) >>17 ; + l2x0_size = ways * (data->way_size_0 << way_size_bits); fns = data->outer_cache;if (data->fixup)
@@ -822,6 +826,7 @@ static void __init l2x0_of_parse(const struct device_node *np,static const struct l2c_init_data of_l2c210_data__initconst = { .type ="L2C-210" , + .way_size_0 =SZ_8K , .num_lock =1 , .of_parse = l2x0_of_parse, .enable = l2c_enable,
@@ -838,6 +843,7 @@ static const struct l2c_init_data of_l2c210_data __initconst = {static const struct l2c_init_data of_l2c220_data__initconst = { .type ="L2C-220" , + .way_size_0 =SZ_8K , .num_lock =1 , .of_parse = l2x0_of_parse, .enable = l2c_enable,
@@ -888,6 +894,7 @@ static void __init l2c310_of_parse(const struct device_node *np,static const struct l2c_init_data of_l2c310_data__initconst = { .type ="L2C-310" , + .way_size_0 =SZ_8K , .num_lock =8 , .of_parse = l2c310_of_parse, .enable = l2c_enable,
@@ -1067,6 +1074,7 @@ static void __init aurora_of_parse(const struct device_node *np,static const struct l2c_init_data of_aurora_with_outer_data__initconst = { .type ="Aurora" , + .way_size_0 =SZ_4K , .num_lock =4 , .of_parse = aurora_of_parse, .enable = l2c_enable,
@@ -1085,6 +1093,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = {static const struct l2c_init_data of_aurora_no_outer_data__initconst = { .type ="Aurora" , + .way_size_0 =SZ_4K , .num_lock =4 , .of_parse = aurora_of_parse, .enable = aurora_enable_no_outer,
@@ -1234,6 +1243,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end)/* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */ static const struct l2c_init_data of_bcm_l2x0_data__initconst = { .type ="BCM-L2C-310" , + .way_size_0 =SZ_8K , .num_lock =8 , .of_parse = l2c310_of_parse, .enable = l2c_enable,
@@ -1273,6 +1283,7 @@ static void tauros3_resume(void)static const struct l2c_init_data of_tauros3_data__initconst = { .type ="Tauros3" , + .way_size_0 =SZ_8K , .num_lock =8 , .enable = l2c_enable, .save = tauros3_save,
Signature · 1 line
1.8.3.1
PATCH 40/222 ARM: l2c: move errata configuration options to arch/arm/mm/Kconfig
In reply to Russell King - ARM LinuxMove the L2C-310 errata configuration options to arch/arm/mm/Kconfig along side the option which enables support for this device.
--- arch/arm/Kconfig | 51 --------------------------------------------------- arch/arm/mm/Kconfig | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 51 deletions(-)
arch/arm/Kconfig +0 -51
@@ -1229,19 +1229,6 @@ config ARM_ERRATA_742231 register of the Cortex-A9 which reduces the linefill issuing capabilities of the processor. -config PL310_ERRATA_588369 - bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines" - depends on CACHE_L2X0 - help - The PL310 L2 cache controller implements three types of Clean & - Invalidate maintenance operations: by Physical Address - (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC). - They are architecturally defined to behave as the execution of a - clean operation followed immediately by an invalidate operation, - both performing to the same memory location. This functionality - is not correctly implemented in PL310 as clean lines are not - invalidated as a result of these operations. - config ARM_ERRATA_643719 bool "ARM errata: LoUIS bit field in CLIDR register is incorrect" depends on CPU_V7 && SMP
@@ -1264,17 +1251,6 @@ config ARM_ERRATA_720789 tables. The workaround changes the TLB flushing routines to invalidate entries regardless of the ASID. -config PL310_ERRATA_727915 - bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption" - depends on CACHE_L2X0 - help - PL310 implements the Clean & Invalidate by Way L2 cache maintenance - operation (offset 0x7FC). This operation runs in background so that - PL310 can handle normal accesses while it is in progress. Under very - rare circumstances, due to this erratum, write data can be lost when - PL310 treats a cacheable write transaction during a Clean & - Invalidate by Way operation. - config ARM_ERRATA_743622 bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption" depends on CPU_V7
@@ -1300,21 +1276,6 @@ config ARM_ERRATA_751472 operation is received by a CPU before the ICIALLUIS has completed, potentially leading to corrupted entries in the cache or TLB. -config PL310_ERRATA_753970 - bool "PL310 errata: cache sync operation may be faulty" - depends on CACHE_PL310 - help - This option enables the workaround for the 753970 PL310 (r3p0) erratum. - - Under some condition the effect of cache sync operation on - the store buffer still remains when the operation completes. - This means that the store buffer is always asked to drain and - this prevents it from merging any further writes. The workaround - is to replace the normal offset of cache sync operation (0x730) - by another offset targeting an unmapped PL310 register 0x740. - This has the same effect as the cache sync operation: store buffer - drain and waiting for all buffers empty. - config ARM_ERRATA_754322 bool "ARM errata: possible faulty MMU translations following an ASID switch" depends on CPU_V7
@@ -1363,18 +1324,6 @@ config ARM_ERRATA_764369 relevant cache maintenance functions and sets a specific bit in the diagnostic control register of the SCU. -config PL310_ERRATA_769419 - bool "PL310 errata: no automatic Store Buffer drain" - depends on CACHE_L2X0 - help - On revisions of the PL310 prior to r3p2, the Store Buffer does - not automatically drain. This can cause normal, non-cacheable - writes to be retained when the memory system is idle, leading - to suboptimal I/O performance for drivers using coherent DMA. - This option adds a write barrier to the cpu_idle loop so that, - on systems with an outer cache, the store buffer is drained - explicitly. - config ARM_ERRATA_775420 bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock" depends on CPU_V7
arch/arm/mm/Kconfig +51 -0
57 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 41/222 ARM: l2c: provide generic hook to intercept writes to secure registers
In reply to Russell King - ARM LinuxWhen Linux is running in the non-secure world, any write to a secure L2C register will generate an abort. Platforms normally have to call firmware to work around this. Provide a hook for them to intercept any L2C secure register write.
l2c_write_sec() avoids writes to secure registers which are already set to the appropriate value, thus avoiding the overhead of needlessly calling into the secure monitor.
--- arch/arm/include/asm/outercache.h | 5 ++++- arch/arm/mm/cache-l2x0.c | 42 ++++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 13 deletions(-)
arch/arm/include/asm/outercache.h +4 -1
@@ -33,8 +33,11 @@ struct outer_cache_fns {#ifdef CONFIG_OUTER_CACHE_SYNC void (*sync)(void );#endif -void (*set_debug)(unsigned long );void (*resume)(void ); + +/* This is an ARM L2C thing */ +void (*set_debug)(unsigned long ); +void (*write_sec)(unsigned long ,unsigned ); };extern struct outer_cache_fns outer_cache;
arch/arm/mm/cache-l2x0.c +30 -12
99 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 42/222 ARM: l2c: omap2: implement new write_sec method
In reply to Russell King - ARM LinuxWith the write_sec method, we no longer need to override the default L2C disable method, and we no longer need the L2C set_debug method. Both of these can be handled via the write_sec method.
--- arch/arm/mach-omap2/omap4-common.c | 42 +++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 16 deletions(-)
arch/arm/mach-omap2/omap4-common.c +26 -16
@@ -167,17 +167,33 @@ void __iomem *omap4_get_l2cache_base(void)return l2cache_base; } -static void omap4_l2x0_disable (void ) +static void omap4_l2c310_write_sec (unsigned long val,unsigned reg) { -outer_flush_all (); -/* Disable PL310 L2 Cache controller */ -omap_smc1 (0x102 ,0x0 ); -} +unsigned smc_op; -static void omap4_l2x0_set_debug (unsigned long val) -{ -/* Program PL310 L2 Cache controller debug register */ -omap_smc1 (0x100 , val); +switch (reg) { +case L2X0_CTRL : + smc_op =OMAP4_MON_L2X0_CTRL_INDEX ; +break ; + +case L2X0_AUX_CTRL : + smc_op =OMAP4_MON_L2X0_AUXCTRL_INDEX ; +break ; + +case L2X0_DEBUG_CTRL : + smc_op =OMAP4_MON_L2X0_DBG_CTRL_INDEX ; +break ; + +case L310_PREFETCH_CTRL : + smc_op =OMAP4_MON_L2X0_PREFETCH_INDEX ; +break ; + +default : +WARN_ONCE (1 ,"OMAP L2C310: ignoring write to reg 0x%x\n" , reg); +return ; + } + +omap_smc1 (smc_op, val); }static int __init omap_l2_cache_init (void )
@@ -212,18 +228,12 @@ static int __init omap_l2_cache_init(void)/* Enable PL310 L2 Cache controller */ omap_smc1 (0x102 ,0x1 ); + outer_cache.write_sec = omap4_l2c310_write_sec;if (of_have_populated_dt ())l2x0_of_init (aux_ctrl,L2X0_AUX_CTRL_MASK );else l2x0_init (l2cache_base, aux_ctrl,L2X0_AUX_CTRL_MASK ); -/* -* Override default outer_cache.disable with a OMAP4 -* specific one -*/ - outer_cache.disable = omap4_l2x0_disable; - outer_cache.set_debug = omap4_l2x0_set_debug; -return 0 ; }omap_early_initcall (omap_l2_cache_init);
Signature · 1 line
1.8.3.1
PATCH 43/222 ARM: l2c: omap2: remove explicit SMI calls to enable L2 cache
In reply to Russell King - ARM LinuxNow that OMAP2 uses the write_sec method, we don't need to enable the L2 cache in OMAP2 specific code; this can be done via the normal mechanisms in the L2C code. Remove the OMAP2 specific code.
--- arch/arm/mach-omap2/omap4-common.c | 5 ----- 1 file changed, 5 deletions(-)
arch/arm/mach-omap2/omap4-common.c +0 -5
@@ -223,11 +223,6 @@ static int __init omap_l2_cache_init(void) (1 <<L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT ) | (1 <<L2X0_AUX_CTRL_EARLY_BRESP_SHIFT ); -omap_smc1 (0x109 , aux_ctrl); - -/* Enable PL310 L2 Cache controller */ -omap_smc1 (0x102 ,0x1 ); - outer_cache.write_sec = omap4_l2c310_write_sec;if (of_have_populated_dt ())l2x0_of_init (aux_ctrl,L2X0_AUX_CTRL_MASK );
Signature · 1 line
1.8.3.1
PATCH 44/222 ARM: l2c: highbank: implement new write_sec method
In reply to Russell King - ARM LinuxWith the write_sec method, we no longer need to override the default L2C disable method. This can be handled via the write_sec method instead.
--- arch/arm/mach-highbank/highbank.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
arch/arm/mach-highbank/highbank.c +7 -5
@@ -51,11 +51,13 @@ static void __init highbank_scu_map_io(void) } -static void highbank_l2x0_disable (void ) +static void highbank_l2c310_write_sec (unsigned long val,unsigned reg) { -outer_flush_all (); -/* Disable PL310 L2 Cache controller */ -highbank_smc1 (0x102 ,0x0 ); +if (reg ==L2X0_CTRL ) +highbank_smc1 (0x102 , val); +else +WARN_ONCE (1 ,"Highbank L2C310: ignoring write to reg 0x%x\n" , + reg); }static void __init highbank_init_irq (void )
@@ -69,8 +71,8 @@ static void __init highbank_init_irq(void)if (IS_ENABLED (CONFIG_CACHE_L2X0 ) &&of_find_compatible_node (NULL ,NULL ,"arm,pl310-cache" )) {highbank_smc1 (0x102 ,0x1 ); + outer_cache.write_sec = highbank_l2c310_write_sec;l2x0_of_init (0 , ~0 ); - outer_cache.disable = highbank_l2x0_disable; } }
Signature · 1 line
1.8.3.1
PATCH 45/222 ARM: l2c: highbank: remove explicit SMI call in L2 cache initialisation
In reply to Russell King - ARM LinuxNow that highbank uses the write_sec method, we don't need to enable the L2 cache in SoC specific code; this can be done via the normal mechanisms in the L2C code.
Checking with Rob Herring:
Quoted 7 lines
Quoted 3 lines
Can we kill the "
highbank_smc1(0x102, 0x1);" here? That meansl2x0_of_init()will see the L2 cache disabled, and will try to enable it via thewrite_sechook, so it should do the right thing.Yes, that should work. You should be able to just call
l2x0_of_initunconditionally. The condition was really to just avoid the smc on Midway which does get handled on h/w, but not if running virtualized.
So also drop the DT check too. I'm leaving the config check in place so that if L2 is disabled, the write_sec hook can be optimised away.
--- arch/arm/mach-highbank/highbank.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/arm/mach-highbank/highbank.c +1 -3
@@ -68,9 +68,7 @@ static void __init highbank_init_irq(void)highbank_scu_map_io ();/* Enable PL310 L2 Cache controller */ -if (IS_ENABLED (CONFIG_CACHE_L2X0 ) && -of_find_compatible_node (NULL ,NULL ,"arm,pl310-cache" )) { -highbank_smc1 (0x102 ,0x1 ); +if (IS_ENABLED (CONFIG_CACHE_L2X0 )) { outer_cache.write_sec = highbank_l2c310_write_sec;l2x0_of_init (0 , ~0 ); }
Signature · 1 line
1.8.3.1
PATCH 46/222 ARM: l2c: ux500: implement dummy write_sec method
In reply to Russell King - ARM Linuxux500 can't write to any of the secure registers on the L2C controllers, so provide a dummy handler which ignores all writes.
--- arch/arm/mach-ux500/cache-l2x0.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
arch/arm/mach-ux500/cache-l2x0.c +10 -9
@@ -35,6 +35,14 @@ static int __init ux500_l2x0_unlock(void)return 0 ; } +static void ux500_l2c310_write_sec (unsigned long val,unsigned reg) +{ +/* +* We can't write to secure registers as we are in non-secure +* mode, until we have some SMI service available. +*/ +} +static int __init ux500_l2x0_init (void ) {u32 aux_val =0x3e000000 ;
@@ -56,21 +64,14 @@ static int __init ux500_l2x0_init(void)/* 64KB way size */ aux_val |= (0x3 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ); + outer_cache.write_sec = ux500_l2c310_write_sec; +/* 64KB way size, 8 way associativity, force WA */ if (of_have_populated_dt ())l2x0_of_init (aux_val,0xc0000fff );else l2x0_init (l2x0_base, aux_val,0xc0000fff ); -/* -* We can't disable l2 as we are in non secure mode, currently -* this seems be called only during kexec path. So let's -* override outer.disable with nasty assignment until we have -* some SMI service available. -*/ - outer_cache.disable =NULL ; - outer_cache.set_debug =NULL ; -return 0 ; }
Signature · 1 line
1.8.3.1
PATCH 47/222 ARM: l2c: remove old .set_debug method
In reply to Russell King - ARM LinuxWe no longer need or require the .set_debug method; we handle everything it used to do via the .write_sec method instead.
--- arch/arm/include/asm/outercache.h | 1 - arch/arm/mm/cache-l2x0.c | 21 ++------------------- 2 files changed, 2 insertions(+), 20 deletions(-)
arch/arm/include/asm/outercache.h +0 -1
@@ -36,7 +36,6 @@ struct outer_cache_fns {void (*resume)(void );/* This is an ARM L2C thing */ -void (*set_debug)(unsigned long );void (*write_sec)(unsigned long ,unsigned ); };
arch/arm/mm/cache-l2x0.c +2 -19
@@ -80,10 +80,7 @@ static void l2c_write_sec(unsigned long val, void __iomem *base, unsigned reg)*/ static inline void l2c_set_debug (void __iomem *base,unsigned long val) { -if (outer_cache.set_debug) - outer_cache.set_debug (val); -else -l2c_write_sec (val, base,L2X0_DEBUG_CTRL ); +l2c_write_sec (val, base,L2X0_DEBUG_CTRL ); }static void __l2c_op_way (void __iomem *reg)
@@ -154,8 +151,7 @@ static inline void cache_sync(void)#if defined(CONFIG_PL310_ERRATA_588369 ) || defined(CONFIG_PL310_ERRATA_727915 )static inline void debug_writel (unsigned long val) { -if (outer_cache.set_debug || outer_cache.write_sec) -l2c_set_debug (l2x0_base, val); +l2c_set_debug (l2x0_base, val); }#else /* Optimised out for non-errata case */
@@ -489,11 +485,6 @@ static const struct l2c_init_data l2c220_data = {* Affects: store buffer * store buffer is not automatically drained. */ -static void l2c310_set_debug (unsigned long val) -{ -writel_relaxed (val, l2x0_base +L2X0_DEBUG_CTRL ); -} -static void l2c310_inv_range_erratum (unsigned long start,unsigned long end) {void __iomem *base = l2x0_base;
@@ -631,10 +622,6 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id,const char *errata[4 ];unsigned n =0 ; -/* For compatibility */ -if (revision <=L310_CACHE_ID_RTL_R3P0 ) - fns->set_debug = l2c310_set_debug; - if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) && revision < L310_CACHE_ID_RTL_R2P0 &&/* For bcm compatibility */
@@ -684,7 +671,6 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .flush_all = l2c210_flush_all, .disable = l2c_disable, .sync = l2c210_sync, - .set_debug = l2c310_set_debug, .resume = l2c310_resume, }, };
@@ -750,8 +736,6 @@ static void __init __l2c_init(const struct l2c_init_data *data, fns.write_sec = outer_cache.write_sec;if (data->fixup) data->fixup (l2x0_base, cache_id, &fns); -if (fns.write_sec) - fns.set_debug =NULL ;/* * Check if l2x0 controller is already enabled. If we are booting
@@ -925,7 +909,6 @@ static const struct l2c_init_data of_l2c310_data __initconst = { .flush_all = l2c210_flush_all, .disable = l2c_disable, .sync = l2c210_sync, - .set_debug = l2c310_set_debug, .resume = l2c310_resume, }, };
Signature · 1 line
1.8.3.1
PATCH 48/222 ARM: l2c: implement L2C-310 erratum 752271 in core L2C code
In reply to Russell King - ARM LinuxRather than having SoCs work around L2C erratum themselves, move them into core code. This erratum affects the double linefill feature which needs to be disabled for r3p0 to r3p1-50rel0.
--- arch/arm/mm/cache-l2x0.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
arch/arm/mm/cache-l2x0.c +17 -1
@@ -476,6 +476,11 @@ static const struct l2c_init_data l2c220_data = {* hit the line between the clean operation and invalidate operation, * resulting in the store being lost. * +* 752271: PL310 R3P0->R3P1-50REL0, fixed R3P2. +* Affects: 8x64-bit (double fill) line fetches +* double fill line fetches can fail to cause dirty data to be evicted +* from the cache before the new data overwrites the second line. +* * 753970: PL310 R3P0, fixed R3P1. * Affects: sync * prevents merging writes after the sync operation, until another L2C
@@ -619,7 +624,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, struct outer_cache_fns *fns) {unsigned revision = cache_id &L2X0_CACHE_ID_RTL_MASK ; -const char *errata[4 ]; +const char *errata[8 ];unsigned n =0 ; if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) &&
@@ -638,6 +643,17 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, errata[n++] ="727915" ; } +if (revision >=L310_CACHE_ID_RTL_R3P0 && + revision <L310_CACHE_ID_RTL_R3P2 ) { +u32 val =readl_relaxed (base +L2X0_PREFETCH_CTRL ); +/* I don't think bit23 is required here... but iMX6 does so */ +if (val & (BIT (30 ) |BIT (23 ))) { + val &= ~(BIT (30 ) |BIT (23 )); +l2c_write_sec (val, base,L2X0_PREFETCH_CTRL ); + errata[n++] ="752271" ; + } + } +if (IS_ENABLED (CONFIG_PL310_ERRATA_753970 ) && revision ==L310_CACHE_ID_RTL_R3P0 ) { sync_reg_offset =L2X0_DUMMY_REG ;
Signature · 1 line
1.8.3.1
PATCH 49/222 ARM: l2c: fix register naming
In reply to Russell King - ARM LinuxWe have a mixture of different devices with different register layouts, but we group all the bits together in an opaque mess. Split them out into those which are L2C-310 specific and ones which refer to earlier devices. Provide full auxiliary control register definitions.
--- arch/arm/include/asm/hardware/cache-l2x0.h | 73 ++++++++++++++++++++---------- arch/arm/mach-cns3xxx/core.c | 8 ++-- arch/arm/mach-exynos/sleep.S | 8 ++-- arch/arm/mach-imx/system.c | 8 ++-- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 2 +- arch/arm/mach-omap2/omap4-common.c | 18 ++++---- arch/arm/mach-prima2/l2x0.c | 5 +- arch/arm/mach-realview/realview_pbx.c | 4 +- arch/arm/mach-spear/spear13xx.c | 6 +-- arch/arm/mach-sti/board-dt.c | 8 ++-- arch/arm/mach-tegra/sleep.h | 8 ++-- arch/arm/mach-ux500/cache-l2x0.c | 4 +- arch/arm/mach-vexpress/ct-ca9x4.c | 4 +- arch/arm/mm/cache-l2x0.c | 57 +++++++++++------------ 14 files changed, 118 insertions(+), 95 deletions(-)
arch/arm/include/asm/hardware/cache-l2x0.h +48 -25
@@ -26,8 +26,8 @@#define L2X0_CACHE_TYPE 0x004#define L2X0_CTRL 0x100#define L2X0_AUX_CTRL 0x104 -#define L2X0_TAG_LATENCY_CTRL 0x108 -#define L2X0_DATA_LATENCY_CTRL 0x10C +#define L310_TAG_LATENCY_CTRL 0x108 +#define L310_DATA_LATENCY_CTRL 0x10C#define L2X0_EVENT_CNT_CTRL 0x200#define L2X0_EVENT_CNT1_CFG 0x204#define L2X0_EVENT_CNT0_CFG 0x208
@@ -54,16 +54,16 @@#define L2X0_LOCKDOWN_WAY_D_BASE 0x900#define L2X0_LOCKDOWN_WAY_I_BASE 0x904#define L2X0_LOCKDOWN_STRIDE 0x08 -#define L2X0_ADDR_FILTER_START 0xC00 -#define L2X0_ADDR_FILTER_END 0xC04 +#define L310_ADDR_FILTER_START 0xC00 +#define L310_ADDR_FILTER_END 0xC04#define L2X0_TEST_OPERATION 0xF00#define L2X0_LINE_DATA 0xF10#define L2X0_LINE_TAG 0xF30#define L2X0_DEBUG_CTRL 0xF40 -#define L2X0_PREFETCH_CTRL 0xF60 -#define L2X0_POWER_CTRL 0xF80 -#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1) -#define L2X0_STNDBY_MODE_EN (1 << 0) +#define L310_PREFETCH_CTRL 0xF60 +#define L310_POWER_CTRL 0xF80 +#define L310_DYNAMIC_CLK_GATING_EN (1 << 1) +#define L310_STNDBY_MODE_EN (1 << 0)/* Registers shifts and masks */ #define L2X0_CACHE_ID_PART_MASK (0xf << 6)
@@ -88,29 +88,52 @@#define L310_CACHE_ID_RTL_R3P3 0x09#define L2X0_AUX_CTRL_MASK 0xc0000fff +/* L2C auxiliary control register - bits common to L2C-210/220/310 */ +#define L2C_AUX_CTRL_WAY_SIZE_SHIFT 17 +#define L2C_AUX_CTRL_WAY_SIZE_MASK (7 << 17) +#define L2C_AUX_CTRL_WAY_SIZE (n) ((n) << 17) +#define L2C_AUX_CTRL_EVTMON_ENABLE BIT(20) +#define L2C_AUX_CTRL_PARITY_ENABLE BIT(21) +#define L2C_AUX_CTRL_SHARED_OVERRIDE BIT(22) +/* L2C-210/220 common bits */ #define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0 -#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7 +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK (7 << 0)#define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3 -#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3) +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (7 << 3)#define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6 -#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6) +#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (7 << 6)#define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9 -#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9) -#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16 -#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17 -#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17) -#define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT 22 -#define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT 26 -#define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT 27 -#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28 -#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29 -#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30 +#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (7 << 9) +#define L2X0_AUX_CTRL_ASSOC_SHIFT 13 +#define L2X0_AUX_CTRL_ASSOC_MASK (15 << 13) +/* L2C-210 specific bits */ +#define L210_AUX_CTRL_WRAP_DISABLE BIT(12) +#define L210_AUX_CTRL_WA_OVERRIDE BIT(23) +#define L210_AUX_CTRL_EXCLUSIVE_ABORT BIT(24) +/* L2C-220 specific bits */ +#define L220_AUX_CTRL_EXCLUSIVE_CACHE BIT(12) +#define L220_AUX_CTRL_FWA_SHIFT 23 +#define L220_AUX_CTRL_FWA_MASK (3 << 23) +#define L220_AUX_CTRL_NS_LOCKDOWN BIT(26) +#define L220_AUX_CTRL_NS_INT_CTRL BIT(27) +/* L2C-310 specific bits */ +#define L310_AUX_CTRL_FULL_LINE_ZERO BIT(0)/* R2P0+ */ +#define L310_AUX_CTRL_HIGHPRIO_SO_DEV BIT(10)/* R2P0+ */ +#define L310_AUX_CTRL_STORE_LIMITATION BIT(11)/* R2P0+ */ +#define L310_AUX_CTRL_EXCLUSIVE_CACHE BIT(12) +#define L310_AUX_CTRL_ASSOCIATIVITY_16 BIT(16) +#define L310_AUX_CTRL_CACHE_REPLACE_RR BIT(25)/* R2P0+ */ +#define L310_AUX_CTRL_NS_LOCKDOWN BIT(26) +#define L310_AUX_CTRL_NS_INT_CTRL BIT(27) +#define L310_AUX_CTRL_DATA_PREFETCH BIT(28) +#define L310_AUX_CTRL_INSTR_PREFETCH BIT(29) +#define L310_AUX_CTRL_EARLY_BRESP BIT(30)/* R2P0+ */ -#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0 -#define L2X0_LATENCY_CTRL_RD_SHIFT 4 -#define L2X0_LATENCY_CTRL_WR_SHIFT 8 +#define L310_LATENCY_CTRL_SETUP (n) ((n) << 0) +#define L310_LATENCY_CTRL_RD (n) ((n) << 4) +#define L310_LATENCY_CTRL_WR (n) ((n) << 8) -#define L2X0_ADDR_FILTER_EN 1 +#define L310_ADDR_FILTER_EN 1#define L2X0_CTRL_EN 1
arch/arm/mach-cns3xxx/core.c +4 -4
@@ -272,9 +272,9 @@ void __init cns3xxx_l2x0_init(void)* * 1 cycle of latency for setup, read and write accesses */ - val =readl (base +L2X0_TAG_LATENCY_CTRL ); + val =readl (base +L310_TAG_LATENCY_CTRL ); val &=0xfffff888 ; -writel (val, base +L2X0_TAG_LATENCY_CTRL ); +writel (val, base +L310_TAG_LATENCY_CTRL );/* * Data RAM Control register
@@ -285,9 +285,9 @@ void __init cns3xxx_l2x0_init(void)* * 1 cycle of latency for setup, read and write accesses */ - val =readl (base +L2X0_DATA_LATENCY_CTRL ); + val =readl (base +L310_DATA_LATENCY_CTRL ); val &=0xfffff888 ; -writel (val, base +L2X0_DATA_LATENCY_CTRL ); +writel (val, base +L310_DATA_LATENCY_CTRL );/* 32 KiB, 8-way, parity disable */ l2x0_init (base,0x00540000 ,0xfe000fff );
arch/arm/mach-exynos/sleep.S +4 -4
@@ -65,13 +65,13 @@ ENTRY(exynos_cpu_resume) ldr r2, [r0, #L2X0_R_AUX_CTRL] str r2, [r1, #L2X0_AUX_CTRL] ldr r2, [r0, #L2X0_R_TAG_LATENCY] - str r2, [r1, #L2X0_TAG_LATENCY_CTRL] + str r2, [r1, #L310_TAG_LATENCY_CTRL] ldr r2, [r0, #L2X0_R_DATA_LATENCY] - str r2, [r1, #L2X0_DATA_LATENCY_CTRL] + str r2, [r1, #L310_DATA_LATENCY_CTRL] ldr r2, [r0, #L2X0_R_PREFETCH_CTRL] - str r2, [r1, #L2X0_PREFETCH_CTRL] + str r2, [r1, #L310_PREFETCH_CTRL] ldr r2, [r0, #L2X0_R_PWR_CTRL] - str r2, [r1, #L2X0_POWER_CTRL] + str r2, [r1, #L310_POWER_CTRL] mov r2, #1 str r2, [r1, #L2X0_CTRL] skip_l2_resume:
arch/arm/mach-imx/system.c +4 -4
@@ -124,7 +124,7 @@ void __init imx_init_l2cache(void) }/* Configure the L2 PREFETCH and POWER registers */ - val =readl_relaxed (l2x0_base +L2X0_PREFETCH_CTRL ); + val =readl_relaxed (l2x0_base +L310_PREFETCH_CTRL ); val |=0x70800000 ;/* * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0
@@ -137,9 +137,9 @@ void __init imx_init_l2cache(void)*/ if (cpu_is_imx6q ()) val &= ~(1 <<30 |1 <<23 ); -writel_relaxed (val, l2x0_base +L2X0_PREFETCH_CTRL ); - val =L2X0_DYNAMIC_CLK_GATING_EN |L2X0_STNDBY_MODE_EN ; -writel_relaxed (val, l2x0_base +L2X0_POWER_CTRL ); +writel_relaxed (val, l2x0_base +L310_PREFETCH_CTRL ); + val =L310_DYNAMIC_CLK_GATING_EN |L310_STNDBY_MODE_EN ; +writel_relaxed (val, l2x0_base +L310_POWER_CTRL );iounmap (l2x0_base);of_node_put (np);
arch/arm/mach-omap2/omap-mpuss-lowpower.c +1 -1
@@ -194,7 +194,7 @@ static void save_l2x0_context(void)if (l2x0_base) { val =__raw_readl (l2x0_base +L2X0_AUX_CTRL );__raw_writel (val, sar_base +L2X0_AUXCTRL_OFFSET ); - val =__raw_readl (l2x0_base +L2X0_PREFETCH_CTRL ); + val =__raw_readl (l2x0_base +L310_PREFETCH_CTRL );__raw_writel (val, sar_base +L2X0_PREFETCH_CTRL_OFFSET ); } }
arch/arm/mach-omap2/omap4-common.c +9 -9
@@ -213,15 +213,15 @@ static int __init omap_l2_cache_init(void)return -ENOMEM ;/* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ - aux_ctrl = (1 <<L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT ) | - (0x1 <<25 ) | - (0x1 <<L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT ) | - (0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT)) | - (0x3 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ) | - (1 <<L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT ) | - (1 <<L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT ) | - (1 <<L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT ) | - (1 <<L2X0_AUX_CTRL_EARLY_BRESP_SHIFT ); + aux_ctrl =L310_AUX_CTRL_ASSOCIATIVITY_16 | +L310_AUX_CTRL_CACHE_REPLACE_RR | +L310_AUX_CTRL_NS_LOCKDOWN | +L310_AUX_CTRL_NS_INT_CTRL | +L2C_AUX_CTRL_WAY_SIZE (3 ) | +L2C_AUX_CTRL_SHARED_OVERRIDE | +L310_AUX_CTRL_DATA_PREFETCH | +L310_AUX_CTRL_INSTR_PREFETCH | +L310_AUX_CTRL_EARLY_BRESP ; outer_cache.write_sec = omap4_l2c310_write_sec;if (of_have_populated_dt ())
arch/arm/mach-prima2/l2x0.c +2 -3
@@ -17,13 +17,12 @@ struct l2x0_aux { };static const struct l2x0_aux prima2_l2x0_aux__initconst = { - .val =2 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT , + .val =L2C_AUX_CTRL_WAY_SIZE (2 ), .mask =0 , };static const struct l2x0_aux marco_l2x0_aux__initconst = { - .val = (2 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ) | - (1 <<L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT ), + .val =L2C_AUX_CTRL_WAY_SIZE (2 ) |L310_AUX_CTRL_ASSOCIATIVITY_16 , .mask =L2X0_AUX_CTRL_MASK , };
arch/arm/mach-realview/realview_pbx.c +2 -2
@@ -370,8 +370,8 @@ static void __init realview_pbx_init(void)__io_address (REALVIEW_PBX_TILE_L220_BASE );/* set RAM latencies to 1 cycle for eASIC */ -writel (0 , l2x0_base +L2X0_TAG_LATENCY_CTRL ); -writel (0 , l2x0_base +L2X0_DATA_LATENCY_CTRL ); +writel (0 , l2x0_base +L310_TAG_LATENCY_CTRL ); +writel (0 , l2x0_base +L310_DATA_LATENCY_CTRL );/* 16KB way size, 8-way associativity, parity disabled * Bits: .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */
arch/arm/mach-spear/spear13xx.c +3 -3
@@ -38,14 +38,14 @@ void __init spear13xx_l2x0_init(void)if (!IS_ENABLED (CONFIG_CACHE_L2X0 ))return ; -writel_relaxed (0x06 ,VA_L2CC_BASE +L2X0_PREFETCH_CTRL ); +writel_relaxed (0x06 ,VA_L2CC_BASE +L310_PREFETCH_CTRL );/* * Program following latencies in order to make * SPEAr1340 work@600 MHz */ -writel_relaxed (0x221 ,VA_L2CC_BASE +L2X0_TAG_LATENCY_CTRL ); -writel_relaxed (0x441 ,VA_L2CC_BASE +L2X0_DATA_LATENCY_CTRL ); +writel_relaxed (0x221 ,VA_L2CC_BASE +L310_TAG_LATENCY_CTRL ); +writel_relaxed (0x441 ,VA_L2CC_BASE +L310_DATA_LATENCY_CTRL );l2x0_init (VA_L2CC_BASE ,0x70A60001 ,0xfe00ffff ); }
arch/arm/mach-sti/board-dt.c +4 -4
@@ -19,10 +19,10 @@ void __init stih41x_l2x0_init(void)u32 way_size =0x4 ;u32 aux_ctrl;/* may be this can be encoded in macros like BIT*() */ - aux_ctrl = (0x1 <<L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT ) | - (0x1 <<L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT ) | - (0x1 <<L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT ) | - (way_size <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ); + aux_ctrl =L2C_AUX_CTRL_SHARED_OVERRIDE | +L310_AUX_CTRL_DATA_PREFETCH | +L310_AUX_CTRL_INSTR_PREFETCH | +L2C_AUX_CTRL_WAY_SIZE (way_size);l2x0_of_init (aux_ctrl,L2X0_AUX_CTRL_MASK ); }
arch/arm/mach-tegra/sleep.h +4 -4
@@ -134,13 +134,13 @@ tst \tmp3, #L2X0_CTRL_ENbne exit_l2_resume ldr \tmp3, [\tmp1, #L2X0_R_TAG_LATENCY] - str \tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL] + str \tmp3, [\tmp2, #L310_TAG_LATENCY_CTRL] ldr \tmp3, [\tmp1, #L2X0_R_DATA_LATENCY] - str \tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL] + str \tmp3, [\tmp2, #L310_DATA_LATENCY_CTRL] ldr \tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL] - str \tmp3, [\tmp2, #L2X0_PREFETCH_CTRL] + str \tmp3, [\tmp2, #L310_PREFETCH_CTRL] ldr \tmp3, [\tmp1, #L2X0_R_PWR_CTRL] - str \tmp3, [\tmp2, #L2X0_POWER_CTRL] + str \tmp3, [\tmp2, #L310_POWER_CTRL] ldr \tmp3, [\tmp1, #L2X0_R_AUX_CTRL] str \tmp3, [\tmp2, #L2X0_AUX_CTRL] mov \tmp3, #L2X0_CTRL_EN
arch/arm/mach-ux500/cache-l2x0.c +2 -2
@@ -59,10 +59,10 @@ static int __init ux500_l2x0_init(void)/* DBx540's L2 has 128KB way size */ if (cpu_is_ux540_family ())/* 128KB way size */ - aux_val |= (0x4 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ); + aux_val |=L2C_AUX_CTRL_WAY_SIZE (4 );else /* 64KB way size */ - aux_val |= (0x3 <<L2X0_AUX_CTRL_WAY_SIZE_SHIFT ); + aux_val |=L2C_AUX_CTRL_WAY_SIZE (3 ); outer_cache.write_sec = ux500_l2c310_write_sec;
arch/arm/mach-vexpress/ct-ca9x4.c +2 -2
@@ -145,8 +145,8 @@ static void __init ct_ca9x4_init(void)void __iomem *l2x0_base =ioremap (CT_CA9X4_L2CC ,SZ_4K );/* set RAM latencies to 1 cycle for this core tile. */ -writel (0 , l2x0_base +L2X0_TAG_LATENCY_CTRL ); -writel (0 , l2x0_base +L2X0_DATA_LATENCY_CTRL ); +writel (0 , l2x0_base +L310_TAG_LATENCY_CTRL ); +writel (0 , l2x0_base +L310_DATA_LATENCY_CTRL );l2x0_init (l2x0_base,0x00400000 ,0xfe0fffff );#endif
arch/arm/mm/cache-l2x0.c +29 -28
136 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 50/222 ARM: l2c: add automatic enable of early BRESP
In reply to Russell King - ARM LinuxThe AXI bus protocol requires that a write response should only be sent back to the master when the last write has been accepted. Early BRESP allows the L2C-310 to send the write response as soon as the store buffer accepts the write address.
Cortex-A9 processors can signal to the L2C-310 that they wish to be notified early, and if this optimisation is enabled, the L2C-310 can signal an early write response.
--- arch/arm/mm/cache-l2x0.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-)
arch/arm/mm/cache-l2x0.c +22 -3
@@ -24,6 +24,7 @@#include <linux/of_address.h> #include <asm/cacheflush.h> +#include <asm/cputype.h> #include <asm/hardware/cache-l2x0.h> #include "cache-tauros3.h" #include "cache-aurora-l2.h"
@@ -620,6 +621,24 @@ static void l2c310_resume(void) } } +static void __init l2c310_enable (void __iomem *base,u32 aux,unsigned num_lock) +{ +unsigned rev =readl_relaxed (base +L2X0_CACHE_ID ) &L2X0_CACHE_ID_PART_MASK ; +bool cortex_a9 =read_cpuid_part_number () ==ARM_CPU_PART_CORTEX_A9 ; + +if (rev >=L310_CACHE_ID_RTL_R2P0 ) { +if (cortex_a9) { + aux |=L310_AUX_CTRL_EARLY_BRESP ; +pr_info ("L2C-310 enabling early BRESP for Cortex-A9\n" ); + }else if (aux &L310_AUX_CTRL_EARLY_BRESP ) { +pr_warn ("L2C-310 early BRESP only supported with Cortex-A9\n" ); + aux &= ~L310_AUX_CTRL_EARLY_BRESP ; + } + } + +l2c_enable (base, aux, num_lock); +} +static void __init l2c310_fixup (void __iomem *base,u32 cache_id,struct outer_cache_fns *fns) {
@@ -677,7 +696,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .type = "L2C-310", .way_size_0 = SZ_8K, .num_lock = 8, - .enable = l2c_enable, + .enable = l2c310_enable, .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = {
@@ -916,7 +935,7 @@ static const struct l2c_init_data of_l2c310_data __initconst = { .way_size_0 = SZ_8K, .num_lock = 8, .of_parse = l2c310_of_parse, - .enable = l2c_enable, + .enable = l2c310_enable, .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = {
@@ -1264,7 +1283,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .way_size_0 = SZ_8K, .num_lock = 8, .of_parse = l2c310_of_parse, - .enable = l2c_enable, + .enable = l2c310_enable, .save = l2c310_save, .outer_cache = { .inv_range = bcm_inv_range,
Signature · 1 line
1.8.3.1
PATCH 51/222 ARM: l2c: remove platforms/SoCs setting early BRESP
In reply to Russell King - ARM LinuxSince we now automatically enable early BRESP in core L2C-310 code when we detect a Cortex-A9, we don't need platforms/SoCs to set this bit explicitly. Instead, they should seek to preserve the value of bit 30 in the auxiliary control register.
--- arch/arm/mach-berlin/berlin.c | 2 +- arch/arm/mach-exynos/exynos.c | 4 ++-- arch/arm/mach-omap2/omap4-common.c | 3 +-- arch/arm/mach-shmobile/board-armadillo800eva-reference.c | 4 ++-- arch/arm/mach-shmobile/board-armadillo800eva.c | 4 ++-- arch/arm/mach-shmobile/board-kzm9g-reference.c | 4 ++-- arch/arm/mach-shmobile/board-kzm9g.c | 4 ++-- arch/arm/mach-shmobile/setup-r8a7778.c | 4 ++-- arch/arm/mach-shmobile/setup-r8a7779.c | 4 ++-- arch/arm/mach-spear/spear13xx.c | 2 +- arch/arm/mach-tegra/tegra.c | 4 ++-- 11 files changed, 19 insertions(+), 20 deletions(-)
arch/arm/mach-berlin/berlin.c +1 -1
@@ -24,7 +24,7 @@ static void __init berlin_init_machine(void)* with DT probing for L2CCs, berlin_init_machine can be removed. * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc */ -l2x0_of_init (0x70c00000 ,0xfeffffff ); +l2x0_of_init (0x30c00000 ,0xfeffffff );of_platform_populate (NULL , of_default_bus_match_table,NULL ,NULL ); }
arch/arm/mach-exynos/exynos.c +2 -2
@@ -32,8 +32,8 @@#include "mfc.h" #include "regs-pmu.h" -#define L2_AUX_VAL 0x7C470001 -#define L2_AUX_MASK 0xC200ffff +#define L2_AUX_VAL 0x3c470001 +#define L2_AUX_MASK 0xc200ffffstatic struct map_desc exynos4_iodesc[]__initdata = { {
arch/arm/mach-omap2/omap4-common.c +1 -2
@@ -220,8 +220,7 @@ static int __init omap_l2_cache_init(void)L2C_AUX_CTRL_WAY_SIZE (3 ) |L2C_AUX_CTRL_SHARED_OVERRIDE |L310_AUX_CTRL_DATA_PREFETCH | -L310_AUX_CTRL_INSTR_PREFETCH | -L310_AUX_CTRL_EARLY_BRESP ; +L310_AUX_CTRL_INSTR_PREFETCH ; outer_cache.write_sec = omap4_l2c310_write_sec;if (of_have_populated_dt ())
arch/arm/mach-shmobile/board-armadillo800eva-reference.c +2 -2
@@ -164,8 +164,8 @@ static void __init eva_init(void)r8a7740_meram_workaround ();#ifdef CONFIG_CACHE_L2X0 -/* Early BRESP enable, Shared attribute override enable, 32K*8way */ -l2x0_init (IOMEM (0xf0002000 ),0x40440000 ,0x82000fff ); +/* Shared attribute override enable, 32K*8way */ +l2x0_init (IOMEM (0xf0002000 ),0x00440000 ,0xc2000fff );#endif r8a7740_add_standard_devices_dt ();
arch/arm/mach-shmobile/board-armadillo800eva.c +2 -2
@@ -1270,8 +1270,8 @@ static void __init eva_init(void)#ifdef CONFIG_CACHE_L2X0 -/* Early BRESP enable, Shared attribute override enable, 32K*8way */ -l2x0_init (IOMEM (0xf0002000 ),0x40440000 ,0x82000fff ); +/* Shared attribute override enable, 32K*8way */ +l2x0_init (IOMEM (0xf0002000 ),0x00440000 ,0xc2000fff );#endif i2c_register_board_info (0 , i2c0_devices,ARRAY_SIZE (i2c0_devices));
arch/arm/mach-shmobile/board-kzm9g-reference.c +2 -2
@@ -36,8 +36,8 @@ static void __init kzm_init(void)sh73a0_add_standard_devices_dt ();#ifdef CONFIG_CACHE_L2X0 -/* Early BRESP enable, Shared attribute override enable, 64K*8way */ -l2x0_init (IOMEM (0xf0100000 ),0x40460000 ,0x82000fff ); +/* Shared attribute override enable, 64K*8way */ +l2x0_init (IOMEM (0xf0100000 ),0x00460000 ,0xc2000fff );#endif }
arch/arm/mach-shmobile/board-kzm9g.c +2 -2
@@ -876,8 +876,8 @@ static void __init kzm_init(void)gpio_request_one (223 ,GPIOF_IN ,NULL );/* IRQ8 */ #ifdef CONFIG_CACHE_L2X0 -/* Early BRESP enable, Shared attribute override enable, 64K*8way */ -l2x0_init (IOMEM (0xf0100000 ),0x40460000 ,0x82000fff ); +/* Shared attribute override enable, 64K*8way */ +l2x0_init (IOMEM (0xf0100000 ),0x00460000 ,0xc2000fff );#endif i2c_register_board_info (0 , i2c0_devices,ARRAY_SIZE (i2c0_devices));
arch/arm/mach-shmobile/setup-r8a7778.c +2 -2
@@ -298,10 +298,10 @@ void __init r8a7778_add_dt_devices(void)void __iomem *base =ioremap_nocache (0xf0100000 ,0x1000 );if (base) {/* -* Early BRESP enable, Shared attribute override enable, 64K*16way +* Shared attribute override enable, 64K*16way * don't call iounmap(base) */ -l2x0_init (base,0x40470000 ,0x82000fff ); +l2x0_init (base,0x00470000 ,0xc2000fff ); }#endif
arch/arm/mach-shmobile/setup-r8a7779.c +2 -2
@@ -700,8 +700,8 @@ static struct platform_device *r8a7779_standard_devices[] __initdata = {void __init r8a7779_add_standard_devices (void ) {#ifdef CONFIG_CACHE_L2X0 -/* Early BRESP enable, Shared attribute override enable, 64K*16way */ -l2x0_init (IOMEM (0xf0100000 ),0x40470000 ,0x82000fff ); +/* Shared attribute override enable, 64K*16way */ +l2x0_init (IOMEM (0xf0100000 ),0x00470000 ,0xc2000fff );#endif r8a7779_pm_init ();
arch/arm/mach-spear/spear13xx.c +1 -1
@@ -46,7 +46,7 @@ void __init spear13xx_l2x0_init(void)*/ writel_relaxed (0x221 ,VA_L2CC_BASE +L310_TAG_LATENCY_CTRL );writel_relaxed (0x441 ,VA_L2CC_BASE +L310_DATA_LATENCY_CTRL ); -l2x0_init (VA_L2CC_BASE ,0x70A60001 ,0xfe00ffff ); +l2x0_init (VA_L2CC_BASE ,0x30a60001 ,0xfe00ffff ); }/*
arch/arm/mach-tegra/tegra.c +2 -2
@@ -89,9 +89,9 @@ static void __init tegra_init_cache(void) cache_type =readl (p +L2X0_CACHE_TYPE ); aux_ctrl = (cache_type &0x700 ) << (17 -8 ); - aux_ctrl |=0x7C400001 ; + aux_ctrl |=0x3c400001 ; - ret =l2x0_of_init (aux_ctrl,0x8200c3fe ); + ret =l2x0_of_init (aux_ctrl,0xc200c3fe );if (!ret) l2x0_saved_regs_addr =virt_to_phys (&l2x0_saved_regs);#endif
Signature · 1 line
1.8.3.1
PATCH 52/222 ARM: l2c: tegra: remove associativity and way size from aux_ctrl
In reply to Russell King - ARM Linux--- arch/arm/mach-tegra/tegra.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-)
arch/arm/mach-tegra/tegra.c +1 -17
@@ -73,25 +73,9 @@ u32 tegra_uart_config[3] = {static void __init tegra_init_cache (void ) {#ifdef CONFIG_CACHE_L2X0 -static const struct of_device_id pl310_ids[]__initconst = { - { .compatible ="arm,pl310-cache" , }, - {} - }; - -struct device_node *np;int ret; -void __iomem *p =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ) +0x3000 ; -u32 aux_ctrl, cache_type; - - np =of_find_matching_node (NULL , pl310_ids); -if (!np) -return ; - - cache_type =readl (p +L2X0_CACHE_TYPE ); - aux_ctrl = (cache_type &0x700 ) << (17 -8 ); - aux_ctrl |=0x3c400001 ; - ret =l2x0_of_init (aux_ctrl,0xc200c3fe ); + ret =l2x0_of_init (0x3c400001 ,0xc20fc3fe );if (!ret) l2x0_saved_regs_addr =virt_to_phys (&l2x0_saved_regs);#endif
Signature · 1 line
1.8.3.1
PATCH 53/222 ARM: l2c: ux500: remove associativity and way size from aux_ctrl
In reply to Russell King - ARM Linux--- arch/arm/mach-ux500/cache-l2x0.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-)
arch/arm/mach-ux500/cache-l2x0.c +2 -13
@@ -45,8 +45,6 @@ static void ux500_l2c310_write_sec(unsigned long val, unsigned reg)static int __init ux500_l2x0_init (void ) { -u32 aux_val =0x3e000000 ; -if (cpu_is_u8500_family () ||cpu_is_ux540_family ()) l2x0_base =__io_address (U8500_L2CC_BASE );else
@@ -56,21 +54,12 @@ static int __init ux500_l2x0_init(void)/* Unlock before init */ ux500_l2x0_unlock (); -/* DBx540's L2 has 128KB way size */ -if (cpu_is_ux540_family ()) -/* 128KB way size */ - aux_val |=L2C_AUX_CTRL_WAY_SIZE (4 ); -else -/* 64KB way size */ - aux_val |=L2C_AUX_CTRL_WAY_SIZE (3 ); - outer_cache.write_sec = ux500_l2c310_write_sec; -/* 64KB way size, 8 way associativity, force WA */ if (of_have_populated_dt ()) -l2x0_of_init (aux_val,0xc0000fff ); +l2x0_of_init (0x3e000000 ,0xc00f0fff );else -l2x0_init (l2x0_base, aux_val,0xc0000fff ); +l2x0_init (l2x0_base,0x3e000000 ,0xc00f0fff );return 0 ; }
Signature · 1 line
1.8.3.1
PATCH 54/222 ARM: l2c: ux500: don't try to change the L2 cache auxiliary control register
In reply to Russell King - ARM Linuxux500 can't change the auxiliary control register, so there's no point passing values to try and modify it to the l2x0 init functions.
--- arch/arm/mach-ux500/cache-l2x0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/mach-ux500/cache-l2x0.c +2 -2
@@ -57,9 +57,9 @@ static int __init ux500_l2x0_init(void) outer_cache.write_sec = ux500_l2c310_write_sec;if (of_have_populated_dt ()) -l2x0_of_init (0x3e000000 ,0xc00f0fff ); +l2x0_of_init (0 , ~0 );else -l2x0_init (l2x0_base,0x3e000000 ,0xc00f0fff ); +l2x0_init (l2x0_base,0 , ~0 );return 0 ; }
Signature · 1 line
1.8.3.1
PATCH 55/222 ARM: l2c: cns3xxx: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/mach-cns3xxx/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-cns3xxx/core.c +1 -1
@@ -290,7 +290,7 @@ void __init cns3xxx_l2x0_init(void)writel (val, base +L310_DATA_LATENCY_CTRL );/* 32 KiB, 8-way, parity disable */ - l2x0_init(base, 0x00540000, 0xfe000fff); + l2x0_init(base, 0x00500000, 0xfe0f0fff); }#endif /* CONFIG_CACHE_L2X0 */
Signature · 1 line
1.8.3.1
PATCH 56/222 ARM: l2c: exynos: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/mach-exynos/exynos.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
arch/arm/mach-exynos/exynos.c +1 -4
@@ -32,9 +32,6 @@#include "mfc.h" #include "regs-pmu.h" -#define L2_AUX_VAL 0x3c470001 -#define L2_AUX_MASK 0xc200ffff -static struct map_desc exynos4_iodesc[]__initdata = { { .virtual = (unsigned long )S3C_VA_SYS ,
@@ -323,7 +320,7 @@ static int __init exynos4_l2x0_cache_init(void) {int ret; - ret =l2x0_of_init (L2_AUX_VAL ,L2_AUX_MASK ); + ret =l2x0_of_init (0x3c400001 ,0xc20fffff );if (ret)return ret;
Signature · 1 line
1.8.3.1
PATCH 57/222 ARM: l2c: nomadik: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/mach-nomadik/cpu-8815.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-nomadik/cpu-8815.c +1 -1
@@ -147,7 +147,7 @@ static void __init cpu8815_init_of(void) {#ifdef CONFIG_CACHE_L2X0 /* At full speed latency must be >=2, so 0x249 in low bits */ -l2x0_of_init (0x00730249 ,0xfe000fff ); +l2x0_of_init (0x00700249 ,0xfe0fefff );#endif of_platform_populate (NULL , of_default_bus_match_table,NULL ,NULL ); }
Signature · 1 line
1.8.3.1
PATCH 58/222 ARM: l2c: omap2: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/mach-omap2/omap4-common.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
arch/arm/mach-omap2/omap4-common.c +3 -5
@@ -213,20 +213,18 @@ static int __init omap_l2_cache_init(void)return -ENOMEM ;/* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ - aux_ctrl =L310_AUX_CTRL_ASSOCIATIVITY_16 | -L310_AUX_CTRL_CACHE_REPLACE_RR | + aux_ctrl =L310_AUX_CTRL_CACHE_REPLACE_RR |L310_AUX_CTRL_NS_LOCKDOWN |L310_AUX_CTRL_NS_INT_CTRL | -L2C_AUX_CTRL_WAY_SIZE (3 ) |L2C_AUX_CTRL_SHARED_OVERRIDE |L310_AUX_CTRL_DATA_PREFETCH |L310_AUX_CTRL_INSTR_PREFETCH ; outer_cache.write_sec = omap4_l2c310_write_sec;if (of_have_populated_dt ()) -l2x0_of_init (aux_ctrl,L2X0_AUX_CTRL_MASK ); +l2x0_of_init (aux_ctrl,0xc19fffff );else -l2x0_init (l2cache_base, aux_ctrl,L2X0_AUX_CTRL_MASK ); +l2x0_init (l2cache_base, aux_ctrl,0xc19fffff );return 0 ; }
Signature · 1 line
1.8.3.1
PATCH 59/222 ARM: l2c: prima2: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/boot/dts/marco.dtsi | 2 +- arch/arm/boot/dts/prima2.dtsi | 2 +- arch/arm/mach-prima2/l2x0.c | 33 +-------------------------------- 3 files changed, 3 insertions(+), 34 deletions(-)
arch/arm/boot/dts/marco.dtsi +1 -1
@@ -36,7 +36,7 @@ ranges = <0x40000000 0x40000000 0xa0000000>; l2-cache-controller at c0030000 { - compatible = "sirf,marco-pl310-cache", "arm,pl310-cache"; + compatible = "arm,pl310-cache"; reg = <0xc0030000 0x1000>; interrupts = <0 59 0>; arm,tag-latency = <1 1 1>;
arch/arm/boot/dts/prima2.dtsi +1 -1
@@ -48,7 +48,7 @@ ranges = <0x40000000 0x40000000 0x80000000>; l2-cache-controller at 80040000 { - compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache"; + compatible = "arm,pl310-cache"; reg = <0x80040000 0x1000>; interrupts = <59>; arm,tag-latency = <1 1 1>;
arch/arm/mach-prima2/l2x0.c +1 -32
@@ -8,41 +8,10 @@#include <linux/init.h> #include <linux/kernel.h> -#include <linux/of.h> #include <asm/hardware/cache-l2x0.h> -struct l2x0_aux { -u32 val; -u32 mask; -}; - -static const struct l2x0_aux prima2_l2x0_aux__initconst = { - .val =L2C_AUX_CTRL_WAY_SIZE (2 ), - .mask =0 , -}; - -static const struct l2x0_aux marco_l2x0_aux__initconst = { - .val =L2C_AUX_CTRL_WAY_SIZE (2 ) |L310_AUX_CTRL_ASSOCIATIVITY_16 , - .mask =L2X0_AUX_CTRL_MASK , -}; - -static const struct of_device_id sirf_l2x0_ids[]__initconst = { - { .compatible ="sirf,prima2-pl310-cache" , .data = &prima2_l2x0_aux, }, - { .compatible ="sirf,marco-pl310-cache" , .data = &marco_l2x0_aux, }, - {}, -}; -static int __init sirfsoc_l2x0_init (void ) { -struct device_node *np; -const struct l2x0_aux *aux; - - np =of_find_matching_node (NULL , sirf_l2x0_ids); -if (np) { - aux =of_match_node (sirf_l2x0_ids, np)->data; -return l2x0_of_init (aux->val, aux->mask); - } - -return 0 ; +return l2x0_of_init (0 , ~0 ); }early_initcall (sirfsoc_l2x0_init);
Signature · 1 line
1.8.3.1
PATCH 60/222 ARM: l2c: shmobile: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/mach-shmobile/board-armadillo800eva-reference.c | 2 +- arch/arm/mach-shmobile/board-armadillo800eva.c | 2 +- arch/arm/mach-shmobile/board-kzm9g-reference.c | 2 +- arch/arm/mach-shmobile/board-kzm9g.c | 2 +- arch/arm/mach-shmobile/setup-r8a7778.c | 2 +- arch/arm/mach-shmobile/setup-r8a7779.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
arch/arm/mach-shmobile/board-armadillo800eva-reference.c +1 -1
@@ -165,7 +165,7 @@ static void __init eva_init(void)#ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 32K*8way */ -l2x0_init (IOMEM (0xf0002000 ),0x00440000 ,0xc2000fff ); +l2x0_init (IOMEM (0xf0002000 ),0x00400000 ,0xc20f0fff );#endif r8a7740_add_standard_devices_dt ();
arch/arm/mach-shmobile/board-armadillo800eva.c +1 -1
@@ -1271,7 +1271,7 @@ static void __init eva_init(void)#ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 32K*8way */ -l2x0_init (IOMEM (0xf0002000 ),0x00440000 ,0xc2000fff ); +l2x0_init (IOMEM (0xf0002000 ),0x00400000 ,0xc20f0fff );#endif i2c_register_board_info (0 , i2c0_devices,ARRAY_SIZE (i2c0_devices));
arch/arm/mach-shmobile/board-kzm9g-reference.c +1 -1
@@ -37,7 +37,7 @@ static void __init kzm_init(void)#ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*8way */ -l2x0_init (IOMEM (0xf0100000 ),0x00460000 ,0xc2000fff ); +l2x0_init (IOMEM (0xf0100000 ),0x00400000 ,0xc20f0fff );#endif }
arch/arm/mach-shmobile/board-kzm9g.c +1 -1
@@ -877,7 +877,7 @@ static void __init kzm_init(void)#ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*8way */ -l2x0_init (IOMEM (0xf0100000 ),0x00460000 ,0xc2000fff ); +l2x0_init (IOMEM (0xf0100000 ),0x00400000 ,0xc20f0fff );#endif i2c_register_board_info (0 , i2c0_devices,ARRAY_SIZE (i2c0_devices));
arch/arm/mach-shmobile/setup-r8a7778.c +1 -1
@@ -301,7 +301,7 @@ void __init r8a7778_add_dt_devices(void)* Shared attribute override enable, 64K*16way * don't call iounmap(base) */ - l2x0_init(base, 0x00470000, 0xc2000fff); + l2x0_init(base, 0x00400000, 0xc20f0fff); }#endif
arch/arm/mach-shmobile/setup-r8a7779.c +1 -1
@@ -701,7 +701,7 @@ void __init r8a7779_add_standard_devices(void) {#ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*16way */ -l2x0_init (IOMEM (0xf0100000 ),0x00470000 ,0xc2000fff ); +l2x0_init (IOMEM (0xf0100000 ),0x00400000 ,0xc20f0fff );#endif r8a7779_pm_init ();
Signature · 1 line
1.8.3.1
PATCH 61/222 ARM: l2c: spear13xx: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/mach-spear/spear13xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-spear/spear13xx.c +1 -1
@@ -46,7 +46,7 @@ void __init spear13xx_l2x0_init(void)*/ writel_relaxed (0x221 ,VA_L2CC_BASE +L310_TAG_LATENCY_CTRL );writel_relaxed (0x441 ,VA_L2CC_BASE +L310_DATA_LATENCY_CTRL ); -l2x0_init (VA_L2CC_BASE ,0x30a60001 ,0xfe00ffff ); +l2x0_init (VA_L2CC_BASE ,0x30a00001 ,0xfe0fffff ); }/*
Signature · 1 line
1.8.3.1
PATCH 62/222 ARM: l2c: sti: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/mach-sti/board-dt.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
arch/arm/mach-sti/board-dt.c +3 -9
@@ -16,15 +16,9 @@void __init stih41x_l2x0_init (void ) { -u32 way_size =0x4 ; -u32 aux_ctrl; -/* may be this can be encoded in macros like BIT*() */ - aux_ctrl =L2C_AUX_CTRL_SHARED_OVERRIDE | -L310_AUX_CTRL_DATA_PREFETCH | -L310_AUX_CTRL_INSTR_PREFETCH | -L2C_AUX_CTRL_WAY_SIZE (way_size); - -l2x0_of_init (aux_ctrl,L2X0_AUX_CTRL_MASK ); +l2x0_of_init (L2C_AUX_CTRL_SHARED_OVERRIDE | +L310_AUX_CTRL_DATA_PREFETCH | +L310_AUX_CTRL_INSTR_PREFETCH ,0xc00f0fff ); }static void __init stih41x_machine_init (void )
Signature · 1 line
1.8.3.1
PATCH 63/222 ARM: l2c: zynq: remove cache size override
In reply to Russell King - ARM Linux--- arch/arm/mach-zynq/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-zynq/common.c +1 -1
@@ -70,7 +70,7 @@ static void __init zynq_init_machine(void)/* * 64KB way size, 8-way associativity, parity disabled */ -l2x0_of_init (0x02060000 ,0xF0F0FFFF ); +l2x0_of_init (0x02000000 ,0xf0ffffff );of_platform_populate (NULL , of_default_bus_match_table,NULL ,NULL );
Signature · 1 line
1.8.3.1
PATCH 64/222 ARM: l2c: realview: improve commentry about the L2 cache requirements
In reply to Russell King - ARM LinuxAdd better commentry about the L2 cache requirements on these platforms. Unfortunately, the auxiliary control register is not pre-set to indicate the correct cache parameters, so we have to manually program these.
--- arch/arm/mach-realview/realview_eb.c | 9 +++++++-- arch/arm/mach-realview/realview_pb1176.c | 8 +++++++- arch/arm/mach-realview/realview_pb11mp.c | 9 +++++++-- 3 files changed, 21 insertions(+), 5 deletions(-)
arch/arm/mach-realview/realview_eb.c +7 -2
@@ -442,8 +442,13 @@ static void __init realview_eb_init(void)realview_eb11mp_fixup ();#ifdef CONFIG_CACHE_L2X0 -/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled -* Bits: .... ...0 0111 1001 0000 .... .... .... */ +/* +* The PL220 needs to be manually configured as the hardware +* doesn't report the correct sizes. +* 1MB (128KB/way), 8-way associativity, event monitor and +* parity enabled, ignore share bit, no force write allocate +* Bits: .... ...0 0111 1001 0000 .... .... .... +*/ l2x0_init (__io_address (REALVIEW_EB11MP_L220_BASE ),0x00790000 ,0xfe000fff );#endif platform_device_register (&pmu_device);
arch/arm/mach-realview/realview_pb1176.c +7 -1
@@ -355,7 +355,13 @@ static void __init realview_pb1176_init(void)int i;#ifdef CONFIG_CACHE_L2X0 -/* 128Kb (16Kb/way) 8-way associativity. evmon/parity/share enabled. */ +/* +* The PL220 needs to be manually configured as the hardware +* doesn't report the correct sizes. +* 128kB (16kB/way), 8-way associativity, event monitor and +* parity enabled, ignore share bit, no force write allocate +* Bits: .... ...0 0111 0011 0000 .... .... .... +*/ l2x0_init (__io_address (REALVIEW_PB1176_L220_BASE ),0x00730000 ,0xfe000fff );#endif
arch/arm/mach-realview/realview_pb11mp.c +7 -2
@@ -337,8 +337,13 @@ static void __init realview_pb11mp_init(void)int i;#ifdef CONFIG_CACHE_L2X0 -/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled -* Bits: .... ...0 0111 1001 0000 .... .... .... */ +/* +* The PL220 needs to be manually configured as the hardware +* doesn't report the correct sizes. +* 1MB (128KB/way), 8-way associativity, event monitor and +* parity enabled, ignore share bit, no force write allocate +* Bits: .... ...0 0111 1001 0000 .... .... .... +*/ l2x0_init (__io_address (REALVIEW_TC11MP_L220_BASE ),0x00790000 ,0xfe000fff );#endif
Signature · 1 line
1.8.3.1
PATCH 65/222 ARM: l2c: kill L2X0_AUX_CTRL_MASK before anyone else makes use of this
In reply to Russell King - ARM LinuxL2X0_AUX_CTRL_MASK is not useful for PL310s. It would be better if people thought about their value for this rather than cargo-cult programming.
--- arch/arm/include/asm/hardware/cache-l2x0.h | 1 - 1 file changed, 1 deletion(-)
arch/arm/include/asm/hardware/cache-l2x0.h +0 -1
@@ -87,7 +87,6 @@#define L310_CACHE_ID_RTL_R3P2 0x08#define L310_CACHE_ID_RTL_R3P3 0x09 -#define L2X0_AUX_CTRL_MASK 0xc0000fff/* L2C auxiliary control register - bits common to L2C-210/220/310 */ #define L2C_AUX_CTRL_WAY_SIZE_SHIFT 17#define L2C_AUX_CTRL_WAY_SIZE_MASK (7 << 17)
Signature · 1 line
1.8.3.1
PATCH 66/222 ARM: l2c: print a warning with L2C-310 caches if the cache size is modified
In reply to Russell King - ARM LinuxAs we have now removed all instances of the L2C-310 having its cache size "modified" via platform/SoC code, discourage new cases showing up by printing a warning.
--- arch/arm/mm/cache-l2x0.c | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/mm/cache-l2x0.c +2 -0
@@ -732,6 +732,8 @@ static void __init __l2c_init(const struct l2c_init_data *data,/* Determine the number of ways */ switch (cache_id &L2X0_CACHE_ID_PART_MASK ) {case L2X0_CACHE_ID_PART_L310 : +if ((aux_val | ~aux_mask) & (L2C_AUX_CTRL_WAY_SIZE_MASK |L310_AUX_CTRL_ASSOCIATIVITY_16 )) +pr_warn ("L2C: DT/platform tries to modify or specify cache size\n" );if (aux & (1 <<16 )) ways =16 ;else
Signature · 1 line
1.8.3.1
PATCH 67/222 ARM: l2c: vexpress ca9x4: move L2 cache initialisation earlier
In reply to Russell King - ARM LinuxIt is beneficial to have the L2 cache up and running earlier in the system boot. Not only will this allow for simpler code when we come to enable some features, but it also means that we get a more accurate bogomips value for the udelay() loop. Calibrating the loop with the L2 cache off, and then running with the L2 cache on is not the best idea.
--- arch/arm/mach-vexpress/ct-ca9x4.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
arch/arm/mach-vexpress/ct-ca9x4.c +18 -10
@@ -45,6 +45,23 @@ static void __init ct_ca9x4_map_io(void)iotable_init (ct_ca9x4_io_desc,ARRAY_SIZE (ct_ca9x4_io_desc)); } +static void __init ca9x4_l2_init (void ) +{ +#ifdef CONFIG_CACHE_L2X0 +void __iomem *l2x0_base =ioremap (CT_CA9X4_L2CC ,SZ_4K ); + +if (l2x0_base) { +/* set RAM latencies to 1 cycle for this core tile. */ +writel (0 , l2x0_base +L310_TAG_LATENCY_CTRL ); +writel (0 , l2x0_base +L310_DATA_LATENCY_CTRL ); + +l2x0_init (l2x0_base,0x00400000 ,0xfe0fffff ); + }else { +pr_err ("L2C: unable to map L2 cache controller\n" ); + } +#endif +} +#ifdef CONFIG_HAVE_ARM_TWD static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER);
@@ -63,6 +80,7 @@ static void __init ct_ca9x4_init_irq(void)gic_init (0 ,29 ,ioremap (A9_MPCORE_GIC_DIST ,SZ_4K ),ioremap (A9_MPCORE_GIC_CPU ,SZ_256 ));ca9x4_twd_init (); +ca9x4_l2_init (); }static int ct_ca9x4_clcd_setup (struct clcd_fb *fb)
@@ -141,16 +159,6 @@ static void __init ct_ca9x4_init(void) {int i; -#ifdef CONFIG_CACHE_L2X0 -void __iomem *l2x0_base =ioremap (CT_CA9X4_L2CC ,SZ_4K ); - -/* set RAM latencies to 1 cycle for this core tile. */ -writel (0 , l2x0_base +L310_TAG_LATENCY_CTRL ); -writel (0 , l2x0_base +L310_DATA_LATENCY_CTRL ); - -l2x0_init (l2x0_base,0x00400000 ,0xfe0fffff ); -#endif -for (i =0 ; i <ARRAY_SIZE (ct_ca9x4_amba_devs); i++)amba_device_register (ct_ca9x4_amba_devs[i], &iomem_resource);
Signature · 1 line
1.8.3.1
PATCH 68/222 ARM: l2c: add L2C-310 power control DT properties
In reply to Russell King - ARM LinuxAdd two new properties for setting thte L3 power control register. Two new properties are added:
arm,dynamic-clk-gating
arm,standby-mode
iMX6 sets both these, add the properties there.
--- Documentation/devicetree/bindings/arm/l2cc.txt | 2 ++ arch/arm/boot/dts/imx6qdl.dtsi | 2 ++ arch/arm/boot/dts/imx6sl.dtsi | 2 ++ arch/arm/mm/cache-l2x0.c | 10 ++++++++++ 4 files changed, 16 insertions(+)
Documentation/devicetree/bindings/arm/l2cc.txt +2 -0
@@ -40,6 +40,8 @@ implementations of the L2 cache controller with compatible programming models. - arm,filter-ranges : <start length> Starting address and length of window to filter. Addresses in the filter window are directed to the M1 port. Other addresses will go to the M0 port. +- arm,dynamic-clk-gating : Enables dynamic clock gating (PL310) +- arm,standby-mode : Enables standby mode (PL310) - interrupts : 1 combined interrupt. - cache-id-part: cache id part number to be used if it is not present on hardware
arch/arm/boot/dts/imx6qdl.dtsi +2 -0
@@ -125,6 +125,8 @@ cache-level = <2>; arm,tag-latency = <4 2 3>; arm,data-latency = <4 2 3>; + arm,dynamic-clk-gating; + arm,standby-mode; }; pcie: pcie at 0x01000000 {
arch/arm/boot/dts/imx6sl.dtsi +2 -0
@@ -111,6 +111,8 @@ cache-level = <2>; arm,tag-latency = <4 2 3>; arm,data-latency = <4 2 3>; + arm,dynamic-clk-gating; + arm,standby-mode; }; pmu {
arch/arm/mm/cache-l2x0.c +10 -0
@@ -904,6 +904,7 @@ static void __init l2c310_of_parse(const struct device_node *np,u32 data[3 ] = {0 ,0 ,0 };u32 tag[3 ] = {0 ,0 ,0 };u32 filter[2 ] = {0 ,0 }; +u32 val;of_property_read_u32_array (np,"arm,tag-latency" , tag,ARRAY_SIZE (tag));if (tag[0 ] && tag[1 ] && tag[2 ])
@@ -930,6 +931,15 @@ static void __init l2c310_of_parse(const struct device_node *np,writel_relaxed ((filter[0 ] & ~(SZ_1M -1 )) |L310_ADDR_FILTER_EN , l2x0_base +L310_ADDR_FILTER_START ); } + + val =0 ; +if (of_property_read_bool (np,"arm,dynamic-clk-gating" )) + val |=L310_DYNAMIC_CLK_GATING_EN ; +if (of_property_read_bool (np,"arm,standby-mode" )) + val |=L310_STNDBY_MODE_EN ; + +if (val) +l2c_write_sec (val, l2x0_base,L310_POWER_CTRL ); }static const struct l2c_init_data of_l2c310_data__initconst = {
Signature · 1 line
1.8.3.1
PATCH 69/222 ARM: l2c: check that DT files specify the required "cache-unified" property
In reply to Russell King - ARM LinuxThis is a required property, and should always be specified.
--- arch/arm/mm/cache-l2x0.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/arm/mm/cache-l2x0.c +4 -0
@@ -1378,6 +1378,10 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) data =of_match_node (l2x0_ids, np)->data; +/* All L2 caches are unified, so this property should be specified */ +if (!of_property_read_bool (np,"cache-unified" )) +pr_err ("L2C: device tree omits to specify unified cache\n" ); +/* L2 configuration can only be changed if the cache is disabled */ if (!(readl_relaxed (l2x0_base +L2X0_CTRL ) &L2X0_CTRL_EN ))if (data->of_parse)
Signature · 1 line
1.8.3.1
PATCH 70/222 ARM: l2c: add warnings for stuff modifying aux_ctrl register values
In reply to Russell King - ARM Linux--- arch/arm/mm/cache-l2x0.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-)
arch/arm/mm/cache-l2x0.c +23 -4
@@ -715,7 +715,15 @@ static void __init __l2c_init(const struct l2c_init_data *data, {struct outer_cache_fns fns;unsigned way_size_bits, ways; -u32 aux; +u32 aux, old_aux; + +/* +* Sanity check the aux values. aux_mask is the bits we preserve +* from reading the hardware register, and aux_val is the bits we +* set. +*/ +if (aux_val & aux_mask) +pr_alert ("L2C: platform provided aux values permit register corruption.\n" );/* * It is strange to save the register state before initialisation,
@@ -724,11 +732,14 @@ static void __init __l2c_init(const struct l2c_init_data *data,if (data->save) data->save (l2x0_base); - aux =readl_relaxed (l2x0_base +L2X0_AUX_CTRL ); - + old_aux = aux =readl_relaxed (l2x0_base +L2X0_AUX_CTRL ); aux &= aux_mask; aux |= aux_val; +if (old_aux != aux) +pr_warn ("L2C: DT/platform modifies aux control register: 0x%08x -> 0x%08x\n" , + old_aux, aux); +/* Determine the number of ways */ switch (cache_id &L2X0_CACHE_ID_PART_MASK ) {case L2X0_CACHE_ID_PART_L310 :
@@ -1361,7 +1372,7 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)const struct l2c_init_data *data;struct device_node *np;struct resource res; -u32 cache_id; +u32 cache_id, old_aux; np =of_find_matching_node (NULL , l2x0_ids);if (!np)
@@ -1378,6 +1389,14 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) data =of_match_node (l2x0_ids, np)->data; + old_aux =readl_relaxed (l2x0_base +L2X0_AUX_CTRL ); +if (old_aux != ((old_aux & aux_mask) | aux_val)) { +pr_warn ("L2C: platform modifies aux control register: 0x%08x -> 0x%08x\n" , + old_aux, (old_aux & aux_mask) | aux_val); + }else if (aux_mask != ~0U && aux_val !=0 ) { +pr_alert ("L2C: platform provided aux values match the hardware, so have no effect. Please remove them.\n" ); + } +/* All L2 caches are unified, so this property should be specified */ if (!of_property_read_bool (np,"cache-unified" ))pr_err ("L2C: device tree omits to specify unified cache\n" );
Signature · 1 line
1.8.3.1
PATCH 71/222 net:fec: remove unnecessary ip stack includes
In reply to Russell King - ARM LinuxCommit 4c09eed9dc42 (net: fec: Enable imx6 enet checksum acceleration.) added support for hardware checksum support, adding six new includes for things like tcp, udp, ip, icmp, but never made use of anything provided by those header files. Let's remove this bloat.
--- drivers/net/ethernet/freescale/fec_main.c | 6 ------ 1 file changed, 6 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +0 -6
@@ -33,12 +33,6 @@#include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <net/ip.h> -#include <linux/tcp.h> -#include <linux/udp.h> -#include <linux/icmp.h> #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/bitops.h>
Signature · 1 line
1.8.3.1
PATCH 71/222 net:fec: remove unnecessary ip stack includes
Quoted 6 lines · Russell King
Commit
4c09eed9dc42(net: fec: Enable imx6 enet checksum acceleration.) added support for hardware checksum support, adding six new includes for things like tcp, udp, ip, icmp, but never made use of anything provided by those header files. Let's remove this bloat.Signed-off-by Russell King <[email protected]>
Russell
I see patches from 71 to 126 are related with fec driver. But maintainer David S. Miller is not in to list.
Do you need someone follow up this patches and resent to David
S Miller till accepted by david? Or you will do it by yourself?
Best regards
Frank Li
Quoted 29 lines
--- drivers/net/ethernet/freescale/fec_main.c | 6 ------ 1 file changed, 6 deletions(-)drivers/net/ethernet/freescale/fec_main.c +0
-7@@ -33,12 +33,6 @@#include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <net/ip.h> -#include <linux/tcp.h> -#include <linux/udp.h> -#include <linux/icmp.h> #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/bitops.h> --1.8.3.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 71/222 net:fec: remove unnecessary ip stack includes
Quoted 9 lines · Frank Li
Quoted 6 lines · Russell King
Commit
4c09eed9dc42(net: fec: Enable imx6 enet checksum acceleration.) added support for hardware checksum support, adding six new includes for things like tcp, udp, ip, icmp, but never made use of anything provided by those header files. Let's remove this bloat.Signed-off-by Russell King <[email protected]>
Quoted 7 lines
Russell
I see patches from 71 to 126 are related with fec driver. But maintainer David S. Miller is not in to list.
Do you need someone follow up this patches and resent to David
S Miller till accepted by david? Or you will do it by yourself?
I know they need to re-worked to convert unsigned -> unsigned int before David sees them, otherwise it'd be an instant review failure. Doing the conversion is the easy bit, doing it without hitting the 80 column limit is much harder...
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 72/222 net:fec: reorder ethtool ops to match order in struct declaration
In reply to Russell King - ARM LinuxThis allows us to merge two separate preprocessor conditionals together.
--- drivers/net/ethernet/freescale/fec_main.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +5 -7
@@ -1639,21 +1639,19 @@ static int fec_enet_nway_reset(struct net_device *dev) }static const struct ethtool_ops fec_enet_ethtool_ops = { -#if !defined(CONFIG_M5272) - .get_pauseparam = fec_enet_get_pauseparam, - .set_pauseparam = fec_enet_set_pauseparam, -#endif .get_settings = fec_enet_get_settings, .set_settings = fec_enet_set_settings, .get_drvinfo = fec_enet_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_ts_info = fec_enet_get_ts_info, .nway_reset = fec_enet_nway_reset, + .get_link = ethtool_op_get_link, #ifndef CONFIG_M5272 - .get_ethtool_stats = fec_enet_get_ethtool_stats, + .get_pauseparam = fec_enet_get_pauseparam, + .set_pauseparam = fec_enet_set_pauseparam, .get_strings = fec_enet_get_strings, + .get_ethtool_stats = fec_enet_get_ethtool_stats, .get_sset_count = fec_enet_get_sset_count, #endif + .get_ts_info = fec_enet_get_ts_info, };static int fec_enet_ioctl (struct net_device *ndev,struct ifreq *rq,int cmd)
Signature · 1 line
1.8.3.1
PATCH 73/222 net:fec: remove checking for NULL phy_dev in fec_enet_close()
In reply to Russell King - ARM Linuxfep->phy_dev can not be NULL here for two reasons:
- fec_enet_open() will have successfully connected the phy, or will have failed.
- fec_enet_open() will have called phy_start(fep->phy_dev), which unconditionally dereferences this pointer.
If it were to be NULL here, then fec_enet_open() will have already oopsed.
--- drivers/net/ethernet/freescale/fec_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +2 -4
@@ -1798,10 +1798,8 @@ fec_enet_close(struct net_device *ndev)netif_stop_queue (ndev);fec_stop (ndev); -if (fep->phy_dev) { -phy_stop (fep->phy_dev); -phy_disconnect (fep->phy_dev); - } +phy_stop (fep->phy_dev); +phy_disconnect (fep->phy_dev);fec_enet_free_buffers (ndev);
Signature · 1 line
1.8.3.1
PATCH 74/222 net:fec: ensure that a disconnected phy isn't configured
In reply to Russell King - ARM LinuxWhen we disconnect from a phy, we should forget our pointer to it so we don't accidentally try to configure it. We handle a NULL phy pointer correctly in most places, except fec_enet_set_pauseparam(). Fix this too.
--- drivers/net/ethernet/freescale/fec_main.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/freescale/fec_main.c +4 -0
@@ -1496,6 +1496,9 @@ static int fec_enet_set_pauseparam(struct net_device *ndev, {struct fec_enet_private *fep =netdev_priv (ndev); +if (!fep->phy_dev) +return -ENODEV ; +if (pause->tx_pause != pause->rx_pause) {netdev_info (ndev,"hardware only support enable/disable both tx and rx" );
@@ -1800,6 +1803,7 @@ fec_enet_close(struct net_device *ndev)phy_stop (fep->phy_dev);phy_disconnect (fep->phy_dev); + fep->phy_dev =NULL ;fec_enet_free_buffers (ndev);
Signature · 1 line
1.8.3.1
PATCH 75/222 net:fec: add support for dumping transmit ring on timeout
In reply to Russell King - ARM LinuxWhen we timeout on transmit, it would be useful to dump the transmit ring, so we can see the ring state. This can be helpful to diagnose the cause of transmit timeouts.
--- drivers/net/ethernet/freescale/fec_main.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
drivers/net/ethernet/freescale/fec_main.c +23 -0
@@ -291,6 +291,27 @@ static void *swap_buffer(void *bufaddr, int len)return bufaddr; } +static void fec_dump (struct net_device *ndev) +{ +struct fec_enet_private *fep =netdev_priv (ndev); +struct bufdesc *bdp = fep->tx_bd_base; +unsigned index =0 ; + +netdev_info (ndev,"TX ring dump\n" ); +pr_info ("Nr SC addr len SKB\n" ); + +do { +pr_info ("%3u %c%c 0x%04x 0x%08lx %4u %p\n" , + index, + bdp == fep->cur_tx ?'S' :' ' , + bdp == fep->dirty_tx ?'H' :' ' , + bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen, + fep->tx_skbuff[index]); + bdp =fec_enet_get_nextdesc (bdp, fep); + index++; + }while (bdp != fep->tx_bd_base); +} +static int fec_enet_clear_csum (struct sk_buff *skb,struct net_device *ndev) {
@@ -717,6 +738,8 @@ fec_timeout(struct net_device *ndev) {struct fec_enet_private *fep =netdev_priv (ndev); +fec_dump (ndev); + ndev->stats.tx_errors++; fep->delay_work.timeout = true;
Signature · 1 line
1.8.3.1
PATCH 76/222 net:fec: use netif_tx_disable() rather than netif_stop_queue()
In reply to Russell King - ARM LinuxWe use netif_stop_queue() in several places where we want to ensure that the start_xmit function is not running. netif_stop_queue() is not sufficient to achieve that - it merely sets a flag to indicate that the transmit queue(s) should not be run.
netif_tx_disable() gives this guarantee, since it takes the transmit queue lock while marking the queue stopped. This will wait for the transmit function to complete before returning.
--- drivers/net/ethernet/freescale/fec_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +2 -2
@@ -522,7 +522,7 @@ fec_restart(struct net_device *ndev, int duplex)if (netif_running (ndev)) {netif_device_detach (ndev);napi_disable (&fep->napi); -netif_stop_queue (ndev); +netif_tx_disable (ndev);netif_tx_lock_bh (ndev); }
@@ -1821,7 +1821,7 @@ fec_enet_close(struct net_device *ndev)/* Don't know what to do yet. */ napi_disable (&fep->napi); fep->opened =0 ; -netif_stop_queue (ndev); +netif_tx_disable (ndev);fec_stop (ndev);phy_stop (fep->phy_dev);
Signature · 1 line
1.8.3.1
PATCH 77/222 net:fec: iMX6 FEC does not support half-duplex gigabit
In reply to Russell King - ARM LinuxThe iMX6 gigabit FEC does not support half-duplex gigabit operation. Phys attacked to the FEC may support this, and we currently do nothing to disable this feature. This may result in an invalid configuration. Mask out phy support for gigabit half-duplex operation.
--- drivers/net/ethernet/freescale/fec_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/freescale/fec_main.c +1 -0
@@ -1316,6 +1316,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)/* mask with MAC supported features */ if (id_entry->driver_data &FEC_QUIRK_HAS_GBIT ) { phy_dev->supported &=PHY_GBIT_FEATURES ; + phy_dev->supported &= ~SUPPORTED_1000baseT_Half;#if !defined(CONFIG_M5272 ) phy_dev->supported |= SUPPORTED_Pause;#endif
Signature · 1 line
1.8.3.1
PATCH 78/222 net:fec: clean up transmit descriptor setup
In reply to Russell King - ARM LinuxAvoid writing any state until we're certain we can proceed with the
transmission: this avoids writing mapping error address values to the descriptors, or setting the skbuff pointer until we have successfully mapped the skb.
--- drivers/net/ethernet/freescale/fec_main.c | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +16 -16
@@ -337,6 +337,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)void *bufaddr;unsigned short status;unsigned int index; +unsigned length; +dma_addr_t addr;/* Fill in a Tx ring entry */ bdp = fep->cur_tx;
@@ -362,7 +364,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)/* Set buffer length and buffer pointer */ bufaddr = skb->data; - bdp->cbd_datlen = skb->len; + length = skb->len;/* * On some FEC implementations data must be aligned on
@@ -376,7 +378,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) index = bdp - fep->tx_bd_base;if (((unsigned long ) bufaddr) &FEC_ALIGNMENT ) { -memcpy (fep->tx_bounce[index], skb->data, skb->len); +memcpy (fep->tx_bounce[index], skb->data, length); bufaddr = fep->tx_bounce[index]; }
@@ -386,25 +388,23 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)* swap every frame going to and coming from the controller. */ if (id_entry->driver_data &FEC_QUIRK_SWAP_FRAME ) -swap_buffer (bufaddr, skb->len); +swap_buffer (bufaddr, length); -/* Save skb pointer */ - fep->tx_skbuff[index] = skb; - -/* Push the data cache so the CPM does not get stale memory -* data. -*/ - bdp->cbd_bufaddr =dma_map_single (&fep->pdev->dev, bufaddr, - skb->len,DMA_TO_DEVICE ); -if (dma_mapping_error (&fep->pdev->dev, bdp->cbd_bufaddr)) { - bdp->cbd_bufaddr =0 ; - fep->tx_skbuff[index] =NULL ; +/* Push the data cache so the CPM does not get stale memory data. */ + addr =dma_map_single (&fep->pdev->dev, bufaddr, length,DMA_TO_DEVICE ); +if (dma_mapping_error (&fep->pdev->dev, addr)) {dev_kfree_skb_any (skb);if (net_ratelimit ())netdev_err (ndev,"Tx DMA memory map failed\n" );return NETDEV_TX_OK ; } +/* Save skb pointer */ + fep->tx_skbuff[index] = skb; + + bdp->cbd_datlen = length; + bdp->cbd_bufaddr = addr; +if (fep->bufdesc_ex) {struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
@@ -489,7 +489,7 @@ static void fec_enet_bd_init(struct net_device *dev)/* Initialize the BD for every fragment in the page. */ bdp->cbd_sc =0 ; -if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) { +if (fep->tx_skbuff[i]) {dev_kfree_skb_any (fep->tx_skbuff[i]); fep->tx_skbuff[i] =NULL ; }
@@ -793,6 +793,7 @@ fec_enet_tx(struct net_device *ndev) index = bdp - fep->tx_bd_base; skb = fep->tx_skbuff[index]; + fep->tx_skbuff[index] =NULL ;dma_unmap_single (&fep->pdev->dev, bdp->cbd_bufaddr, skb->len,DMA_TO_DEVICE ); bdp->cbd_bufaddr =0 ;
@@ -842,7 +843,6 @@ fec_enet_tx(struct net_device *ndev)/* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any (skb); - fep->tx_skbuff[index] =NULL ; fep->dirty_tx = bdp;
Signature · 1 line
1.8.3.1
PATCH 79/222 net:fec: make rx skb allocation/map more robust
In reply to Russell King - ARM LinuxAllocate, and then map the receive skb before writing any data to the ring descriptor or storing the skb. This means we have ring data in one of two states: either fully setup, or not setup. This simplifies the cleanup, which could end up calling dma_unmap_single() on a DMA error value.
--- drivers/net/ethernet/freescale/fec_main.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +10 -6
@@ -1712,12 +1712,11 @@ static void fec_enet_free_buffers(struct net_device *ndev) bdp = fep->rx_bd_base;for (i =0 ; i < fep->rx_ring_size; i++) { skb = fep->rx_skbuff[i]; - -if (bdp->cbd_bufaddr) +if (skb) {dma_unmap_single (&fep->pdev->dev, bdp->cbd_bufaddr,FEC_ENET_RX_FRSIZE ,DMA_FROM_DEVICE ); -if (skb)dev_kfree_skb (skb); + } bdp =fec_enet_get_nextdesc (bdp, fep); }
@@ -1735,21 +1734,26 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) bdp = fep->rx_bd_base;for (i =0 ; i < fep->rx_ring_size; i++) { +dma_addr_t addr; + skb =netdev_alloc_skb (ndev,FEC_ENET_RX_FRSIZE );if (!skb) {fec_enet_free_buffers (ndev);return -ENOMEM ; } - fep->rx_skbuff[i] = skb; - bdp->cbd_bufaddr =dma_map_single (&fep->pdev->dev, skb->data, + addr =dma_map_single (&fep->pdev->dev, skb->data,FEC_ENET_RX_FRSIZE ,DMA_FROM_DEVICE ); -if (dma_mapping_error (&fep->pdev->dev, bdp->cbd_bufaddr)) { +if (dma_mapping_error (&fep->pdev->dev, addr)) { +dev_kfree_skb (skb);fec_enet_free_buffers (ndev);if (net_ratelimit ())netdev_err (ndev,"Rx DMA memory map failed\n" );return -ENOMEM ; } + + fep->rx_skbuff[i] = skb; + bdp->cbd_bufaddr = addr; bdp->cbd_sc =BD_ENET_RX_EMPTY ;if (fep->bufdesc_ex) {
Signature · 1 line
1.8.3.1
PATCH 80/222 net:fec: ensure fec_enet_free_buffers() properly cleans the rings
In reply to Russell King - ARM LinuxEnsure that we do not double-free any allocations, and that any transmit skbuffs are properly freed when we clean up the rings.
--- drivers/net/ethernet/freescale/fec_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/fec_main.c +8 -1
@@ -1712,6 +1712,7 @@ static void fec_enet_free_buffers(struct net_device *ndev) bdp = fep->rx_bd_base;for (i =0 ; i < fep->rx_ring_size; i++) { skb = fep->rx_skbuff[i]; + fep->rx_skbuff[i] =NULL ;if (skb) {dma_unmap_single (&fep->pdev->dev, bdp->cbd_bufaddr,FEC_ENET_RX_FRSIZE ,DMA_FROM_DEVICE );
@@ -1721,8 +1722,14 @@ static void fec_enet_free_buffers(struct net_device *ndev) } bdp = fep->tx_bd_base; -for (i =0 ; i < fep->tx_ring_size; i++) +for (i =0 ; i < fep->tx_ring_size; i++) {kfree (fep->tx_bounce[i]); + fep->tx_bounce[i] =NULL ; + skb = fep->tx_skbuff[i]; + fep->tx_skbuff[i] =NULL ; +if (skb) +dev_kfree_skb (skb); + } }static int fec_enet_alloc_buffers (struct net_device *ndev)
Signature · 1 line
1.8.3.1
PATCH 81/222 net:fec: fix missing kmalloc() failure check in fec_enet_alloc_buffers()
In reply to Russell King - ARM Linuxfec_enet_alloc_buffers() appears to assume that kmalloc() will never fail. This is an unreasonable assumption. Add a proper check and failure cleanup path.
--- drivers/net/ethernet/freescale/fec_main.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +9 -6
@@ -1744,19 +1744,16 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)dma_addr_t addr; skb =netdev_alloc_skb (ndev,FEC_ENET_RX_FRSIZE ); -if (!skb) { -fec_enet_free_buffers (ndev); -return -ENOMEM ; - } +if (!skb) + goto err_alloc; addr =dma_map_single (&fep->pdev->dev, skb->data,FEC_ENET_RX_FRSIZE ,DMA_FROM_DEVICE );if (dma_mapping_error (&fep->pdev->dev, addr)) {dev_kfree_skb (skb); -fec_enet_free_buffers (ndev);if (net_ratelimit ())netdev_err (ndev,"Rx DMA memory map failed\n" ); -return -ENOMEM ; + goto err_alloc; } fep->rx_skbuff[i] = skb;
@@ -1778,6 +1775,8 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) bdp = fep->tx_bd_base;for (i =0 ; i < fep->tx_ring_size; i++) { fep->tx_bounce[i] =kmalloc (FEC_ENET_TX_FRSIZE ,GFP_KERNEL ); +if (!fep->tx_bounce[i]) + goto err_alloc; bdp->cbd_sc =0 ; bdp->cbd_bufaddr =0 ;
@@ -1795,6 +1794,10 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) bdp->cbd_sc |=BD_SC_WRAP ;return 0 ; + + err_alloc: +fec_enet_free_buffers (ndev); +return -ENOMEM ; } static int
Signature · 1 line
1.8.3.1
PATCH 82/222 net:fec: ensure that we dma unmap the transmit descriptors
In reply to Russell King - ARM LinuxOn transmit timeout or close, dirty transmit descriptors were not being correctly cleaned: the only time that DMA mappings are cleaned is when scanning the TX ring after a transmit interrupt. Fix this.
--- drivers/net/ethernet/freescale/fec_main.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +17 -4
@@ -327,6 +327,17 @@ fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)return 0 ; } +static void +fec_enet_tx_unmap (struct bufdesc *bdp,struct fec_enet_private *fep) +{ +dma_addr_t addr = bdp->cbd_bufaddr; +unsigned length = bdp->cbd_datlen; + + bdp->cbd_bufaddr =0 ; + +dma_unmap_single (&fep->pdev->dev, addr, length,DMA_TO_DEVICE ); +} +static netdev_tx_t fec_enet_start_xmit (struct sk_buff *skb,struct net_device *ndev) {
@@ -489,11 +500,12 @@ static void fec_enet_bd_init(struct net_device *dev)/* Initialize the BD for every fragment in the page. */ bdp->cbd_sc =0 ; +if (bdp->cbd_bufaddr) +fec_enet_tx_unmap (bdp, fep);if (fep->tx_skbuff[i]) {dev_kfree_skb_any (fep->tx_skbuff[i]); fep->tx_skbuff[i] =NULL ; } - bdp->cbd_bufaddr =0 ; bdp =fec_enet_get_nextdesc (bdp, fep); }
@@ -792,11 +804,10 @@ fec_enet_tx(struct net_device *ndev)else index = bdp - fep->tx_bd_base; +fec_enet_tx_unmap (bdp, fep); + skb = fep->tx_skbuff[index]; fep->tx_skbuff[index] =NULL ; -dma_unmap_single (&fep->pdev->dev, bdp->cbd_bufaddr, skb->len, -DMA_TO_DEVICE ); - bdp->cbd_bufaddr =0 ;/* Check for errors. */ if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1723,6 +1734,8 @@ static void fec_enet_free_buffers(struct net_device *ndev) bdp = fep->tx_bd_base;for (i =0 ; i < fep->tx_ring_size; i++) { +if (bdp->cbd_bufaddr) +fec_enet_tx_unmap (bdp, fep);kfree (fep->tx_bounce[i]); fep->tx_bounce[i] =NULL ; skb = fep->tx_skbuff[i];
Signature · 1 line
1.8.3.1
PATCH 83/222 net:fec: remove useless fep->opened
In reply to Russell King - ARM Linuxnapi_disable() waits until the NAPI processing has completed, and then prevents any further polls. At this point, the driver then clears fep->opened. The NAPI poll function uses this to stop processing in the receive path. Hence, it will never see this variable cleared, because the NAPI poll has to complete before it will be cleared.
Therefore, this variable serves no purpose, so let's remove it.
--- drivers/net/ethernet/freescale/fec.h | 1 - drivers/net/ethernet/freescale/fec_main.c | 5 ----- 2 files changed, 6 deletions(-)
drivers/net/ethernet/freescale/fec.h +0 -1
@@ -301,7 +301,6 @@ struct fec_enet_private {struct platform_device *pdev; -int opened;int dev_id;/* Phylib and MDIO interface */
drivers/net/ethernet/freescale/fec_main.c +0 -5
@@ -914,9 +914,6 @@ fec_enet_rx(struct net_device *ndev, int budget)if ((status &BD_ENET_RX_LAST ) ==0 )netdev_err (ndev,"rcv is not +last\n" ); -if (!fep->opened) - goto rx_processing_done; -/* Check for errors. */ if (status & (BD_ENET_RX_LG |BD_ENET_RX_SH |BD_ENET_RX_NO |BD_ENET_RX_CR |BD_ENET_RX_OV )) {
@@ -1837,7 +1834,6 @@ fec_enet_open(struct net_device *ndev)napi_enable (&fep->napi);phy_start (fep->phy_dev);netif_start_queue (ndev); - fep->opened =1 ;return 0 ; }
@@ -1848,7 +1844,6 @@ fec_enet_close(struct net_device *ndev)/* Don't know what to do yet. */ napi_disable (&fep->napi); - fep->opened =0 ;netif_tx_disable (ndev);fec_stop (ndev);
Signature · 1 line
1.8.3.1
PATCH 84/222 net:fec: stop the phy before shutting down the MAC
In reply to Russell King - ARM LinuxWhen the network interface goes down, stop the phy to prevent further link up status changes before taking the MAC or netif sections down. This prevents further reception of link up events which could potentially call fec_restart().
Since phy_stop() takes the mutex which adjust_link() runs under, we also ensure that adjust_link() will not already be processing a link up event.
We also need to do this when suspending as well - we don't want a mis-timed phy state change to restart the MAC after we have stopped it for suspend, and thus need to restart the phy when resuming.
--- drivers/net/ethernet/freescale/fec_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/fec_main.c +4 -1
@@ -1842,12 +1842,13 @@ fec_enet_close(struct net_device *ndev) {struct fec_enet_private *fep =netdev_priv (ndev); +phy_stop (fep->phy_dev); +/* Don't know what to do yet. */ napi_disable (&fep->napi);netif_tx_disable (ndev);fec_stop (ndev); -phy_stop (fep->phy_dev);phy_disconnect (fep->phy_dev); fep->phy_dev =NULL ;
@@ -2333,6 +2334,7 @@ fec_suspend(struct device *dev)struct fec_enet_private *fep =netdev_priv (ndev);if (netif_running (ndev)) { +phy_stop (fep->phy_dev);fec_stop (ndev);netif_device_detach (ndev); }
@@ -2385,6 +2387,7 @@ fec_resume(struct device *dev)if (netif_running (ndev)) {fec_restart (ndev, fep->full_duplex);netif_device_attach (ndev); +phy_start (fep->phy_dev); }return 0 ;
Signature · 1 line
1.8.3.1
PATCH 85/222 net:fec: improve safety of suspend/resume/transmit timeout paths
In reply to Russell King - ARM LinuxWe need to hold the rtnl lock while suspending, resuming or processing the transmit timeout to ensure that netif_running() will not change state beneath us while we bring up, take down or restart the hardware.
--- drivers/net/ethernet/freescale/fec_main.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/net/ethernet/freescale/fec_main.c +7 -0
@@ -767,8 +767,10 @@ static void fec_enet_work(struct work_struct *work)if (fep->delay_work.timeout) { fep->delay_work.timeout = false; +rtnl_lock ();fec_restart (fep->netdev, fep->full_duplex);netif_wake_queue (fep->netdev); +rtnl_unlock (); }if (fep->delay_work.trig_tx) {
@@ -2333,11 +2335,14 @@ fec_suspend(struct device *dev)struct net_device *ndev =dev_get_drvdata (dev);struct fec_enet_private *fep =netdev_priv (ndev); +rtnl_lock ();if (netif_running (ndev)) {phy_stop (fep->phy_dev);fec_stop (ndev);netif_device_detach (ndev); } +rtnl_unlock (); +if (fep->clk_ptp)clk_disable_unprepare (fep->clk_ptp);if (fep->clk_enet_out)
@@ -2384,11 +2389,13 @@ fec_resume(struct device *dev) goto failed_clk_ptp; } +rtnl_lock ();if (netif_running (ndev)) {fec_restart (ndev, fep->full_duplex);netif_device_attach (ndev);phy_start (fep->phy_dev); } +rtnl_unlock ();return 0 ;
Signature · 1 line
1.8.3.1
PATCH 86/222 net:fec: ensure fec_enet_close() copes with resume failure
In reply to Russell King - ARM LinuxWhen the FEC is suspended, the device is detached. Upon resume failure, the device is left in detached mode, possibly with some of the required clocks not running. We don't want to be poking the device in that state because as it may cause bus errors.
If the device is marked detached, avoid calling fec_stop().
This depends upon: "net:fec: improve safety of suspend/resume paths"
--- drivers/net/ethernet/freescale/fec_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +2 -2
@@ -1846,10 +1846,10 @@ fec_enet_close(struct net_device *ndev)phy_stop (fep->phy_dev); -/* Don't know what to do yet. */ napi_disable (&fep->napi);netif_tx_disable (ndev); -fec_stop (ndev); +if (netif_device_present (ndev)) +fec_stop (ndev);phy_disconnect (fep->phy_dev); fep->phy_dev =NULL ;
Signature · 1 line
1.8.3.1
PATCH 87/222 net:fec: only run a restart or stop if the device is present and running
In reply to Russell King - ARM LinuxAvoid calling fec_restart() or fec_stop() while the device is down or not present (iow suspended.)
Although the ndo_timeout method will only be called if the device is present and running, we defer this to a work queue. The work queue can run independently, and so needs to repeat these checks to ensure that a restart doesn't occur after the device has been taken down or detached for suspend. In this case, we call fec_restart() in the resume path, so nothing is lost.
For fec_set_features, we add a call to fec_restart() in fec_enet_open() to ensure that the hardware is appropriate programmed when the interface is opened. fec_set_features() call should not occur while we're suspended, so we don't have to worry about that case.
The adjust_link needs similar treatment - this also is called from a work queue, which may be run independently after we have taken the device down and detached it. In this case, we just mark the link down and take no further action. We will reset things appropriately once the device is up and running again, at which point we will receive another adjust_link callback.
--- drivers/net/ethernet/freescale/fec_main.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +14 -5
@@ -764,12 +764,15 @@ static void fec_enet_work(struct work_struct *work)container_of (work, struct fec_enet_private, delay_work.delay_work.work); +struct net_device *ndev = fep->netdev;if (fep->delay_work.timeout) { fep->delay_work.timeout = false;rtnl_lock (); -fec_restart (fep->netdev, fep->full_duplex); -netif_wake_queue (fep->netdev); +if (netif_device_present (ndev) ||netif_running (ndev)) { +fec_restart (ndev, fep->full_duplex); +netif_wake_queue (ndev); + }rtnl_unlock (); }
@@ -1200,7 +1203,14 @@ static void fec_enet_adjust_link(struct net_device *ndev)return ; } -if (phy_dev->link) { +/* +* If the netdev is down, or is going down, we're not interested +* in link state events, so just mark our idea of the link as down +* and ignore the event. +*/ +if (!netif_running (ndev) || !netif_device_present (ndev)) { + fep->link =0 ; + }else if (phy_dev->link) {if (!fep->link) { fep->link = phy_dev->link; status_change =1 ;
@@ -1833,6 +1843,7 @@ fec_enet_open(struct net_device *ndev)return ret; } +fec_restart (ndev, fep->full_duplex);napi_enable (&fep->napi);phy_start (fep->phy_dev);netif_start_queue (ndev);
@@ -1997,8 +2008,6 @@ static int fec_set_features(struct net_device *netdev,fec_stop (netdev);fec_restart (netdev, fep->phy_dev->duplex);netif_wake_queue (netdev); - }else { -fec_restart (netdev, fep->phy_dev->duplex); } }
Signature · 1 line
1.8.3.1
PATCH 88/222 net:fec: move calls to quiesce/resume packet processing out of fec_restart()
In reply to Russell King - ARM LinuxMove the calls to quiesce and resume packet processing out of fec_restart() to its call sites. This is the first step in a two stage clean up of this code, where we just move the calls out of fec_restart() without changing them. Not everywhere needs to issue these calls, and not everywhere needs all of these calls to be issued.
--- drivers/net/ethernet/freescale/fec_main.c | 64 ++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 19 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +45 -19
@@ -515,9 +515,10 @@ static void fec_enet_bd_init(struct net_device *dev) fep->dirty_tx = bdp; } -/* This function is called to start or restart the FEC during a link -* change. This only happens when switching between half and full -* duplex. +/* +* This function is called to start or restart the FEC during a link +* change, transmit timeout, or to reconfigure the FEC. The network +* packet processing for this device must be stopped before this call. */ static void fec_restart (struct net_device *ndev,int duplex)
@@ -531,13 +532,6 @@ fec_restart(struct net_device *ndev, int duplex)u32 rcntl =OPT_FRAME_SIZE |0x04 ;u32 ecntl =0x2 ;/* ETHEREN */ -if (netif_running (ndev)) { -netif_device_detach (ndev); -napi_disable (&fep->napi); -netif_tx_disable (ndev); -netif_tx_lock_bh (ndev); - } -/* Whack a reset. We should wait for this. */ writel (1 , fep->hwp +FEC_ECNTRL );udelay (10 );
@@ -706,13 +700,6 @@ fec_restart(struct net_device *ndev, int duplex)/* Enable interrupts we wish to service */ writel (FEC_DEFAULT_IMASK , fep->hwp +FEC_IMASK ); - -if (netif_running (ndev)) { -netif_tx_unlock_bh (ndev); -netif_wake_queue (ndev); -napi_enable (&fep->napi); -netif_device_attach (ndev); - } } static void
@@ -770,8 +757,15 @@ static void fec_enet_work(struct work_struct *work) fep->delay_work.timeout = false;rtnl_lock ();if (netif_device_present (ndev) ||netif_running (ndev)) { +netif_device_detach (ndev); +napi_disable (&fep->napi); +netif_tx_disable (ndev); +netif_tx_lock_bh (ndev);fec_restart (ndev, fep->full_duplex); +netif_tx_unlock_bh (ndev);netif_wake_queue (ndev); +napi_enable (&fep->napi); +netif_device_attach (ndev); }rtnl_unlock (); }
@@ -1225,8 +1219,17 @@ static void fec_enet_adjust_link(struct net_device *ndev) }/* if any of the above changed restart the FEC */ -if (status_change) +if (status_change) { +netif_device_detach (ndev); +napi_disable (&fep->napi); +netif_tx_disable (ndev); +netif_tx_lock_bh (ndev);fec_restart (ndev, phy_dev->duplex); +netif_tx_unlock_bh (ndev); +netif_wake_queue (ndev); +napi_enable (&fep->napi); +netif_device_attach (ndev); + } }else {if (fep->link) {fec_stop (ndev);
@@ -1568,8 +1571,17 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,fec_stop (ndev);phy_start_aneg (fep->phy_dev); } -if (netif_running (ndev)) +if (netif_running (ndev)) { +netif_device_detach (ndev); +napi_disable (&fep->napi); +netif_tx_disable (ndev); +netif_tx_lock_bh (ndev);fec_restart (ndev,0 ); +netif_tx_unlock_bh (ndev); +netif_wake_queue (ndev); +napi_enable (&fep->napi); +netif_device_attach (ndev); + }return 0 ; }
@@ -2006,8 +2018,15 @@ static int fec_set_features(struct net_device *netdev,if (netif_running (netdev)) {fec_stop (netdev); +netif_device_detach (netdev); +napi_disable (&fep->napi); +netif_tx_disable (netdev); +netif_tx_lock_bh (netdev);fec_restart (netdev, fep->phy_dev->duplex); +netif_tx_unlock_bh (netdev);netif_wake_queue (netdev); +napi_enable (&fep->napi); +netif_device_attach (netdev); } }
@@ -2400,7 +2419,14 @@ fec_resume(struct device *dev)rtnl_lock ();if (netif_running (ndev)) { +netif_device_detach (ndev); +napi_disable (&fep->napi); +netif_tx_disable (ndev); +netif_tx_lock_bh (ndev);fec_restart (ndev, fep->full_duplex); +netif_tx_unlock_bh (ndev); +netif_wake_queue (ndev); +napi_enable (&fep->napi);netif_device_attach (ndev);phy_start (fep->phy_dev); }
Signature · 1 line
1.8.3.1
PATCH 89/222 net:fec: remove inappropriate calls around fec_restart()
In reply to Russell King - ARM LinuxThis is the second stage to "move calls to quiesce/resume packet processing out of fec_restart()", where we remove calls which are not appropriate to the call site.
In the majority of cases, there is no need to detach and reattach the interface as we are holding the queue xmit lock across the reset. The exception to that is in fec_resume(), where we are already detached by the suspend function. Here, we can remove the call to detach the interface.
We also do not need to stop the transmit queue. Holding the xmit lock is enough to ensure that the transmit packet processing is not running while we perform our task. However, since fec_restart() always cleans the rings, we call netif_wake_queue() (or netif_device_attach() in the case of resume) just before dropping the xmit lock. This prevents the watchdog firing.
Lastly, always call napi_enable() after the device has been reattached in the resume path so that we know that the transmit packet processing is already in an enabled state, so we don't call netif_wake_queue() while detached.
--- drivers/net/ethernet/freescale/fec_main.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +6 -20
@@ -757,15 +757,12 @@ static void fec_enet_work(struct work_struct *work) fep->delay_work.timeout = false;rtnl_lock ();if (netif_device_present (ndev) ||netif_running (ndev)) { -netif_device_detach (ndev);napi_disable (&fep->napi); -netif_tx_disable (ndev);netif_tx_lock_bh (ndev);fec_restart (ndev, fep->full_duplex); -netif_tx_unlock_bh (ndev);netif_wake_queue (ndev); +netif_tx_unlock_bh (ndev);napi_enable (&fep->napi); -netif_device_attach (ndev); }rtnl_unlock (); }
@@ -1220,15 +1217,12 @@ static void fec_enet_adjust_link(struct net_device *ndev)/* if any of the above changed restart the FEC */ if (status_change) { -netif_device_detach (ndev);napi_disable (&fep->napi); -netif_tx_disable (ndev);netif_tx_lock_bh (ndev);fec_restart (ndev, phy_dev->duplex); -netif_tx_unlock_bh (ndev);netif_wake_queue (ndev); +netif_tx_unlock_bh (ndev);napi_enable (&fep->napi); -netif_device_attach (ndev); } }else {if (fep->link) {
@@ -1572,15 +1566,12 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,phy_start_aneg (fep->phy_dev); }if (netif_running (ndev)) { -netif_device_detach (ndev);napi_disable (&fep->napi); -netif_tx_disable (ndev);netif_tx_lock_bh (ndev);fec_restart (ndev,0 ); -netif_tx_unlock_bh (ndev);netif_wake_queue (ndev); +netif_tx_unlock_bh (ndev);napi_enable (&fep->napi); -netif_device_attach (ndev); }return 0 ;
@@ -2018,15 +2009,12 @@ static int fec_set_features(struct net_device *netdev,if (netif_running (netdev)) {fec_stop (netdev); -netif_device_detach (netdev);napi_disable (&fep->napi); -netif_tx_disable (netdev);netif_tx_lock_bh (netdev);fec_restart (netdev, fep->phy_dev->duplex); -netif_tx_unlock_bh (netdev);netif_wake_queue (netdev); +netif_tx_unlock_bh (netdev);napi_enable (&fep->napi); -netif_device_attach (netdev); } }
@@ -2419,15 +2407,13 @@ fec_resume(struct device *dev)rtnl_lock ();if (netif_running (ndev)) { -netif_device_detach (ndev);napi_disable (&fep->napi); -netif_tx_disable (ndev);netif_tx_lock_bh (ndev);fec_restart (ndev, fep->full_duplex); +netif_device_attach (ndev);netif_tx_unlock_bh (ndev); -netif_wake_queue (ndev); -napi_enable (&fep->napi);netif_device_attach (ndev); +napi_enable (&fep->napi);phy_start (fep->phy_dev); }rtnl_unlock ();
Signature · 1 line
1.8.3.1
PATCH 90/222 net:fec: quiesce packet processing before stopping device in fec_suspend()
In reply to Russell King - ARM Linuxfec_suspend() calls fec_stop() to stop the transmit ring while the transmit packet processing is still active. This can lead to the transmit queue being restarted by an intervening packet queued for transmission, or by the tx quirk timer expiring. Fix this by moving the call to fec_enet_netif_quiesce() before fec_stop(). We must remove the corresponding call to fec_enet_netif_quiesce() from the resume path.
We also need to avoid calling fec_enet_netif_quiesce() inside fec_enet_close() to cover the failed resume scenario otherwise fec_enet_close() will hang in napi_disable().
--- drivers/net/ethernet/freescale/fec_main.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +9 -7
@@ -1860,10 +1860,11 @@ fec_enet_close(struct net_device *ndev)phy_stop (fep->phy_dev); -napi_disable (&fep->napi); -netif_tx_disable (ndev); -if (netif_device_present (ndev)) +if (netif_device_present (ndev)) { +napi_disable (&fep->napi); +netif_tx_disable (ndev);fec_stop (ndev); + }phy_disconnect (fep->phy_dev); fep->phy_dev =NULL ;
@@ -2354,8 +2355,11 @@ fec_suspend(struct device *dev)rtnl_lock ();if (netif_running (ndev)) {phy_stop (fep->phy_dev); -fec_stop (ndev); +napi_disable (&fep->napi); +netif_tx_lock_bh (ndev);netif_device_detach (ndev); +netif_tx_unlock_bh (ndev); +fec_stop (ndev); }rtnl_unlock ();
@@ -2407,12 +2411,10 @@ fec_resume(struct device *dev)rtnl_lock ();if (netif_running (ndev)) { -napi_disable (&fep->napi); -netif_tx_lock_bh (ndev);fec_restart (ndev, fep->full_duplex); +netif_tx_lock_bh (ndev);netif_device_attach (ndev);netif_tx_unlock_bh (ndev); -netif_device_attach (ndev);napi_enable (&fep->napi);phy_start (fep->phy_dev); }
Signature · 1 line
1.8.3.1
PATCH 91/222 net:fec: quiesce packet processing before stopping device in fec_set_features()
In reply to Russell King - ARM Linuxfec_set_features() calls fec_stop() to stop the transmit ring while the transmit queue is still active. This can lead to the transmit ring being restarted by an intervening packet queued for transmission, or by the tx quirk timer expiring. Fix this by moving the call to fec_enet_netif_quiesce() before fec_stop().
--- drivers/net/ethernet/freescale/fec_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/freescale/fec_main.c +1 -1
@@ -2009,9 +2009,9 @@ static int fec_set_features(struct net_device *netdev, fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED ;if (netif_running (netdev)) { -fec_stop (netdev);napi_disable (&fep->napi);netif_tx_lock_bh (netdev); +fec_stop (netdev);fec_restart (netdev, fep->phy_dev->duplex);netif_wake_queue (netdev);netif_tx_unlock_bh (netdev);
Signature · 1 line
1.8.3.1
PATCH 92/222 net:fec: quiesce packet processing before changing features
In reply to Russell King - ARM LinuxChanging the features (receive checksumming) requires the hardware to be reprogrammed, and also changes the checks in the receive packet processing.
The current implementation has a race - fec_set_features() changes the flags which alter the receive packet processing while we are active. Only afterwards do we shutdown and reconfigure the hardware.
This can lead to packets being received and marked with a valid checksum (via CHECKSUM_UNNECESSARY) when the hardware checksum validation has not yet been enabled.
We must quiesce the device, then change the software configuration for this feature, and then resume the device if it was previously running.
The resulting code structure also allows us to add other configuration features in this path without having to quiesce and resume the network interface and device.
--- drivers/net/ethernet/freescale/fec_main.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +16 -9
@@ -1993,12 +1993,21 @@ static void fec_poll_controller(struct net_device *dev) }#endif +#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM +static int fec_set_features (struct net_device *netdev,netdev_features_t features) {struct fec_enet_private *fep =netdev_priv (netdev);netdev_features_t changed = features ^ netdev->features; +/* Quiesce the device if necessary */ +if (netif_running (netdev) && changed &FEATURES_NEED_QUIESCE ) { +napi_disable (&fep->napi); +netif_tx_lock_bh (netdev); +fec_stop (netdev); + } + netdev->features = features;/* Receive checksum has been changed */
@@ -2007,16 +2016,14 @@ static int fec_set_features(struct net_device *netdev, fep->csum_flags |=FLAG_RX_CSUM_ENABLED ; else fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED; + } -if (netif_running (netdev)) { -napi_disable (&fep->napi); -netif_tx_lock_bh (netdev); -fec_stop (netdev); -fec_restart (netdev, fep->phy_dev->duplex); -netif_wake_queue (netdev); -netif_tx_unlock_bh (netdev); -napi_enable (&fep->napi); - } +/* Resume the device after updates */ +if (netif_running (netdev) && changed &FEATURES_NEED_QUIESCE ) { +fec_restart (netdev, fep->phy_dev->duplex); +netif_wake_queue (netdev); +netif_tx_unlock_bh (netdev); +napi_enable (&fep->napi); }return 0 ;
Signature · 1 line
1.8.3.1
PATCH 93/222 net:fec: quiesce packet processing when taking link down in fec_enet_adjust_link()
In reply to Russell King - ARM LinuxWhen the link goes down, the adjust_link method will be called, but there is no synchronisation to ensure that we won't be processing some last remaining packets while performing a reset of the device.
Add the necessary synchronisation to ensure that packet processing is complete before we stop and reset the FEC.
--- drivers/net/ethernet/freescale/fec_main.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/freescale/fec_main.c +4 -0
@@ -1226,7 +1226,11 @@ static void fec_enet_adjust_link(struct net_device *ndev) } }else {if (fep->link) { +napi_disable (&fep->napi); +netif_tx_lock_bh (ndev);fec_stop (ndev); +netif_tx_unlock_bh (ndev); +napi_enable (&fep->napi); fep->link = phy_dev->link; status_change =1 ; }
Signature · 1 line
1.8.3.1
PATCH 94/222 net:fec: fix ethtool set_pauseparam duplex bug
In reply to Russell King - ARM LinuxSetting the pause parameters causes a running network interface to be restarted. However, the restart forces the FEC into half-duplex mode, whether or not the remote end is in half-duplex mode. Misconfigured duplex mode is a known source of problems on a link.
Fix this by always preserving the duplex mode on configuration changes.
--- drivers/net/ethernet/freescale/fec_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/freescale/fec_main.c +1 -1
@@ -1572,7 +1572,7 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,if (netif_running (ndev)) {napi_disable (&fep->napi);netif_tx_lock_bh (ndev); -fec_restart (ndev,0 ); +fec_restart (ndev, fep->full_duplex);netif_wake_queue (ndev);netif_tx_unlock_bh (ndev);napi_enable (&fep->napi);
Signature · 1 line
1.8.3.1
PATCH 95/222 net:fec: clean up duplex mode handling
In reply to Russell King - ARM LinuxMany places call fec_restart() with the second parameter being some kind of previously saved duplex value, but only two places call it with some other setting. This is at odds with how the other link settings are handled, and used to be racy before the rtnl locks were added to fec_restart()'s various call paths.
Clean this up so all link capabilities are handled in the same way - saved into the fec_enet_private structure, and then fec_restart() acts on those settings.
--- drivers/net/ethernet/freescale/fec_main.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +12 -12
@@ -521,7 +521,7 @@ static void fec_enet_bd_init(struct net_device *dev)* packet processing for this device must be stopped before this call. */ static void -fec_restart (struct net_device *ndev,int duplex) +fec_restart (struct net_device *ndev) {struct fec_enet_private *fep =netdev_priv (ndev); const struct platform_device_id *id_entry =
@@ -572,7 +572,7 @@ fec_restart(struct net_device *ndev, int duplex) }/* Enable MII mode */ -if (duplex) { +if (fep->full_duplex ==DUPLEX_FULL ) {/* FD enable */ writel (0x04 , fep->hwp +FEC_X_CNTRL ); }else {
@@ -581,8 +581,6 @@ fec_restart(struct net_device *ndev, int duplex)writel (0x0 , fep->hwp +FEC_X_CNTRL ); } - fep->full_duplex = duplex; -/* Set MII speed */ writel (fep->phy_speed, fep->hwp +FEC_MII_SPEED );
@@ -759,7 +757,7 @@ static void fec_enet_work(struct work_struct *work)if (netif_device_present (ndev) ||netif_running (ndev)) {napi_disable (&fep->napi);netif_tx_lock_bh (ndev); -fec_restart (ndev, fep->full_duplex); +fec_restart (ndev);netif_wake_queue (ndev);netif_tx_unlock_bh (ndev);napi_enable (&fep->napi);
@@ -1207,8 +1205,10 @@ static void fec_enet_adjust_link(struct net_device *ndev) status_change =1 ; } -if (fep->full_duplex != phy_dev->duplex) +if (fep->full_duplex != phy_dev->duplex) { + fep->full_duplex = phy_dev->duplex; status_change =1 ; + }if (phy_dev->speed != fep->speed) { fep->speed = phy_dev->speed;
@@ -1219,7 +1219,7 @@ static void fec_enet_adjust_link(struct net_device *ndev)if (status_change) {napi_disable (&fep->napi);netif_tx_lock_bh (ndev); -fec_restart (ndev, phy_dev->duplex); +fec_restart (ndev);netif_wake_queue (ndev);netif_tx_unlock_bh (ndev);napi_enable (&fep->napi);
@@ -1572,7 +1572,7 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,if (netif_running (ndev)) {napi_disable (&fep->napi);netif_tx_lock_bh (ndev); -fec_restart (ndev, fep->full_duplex); +fec_restart (ndev);netif_wake_queue (ndev);netif_tx_unlock_bh (ndev);napi_enable (&fep->napi);
@@ -1850,7 +1850,7 @@ fec_enet_open(struct net_device *ndev)return ret; } -fec_restart (ndev, fep->full_duplex); +fec_restart (ndev);napi_enable (&fep->napi);phy_start (fep->phy_dev);netif_start_queue (ndev);
@@ -2024,7 +2024,7 @@ static int fec_set_features(struct net_device *netdev,/* Resume the device after updates */ if (netif_running (netdev) && changed &FEATURES_NEED_QUIESCE ) { -fec_restart (netdev, fep->phy_dev->duplex); +fec_restart (netdev);netif_wake_queue (netdev);netif_tx_unlock_bh (netdev);napi_enable (&fep->napi);
@@ -2110,7 +2110,7 @@ static int fec_enet_init(struct net_device *ndev) fep->csum_flags |=FLAG_RX_CSUM_ENABLED ; } -fec_restart (ndev,0 ); +fec_restart (ndev);return 0 ; }
@@ -2422,7 +2422,7 @@ fec_resume(struct device *dev)rtnl_lock ();if (netif_running (ndev)) { -fec_restart (ndev, fep->full_duplex); +fec_restart (ndev);netif_tx_lock_bh (ndev);netif_device_attach (ndev);netif_tx_unlock_bh (ndev);
Signature · 1 line
1.8.3.1
PATCH 96/222 net:fec: add barrier to transmit path to ensure proper ordering
In reply to Russell King - ARM LinuxEnsure that the writes to the descriptor data is visible to the hardware before the descriptor is handed over to the hardware.
Having discussed this with Will Deacon, we need a wmb() between writing the descriptor data and handing the descriptor over to the hardware. The corresponding rmb() is in the ethernet hardware.
--- drivers/net/ethernet/freescale/fec_main.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/net/ethernet/freescale/fec_main.c +7 -0
@@ -436,6 +436,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) } } +/* +* We need the preceding stores to the descriptor to complete +* before updating the status field, which hands it over to the +* hardware. The corresponding rmb() is "in the hardware". +*/ +wmb (); +/* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. */
Signature · 1 line
1.8.3.1
PATCH 97/222 net:fec: add barrier to receive path to ensure proper ordering
In reply to Russell King - ARM LinuxJust as we need a barrier in the transmit path, we also need a barrier in the receive path to ensure that we don't modify a handed over descriptor.
--- drivers/net/ethernet/freescale/fec_main.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +13 -7
@@ -1036,13 +1036,6 @@ fec_enet_rx(struct net_device *ndev, int budget)dma_sync_single_for_device (&fep->pdev->dev, bdp->cbd_bufaddr,FEC_ENET_RX_FRSIZE ,DMA_FROM_DEVICE ); rx_processing_done: -/* Clear the status flags for this buffer */ - status &= ~BD_ENET_RX_STATS ; - -/* Mark the buffer empty */ - status |=BD_ENET_RX_EMPTY ; - bdp->cbd_sc = status; -if (fep->bufdesc_ex) {struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
@@ -1051,6 +1044,19 @@ fec_enet_rx(struct net_device *ndev, int budget) ebdp->cbd_bdu =0 ; } +/* +* Ensure that the previous writes have completed before +* the status update becomes visible. +*/ +wmb (); + +/* Clear the status flags for this buffer */ + status &= ~BD_ENET_RX_STATS ; + +/* Mark the buffer empty */ + status |=BD_ENET_RX_EMPTY ; + bdp->cbd_sc = status; +/* Update BD pointer to next entry */ bdp =fec_enet_get_nextdesc (bdp, fep);
Signature · 1 line
1.8.3.1
PATCH 98/222 net:fec: better implementation of iMX6 ERR006358 quirk
In reply to Russell King - ARM LinuxUsing a (delayed) workqueue for ERR006358 is not correct - a work queue is a single-trigger device. Once the work queue has been scheduled, it can't be re-scheduled until it has been run. This can cause problems - with an appropriate packet timing, we can end up with packets queued, but not sent by the hardware, resulting in the transmit timeout firing.
Re-implement this as per the workaround detailed in the ERR006358 documentation - if there are packets waiting to be sent when we service the transmit ring, and we see that the transmitter is not running, kick the transmitter to run the pending entries in the ring.
Testing here with a 10Mbit half duplex link sees the resulting iperf TCP bandwidth increase from between 1 to 2Mbps to between 8 to 9Mbps.
--- drivers/net/ethernet/freescale/fec.h | 1 - drivers/net/ethernet/freescale/fec_main.c | 20 +++++++------------- 2 files changed, 7 insertions(+), 14 deletions(-)
drivers/net/ethernet/freescale/fec.h +0 -1
@@ -259,7 +259,6 @@ struct bufdesc_ex {struct fec_enet_delayed_work {struct delayed_work delay_work;bool timeout; -bool trig_tx; };/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
drivers/net/ethernet/freescale/fec_main.c +7 -13
@@ -344,7 +344,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)struct fec_enet_private *fep =netdev_priv (ndev);const struct platform_device_id *id_entry =platform_get_device_id (fep->pdev); -struct bufdesc *bdp, *bdp_pre; +struct bufdesc *bdp;void *bufaddr;unsigned short status;unsigned int index;
@@ -450,13 +450,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | BD_ENET_TX_LAST | BD_ENET_TX_TC); bdp->cbd_sc = status; - bdp_pre =fec_enet_get_prevdesc (bdp, fep); -if ((id_entry->driver_data &FEC_QUIRK_ERR006358 ) && - !(bdp_pre->cbd_sc &BD_ENET_TX_READY )) { - fep->delay_work.trig_tx = true; -schedule_delayed_work (&(fep->delay_work.delay_work), -msecs_to_jiffies (1 )); - }/* If this was the last BD in the ring, start at the beginning again. */ bdp =fec_enet_get_nextdesc (bdp, fep);
@@ -771,11 +764,6 @@ static void fec_enet_work(struct work_struct *work) }rtnl_unlock (); } - -if (fep->delay_work.trig_tx) { - fep->delay_work.trig_tx = false; -writel (0 , fep->hwp +FEC_X_DES_ACTIVE ); - } } static void
@@ -868,6 +856,12 @@ fec_enet_tx(struct net_device *ndev)netif_wake_queue (ndev); } } + +/* ERR006538: Keep the transmitter going */ +if (fep->dirty_tx != fep->cur_tx && +readl (fep->hwp +FEC_X_DES_ACTIVE ) ==0 ) +writel (0 , fep->hwp +FEC_X_DES_ACTIVE ); +return ; }
Signature · 1 line
1.8.3.1
PATCH 99/222 net:fec: avoid hitting transmitter if it is still running
In reply to Russell King - ARM Linux--- drivers/net/ethernet/freescale/fec_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/fec_main.c +2 -1
@@ -462,7 +462,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)netif_stop_queue (ndev);/* Trigger transmission start */ -writel (0 , fep->hwp +FEC_X_DES_ACTIVE ); +if (readl (fep->hwp +FEC_X_DES_ACTIVE ) ==0 ) +writel (0 , fep->hwp +FEC_X_DES_ACTIVE );return NETDEV_TX_OK ; }
Signature · 1 line
1.8.3.1
PATCH 100/222 net:fec: remove delayed work
In reply to Russell King - ARM LinuxWe no longer need a delayed work in this driver, since we no longer have the requirement to delay any work - instead, use a work_struct directly.
--- drivers/net/ethernet/freescale/fec.h | 8 ++------ drivers/net/ethernet/freescale/fec_main.c | 34 +++++++++++++------------------ 2 files changed, 16 insertions(+), 26 deletions(-)
drivers/net/ethernet/freescale/fec.h +2 -6
@@ -256,11 +256,6 @@ struct bufdesc_ex {#define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR)#define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR) -struct fec_enet_delayed_work { -struct delayed_work delay_work; -bool timeout; -}; -/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and * tx_bd_base always point to the base of the buffer descriptors. The * cur_rx and cur_tx point to the currently available buffer.
@@ -319,6 +314,8 @@ struct fec_enet_private {struct napi_struct napi;int csum_flags; +struct work_struct tx_timeout_work; +struct ptp_clock *ptp_clock;struct ptp_clock_info ptp_caps;unsigned long last_overflow_check;
@@ -331,7 +328,6 @@ struct fec_enet_private {int hwts_rx_en;int hwts_tx_en;struct timer_list time_keep; -struct fec_enet_delayed_work delay_work;struct regulator *reg_phy; };
drivers/net/ethernet/freescale/fec_main.c +14 -20
@@ -740,31 +740,25 @@ fec_timeout(struct net_device *ndev) ndev->stats.tx_errors++; - fep->delay_work.timeout = true; -schedule_delayed_work (&(fep->delay_work.delay_work),0 ); +schedule_work (&fep->tx_timeout_work); } -static void fec_enet_work (struct work_struct *work) +static void fec_enet_timeout_work (struct work_struct *work) {struct fec_enet_private *fep = -container_of (work, - struct fec_enet_private, - delay_work.delay_work.work); + container_of(work, struct fec_enet_private, tx_timeout_work);struct net_device *ndev = fep->netdev; -if (fep->delay_work.timeout) { - fep->delay_work.timeout = false; -rtnl_lock (); -if (netif_device_present (ndev) ||netif_running (ndev)) { -napi_disable (&fep->napi); -netif_tx_lock_bh (ndev); -fec_restart (ndev); -netif_wake_queue (ndev); -netif_tx_unlock_bh (ndev); -napi_enable (&fep->napi); - } -rtnl_unlock (); +rtnl_lock (); +if (netif_device_present (ndev) ||netif_running (ndev)) { +napi_disable (&fep->napi); +netif_tx_lock_bh (ndev); +fec_restart (ndev); +netif_wake_queue (ndev); +netif_tx_unlock_bh (ndev); +napi_enable (&fep->napi); } +rtnl_unlock (); } static void
@@ -2312,7 +2306,7 @@ fec_probe(struct platform_device *pdev)if (fep->bufdesc_ex && fep->ptp_clock)netdev_info (ndev,"registered PHC device %d\n" , fep->dev_id); -INIT_DELAYED_WORK (&(fep->delay_work.delay_work), fec_enet_work); +INIT_WORK (&fep->tx_timeout_work, fec_enet_timeout_work);return 0 ; failed_register:
@@ -2345,7 +2339,7 @@ fec_drv_remove(struct platform_device *pdev)struct net_device *ndev =platform_get_drvdata (pdev);struct fec_enet_private *fep =netdev_priv (ndev); -cancel_delayed_work_sync (&(fep->delay_work.delay_work)); +cancel_work_sync (&fep->tx_timeout_work);unregister_netdev (ndev);fec_enet_mii_remove (fep);del_timer_sync (&fep->time_keep);
Signature · 1 line
1.8.3.1
PATCH 101/222 net:fec: fix interrupt handling races
In reply to Russell King - ARM LinuxWhile running: while :; do iperf -c <HOST> -P 4; done, transmit timeouts are regularly reported. With the tx ring dumping in place, we can see that all entries are in use, and the hardware has finished transmitting these packets. However, the driver has not reclaimed these ring entries.
This can occur if the interrupt handler is invoked at the wrong moment - eg:
CPU0 CPU1 fec_enet_tx() interrupt, IEVENT = FEC_ENET_TXF FEC_ENET_TXF cleared napi_schedule_prep() napi_complete()
The result is that we clear the transmit interrupt, but we don't trigger any cleaning of the transmit ring. Instead, use a different strategy:
- When receiving a transmit or receive interrupt, disable both tx and rx interrupts, but do not acknowledge them. Schedule a napi poll. Don't loop.
- When we are polled, read IEVENT, acknowledging the pending transmit and receive interrupts, before then going on to process the appropriate rings.
This allows us to avoid the race, and has a number of other advantages:
- we cut down on the number of transmit interrupts we have to process.
- we only look at the rings which have pending events.
- we gain additional throughput: the iperf total bandwidth increases from about 180Mbps to 240Mbps:
[ 3] 0.0-10.0 sec 68.1 MBytes 57.0 Mbits/sec [ 5] 0.0-10.0 sec 72.4 MBytes 60.5 Mbits/sec [ 4] 0.0-10.1 sec 76.1 MBytes 63.5 Mbits/sec [ 6] 0.0-10.1 sec 71.9 MBytes 59.9 Mbits/sec [SUM] 0.0-10.1 sec 288 MBytes 241 Mbits/sec
--- drivers/net/ethernet/freescale/fec_main.c | 40 +++++++++++++++++-------------- 1 file changed, 22 insertions(+), 18 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +22 -18
@@ -1065,29 +1065,25 @@ fec_enet_interrupt(int irq, void *dev_id) {struct net_device *ndev = dev_id;struct fec_enet_private *fep =netdev_priv (ndev); +const unsigned napi_mask =FEC_ENET_RXF |FEC_ENET_TXF ;uint int_events;irqreturn_t ret =IRQ_NONE ; -do { - int_events =readl (fep->hwp +FEC_IEVENT ); -writel (int_events, fep->hwp +FEC_IEVENT ); + int_events =readl (fep->hwp +FEC_IEVENT ); +writel (int_events & ~napi_mask, fep->hwp +FEC_IEVENT ); -if (int_events & (FEC_ENET_RXF |FEC_ENET_TXF )) { - ret =IRQ_HANDLED ; +if (int_events & napi_mask) { + ret =IRQ_HANDLED ; -/* Disable the RX interrupt */ -if (napi_schedule_prep (&fep->napi)) { -writel (FEC_RX_DISABLED_IMASK , - fep->hwp +FEC_IMASK ); -__napi_schedule (&fep->napi); - } - } +/* Disable the NAPI interrupts */ +writel (FEC_ENET_MII , fep->hwp +FEC_IMASK ); +napi_schedule (&fep->napi); + } -if (int_events &FEC_ENET_MII ) { - ret =IRQ_HANDLED ; -complete (&fep->mdio_done); - } - }while (int_events); +if (int_events &FEC_ENET_MII ) { + ret =IRQ_HANDLED ; +complete (&fep->mdio_done); + }return ret; }
@@ -1095,8 +1091,16 @@ fec_enet_interrupt(int irq, void *dev_id)static int fec_enet_rx_napi (struct napi_struct *napi,int budget) {struct net_device *ndev = napi->dev; -int pkts =fec_enet_rx (ndev, budget);struct fec_enet_private *fep =netdev_priv (ndev); +int pkts; + +/* +* Clear any pending transmit or receive interrupts before +* processing the rings to avoid racing with the hardware. +*/ +writel (FEC_ENET_RXF |FEC_ENET_TXF , fep->hwp +FEC_IEVENT ); + + pkts =fec_enet_rx (ndev, budget);fec_enet_tx (ndev);
Signature · 1 line
1.8.3.1
PATCH 102/222 net:fec: clear receive interrupts before processing a packet
In reply to Russell King - ARM LinuxClear any pending receive interrupt before we process a pending packet. This helps to avoid any spurious interrupts being raised after we have fully cleaned the receive ring, while still allowing an interrupt to be raised if we receive another packet.
The timing of this is critical: we must do this prior to reading the next packet status to avoid delaying a pending packet.
--- drivers/net/ethernet/freescale/fec_main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/freescale/fec_main.c +2 -0
@@ -904,6 +904,8 @@ fec_enet_rx(struct net_device *ndev, int budget)if ((status &BD_ENET_RX_LAST ) ==0 )netdev_err (ndev,"rcv is not +last\n" ); +writel (FEC_ENET_RXF , fep->hwp +FEC_IEVENT ); +/* Check for errors. */ if (status & (BD_ENET_RX_LG |BD_ENET_RX_SH |BD_ENET_RX_NO |BD_ENET_RX_CR |BD_ENET_RX_OV )) {
Signature · 1 line
1.8.3.1
PATCH 103/222 net:fec: remove useless status check in tx reap path
In reply to Russell King - ARM LinuxRemove a useless status check in the transmit reap path - we have already checked that the DB_ENET_TX_READY bit is clear, so there is no way this test can ever be true.
--- drivers/net/ethernet/freescale/fec_main.c | 3 --- 1 file changed, 3 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +0 -3
@@ -827,9 +827,6 @@ fec_enet_tx(struct net_device *ndev)skb_tstamp_tx (skb, &shhwtstamps); } -if (status &BD_ENET_TX_READY ) -netdev_err (ndev,"HEY! Enet xmit interrupt and TX_READY\n" ); -/* Deferred means some collisions occurred during transmit, * but we eventually sent the packet OK. */
Signature · 1 line
1.8.3.1
PATCH 104/222 net:fec: use a union for the buffer descriptors
In reply to Russell King - ARM LinuxUsing a union gives clearer C code than the existing solution, and allows the removal of some odd code from the receive path whose purpose was to merely store the enhanced buffer descriptor.
--- drivers/net/ethernet/freescale/fec.h | 13 +- drivers/net/ethernet/freescale/fec_main.c | 194 ++++++++++++++---------------- 2 files changed, 96 insertions(+), 111 deletions(-)
drivers/net/ethernet/freescale/fec.h +9 -4
@@ -170,6 +170,11 @@ struct bufdesc_ex {unsigned short res0[4 ]; }; +union bufdesc_u { +struct bufdesc bd; +struct bufdesc_ex ebd; +}; +/* * The following definitions courtesy of commproc.h, which where * Copyright (c) 1997 Dan Malek (dmalek at jlc.net).
@@ -283,12 +288,12 @@ struct fec_enet_private {/* CPM dual port RAM relative addresses */ dma_addr_t bd_dma;/* Address of Rx and Tx buffers */ -struct bufdesc *rx_bd_base; -struct bufdesc *tx_bd_base; +union bufdesc_u *rx_bd_base; +union bufdesc_u *tx_bd_base;/* The next free ring entry */ -struct bufdesc *cur_rx, *cur_tx; +union bufdesc_u *cur_rx, *cur_tx;/* The ring entries to be free()ed */ -struct bufdesc *dirty_tx; +union bufdesc_u *dirty_tx;unsigned short tx_ring_size;unsigned short rx_ring_size;
drivers/net/ethernet/freescale/fec_main.c +87 -107
478 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 105/222 net:fec: consolidate hwtstamp implementation
In reply to Russell King - ARM LinuxBoth transmit and receive use the same infrastructure for calculating the packet timestamp. Rather than duplicating the code, provide a function to do this common work. Model this function in the Intel e1000e version which avoids calling ns_to_ktime() within the spinlock; the spinlock is critical for timecounter_cyc2time() but not ns_to_ktime().
--- drivers/net/ethernet/freescale/fec_main.c | 37 ++++++++++++++++--------------- 1 file changed, 19 insertions(+), 18 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +19 -18
@@ -756,6 +756,21 @@ static void fec_enet_timeout_work(struct work_struct *work) }static void +fec_enet_hwtstamp (struct fec_enet_private *fep,unsigned ts, +struct skb_shared_hwtstamps *hwtstamps) +{ +unsigned long flags; +u64 ns; + +spin_lock_irqsave (&fep->tmreg_lock, flags); + ns =timecounter_cyc2time (&fep->tc, ts); +spin_unlock_irqrestore (&fep->tmreg_lock, flags); + +memset (hwtstamps,0 ,sizeof (*hwtstamps)); + hwtstamps->hwtstamp =ns_to_ktime (ns); +} + +static void fec_enet_tx (struct net_device *ndev) {struct fec_enet_private *fep;
@@ -809,13 +824,8 @@ fec_enet_tx(struct net_device *ndev)if (unlikely (skb_shinfo (skb)->tx_flags &SKBTX_IN_PROGRESS ) && fep->bufdesc_ex) {struct skb_shared_hwtstamps shhwtstamps; -unsigned long flags; -memset (&shhwtstamps,0 ,sizeof (shhwtstamps)); -spin_lock_irqsave (&fep->tmreg_lock, flags); - shhwtstamps.hwtstamp =ns_to_ktime ( -timecounter_cyc2time (&fep->tc, bdp->ebd.ts)); -spin_unlock_irqrestore (&fep->tmreg_lock, flags); +fec_enet_hwtstamp (fep, bdp->ebd.ts, &shhwtstamps);skb_tstamp_tx (skb, &shhwtstamps); }
@@ -974,18 +984,9 @@ fec_enet_rx(struct net_device *ndev, int budget) skb->protocol =eth_type_trans (skb, ndev);/* Get receive timestamp from the skb */ -if (fep->hwts_rx_en && fep->bufdesc_ex) { -struct skb_shared_hwtstamps *shhwtstamps = -skb_hwtstamps (skb); -unsigned long flags; - -memset (shhwtstamps,0 ,sizeof (*shhwtstamps)); - -spin_lock_irqsave (&fep->tmreg_lock, flags); - shhwtstamps->hwtstamp =ns_to_ktime ( -timecounter_cyc2time (&fep->tc, bdp->ebd.ts)); -spin_unlock_irqrestore (&fep->tmreg_lock, flags); - } +if (fep->hwts_rx_en && fep->bufdesc_ex) +fec_enet_hwtstamp (fep, bdp->ebd.ts, +skb_hwtstamps (skb));if (fep->bufdesc_ex && (fep->csum_flags &FLAG_RX_CSUM_ENABLED )) {
Signature · 1 line
1.8.3.1
PATCH 106/222 net:fec: better indexing for transmit descriptor ring
In reply to Russell King - ARM LinuxMaintaining the transmit ring position via pointers is inefficient, especially when it involves complex pointer manipulation, and overlap with the receive descriptor logic.
Re-implement this using indexes, and a single function which returns the descriptor (appropriate to the descriptor type). As an additional benefit, using a union allows cleaner access to the descriptor.
--- drivers/net/ethernet/freescale/fec.h | 6 +- drivers/net/ethernet/freescale/fec_main.c | 142 ++++++++++++++---------------- 2 files changed, 67 insertions(+), 81 deletions(-)
drivers/net/ethernet/freescale/fec.h +3 -3
@@ -291,9 +291,9 @@ struct fec_enet_private {union bufdesc_u *rx_bd_base;union bufdesc_u *tx_bd_base;/* The next free ring entry */ -union bufdesc_u *cur_rx, *cur_tx; -/* The ring entries to be free()ed */ -union bufdesc_u *dirty_tx; +unsigned short tx_next; +unsigned short tx_dirty; +union bufdesc_u *cur_rx;unsigned short tx_ring_size;unsigned short rx_ring_size;
drivers/net/ethernet/freescale/fec_main.c +64 -78
267 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 107/222 net:fec: better indexing for receive descriptor ring
In reply to Russell King - ARM LinuxExtend the previous commit to the receive descriptor ring as well. This gets rid of the two nextdesc/prevdesc functions, since we now just need to get the descriptor for an index instead.
--- drivers/net/ethernet/freescale/fec.h | 2 +- drivers/net/ethernet/freescale/fec_main.c | 98 +++++++++++-------------------- 2 files changed, 35 insertions(+), 65 deletions(-)
drivers/net/ethernet/freescale/fec.h +1 -1
@@ -293,7 +293,7 @@ struct fec_enet_private {/* The next free ring entry */ unsigned short tx_next;unsigned short tx_dirty; -union bufdesc_u *cur_rx; +unsigned short rx_next;unsigned short tx_ring_size;unsigned short rx_ring_size;
drivers/net/ethernet/freescale/fec_main.c +34 -64
200 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 108/222 net:fec: calculate ring space rather than relying on comparing indices
In reply to Russell King - ARM LinuxCalculate the space in the transmit ring rather than comparing indices. This allows us to positively calculate the number of entries remaining, which will be required when we handle fragmented skbs.
--- drivers/net/ethernet/freescale/fec_main.c | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +16 -16
@@ -316,6 +316,12 @@ fec_enet_tx_unmap(union bufdesc_u *bdp, struct fec_enet_private *fep)dma_unmap_single (&fep->pdev->dev, addr, length,DMA_TO_DEVICE ); } +static unsigned ring_free (unsigned ins,unsigned rem,unsigned size) +{ +int num = rem - ins; +return num <0 ? num + size : num; +} +static netdev_tx_t fec_enet_start_xmit (struct sk_buff *skb,struct net_device *ndev) {
@@ -331,11 +337,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)/* Fill in a Tx ring entry */ index = fep->tx_next; - bdp =fec_enet_tx_get (index, fep); - - status = bdp->bd.cbd_sc; -if (status &BD_ENET_TX_READY ) { +if (ring_free (index, fep->tx_dirty, fep->tx_ring_size) <1 ) {/* Ooops. All transmit buffers are full. Bail out. * This should not happen, since ndev->tbusy should be set. */
@@ -349,9 +352,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)return NETDEV_TX_OK ; } -/* Clear all of the status flags */ - status &= ~BD_ENET_TX_STATS ; -/* Set buffer length and buffer pointer */ bufaddr = skb->data; length = skb->len;
@@ -386,6 +386,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)/* Save skb pointer */ fep->tx_skbuff[index] = skb; + bdp =fec_enet_tx_get (index, fep); bdp->bd.cbd_datlen = length; bdp->bd.cbd_bufaddr = addr;
@@ -417,9 +418,9 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)/* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. */ - status |= (BD_ENET_TX_READY |BD_ENET_TX_INTR - |BD_ENET_TX_LAST |BD_ENET_TX_TC ); - bdp->bd.cbd_sc = status; + status = bdp->bd.cbd_sc & ~BD_ENET_TX_STATS ; + bdp->bd.cbd_sc = status |BD_ENET_TX_READY |BD_ENET_TX_INTR | +BD_ENET_TX_LAST |BD_ENET_TX_TC ;skb_tx_timestamp (skb);
@@ -428,7 +429,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) fep->tx_next = index; -if (fep->tx_next == fep->tx_dirty) +if (ring_free (index, fep->tx_dirty, fep->tx_ring_size) <1 )netif_stop_queue (ndev);/* Trigger transmission start */
@@ -808,17 +809,16 @@ fec_enet_tx(struct net_device *ndev)/* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any (skb); -/* Since we have freed up a buffer, the ring is no longer full -*/ -if (netif_queue_stopped (ndev)) -netif_wake_queue (ndev); - fep->tx_dirty = index; }while (1 );/* ERR006538: Keep the transmitter going */ if (index != fep->tx_next &&readl (fep->hwp +FEC_X_DES_ACTIVE ) ==0 )writel (0 , fep->hwp +FEC_X_DES_ACTIVE ); + +if (netif_queue_stopped (ndev) && +ring_free (fep->tx_next, fep->tx_dirty, fep->tx_ring_size)) +netif_wake_queue (ndev); }
Signature · 1 line
1.8.3.1
PATCH 109/222 net:fec: increase transmit ring size
In reply to Russell King - ARM LinuxIncreasing the transmit ring size allows us to queue more packets before needing to stop the transmit queue.
--- drivers/net/ethernet/freescale/fec.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/freescale/fec.h +2 -2
@@ -251,8 +251,8 @@ union bufdesc_u {#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)#define FEC_ENET_TX_FRSIZE 2048#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) -#define TX_RING_SIZE 16/* Must be power of two */ -#define TX_RING_MOD_MASK 15/* for this to work */ +#define TX_RING_SIZE 64/* Must be power of two */ +#define TX_RING_MOD_MASK 63/* for this to work */ #define BD_ENET_RX_INT 0x00800000#define BD_ENET_RX_PTP ((ushort)0x0400)
Signature · 1 line
1.8.3.1
PATCH 110/222 net:fec: increase receive ring size
In reply to Russell King - ARM LinuxIncreasing the receive ring size allows more packets to be received before we run out of ring entries to store the packets. With 16 ring entries, this corresponds with a maximum of 16 * 1514 bytes, or just 23K. At gigabit speeds, this would take around 200us to fill. Increasing this to 64 entries gives us more scope when we have busy workloads, since it increases us to 95K, and around 700us.
Going above this requires the ring buffer allocation to be changed.
--- drivers/net/ethernet/freescale/fec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/freescale/fec.h +1 -1
@@ -245,7 +245,7 @@ union bufdesc_u {* the skbuffer directly. */ -#define FEC_ENET_RX_PAGES 8 +#define FEC_ENET_RX_PAGES 32#define FEC_ENET_RX_FRSIZE 2048#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
Signature · 1 line
1.8.3.1
PATCH 111/222 net:fec: add scatter-gather support
In reply to Russell King - ARM LinuxAdd scatter-gather support for SKB transmission. This allows the driver to make use of GSO, which when enabled allows the iMX6Q to increase TCP transmission throughput from about 320 to 420Mbps, measured with iperf 2.0.5
We adjust the minimum transmit ring space according to whether SG support is enabled or not. This allows non-SG configurations to avoid the tx ring reservation necessary for SG, thereby making full use of their available ring (since non-SG requires just one tx ring entry per packet.)
--- drivers/net/ethernet/freescale/fec.h | 2 + drivers/net/ethernet/freescale/fec_main.c | 204 ++++++++++++++++++++++++------ 2 files changed, 164 insertions(+), 42 deletions(-)
drivers/net/ethernet/freescale/fec.h +2 -0
@@ -280,6 +280,7 @@ struct fec_enet_private {struct clk *clk_enet_out;struct clk *clk_ptp; +unsigned char tx_page_map[TX_RING_SIZE ];/* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE ];struct sk_buff *tx_skbuff[TX_RING_SIZE ];
@@ -293,6 +294,7 @@ struct fec_enet_private {/* The next free ring entry */ unsigned short tx_next;unsigned short tx_dirty; +unsigned short tx_min;unsigned short rx_next;unsigned short tx_ring_size;
drivers/net/ethernet/freescale/fec_main.c +162 -42
353 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 112/222 net:fec: add byte queue limits support
In reply to Russell King - ARM LinuxAdd support for byte queue limits. Information on this feature can be found here: https://lwn.net/Articles/469652/
--- drivers/net/ethernet/freescale/fec_main.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/net/ethernet/freescale/fec_main.c +9 -0
@@ -499,6 +499,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) }skb_tx_timestamp (skb); +netdev_sent_queue (ndev, skb->len);if (++last >= fep->tx_ring_size) last =0 ;
@@ -606,6 +607,7 @@ fec_restart(struct net_device *ndev)writel (PKT_MAXBLR_SIZE , fep->hwp +FEC_R_BUFF_SIZE );fec_enet_bd_init (ndev); +netdev_reset_queue (ndev);/* Set receive and transmit descriptor base. */ writel (fep->bd_dma, fep->hwp +FEC_R_DES_START );
@@ -836,7 +838,9 @@ fec_enet_tx(struct net_device *ndev)unsigned short status;struct sk_buff *skb;unsigned index = fep->tx_dirty; +unsigned pkts_compl, bytes_compl; + pkts_compl = bytes_compl =0 ; do { if (++index >= fep->tx_ring_size) index = 0;
@@ -891,6 +895,9 @@ fec_enet_tx(struct net_device *ndev)skb_tstamp_tx (skb, &shhwtstamps); } + pkts_compl++; + bytes_compl += skb->len; +/* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any (skb); }
@@ -898,6 +905,8 @@ fec_enet_tx(struct net_device *ndev) fep->tx_dirty = index; }while (1 ); +netdev_completed_queue (ndev, pkts_compl, bytes_compl); +/* ERR006538: Keep the transmitter going */ if (index != fep->tx_next &&readl (fep->hwp +FEC_X_DES_ACTIVE ) ==0 )writel (0 , fep->hwp +FEC_X_DES_ACTIVE );
Signature · 1 line
1.8.3.1
PATCH 113/222 net:fec: add better flow control support
In reply to Russell King - ARM LinuxThe FEC hardware in iMX6 is capable of separate control of each flow control path: the receiver can be programmed via the receive control register to detect flow control frames, and the transmitter can be programmed via the receive FIFO thresholds to enable generation of pause frames.
This means we can implement the full range of flow control: both symmetric and asymmetric flow control. We support ethtool configuring all options: forced manual mode, where each path can be controlled individually, and autonegotiation mode.
In autonegotiation mode, the tx/rx enable bits can be used to influence the outcome, though they don't precisely define which paths will be enabled. One combination we don't support is "symmetric only" since we can always configure each path independently, a case which Linux seems to often get wrong.
--- drivers/net/ethernet/freescale/fec.h | 3 +- drivers/net/ethernet/freescale/fec_main.c | 196 ++++++++++++++++++++++-------- 2 files changed, 146 insertions(+), 53 deletions(-)
drivers/net/ethernet/freescale/fec.h +2 -1
@@ -316,7 +316,8 @@ struct fec_enet_private {struct completion mdio_done;int irq[FEC_IRQ_NUM ];int bufdesc_ex; -int pause_flag; +unsigned short pause_flag; +unsigned short pause_mode;struct napi_struct napi;int csum_flags;
drivers/net/ethernet/freescale/fec_main.c +144 -52
263 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 114/222 net:fec: move transmit dma ring address calculation to fec_enet_init()
In reply to Russell King - ARM LinuxMove the calculation of the transmit DMA ring address to fec_enet_init() so the CPU and DMA ring address calculations are localised.
--- drivers/net/ethernet/freescale/fec.h | 3 ++- drivers/net/ethernet/freescale/fec_main.c | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-)
drivers/net/ethernet/freescale/fec.h +2 -1
@@ -287,7 +287,8 @@ struct fec_enet_private {struct sk_buff *rx_skbuff[RX_RING_SIZE ];/* CPM dual port RAM relative addresses */ -dma_addr_t bd_dma; +dma_addr_t rx_bd_dma; +dma_addr_t tx_bd_dma;/* Address of Rx and Tx buffers */ union bufdesc_u *rx_bd_base;union bufdesc_u *tx_bd_base;
drivers/net/ethernet/freescale/fec_main.c +12 -12
@@ -611,14 +611,8 @@ fec_restart(struct net_device *ndev)netdev_reset_queue (ndev);/* Set receive and transmit descriptor base. */ -writel (fep->bd_dma, fep->hwp +FEC_R_DES_START ); -if (fep->bufdesc_ex) -writel ((unsigned long )fep->bd_dma +sizeof (struct bufdesc_ex ) - * fep->rx_ring_size, fep->hwp +FEC_X_DES_START ); -else -writel ((unsigned long )fep->bd_dma +sizeof (struct bufdesc ) - * fep->rx_ring_size, fep->hwp +FEC_X_DES_START ); - +writel (fep->rx_bd_dma, fep->hwp +FEC_R_DES_START ); +writel (fep->tx_bd_dma, fep->hwp +FEC_X_DES_START );for (i =0 ; i <=TX_RING_MOD_MASK ; i++) {if (fep->tx_skbuff[i]) {
@@ -2208,10 +2202,10 @@ static int fec_enet_init(struct net_device *ndev)const struct platform_device_id *id_entry =platform_get_device_id (fep->pdev);union bufdesc_u *cbd_base; +dma_addr_t cbd_dma;/* Allocate memory for buffer descriptors. */ - cbd_base =dma_alloc_coherent (NULL ,PAGE_SIZE , &fep->bd_dma, -GFP_KERNEL ); + cbd_base =dma_alloc_coherent (NULL ,PAGE_SIZE , &cbd_dma,GFP_KERNEL );if (!cbd_base)return -ENOMEM ;
@@ -2230,12 +2224,18 @@ static int fec_enet_init(struct net_device *ndev)/* Set receive and transmit descriptor base. */ fep->rx_bd_base = cbd_base; -if (fep->bufdesc_ex) + fep->rx_bd_dma = cbd_dma; +if (fep->bufdesc_ex) { fep->tx_bd_base = (union bufdesc_u *) (&cbd_base->ebd + fep->rx_ring_size); -else + fep->tx_bd_dma = cbd_dma +sizeof (struct bufdesc_ex ) * + fep->rx_ring_size; + }else { fep->tx_bd_base = (union bufdesc_u *) (&cbd_base->bd + fep->rx_ring_size); + fep->tx_bd_dma = cbd_dma +sizeof (struct bufdesc ) * + fep->rx_ring_size; + }/* The FEC Ethernet specific entries in the device structure */ ndev->watchdog_timeo =TX_TIMEOUT ;
Signature · 1 line
1.8.3.1
PATCH 115/222 net:fec: allocate descriptor rings at device open, and free on device close
In reply to Russell King - ARM LinuxThe driver has had a memory leak for quite some time: when the device is probed, we allocate a page for the descriptor rings, but we never free this.
Rather than trying to free it on the various probe failure paths, move its allocation to device open time - we have to restart the FEC for this to take effect. This also means we can free the descriptor rings when we clean up in the device close function, which gives this a nice symmetry.
--- drivers/net/ethernet/freescale/fec_main.c | 67 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 35 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +32 -35
@@ -607,7 +607,8 @@ fec_restart(struct net_device *ndev)/* Set maximum receive buffer size. */ writel (PKT_MAXBLR_SIZE , fep->hwp +FEC_R_BUFF_SIZE ); -fec_enet_bd_init (ndev); +if (fep->rx_bd_base) +fec_enet_bd_init (ndev);netdev_reset_queue (ndev);/* Set receive and transmit descriptor base. */
@@ -1889,6 +1890,8 @@ static void fec_enet_free_buffers(struct net_device *ndev)if (skb)dev_kfree_skb (skb); } + +dma_free_coherent (NULL ,PAGE_SIZE , fep->rx_bd_base, fep->rx_bd_dma); }static int fec_enet_alloc_buffers (struct net_device *ndev)
@@ -1897,6 +1900,30 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)unsigned int i;struct sk_buff *skb;union bufdesc_u *bdp; +union bufdesc_u *cbd_base; +dma_addr_t cbd_dma; + +/* Allocate memory for buffer descriptors. */ + cbd_base =dma_alloc_coherent (NULL ,PAGE_SIZE , &cbd_dma,GFP_KERNEL ); +if (!cbd_base) +return -ENOMEM ; + +memset (cbd_base,0 ,PAGE_SIZE ); + +/* Set receive and transmit descriptor base. */ + fep->rx_bd_base = cbd_base; + fep->rx_bd_dma = cbd_dma; +if (fep->bufdesc_ex) { + fep->tx_bd_base = (union bufdesc_u *) + (&cbd_base->ebd + fep->rx_ring_size); + fep->tx_bd_dma = cbd_dma +sizeof (struct bufdesc_ex ) * + fep->rx_ring_size; + }else { + fep->tx_bd_base = (union bufdesc_u *) + (&cbd_base->bd + fep->rx_ring_size); + fep->tx_bd_dma = cbd_dma +sizeof (struct bufdesc ) * + fep->rx_ring_size; + }for (i =0 ; i < fep->rx_ring_size; i++) {dma_addr_t addr;
@@ -2192,24 +2219,11 @@ static const struct net_device_ops fec_netdev_ops = { .ndo_set_features = fec_set_features, }; -/* -* XXX: We need to clean up on failure exits here. -* -*/ -static int fec_enet_init (struct net_device *ndev) +static void fec_enet_init (struct net_device *ndev) {struct fec_enet_private *fep =netdev_priv (ndev);const struct platform_device_id *id_entry =platform_get_device_id (fep->pdev); -union bufdesc_u *cbd_base; -dma_addr_t cbd_dma; - -/* Allocate memory for buffer descriptors. */ - cbd_base =dma_alloc_coherent (NULL ,PAGE_SIZE , &cbd_dma,GFP_KERNEL ); -if (!cbd_base) -return -ENOMEM ; - -memset (cbd_base,0 ,PAGE_SIZE ); fep->netdev = ndev;
@@ -2222,20 +2236,8 @@ static int fec_enet_init(struct net_device *ndev) fep->tx_ring_size =TX_RING_SIZE ; fep->rx_ring_size =RX_RING_SIZE ; -/* Set receive and transmit descriptor base. */ - fep->rx_bd_base = cbd_base; - fep->rx_bd_dma = cbd_dma; -if (fep->bufdesc_ex) { - fep->tx_bd_base = (union bufdesc_u *) - (&cbd_base->ebd + fep->rx_ring_size); - fep->tx_bd_dma = cbd_dma +sizeof (struct bufdesc_ex ) * - fep->rx_ring_size; - }else { - fep->tx_bd_base = (union bufdesc_u *) - (&cbd_base->bd + fep->rx_ring_size); - fep->tx_bd_dma = cbd_dma +sizeof (struct bufdesc ) * - fep->rx_ring_size; - } + fep->rx_bd_base = fep->tx_bd_base =NULL ; + fep->rx_bd_dma = fep->tx_bd_dma =0 ;/* The FEC Ethernet specific entries in the device structure */ ndev->watchdog_timeo =TX_TIMEOUT ;
@@ -2272,8 +2274,6 @@ static int fec_enet_init(struct net_device *ndev) fep->tx_min =1 ;fec_restart (ndev); - -return 0 ; }#ifdef CONFIG_OF
@@ -2435,9 +2435,7 @@ fec_probe(struct platform_device *pdev)if (fep->bufdesc_ex)fec_ptp_init (pdev); - ret =fec_enet_init (ndev); -if (ret) - goto failed_init; +fec_enet_init (ndev);for (i =0 ; i <FEC_IRQ_NUM ; i++) { irq =platform_get_irq (pdev, i);
@@ -2474,7 +2472,6 @@ fec_probe(struct platform_device *pdev)fec_enet_mii_remove (fep); failed_mii_init: failed_irq: -failed_init:if (fep->reg_phy)regulator_disable (fep->reg_phy); failed_regulator:
Signature · 1 line
1.8.3.1
PATCH 116/222 net:fec: remove unnecessary code
In reply to Russell King - ARM Linuxfec_enet_bd_init() already frees the transmit skbuffs, so there's no need for fec_restart() to do this again.
--- drivers/net/ethernet/freescale/fec.h | 1 - drivers/net/ethernet/freescale/fec_main.c | 8 -------- 2 files changed, 9 deletions(-)
drivers/net/ethernet/freescale/fec.h +0 -1
@@ -252,7 +252,6 @@ union bufdesc_u {#define FEC_ENET_TX_FRSIZE 2048#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE)#define TX_RING_SIZE 64/* Must be power of two */ -#define TX_RING_MOD_MASK 63/* for this to work */ #define BD_ENET_RX_INT 0x00800000#define BD_ENET_RX_PTP ((ushort)0x0400)
drivers/net/ethernet/freescale/fec_main.c +0 -8
@@ -581,7 +581,6 @@ fec_restart(struct net_device *ndev)struct fec_enet_private *fep =netdev_priv (ndev);const struct platform_device_id *id_entry =platform_get_device_id (fep->pdev); -int i;u32 val;u32 temp_mac[2 ];u32 rcntl =OPT_FRAME_SIZE |0x04 ;
@@ -615,13 +614,6 @@ fec_restart(struct net_device *ndev)writel (fep->rx_bd_dma, fep->hwp +FEC_R_DES_START );writel (fep->tx_bd_dma, fep->hwp +FEC_X_DES_START ); -for (i =0 ; i <=TX_RING_MOD_MASK ; i++) { -if (fep->tx_skbuff[i]) { -dev_kfree_skb_any (fep->tx_skbuff[i]); - fep->tx_skbuff[i] =NULL ; - } - } -/* Enable MII mode */ if (fep->full_duplex ==DUPLEX_FULL ) {/* FD enable */
Signature · 1 line
1.8.3.1
PATCH 117/222 net:fec: consolidate common parts of mdio read/write
In reply to Russell King - ARM LinuxThere is a commonality to fec_enet_mdio_read() and fec_enet_mdio_write() which can be factored out. Factor that commonality out, since we need to add some locking to prevent resets interfering with MDIO accesses.
--- drivers/net/ethernet/freescale/fec_main.c | 41 +++++++++++++------------------ 1 file changed, 17 insertions(+), 24 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +17 -24
@@ -1305,23 +1305,27 @@ static void fec_enet_adjust_link(struct net_device *ndev)phy_print_status (phy_dev); } -static int fec_enet_mdio_read (struct mii_bus *bus,int mii_id,int regnum) +static unsigned long fec_enet_mdio_op (struct fec_enet_private *fep, +unsigned data) { -struct fec_enet_private *fep = bus->priv; -unsigned long time_left; - fep->mii_timeout =0 ;init_completion (&fep->mdio_done); -/* start a read op */ -writel (FEC_MMFR_ST |FEC_MMFR_OP_READ | -FEC_MMFR_PA (mii_id) |FEC_MMFR_RA (regnum) | -FEC_MMFR_TA , fep->hwp +FEC_MII_DATA ); +/* start operation */ +writel (data, fep->hwp +FEC_MII_DATA );/* wait for end of transfer */ - time_left =wait_for_completion_timeout (&fep->mdio_done, +return wait_for_completion_timeout (&fep->mdio_done,usecs_to_jiffies (FEC_MII_TIMEOUT )); -if (time_left ==0 ) { +} + +static int fec_enet_mdio_read (struct mii_bus *bus,int mii_id,int regnum) +{ +struct fec_enet_private *fep = bus->priv; + +if (fec_enet_mdio_op (fep,FEC_MMFR_ST |FEC_MMFR_OP_READ | +FEC_MMFR_PA (mii_id) |FEC_MMFR_RA (regnum) | +FEC_MMFR_TA ) ==0 ) { fep->mii_timeout =1 ;netdev_err (fep->netdev,"MDIO read timeout\n" );return -ETIMEDOUT ;
@@ -1335,21 +1339,10 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) {struct fec_enet_private *fep = bus->priv; -unsigned long time_left; - - fep->mii_timeout =0 ; -init_completion (&fep->mdio_done); -/* start a write op */ -writel (FEC_MMFR_ST |FEC_MMFR_OP_WRITE | -FEC_MMFR_PA (mii_id) |FEC_MMFR_RA (regnum) | -FEC_MMFR_TA |FEC_MMFR_DATA (value), - fep->hwp +FEC_MII_DATA ); - -/* wait for end of transfer */ - time_left =wait_for_completion_timeout (&fep->mdio_done, -usecs_to_jiffies (FEC_MII_TIMEOUT )); -if (time_left ==0 ) { +if (fec_enet_mdio_op (fep,FEC_MMFR_ST |FEC_MMFR_OP_WRITE | +FEC_MMFR_PA (mii_id) |FEC_MMFR_RA (regnum) | +FEC_MMFR_TA |FEC_MMFR_DATA (value)) ==0 ) { fep->mii_timeout =1 ;netdev_err (fep->netdev,"MDIO write timeout\n" );return -ETIMEDOUT ;
Signature · 1 line
1.8.3.1
PATCH 118/222 net:fec: add locking for MDIO bus access
In reply to Russell King - ARM LinuxBoth fec_restart() and fec_stop() both perform a reset of the FEC. This reset can result in an in-process MDIO transfer being terminated, which can lead to the MDIO read/write functions timing out. Add some locking to prevent this occuring.
We can't use a spinlock for this as the MDIO accessor functions use wait_for_completion_timeout(), which sleeps.
--- drivers/net/ethernet/freescale/fec.h | 3 +++ drivers/net/ethernet/freescale/fec_main.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/fec.h +3 -0
@@ -14,6 +14,7 @@/****************************************************************************/ #include <linux/clocksource.h> +#include <linux/mutex.h> #include <linux/net_tstamp.h> #include <linux/ptp_clock_kernel.h>
@@ -300,6 +301,8 @@ struct fec_enet_private {unsigned short tx_ring_size;unsigned short rx_ring_size; +struct mutex mutex; +struct platform_device *pdev;int dev_id;
drivers/net/ethernet/freescale/fec_main.c +29 -1
@@ -795,12 +795,14 @@ static void fec_enet_timeout_work(struct work_struct *work)rtnl_lock ();if (netif_device_present (ndev) ||netif_running (ndev)) { +mutex_lock (&fep->mutex);napi_disable (&fep->napi);netif_tx_lock_bh (ndev);fec_restart (ndev);netif_wake_queue (ndev);netif_tx_unlock_bh (ndev);napi_enable (&fep->napi); +mutex_unlock (&fep->mutex); }rtnl_unlock (); }
@@ -1282,20 +1284,24 @@ static void fec_enet_adjust_link(struct net_device *ndev)/* if any of the above changed restart the FEC */ if (status_change) { +mutex_lock (&fep->mutex);napi_disable (&fep->napi);netif_tx_lock_bh (ndev);fec_restart (ndev);netif_wake_queue (ndev);netif_tx_unlock_bh (ndev);napi_enable (&fep->napi); +mutex_unlock (&fep->mutex); } }else {if (fep->link) { +mutex_lock (&fep->mutex);napi_disable (&fep->napi);netif_tx_lock_bh (ndev);fec_stop (ndev);netif_tx_unlock_bh (ndev);napi_enable (&fep->napi); +mutex_unlock (&fep->mutex); fep->link = phy_dev->link; status_change =1 ; }
@@ -1308,15 +1314,23 @@ static void fec_enet_adjust_link(struct net_device *ndev)static unsigned long fec_enet_mdio_op (struct fec_enet_private *fep,unsigned data) { +unsigned long time_left; + fep->mii_timeout =0 ;init_completion (&fep->mdio_done); +mutex_lock (&fep->mutex); +/* start operation */ writel (data, fep->hwp +FEC_MII_DATA );/* wait for end of transfer */ -return wait_for_completion_timeout (&fep->mdio_done, + time_left =wait_for_completion_timeout (&fep->mdio_done,usecs_to_jiffies (FEC_MII_TIMEOUT )); + +mutex_unlock (&fep->mutex); + +return time_left; }static int fec_enet_mdio_read (struct mii_bus *bus,int mii_id,int regnum)
@@ -1683,6 +1697,7 @@ static int fec_enet_set_pauseparam(struct net_device *ndev, fep->pause_mode = fep->pause_flag;if (netif_running (ndev)) { +mutex_lock (&fep->mutex);napi_disable (&fep->napi);netif_tx_lock_bh (ndev);fec_stop (ndev);
@@ -1690,6 +1705,7 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,netif_wake_queue (ndev);netif_tx_unlock_bh (ndev);napi_enable (&fep->napi); +mutex_unlock (&fep->mutex); } } }
@@ -1983,7 +1999,9 @@ fec_enet_open(struct net_device *ndev)return ret; } +mutex_lock (&fep->mutex);fec_restart (ndev); +mutex_unlock (&fep->mutex);napi_enable (&fep->napi);phy_start (fep->phy_dev);netif_start_queue (ndev);
@@ -2000,7 +2018,9 @@ fec_enet_close(struct net_device *ndev)if (netif_device_present (ndev)) {napi_disable (&fep->napi);netif_tx_disable (ndev); +mutex_lock (&fep->mutex);fec_stop (ndev); +mutex_unlock (&fep->mutex); }phy_disconnect (fep->phy_dev);
@@ -2155,6 +2175,7 @@ static int fec_set_features(struct net_device *netdev,/* Quiesce the device if necessary */ if (netif_running (netdev) && changed &FEATURES_NEED_QUIESCE ) { +mutex_lock (&fep->mutex);napi_disable (&fep->napi);netif_tx_lock_bh (netdev);fec_stop (netdev);
@@ -2182,6 +2203,7 @@ static int fec_set_features(struct net_device *netdev,netif_wake_queue (netdev);netif_tx_unlock_bh (netdev);napi_enable (&fep->napi); +mutex_unlock (&fep->mutex); }return 0 ;
@@ -2324,6 +2346,8 @@ fec_probe(struct platform_device *pdev)/* setup board info structure */ fep =netdev_priv (ndev); +mutex_init (&fep->mutex); +#if !defined(CONFIG_M5272 )/* default enable pause frame auto negotiation */ if (pdev->id_entry &&
@@ -2515,7 +2539,9 @@ fec_suspend(struct device *dev)netif_tx_lock_bh (ndev);netif_device_detach (ndev);netif_tx_unlock_bh (ndev); +mutex_lock (&fep->mutex);fec_stop (ndev); +mutex_unlock (&fep->mutex); }rtnl_unlock ();
@@ -2567,7 +2593,9 @@ fec_resume(struct device *dev)rtnl_lock ();if (netif_running (ndev)) { +mutex_lock (&fep->mutex);fec_restart (ndev); +mutex_unlock (&fep->mutex);netif_tx_lock_bh (ndev);netif_device_attach (ndev);netif_tx_unlock_bh (ndev);
Signature · 1 line
1.8.3.1
PATCH 119/222 net:fec: move bufdesc_ex flag into flags
In reply to Russell King - ARM LinuxAdd a new flags field to contain the mostly static driver configuration, the first of which is the bufdesc_ex flag.
--- drivers/net/ethernet/freescale/fec.h | 3 +- drivers/net/ethernet/freescale/fec_main.c | 48 +++++++++++++++++-------------- 2 files changed, 28 insertions(+), 23 deletions(-)
drivers/net/ethernet/freescale/fec.h +2 -1
@@ -301,6 +301,8 @@ struct fec_enet_private {unsigned short tx_ring_size;unsigned short rx_ring_size; +unsigned char flags; +struct mutex mutex;struct platform_device *pdev;
@@ -318,7 +320,6 @@ struct fec_enet_private {int speed;struct completion mdio_done;int irq[FEC_IRQ_NUM ]; -int bufdesc_ex;unsigned short pause_flag;unsigned short pause_mode;
drivers/net/ethernet/freescale/fec_main.c +26 -22
177 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 120/222 net:fec: move receive checksum flags into new flags member
In reply to Russell King - ARM LinuxThe receive checksum flag is mostly static, so move it into the flags member. In any case, this is checked alongside the BUFDESC_EX flag.
--- drivers/net/ethernet/freescale/fec.h | 2 -- drivers/net/ethernet/freescale/fec_main.c | 11 ++++++----- 2 files changed, 6 insertions(+), 7 deletions(-)
drivers/net/ethernet/freescale/fec.h +0 -2
@@ -258,7 +258,6 @@ union bufdesc_u {#define BD_ENET_RX_PTP ((ushort)0x0400)#define BD_ENET_RX_ICE 0x00000020#define BD_ENET_RX_PCR 0x00000010 -#define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR)#define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR)/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
@@ -324,7 +323,6 @@ struct fec_enet_private {unsigned short pause_mode;struct napi_struct napi; -int csum_flags;struct work_struct tx_timeout_work;
drivers/net/ethernet/freescale/fec_main.c +6 -5
@@ -232,6 +232,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");/* flags */ #define FEC_FLAG_BUFDESC_EX BIT(0) +#define FEC_FLAG_RX_CSUM BIT(1)static int mii_cnt;
@@ -634,7 +635,7 @@ fec_restart(struct net_device *ndev)#if !defined(CONFIG_M5272 )/* set RX checksum */ val =readl (fep->hwp +FEC_RACC ); -if (fep->csum_flags &FLAG_RX_CSUM_ENABLED ) +if (fep->flags &FEC_FLAG_RX_CSUM ) val |=FEC_RACC_OPTIONS ;else val &= ~FEC_RACC_OPTIONS ;
@@ -1042,7 +1043,7 @@ fec_enet_rx(struct net_device *ndev, int budget) skb_hwtstamps(skb));if (fep->flags &FEC_FLAG_BUFDESC_EX && - (fep->csum_flags &FLAG_RX_CSUM_ENABLED )) { + fep->flags &FEC_FLAG_RX_CSUM ) {if (!(bdp->ebd.cbd_esc &FLAG_RX_CSUM_ERROR )) {/* don't check it */ skb->ip_summed =CHECKSUM_UNNECESSARY ;
@@ -2190,9 +2191,9 @@ static int fec_set_features(struct net_device *netdev,/* Receive checksum has been changed */ if (changed &NETIF_F_RXCSUM ) {if (features &NETIF_F_RXCSUM ) - fep->csum_flags |=FLAG_RX_CSUM_ENABLED ; + fep->flags |=FEC_FLAG_RX_CSUM ;else - fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED ; + fep->flags &= ~FEC_FLAG_RX_CSUM ; }/* Set the appropriate minimum transmit ring free threshold */
@@ -2270,7 +2271,7 @@ static void fec_enet_init(struct net_device *ndev) | NETIF_F_RXCSUM); ndev->hw_features |= (NETIF_F_IP_CSUM |NETIF_F_IPV6_CSUM |NETIF_F_RXCSUM ); - fep->csum_flags |=FLAG_RX_CSUM_ENABLED ; + fep->flags |=FEC_FLAG_RX_CSUM ; }if (!(id_entry->driver_data &FEC_QUIRK_SWAP_FRAME )) {
Signature · 1 line
1.8.3.1
PATCH 121/222 net:fec: only enable CTAG_RX and IP checksumming if we have enhanced buffer descriptors
In reply to Russell King - ARM LinuxOnly set the vlan tag and ip checksumming options if we have enhanced buffer descriptors - enhanced descriptors are required for these features.
--- drivers/net/ethernet/freescale/fec_main.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +15 -13
@@ -2259,19 +2259,21 @@ static void fec_enet_init(struct net_device *ndev)writel (FEC_RX_DISABLED_IMASK , fep->hwp +FEC_IMASK );netif_napi_add (ndev, &fep->napi, fec_enet_rx_napi,NAPI_POLL_WEIGHT ); -if (id_entry->driver_data &FEC_QUIRK_HAS_VLAN ) { -/* enable hw VLAN support */ - ndev->features |=NETIF_F_HW_VLAN_CTAG_RX ; - ndev->hw_features |=NETIF_F_HW_VLAN_CTAG_RX ; - } - -if (id_entry->driver_data &FEC_QUIRK_HAS_CSUM ) { -/* enable hw accelerator */ - ndev->features |= (NETIF_F_IP_CSUM |NETIF_F_IPV6_CSUM - |NETIF_F_RXCSUM ); - ndev->hw_features |= (NETIF_F_IP_CSUM |NETIF_F_IPV6_CSUM - |NETIF_F_RXCSUM ); - fep->flags |=FEC_FLAG_RX_CSUM ; +if (fep->flags &FEC_FLAG_BUFDESC_EX ) { +if (id_entry->driver_data &FEC_QUIRK_HAS_VLAN ) { +/* enable hw VLAN support */ + ndev->features |=NETIF_F_HW_VLAN_CTAG_RX ; + ndev->hw_features |=NETIF_F_HW_VLAN_CTAG_RX ; + } + +if (id_entry->driver_data &FEC_QUIRK_HAS_CSUM ) { +/* enable hw accelerator */ + ndev->features |= (NETIF_F_IP_CSUM |NETIF_F_IPV6_CSUM + |NETIF_F_RXCSUM ); + ndev->hw_features |= (NETIF_F_IP_CSUM |NETIF_F_IPV6_CSUM + |NETIF_F_RXCSUM ); + fep->flags |=FEC_FLAG_RX_CSUM ; + } }if (!(id_entry->driver_data &FEC_QUIRK_SWAP_FRAME )) {
Signature · 1 line
1.8.3.1
PATCH 122/222 net:fec: avoid checking more flags than necessary in rx path
In reply to Russell King - ARM LinuxAvoid checking for both the receive checksumming flag and the enhanced buffer descriptor flags - we now only set receive checksumming if we know we have enhanced buffer descriptors.
--- drivers/net/ethernet/freescale/fec_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +1 -2
@@ -1042,8 +1042,7 @@ fec_enet_rx(struct net_device *ndev, int budget)fec_enet_hwtstamp (fep, bdp->ebd.ts,skb_hwtstamps (skb)); -if (fep->flags &FEC_FLAG_BUFDESC_EX && - fep->flags &FEC_FLAG_RX_CSUM ) { +if (fep->flags &FEC_FLAG_RX_CSUM ) {if (!(bdp->ebd.cbd_esc &FLAG_RX_CSUM_ERROR )) {/* don't check it */ skb->ip_summed =CHECKSUM_UNNECESSARY ;
Signature · 1 line
1.8.3.1
PATCH 123/222 net:fec: move vlan receive flag into our private flags
In reply to Russell King - ARM Linux--- drivers/net/ethernet/freescale/fec_main.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +11 -2
@@ -233,6 +233,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");/* flags */ #define FEC_FLAG_BUFDESC_EX BIT(0)#define FEC_FLAG_RX_CSUM BIT(1) +#define FEC_FLAG_RX_VLAN BIT(2)static int mii_cnt;
@@ -1002,8 +1003,8 @@ fec_enet_rx(struct net_device *ndev, int budget)/* If this is a VLAN packet remove the VLAN Tag */ vlan_packet_rcvd = false; -if ((ndev->features &NETIF_F_HW_VLAN_CTAG_RX ) && - fep->flags &FEC_FLAG_BUFDESC_EX && (bdp->ebd.cbd_esc &BD_ENET_RX_VLAN )) { +if (fep->flags &FEC_FLAG_RX_VLAN && + bdp->ebd.cbd_esc &BD_ENET_RX_VLAN ) {/* Push and remove the vlan tag */ struct vlan_hdr *vlan_header = (struct vlan_hdr *) (data +ETH_HLEN );
@@ -2195,6 +2196,13 @@ static int fec_set_features(struct net_device *netdev, fep->flags &= ~FEC_FLAG_RX_CSUM ; } +if (changed &NETIF_F_HW_VLAN_CTAG_RX ) { +if (features &NETIF_F_HW_VLAN_CTAG_RX ) + fep->flags |=FEC_FLAG_RX_VLAN ; +else + fep->flags &= ~FEC_FLAG_RX_VLAN ; + } +/* Set the appropriate minimum transmit ring free threshold */ if (features &NETIF_F_SG ) fep->tx_min =MAX_SKB_FRAGS +1 ;
@@ -2263,6 +2271,7 @@ static void fec_enet_init(struct net_device *ndev)/* enable hw VLAN support */ ndev->features |=NETIF_F_HW_VLAN_CTAG_RX ; ndev->hw_features |=NETIF_F_HW_VLAN_CTAG_RX ; + fep->flags |=FEC_FLAG_RX_VLAN ; }if (id_entry->driver_data &FEC_QUIRK_HAS_CSUM ) {
Signature · 1 line
1.8.3.1
PATCH 124/222 net:fec: add ethtool support for tx/rx ring sizes
In reply to Russell King - ARM LinuxAdd ethtool support to retrieve and set the transmit and receive ring sizes. This allows runtime tuning of these parameters, which can result in better throughput with gigabit parts.
--- drivers/net/ethernet/freescale/fec_main.c | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
drivers/net/ethernet/freescale/fec_main.c +47 -0
@@ -1631,6 +1631,51 @@ static int fec_enet_get_ts_info(struct net_device *ndev, } } +static void fec_enet_get_ringparam (struct net_device *ndev, +struct ethtool_ringparam *ring) +{ +struct fec_enet_private *fep =netdev_priv (ndev); + + ring->rx_max_pending =RX_RING_SIZE ; + ring->tx_max_pending =TX_RING_SIZE ; + ring->rx_pending = fep->rx_ring_size; + ring->tx_pending = fep->tx_ring_size; +} + +static int fec_enet_set_ringparam (struct net_device *ndev, +struct ethtool_ringparam *ring) +{ +struct fec_enet_private *fep =netdev_priv (ndev); +unsigned rx, tx, tx_min; + + tx_min = ndev->features &NETIF_F_SG ?TX_RING_SIZE_MIN_SG :16 ; + + rx =clamp_t (u32, ring->rx_pending,16 ,RX_RING_SIZE ); + tx =clamp_t (u32, ring->tx_pending, tx_min,TX_RING_SIZE ); + +if (tx == fep->tx_ring_size && rx == fep->rx_ring_size) +return 0 ; + +/* Setting the ring size while the interface is down is easy */ +if (!netif_running (ndev)) { + fep->tx_ring_size = tx; + fep->rx_ring_size = rx; + }else { +return -EINVAL ; + +napi_disable (&fep->napi); +netif_tx_lock_bh (ndev); +fec_stop (ndev); +/* reallocate ring */ +fec_restart (ndev); +netif_wake_queue (ndev); +netif_tx_unlock_bh (ndev); +napi_enable (&fep->napi); + } + +return 0 ; +} +#if !defined(CONFIG_M5272 ) static void fec_enet_get_pauseparam(struct net_device *ndev,
@@ -1835,6 +1880,8 @@ static const struct ethtool_ops fec_enet_ethtool_ops = { .get_drvinfo = fec_enet_get_drvinfo, .nway_reset = fec_enet_nway_reset, .get_link = ethtool_op_get_link, + .get_ringparam = fec_enet_get_ringparam, + .set_ringparam = fec_enet_set_ringparam, #ifndef CONFIG_M5272 .get_pauseparam = fec_enet_get_pauseparam, .set_pauseparam = fec_enet_set_pauseparam,
Signature · 1 line
1.8.3.1
PATCH 125/222 net:fec: even larger rings
In reply to Russell King - ARM Linux--- drivers/net/ethernet/freescale/fec.h | 4 +-- drivers/net/ethernet/freescale/fec_main.c | 45 ++++++++++++++++--------------- 2 files changed, 26 insertions(+), 23 deletions(-)
drivers/net/ethernet/freescale/fec.h +2 -2
@@ -246,13 +246,13 @@ union bufdesc_u {* the skbuffer directly. */ -#define FEC_ENET_RX_PAGES 32 +#define FEC_ENET_RX_PAGES 64#define FEC_ENET_RX_FRSIZE 2048#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE)#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)#define FEC_ENET_TX_FRSIZE 2048#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) -#define TX_RING_SIZE 64/* Must be power of two */ +#define TX_RING_SIZE 128/* Must be power of two */ #define BD_ENET_RX_INT 0x00800000#define BD_ENET_RX_PTP ((ushort)0x0400)
drivers/net/ethernet/freescale/fec_main.c +24 -21
69 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 126/222 net:fec: unsorted hacks
In reply to Russell King - ARM Linux--- drivers/net/ethernet/freescale/fec.h | 16 +++- drivers/net/ethernet/freescale/fec_main.c | 126 +++++++++++++++++------------- 2 files changed, 85 insertions(+), 57 deletions(-)
drivers/net/ethernet/freescale/fec.h +12 -4
@@ -208,6 +208,7 @@ union bufdesc_u {#define BD_ENET_RX_OV ((ushort)0x0002)#define BD_ENET_RX_CL ((ushort)0x0001)#define BD_ENET_RX_STATS ((ushort)0x013f)/* All status bits */ +#define BD_ENET_RX_ERROR ((ushort)0x003f)/* Enhanced buffer descriptor control/status used by Ethernet receive */ #define BD_ENET_RX_VLAN 0x00000004
@@ -230,10 +231,17 @@ union bufdesc_u {#define BD_ENET_TX_STATS ((ushort)0x03ff)/* All status bits */ /*enhanced buffer descriptor control/status used by Ethernet transmit*/ -#define BD_ENET_TX_INT 0x40000000 -#define BD_ENET_TX_TS 0x20000000 -#define BD_ENET_TX_PINS 0x10000000 -#define BD_ENET_TX_IINS 0x08000000 +#define BD_ENET_TX_INT BIT(30) +#define BD_ENET_TX_TS BIT(29) +#define BD_ENET_TX_PINS BIT(28) +#define BD_ENET_TX_IINS BIT(27) +#define BD_ENET_TX_TXE BIT(15) +#define BD_ENET_TX_UE BIT(13) +#define BD_ENET_TX_EE BIT(12) +#define BD_ENET_TX_FE BIT(11) +#define BD_ENET_TX_LCE BIT(10) +#define BD_ENET_TX_OE BIT(9) +#define BD_ENET_TX_TSE BIT(8)/* This device has up to three irqs on some platforms */
drivers/net/ethernet/freescale/fec_main.c +73 -53
207 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 127/222 leds: leds-pwm: provide a common function to setup a single led-pwm device
In reply to Russell King - ARM LinuxProvide a common function to setup a single led-pwm device, replacing the platform data initialisation path with this function. This allows us to have a common method of creating these devices in a consistent manner, which then allows us to place the probe failure cleanup in one place.
--- drivers/leds/leds-pwm.c | 85 ++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 39 deletions(-)
drivers/leds/leds-pwm.c +46 -39
@@ -92,6 +92,44 @@ static void led_pwm_cleanup(struct led_pwm_priv *priv) } } +static int led_pwm_add (struct device *dev,struct led_pwm_priv *priv, +struct led_pwm *led) +{ +struct led_pwm_data *led_data = &priv->leds[priv->num_leds]; +int ret; + + led_data->active_low = led->active_low; + led_data->period = led->pwm_period_ns; + led_data->cdev.name = led->name; + led_data->cdev.default_trigger = led->default_trigger; + led_data->cdev.brightness_set = led_pwm_set; + led_data->cdev.brightness =LED_OFF ; + led_data->cdev.max_brightness = led->max_brightness; + led_data->cdev.flags =LED_CORE_SUSPENDRESUME ; + + led_data->pwm =devm_pwm_get (dev, led->name); +if (IS_ERR (led_data->pwm)) { + ret =PTR_ERR (led_data->pwm); +dev_err (dev,"unable to request PWM for %s: %d\n" , + led->name, ret); +return ret; + } + + led_data->can_sleep =pwm_can_sleep (led_data->pwm); +if (led_data->can_sleep) +INIT_WORK (&led_data->work, led_pwm_work); + + ret =led_classdev_register (dev, &led_data->cdev); +if (ret ==0 ) { + priv->num_leds++; + }else { +dev_err (dev,"failed to register PWM led for %s: %d\n" , + led->name, ret); + } + +return ret; +} +static int led_pwm_create_of (struct platform_device *pdev,struct led_pwm_priv *priv) {
@@ -139,8 +177,6 @@ static int led_pwm_create_of(struct platform_device *pdev,return 0 ; err: -led_pwm_cleanup (priv); -return ret; }
@@ -166,51 +202,22 @@ static int led_pwm_probe(struct platform_device *pdev)if (pdata) {for (i =0 ; i < count; i++) { -struct led_pwm *cur_led = &pdata->leds[i]; -struct led_pwm_data *led_dat = &priv->leds[i]; - - led_dat->pwm =devm_pwm_get (&pdev->dev, cur_led->name); -if (IS_ERR (led_dat->pwm)) { - ret =PTR_ERR (led_dat->pwm); -dev_err (&pdev->dev, -"unable to request PWM for %s\n" , - cur_led->name); - goto err; - } - - led_dat->cdev.name = cur_led->name; - led_dat->cdev.default_trigger = cur_led->default_trigger; - led_dat->active_low = cur_led->active_low; - led_dat->period = cur_led->pwm_period_ns; - led_dat->cdev.brightness_set = led_pwm_set; - led_dat->cdev.brightness =LED_OFF ; - led_dat->cdev.max_brightness = cur_led->max_brightness; - led_dat->cdev.flags |=LED_CORE_SUSPENDRESUME ; - - led_dat->can_sleep =pwm_can_sleep (led_dat->pwm); -if (led_dat->can_sleep) -INIT_WORK (&led_dat->work, led_pwm_work); - - ret =led_classdev_register (&pdev->dev, &led_dat->cdev); -if (ret <0 ) - goto err; + ret =led_pwm_add (&pdev->dev, priv, &pdata->leds[i]); +if (ret) +break ; } - priv->num_leds = count; }else { ret =led_pwm_create_of (pdev, priv); -if (ret) -return ret; + } + +if (ret) { +led_pwm_cleanup (priv); +return ret; }platform_set_drvdata (pdev, priv);return 0 ; - -err: - priv->num_leds = i; -led_pwm_cleanup (priv); - -return ret; }static int led_pwm_remove (struct platform_device *pdev)
Signature · 1 line
1.8.3.1
PATCH 128/222 leds: leds-pwm: convert OF parsing code to use led_pwm_add()
In reply to Russell King - ARM LinuxConvert the OF parsing code to use the common PWM LED registration code, which means we have a consistent method, and single point where the registration happens for both paths.
--- drivers/leds/leds-pwm.c | 62 ++++++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 39 deletions(-)
drivers/leds/leds-pwm.c +23 -39
@@ -93,7 +93,7 @@ static void led_pwm_cleanup(struct led_pwm_priv *priv) }static int led_pwm_add (struct device *dev,struct led_pwm_priv *priv, -struct led_pwm *led) +struct led_pwm *led,struct device_node *child) {struct led_pwm_data *led_data = &priv->leds[priv->num_leds];int ret;
@@ -107,7 +107,10 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, led_data->cdev.max_brightness = led->max_brightness; led_data->cdev.flags =LED_CORE_SUSPENDRESUME ; - led_data->pwm =devm_pwm_get (dev, led->name); +if (child) + led_data->pwm =devm_of_pwm_get (dev, child,NULL ); +else + led_data->pwm =devm_pwm_get (dev, led->name);if (IS_ERR (led_data->pwm)) { ret =PTR_ERR (led_data->pwm); dev_err(dev, "unable to request PWM for %s: %d\n",
@@ -115,6 +118,9 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,return ret; } +if (child) + led_data->period =pwm_get_period (led_data->pwm); + led_data->can_sleep =pwm_can_sleep (led_data->pwm);if (led_data->can_sleep)INIT_WORK (&led_data->work, led_pwm_work);
@@ -130,53 +136,30 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,return ret; } -static int led_pwm_create_of (struct platform_device *pdev, -struct led_pwm_priv *priv) +static int led_pwm_create_of (struct device *dev,struct led_pwm_priv *priv) {struct device_node *child; -int ret; - -for_each_child_of_node (pdev->dev.of_node, child) { -struct led_pwm_data *led_dat = &priv->leds[priv->num_leds]; +struct led_pwm led; +int ret =0 ; - led_dat->cdev.name =of_get_property (child,"label" , -NULL ) ? : child->name; +memset (&led,0 ,sizeof (led)); - led_dat->pwm =devm_of_pwm_get (&pdev->dev, child,NULL ); -if (IS_ERR (led_dat->pwm)) { -dev_err (&pdev->dev,"unable to request PWM for %s\n" , - led_dat->cdev.name); - ret =PTR_ERR (led_dat->pwm); - goto err; - } -/* Get the period from PWM core when n*/ - led_dat->period =pwm_get_period (led_dat->pwm); +for_each_child_of_node (dev->of_node, child) { + led.name =of_get_property (child,"label" ,NULL ) ? : + child->name; - led_dat->cdev.default_trigger =of_get_property (child, + led.default_trigger =of_get_property (child,"linux,default-trigger" ,NULL );of_property_read_u32 (child,"max-brightness" , - &led_dat->cdev.max_brightness); - - led_dat->cdev.brightness_set = led_pwm_set; - led_dat->cdev.brightness =LED_OFF ; - led_dat->cdev.flags |=LED_CORE_SUSPENDRESUME ; - - led_dat->can_sleep =pwm_can_sleep (led_dat->pwm); -if (led_dat->can_sleep) -INIT_WORK (&led_dat->work, led_pwm_work); + &led.max_brightness); - ret =led_classdev_register (&pdev->dev, &led_dat->cdev); -if (ret <0 ) { -dev_err (&pdev->dev,"failed to register for %s\n" , - led_dat->cdev.name); + ret =led_pwm_add (dev, priv, &led, child); +if (ret) {of_node_put (child); - goto err; +break ; } - priv->num_leds++; } -return 0 ; -err:return ret; }
@@ -202,12 +185,13 @@ static int led_pwm_probe(struct platform_device *pdev)if (pdata) {for (i =0 ; i < count; i++) { - ret =led_pwm_add (&pdev->dev, priv, &pdata->leds[i]); + ret =led_pwm_add (&pdev->dev, priv, &pdata->leds[i], +NULL );if (ret)break ; } }else { - ret =led_pwm_create_of (pdev, priv); + ret =led_pwm_create_of (&pdev->dev, priv); }if (ret) {
Signature · 1 line
1.8.3.1
PATCH 129/222 leds: leds-pwm: implement PWM inversion
In reply to Russell King - ARM LinuxSome PWM outputs are wired such that the LED they're controlling is connected to supply rather than ground. These PWMs may not support output inversion, or when they do, disabling the PWM may set the PWM output low, causing a "brightness" value of zero to turn the LED fully on.
The platform data for this driver already indicates that this was thought about, and we have the "active_low" property there already. However, the implementation for this is missing.
Add the trivial implementation for this feature.
--- drivers/leds/leds-pwm.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/leds/leds-pwm.c +4 -0
@@ -69,6 +69,10 @@ static void led_pwm_set(struct led_classdev *led_cdev, duty *= brightness;do_div (duty, max); + +if (led_dat->active_low) + duty = led_dat->period - duty; + led_dat->duty = duty;if (led_dat->can_sleep)
Signature · 1 line
1.8.3.1
PATCH 130/222 leds: leds-pwm: add DT support for LEDs wired to supply
In reply to Russell King - ARM LinuxThe non-DT driver allowed an active low property to be specified, but DT is missing this in its description. Add the property to the DT binding document, making it optional. It defaults to active high, which retains compatibility with existing descriptions.
This should only be used for causes where the LED is wired to supply, and the PWM does not sensibly support its own inversion.
--- Documentation/devicetree/bindings/leds/leds-pwm.txt | 2 ++ drivers/leds/leds-pwm.c | 1 + 2 files changed, 3 insertions(+)
Documentation/devicetree/bindings/leds/leds-pwm.txt +2 -0
@@ -13,6 +13,8 @@ node's name represents the name of the corresponding LED. For the pwms and pwm-names property please refer to: Documentation/devicetree/bindings/pwm/pwm.txt - max-brightness : Maximum brightness possible for the LED +- active-low : (optional) For PWMs where the LED is wired to supply + rather than ground. - label : (optional) see Documentation/devicetree/bindings/leds/common.txt - linux,default-trigger : (optional)
drivers/leds/leds-pwm.c +1 -0
@@ -154,6 +154,7 @@ static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv) led.default_trigger =of_get_property (child,"linux,default-trigger" ,NULL ); + led.active_low =of_property_read_bool (child,"active-low" );of_property_read_u32 (child,"max-brightness" , &led.max_brightness);
Signature · 1 line
1.8.3.1
PATCH 131/222 ARM: add support for Cubox-i PWM-driven front panel LED
In reply to Russell King - ARM LinuxThe front panel LED on the Cubox-i is driven by one of the iMX6 PWM channels, and is wired between the PWM output and supply.
--- arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +17 -0
@@ -12,6 +12,19 @@ pinctrl-0 = <&pinctrl_cubox_i_ir>; }; + pwmleds { + compatible = "pwm-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cubox_i_pwm1>; + + front { + active-low; + label = "imx6:red:front"; + max-brightness = <248>; + pwms = <&pwm1 0 50000>; + }; + }; + regulators { compatible = "simple-bus";
@@ -82,6 +95,10 @@ >; }; + pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led { + fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>; + }; + pinctrl_cubox_i_spdif: cubox-i-spdif { fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>; };
Signature · 1 line
1.8.3.1
PATCH 132/222 ASoC: work around block transfer issues with imx-pcm-dma
In reply to Russell King - ARM Linux--- sound/soc/fsl/imx-pcm-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/fsl/imx-pcm-dma.c +1 -1
@@ -44,7 +44,7 @@ static const struct snd_pcm_hardware imx_pcm_hardware = { .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, .period_bytes_min = 128, .period_bytes_max = 65535, /* Limited by SDMA engine */ - .periods_min = 2, + .periods_min = 4, .periods_max = 255, .fifo_size = 0, };
Signature · 1 line
1.8.3.1
PATCH 133/222 ata: ahci_imx: warn when disabling ahci link
In reply to Russell King - ARM LinuxWhen the AHCI link is disabled, it can't be re-enabled except by resetting the entire SoC. Rather than doing this silently print some kernel messages to inform the user, along with how to avoid this.
--- drivers/ata/ahci_imx.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/ata/ahci_imx.c +4 -0
@@ -160,6 +160,10 @@ static void ahci_imx_error_handler(struct ata_port *ap)writel (reg_val |PORT_PHY_CTL_PDDQ_LOC , mmio +PORT_PHY_CTL );imx_sata_disable (hpriv); imxpriv->no_device = true; + +dev_info (ap->dev,"no device found, disabling link.\n" ); +dev_info (ap->dev,"pass " MODULE_PARAM_PREFIX +".hotplug=1 to enable hotplug\n" ); } static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
Signature · 1 line
1.8.3.1
PATCH 134/222 ARM: imx: keep PLLs in bypass while they're locking
In reply to Russell King - ARM LinuxKeep the PLL bypassed while we prepare a clock by powering up the PLL, otherwise we can end up with improper output/gitches which prevents further operation.
--- arch/arm/mach-imx/clk-pllv3.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)
arch/arm/mach-imx/clk-pllv3.c +21 -6
@@ -273,9 +273,10 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,struct clk_pllv3 *pll =to_clk_pllv3 (hw);unsigned long min_rate = parent_rate *27 ;unsigned long max_rate = parent_rate *54 ; -u32 val, div; +u32 val, newval, div;u32 mfn, mfd =1000000 ;s64 temp64; +int ret;if (rate < min_rate || rate > max_rate)return -EINVAL ;
@@ -287,13 +288,27 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, mfn = temp64; val =readl_relaxed (pll->base); - val &= ~pll->div_mask; - val |= div; -writel_relaxed (val, pll->base); + +/* set the PLL into bypass mode */ + newval = val |BM_PLL_BYPASS ; +writel_relaxed (newval, pll->base); + +/* configure the new frequency */ + newval &= ~pll->div_mask; + newval |= div; +writel_relaxed (newval, pll->base);writel_relaxed (mfn, pll->base +PLL_NUM_OFFSET ); -writel_relaxed (mfd, pll->base +PLL_DENOM_OFFSET ); +writel (mfd, pll->base +PLL_DENOM_OFFSET ); -return clk_pllv3_wait_lock (pll); + ret =clk_pllv3_wait_lock (pll); +if (ret ==0 && val &BM_PLL_POWER ) { +/* only if it locked can we switch back to the PLL */ + newval &= ~BM_PLL_BYPASS ; + newval |= val &BM_PLL_BYPASS ; +writel (newval, pll->base); + } + +return ret; }static const struct clk_ops clk_pllv3_av_ops = {
Signature · 1 line
1.8.3.1
PATCH 134/222 ARM: imx: keep PLLs in bypass while they're locking
Quoted 38 lines · Russell King
Keep the PLL bypassed while we prepare a clock by powering up the PLL, otherwise we can end up with improper output/gitches which prevents further operation.
Signed-off-by Russell King <[email protected]>--- arch/arm/mach-imx/clk-pllv3.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)arch/arm/mach-imx/clk-pllv3.c +8
-4@@ -273,9 +273,10 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,struct clk_pllv3 *pll =to_clk_pllv3 (hw);unsigned long min_rate = parent_rate *27 ;unsigned long max_rate = parent_rate *54 ; -u32 val, div; +u32 val, newval, div;u32 mfn, mfd =1000000 ;s64 temp64; +int ret;if (rate < min_rate || rate > max_rate)return -EINVAL ;@@ -287,13 +288,27 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, mfn = temp64; val =readl_relaxed (pll->base); - val &= ~pll->div_mask; - val |= div; -writel_relaxed (val, pll->base); + +/* set the PLL into bypass mode */ + newval = val |BM_PLL_BYPASS ; +writel_relaxed (newval, pll->base); + +/* configure the new frequency */
arch/arm/mach-imx/clk-pllv3.c static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, · line 304
Quoted 10 lines
arch/arm/mach-imx/clk-pllv3.c +6
-2+ newval &= ~pll->div_mask; + newval |= div; +writel_relaxed (newval, pll->base);writel_relaxed (mfn, pll->base +PLL_NUM_OFFSET ); -writel_relaxed (mfd, pll->base +PLL_DENOM_OFFSET ); +writel (mfd, pll->base +PLL_DENOM_OFFSET ); -return clk_pllv3_wait_lock (pll); + ret =clk_pllv3_wait_lock (pll); +if (ret ==0 && val &BM_PLL_POWER ) {
I'm no expert on this, so sorry if I'm wrong ;)
But regarding the check 'val & BM_PLL_POWER' here:
Reading the manual, it seems that both PLL4_AUDIO & PLL5_VIDEO don't have a POWER bit, instead they have a POWERDOWN at bit 12. So for PLL4_AUDIO & PLL5_VIDEO 'val & BM_PLL_POWER' would mean not powered up?
Maybe the check should be done anywhere else, e.g. in clk_pllv3_set_rate()?
Best regards
Dirk
PATCH 134/222 ARM: imx: keep PLLs in bypass while they're locking
Besides the question below regarding 'val & BM_PLL_POWER', three additional questions:
Quoted 4 lines · Dirk Behme
Quoted 3 lines · Russell King
Keep the PLL bypassed while we prepare a clock by powering up the PLL, otherwise we can end up with improper output/gitches which prevents further operation.
Have you seen a real world case to show this patch fixes an issue in real? Have you been seeing anything like "improper output/gitches"?
Quoted 11 lines
arch/arm/mach-imx/clk-pllv3.c static int clk_pllv3_av_set_rate(struct clk_hw
Quoted 11 lines
Signed-off-by Russell King <[email protected]>--- arch/arm/mach-imx/clk-pllv3.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)arch/arm/mach-imx/clk-pllv3.c +0
-0@@ -273,9 +273,10 @@ static int clk_pllv3_av_set_rate(struct clk_hw
We touch here pllv3/av only, while the commit message generically says "keep PLLs in bypass while they're locking" nothing specific to audio/video PLL clock. So isn't similar modification needed for the other set_rate() functions as well?
Quoted 16 lines
Quoted 16 lines
arch/arm/mach-imx/clk-pllv3.c +2
-1*hw, unsigned long rate, struct clk_pllv3 *pll = to_clk_pllv3(hw);unsigned long min_rate = parent_rate *27 ;unsigned long max_rate = parent_rate *54 ; -u32 val, div; +u32 val, newval, div;u32 mfn, mfd =1000000 ;s64 temp64; +int ret;if (rate < min_rate || rate > max_rate)return -EINVAL;arch/arm/mach-imx/clk-pllv3.c +0
-0@@ -287,13 +288,27 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, mfn = temp64;
Quoted 10 lines
arch/arm/mach-imx/clk-pllv3.c static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, · line 296
Quoted 10 lines
arch/arm/mach-imx/clk-pllv3.c +6
-3val =readl_relaxed (pll->base); - val &= ~pll->div_mask; - val |= div; -writel_relaxed (val, pll->base); + +/* set the PLL into bypass mode */ + newval = val |BM_PLL_BYPASS ; +writel_relaxed (newval, pll->base); + +/* configure the new frequency */
Reading the i.MX6 reference manual section '18.5.1.5.3 PLL clock change': 'Before changing the PLL setting, power it down. Power up the PLL after the change.' So we need to power down/up the PLL rather than just bypass for a rate change?
Quoted 13 lines
arch/arm/mach-imx/clk-pllv3.c static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, · line 304
Quoted 10 lines
arch/arm/mach-imx/clk-pllv3.c +6
-2+ newval &= ~pll->div_mask; + newval |= div; +writel_relaxed (newval, pll->base);writel_relaxed (mfn, pll->base +PLL_NUM_OFFSET ); -writel_relaxed (mfd, pll->base +PLL_DENOM_OFFSET ); +writel (mfd, pll->base +PLL_DENOM_OFFSET ); -return clk_pllv3_wait_lock (pll); + ret =clk_pllv3_wait_lock (pll); +if (ret ==0 && val &BM_PLL_POWER ) {I'm no expert on this, so sorry if I'm wrong ;)
Quoted 7 lines
But regarding the check 'val &
BM_PLL_POWER' here:Reading the manual, it seems that both
PLL4_AUDIO&PLL5_VIDEOdon't have a POWER bit, instead they have a POWERDOWN at bit 12. So forPLL4_AUDIO&PLL5_VIDEO'val &BM_PLL_POWER' would mean not powered up?Maybe the check should be done anywhere else, e.g. in
clk_pllv3_set_rate()?
Best regards
Dirk
PATCH 135/222 ARM: imx: set IPU to be derived from the 540MHz PLL3 PFD1 clock
In reply to Russell King - ARM LinuxSet the IPU muxer to derive the clock from the PLL3 FPD1 clock, which increases its clock rate from 198MHz to 270MHz.
--- arch/arm/mach-imx/clk-imx6q.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/arm/mach-imx/clk-imx6q.c +4 -0
@@ -445,6 +445,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)clk_set_parent (clk[ldb_di1_sel], clk[pll5_video_div]); } +if (cpu_is_imx6dl ()) { +clk_set_parent (clk[ipu1_sel], clk[pll3_pfd1_540m]); + } +/* * The gpmi needs 100MHz frequency in the EDO/Sync mode, * We can not get the 100MHz from the pll2_pfd0_352m.
Signature · 1 line
1.8.3.1
PATCH 136/222 regulator: allow GPIO 0 to be used for an enable signal
In reply to Russell King - ARM LinuxGPIO number 0 *is* legal and must be accepted.
--- drivers/regulator/anatop-regulator.c | 1 + drivers/regulator/core.c | 2 +- drivers/regulator/dummy.c | 1 + drivers/regulator/fixed.c | 4 +--- 4 files changed, 4 insertions(+), 4 deletions(-)
drivers/regulator/anatop-regulator.c +1 -0
@@ -267,6 +267,7 @@ static int anatop_regulator_probe(struct platform_device *pdev) config.driver_data = sreg; config.of_node = pdev->dev.of_node; config.regmap = sreg->anatop; + config.ena_gpio = -EINVAL ;/* Only core regulators have the ramp up delay configuration. */ if (sreg->control_reg && sreg->delay_bit_width) {
drivers/regulator/core.c +1 -1
@@ -3459,7 +3459,7 @@ regulator_register(const struct regulator_desc *regulator_desc,dev_set_drvdata (&rdev->dev, rdev); -if (config->ena_gpio &&gpio_is_valid (config->ena_gpio)) { +if (gpio_is_valid (config->ena_gpio)) { ret =regulator_ena_gpio_request (rdev, config);if (ret !=0 ) { rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
drivers/regulator/dummy.c +1 -0
@@ -48,6 +48,7 @@ static int dummy_regulator_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.init_data = &dummy_initdata; + config.ena_gpio = -EINVAL ; dummy_regulator_rdev =regulator_register (&dummy_desc, &config);if (IS_ERR (dummy_regulator_rdev)) {
drivers/regulator/fixed.c +1 -3
@@ -161,9 +161,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.n_voltages =1 ; drvdata->desc.fixed_uV = config->microvolts; - -if (config->gpio >=0 ) - cfg.ena_gpio = config->gpio; + cfg.ena_gpio = config->gpio; cfg.ena_gpio_invert = !config->enable_high;if (config->enabled_at_boot) {if (config->enable_high)
Signature · 1 line
1.8.3.1
PATCH 137/222 ARM: dt: microsom: don't set bit 7 for ethernet mux settings
In reply to Russell King - ARM LinuxBit 6,7 are marked as reserved for the ethernet RGMII pins, so avoid setting these bits.
--- arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi +11 -11
@@ -26,25 +26,25 @@ /* GPIO16 -> AR8035 25MHz */ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0xc0000000 MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x80000000 - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030 + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030 + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030 + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030 + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030 /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1 /* AR8035 pin strapping: IO voltage: pull up */ - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030 /* AR8035 pin strapping: PHYADDR#0: pull down */ - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x130b0 + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x13030 /* AR8035 pin strapping: PHYADDR#1: pull down */ - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x130b0 + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x13030 /* AR8035 pin strapping: MODE#1: pull up */ - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030 /* AR8035 pin strapping: MODE#3: pull up */ - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030 /* AR8035 pin strapping: MODE#0: pull down */ - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x130b0 + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x13030 /* * As the RMII pins are also connected to RGMII
Signature · 1 line
1.8.3.1
PATCH 138/222 ARM: imx6q: clk: Parent DI clocks to video PLL via di_pre_sel
In reply to Russell King - ARM LinuxFrom: Sascha Hauer <[email protected]>
To: linux-arm-kernel at lists.infradead.org
Route the video PLL to the display interface clocks via the di_pre_sel and di_sel muxes by default.
--- arch/arm/mach-imx/clk-imx6q.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/arm/mach-imx/clk-imx6q.c +9 -0
@@ -449,6 +449,15 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)clk_set_parent (clk[ipu1_sel], clk[pll3_pfd1_540m]); } +clk_set_parent (clk[ipu1_di0_pre_sel], clk[pll5_video_div]); +clk_set_parent (clk[ipu1_di1_pre_sel], clk[pll5_video_div]); +clk_set_parent (clk[ipu2_di0_pre_sel], clk[pll5_video_div]); +clk_set_parent (clk[ipu2_di1_pre_sel], clk[pll5_video_div]); +clk_set_parent (clk[ipu1_di0_sel], clk[ipu1_di0_pre]); +clk_set_parent (clk[ipu1_di1_sel], clk[ipu1_di1_pre]); +clk_set_parent (clk[ipu2_di0_sel], clk[ipu2_di0_pre]); +clk_set_parent (clk[ipu2_di1_sel], clk[ipu2_di1_pre]); +/* * The gpmi needs 100MHz frequency in the EDO/Sync mode, * We can not get the 100MHz from the pll2_pfd0_352m.
Signature · 1 line
1.8.3.1
PATCH 139/222 ARM: i.MX6: ipu_di_sel clocks can set parent rates
In reply to Russell King - ARM LinuxFrom: Philipp Zabel <[email protected]>
To: linux-arm-kernel at lists.infradead.org
To obtain exact pixel clocks, allow the DI clock selectors to influence the PLLs that they are derived from.
--- arch/arm/mach-imx/clk-imx6q.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
arch/arm/mach-imx/clk-imx6q.c +8 -8
@@ -258,14 +258,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[ipu2_sel] =imx_clk_mux ("ipu2_sel" , base +0x3c ,14 ,2 , ipu_sels,ARRAY_SIZE (ipu_sels)); clk[ldb_di0_sel] =imx_clk_mux_flags ("ldb_di0_sel" , base +0x2c ,9 ,3 , ldb_di_sels,ARRAY_SIZE (ldb_di_sels),CLK_SET_RATE_PARENT ); clk[ldb_di1_sel] =imx_clk_mux_flags ("ldb_di1_sel" , base +0x2c ,12 ,3 , ldb_di_sels,ARRAY_SIZE (ldb_di_sels),CLK_SET_RATE_PARENT ); - clk[ipu1_di0_pre_sel] =imx_clk_mux ("ipu1_di0_pre_sel" , base +0x34 ,6 ,3 , ipu_di_pre_sels,ARRAY_SIZE (ipu_di_pre_sels)); - clk[ipu1_di1_pre_sel] =imx_clk_mux ("ipu1_di1_pre_sel" , base +0x34 ,15 ,3 , ipu_di_pre_sels,ARRAY_SIZE (ipu_di_pre_sels)); - clk[ipu2_di0_pre_sel] =imx_clk_mux ("ipu2_di0_pre_sel" , base +0x38 ,6 ,3 , ipu_di_pre_sels,ARRAY_SIZE (ipu_di_pre_sels)); - clk[ipu2_di1_pre_sel] =imx_clk_mux ("ipu2_di1_pre_sel" , base +0x38 ,15 ,3 , ipu_di_pre_sels,ARRAY_SIZE (ipu_di_pre_sels)); - clk[ipu1_di0_sel] =imx_clk_mux ("ipu1_di0_sel" , base +0x34 ,0 ,3 , ipu1_di0_sels,ARRAY_SIZE (ipu1_di0_sels)); - clk[ipu1_di1_sel] =imx_clk_mux ("ipu1_di1_sel" , base +0x34 ,9 ,3 , ipu1_di1_sels,ARRAY_SIZE (ipu1_di1_sels)); - clk[ipu2_di0_sel] =imx_clk_mux ("ipu2_di0_sel" , base +0x38 ,0 ,3 , ipu2_di0_sels,ARRAY_SIZE (ipu2_di0_sels)); - clk[ipu2_di1_sel] =imx_clk_mux ("ipu2_di1_sel" , base +0x38 ,9 ,3 , ipu2_di1_sels,ARRAY_SIZE (ipu2_di1_sels)); + clk[ipu1_di0_pre_sel] =imx_clk_mux_flags ("ipu1_di0_pre_sel" , base +0x34 ,6 ,3 , ipu_di_pre_sels,ARRAY_SIZE (ipu_di_pre_sels),CLK_SET_RATE_PARENT ); + clk[ipu1_di1_pre_sel] =imx_clk_mux_flags ("ipu1_di1_pre_sel" , base +0x34 ,15 ,3 , ipu_di_pre_sels,ARRAY_SIZE (ipu_di_pre_sels),CLK_SET_RATE_PARENT ); + clk[ipu2_di0_pre_sel] =imx_clk_mux_flags ("ipu2_di0_pre_sel" , base +0x38 ,6 ,3 , ipu_di_pre_sels,ARRAY_SIZE (ipu_di_pre_sels),CLK_SET_RATE_PARENT ); + clk[ipu2_di1_pre_sel] =imx_clk_mux_flags ("ipu2_di1_pre_sel" , base +0x38 ,15 ,3 , ipu_di_pre_sels,ARRAY_SIZE (ipu_di_pre_sels),CLK_SET_RATE_PARENT ); + clk[ipu1_di0_sel] =imx_clk_mux_flags ("ipu1_di0_sel" , base +0x34 ,0 ,3 , ipu1_di0_sels,ARRAY_SIZE (ipu1_di0_sels),CLK_SET_RATE_PARENT ); + clk[ipu1_di1_sel] =imx_clk_mux_flags ("ipu1_di1_sel" , base +0x34 ,9 ,3 , ipu1_di1_sels,ARRAY_SIZE (ipu1_di1_sels),CLK_SET_RATE_PARENT ); + clk[ipu2_di0_sel] =imx_clk_mux_flags ("ipu2_di0_sel" , base +0x38 ,0 ,3 , ipu2_di0_sels,ARRAY_SIZE (ipu2_di0_sels),CLK_SET_RATE_PARENT ); + clk[ipu2_di1_sel] =imx_clk_mux_flags ("ipu2_di1_sel" , base +0x38 ,9 ,3 , ipu2_di1_sels,ARRAY_SIZE (ipu2_di1_sels),CLK_SET_RATE_PARENT ); clk[hsi_tx_sel] =imx_clk_mux ("hsi_tx_sel" , base +0x30 ,28 ,1 , hsi_tx_sels,ARRAY_SIZE (hsi_tx_sels)); clk[pcie_axi_sel] =imx_clk_mux ("pcie_axi_sel" , base +0x18 ,10 ,1 , pcie_axi_sels,ARRAY_SIZE (pcie_axi_sels)); clk[ssi1_sel] =imx_clk_fixup_mux ("ssi1_sel" , base +0x1c ,10 ,2 , ssi_sels,ARRAY_SIZE (ssi_sels), imx_cscmr1_fixup);
Signature · 1 line
1.8.3.1
PATCH 140/222 ata: ahci_imx: allow hardware parameters to be specified in DT
In reply to Russell King - ARM LinuxVarious SATA phy parameters are board specific, and therefore need to be configured.
--- drivers/ata/ahci_imx.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 160 insertions(+), 8 deletions(-)
drivers/ata/ahci_imx.c +160 -8
@@ -46,6 +46,7 @@ struct imx_ahci_priv {struct regmap *gpr;bool no_device;bool first_time; +u32 phy_params; };static int ahci_imx_hotplug;
@@ -90,14 +91,7 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)IMX6Q_GPR13_SATA_TX_LVL_MASK |IMX6Q_GPR13_SATA_MPLL_CLK_EN |IMX6Q_GPR13_SATA_TX_EDGE_RATE , -IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | -IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | -IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | -IMX6Q_GPR13_SATA_SPD_MODE_3P0G | -IMX6Q_GPR13_SATA_MPLL_SS_EN | -IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | -IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | - IMX6Q_GPR13_SATA_TX_LVL_1_025_V); + imxpriv->phy_params);regmap_update_bits (imxpriv->gpr,IOMUXC_GPR13 ,IMX6Q_GPR13_SATA_MPLL_CLK_EN ,IMX6Q_GPR13_SATA_MPLL_CLK_EN );
@@ -204,6 +198,152 @@ static const struct of_device_id imx_ahci_of_match[] = { };MODULE_DEVICE_TABLE (of, imx_ahci_of_match); +struct reg_value { +u32 of_value; +u32 reg_value; +}; + +struct reg_property { +const char *name; +const struct reg_value *values; +size_t num_values; +u32 def_value; +}; + +static const struct reg_value gpr13_tx_level[] = { + {937 ,IMX6Q_GPR13_SATA_TX_LVL_0_937_V }, + {947 ,IMX6Q_GPR13_SATA_TX_LVL_0_947_V }, + {957 ,IMX6Q_GPR13_SATA_TX_LVL_0_957_V }, + {966 ,IMX6Q_GPR13_SATA_TX_LVL_0_966_V }, + {976 ,IMX6Q_GPR13_SATA_TX_LVL_0_976_V }, + {986 ,IMX6Q_GPR13_SATA_TX_LVL_0_986_V }, + {996 ,IMX6Q_GPR13_SATA_TX_LVL_0_996_V }, + {1005 ,IMX6Q_GPR13_SATA_TX_LVL_1_005_V }, + {1015 ,IMX6Q_GPR13_SATA_TX_LVL_1_015_V }, + {1025 ,IMX6Q_GPR13_SATA_TX_LVL_1_025_V }, + {1035 ,IMX6Q_GPR13_SATA_TX_LVL_1_035_V }, + {1045 ,IMX6Q_GPR13_SATA_TX_LVL_1_045_V }, + {1054 ,IMX6Q_GPR13_SATA_TX_LVL_1_054_V }, + {1064 ,IMX6Q_GPR13_SATA_TX_LVL_1_064_V }, + {1074 ,IMX6Q_GPR13_SATA_TX_LVL_1_074_V }, + {1084 ,IMX6Q_GPR13_SATA_TX_LVL_1_084_V }, + {1094 ,IMX6Q_GPR13_SATA_TX_LVL_1_094_V }, + {1104 ,IMX6Q_GPR13_SATA_TX_LVL_1_104_V }, + {1113 ,IMX6Q_GPR13_SATA_TX_LVL_1_113_V }, + {1123 ,IMX6Q_GPR13_SATA_TX_LVL_1_123_V }, + {1133 ,IMX6Q_GPR13_SATA_TX_LVL_1_133_V }, + {1143 ,IMX6Q_GPR13_SATA_TX_LVL_1_143_V }, + {1152 ,IMX6Q_GPR13_SATA_TX_LVL_1_152_V }, + {1162 ,IMX6Q_GPR13_SATA_TX_LVL_1_162_V }, + {1172 ,IMX6Q_GPR13_SATA_TX_LVL_1_172_V }, + {1182 ,IMX6Q_GPR13_SATA_TX_LVL_1_182_V }, + {1191 ,IMX6Q_GPR13_SATA_TX_LVL_1_191_V }, + {1201 ,IMX6Q_GPR13_SATA_TX_LVL_1_201_V }, + {1211 ,IMX6Q_GPR13_SATA_TX_LVL_1_211_V }, + {1221 ,IMX6Q_GPR13_SATA_TX_LVL_1_221_V }, + {1230 ,IMX6Q_GPR13_SATA_TX_LVL_1_230_V }, + {1240 ,IMX6Q_GPR13_SATA_TX_LVL_1_240_V } +}; + +static const struct reg_value gpr13_tx_boost[] = { + {0 ,IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB }, + {370 ,IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB }, + {740 ,IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB }, + {111 ,IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB }, + {148 ,IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB }, + {185 ,IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB }, + {222 ,IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB }, + {259 ,IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB }, + {296 ,IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB }, + {333 ,IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB }, + {370 ,IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB }, + {407 ,IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB }, + {444 ,IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB }, + {481 ,IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB }, + {528 ,IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB }, + {575 ,IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB } +}; + +static const struct reg_value gpr13_tx_atten[] = { + {8 ,IMX6Q_GPR13_SATA_TX_ATTEN_8_16 }, + {9 ,IMX6Q_GPR13_SATA_TX_ATTEN_9_16 }, + {10 ,IMX6Q_GPR13_SATA_TX_ATTEN_10_16 }, + {12 ,IMX6Q_GPR13_SATA_TX_ATTEN_12_16 }, + {14 ,IMX6Q_GPR13_SATA_TX_ATTEN_14_16 }, + {16 ,IMX6Q_GPR13_SATA_TX_ATTEN_16_16 }, +}; + +static const struct reg_value gpr13_rx_eq[] = { + {500 ,IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB }, + {1000 ,IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB }, + {1500 ,IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB }, + {2000 ,IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB }, + {2500 ,IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB }, + {3000 ,IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB }, + {3500 ,IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB }, + {4000 ,IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB }, +}; + +static const struct reg_property gpr13_props[] = { + { + .name ="fsl,transmit-level-mV" , + .values = gpr13_tx_level, + .num_values =ARRAY_SIZE (gpr13_tx_level), + .def_value =IMX6Q_GPR13_SATA_TX_LVL_1_025_V , + }, { + .name ="fsl,transmit-boost-mdB" , + .values = gpr13_tx_boost, + .num_values =ARRAY_SIZE (gpr13_tx_boost), + .def_value =IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB , + }, { + .name ="fsl,transmit-atten-16ths" , + .values = gpr13_tx_atten, + .num_values =ARRAY_SIZE (gpr13_tx_atten), + .def_value =IMX6Q_GPR13_SATA_TX_ATTEN_9_16 , + }, { + .name ="fsl,receive-eq-mdB" , + .values = gpr13_rx_eq, + .num_values =ARRAY_SIZE (gpr13_rx_eq), + .def_value =IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB , + }, +}; + +static u32 imx_ahci_parse_props (struct device *dev, +const struct reg_property *prop,size_t num) +{ +struct device_node *np = dev->of_node; +u32 reg_value =0 ; +int i, j; + +for (i =0 ; i < num; i++, prop++) { +u32 of_val; + +if (of_property_read_u32 (np, prop->name, &of_val)) { +dev_info (dev,"%s not specified, using %08x\n" , + prop->name, prop->def_value); + reg_value |= prop->def_value; +continue ; + } + +for (j =0 ; j < prop->num_values; j++) { +if (prop->values[j].of_value == of_val) { +dev_info (dev,"%s value %u, using %08x\n" , + prop->name, of_val, prop->values[j].reg_value); + reg_value |= prop->values[j].reg_value; +break ; + } + } + +if (j == prop->num_values) { +dev_err (dev,"DT property %s is not a valid value\n" , + prop->name); + reg_value |= prop->def_value; + } + } + +return reg_value; +} +static int imx_ahci_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;
@@ -231,6 +371,8 @@ static int imx_ahci_probe(struct platform_device *pdev) }if (imxpriv->type ==AHCI_IMX6Q ) { +u32 reg_value; + imxpriv->gpr =syscon_regmap_lookup_by_compatible ("fsl,imx6q-iomuxc-gpr" );if (IS_ERR (imxpriv->gpr)) {
@@ -238,6 +380,16 @@ static int imx_ahci_probe(struct platform_device *pdev) "failed to find fsl,imx6q-iomux-gpr regmap\n");return PTR_ERR (imxpriv->gpr); } + + reg_value =imx_ahci_parse_props (dev, gpr13_props, +ARRAY_SIZE (gpr13_props)); + + imxpriv->phy_params = +IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | +IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | +IMX6Q_GPR13_SATA_SPD_MODE_3P0G | +IMX6Q_GPR13_SATA_MPLL_SS_EN | + reg_value; } hpriv =ahci_platform_get_resources (pdev);
Signature · 1 line
1.8.3.1
PATCH 141/222 ARM: cubox-i: add eSATA DT configuration
In reply to Russell King - ARM Linux--- arch/arm/boot/dts/imx6q-cubox-i.dts | 3 +++ 1 file changed, 3 insertions(+)
arch/arm/boot/dts/imx6q-cubox-i.dts +3 -0
@@ -13,4 +13,7 @@ &sata { status = "okay"; + fsl,transmit-level-mV = <1104>; + fsl,transmit-boost-mdB = <0>; + fsl,transmit-atten-16ths = <9>; };
Signature · 1 line
1.8.3.1
PATCH 142/222 ahci_imx: add disable for spread-spectrum
In reply to Russell King - ARM LinuxSpread-spectrum doesn't work with Cubox-i hardware, so we have to disable this feature. Add a DT property so that platforms can indicate that this feature should not be enabled.
Having it as a negative property keeps existing DT files working.
--- arch/arm/boot/dts/imx6q-cubox-i.dts | 1 + drivers/ata/ahci_imx.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-)
arch/arm/boot/dts/imx6q-cubox-i.dts +1 -0
@@ -16,4 +16,5 @@ fsl,transmit-level-mV = <1104>; fsl,transmit-boost-mdB = <0>; fsl,transmit-atten-16ths = <9>; + fsl,no-spread-spectrum; };
drivers/ata/ahci_imx.c +13 -1
@@ -208,6 +208,7 @@ struct reg_property {const struct reg_value *values;size_t num_values;u32 def_value; +u32 set_value; };static const struct reg_value gpr13_tx_level[] = {
@@ -305,6 +306,10 @@ static const struct reg_property gpr13_props[] = { .values = gpr13_rx_eq, .num_values = ARRAY_SIZE(gpr13_rx_eq), .def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB, + }, { + .name = "fsl,no-spread-spectrum", + .def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN, + .set_value = 0, }, };
@@ -318,6 +323,14 @@ static u32 imx_ahci_parse_props(struct device *dev,for (i =0 ; i < num; i++, prop++) {u32 of_val; +if (prop->num_values ==0 ) { +if (of_property_read_bool (np, prop->name)) + reg_value |= prop->set_value; +else + reg_value |= prop->def_value; +continue ; + } +if (of_property_read_u32 (np, prop->name, &of_val)) {dev_info (dev,"%s not specified, using %08x\n" , prop->name, prop->def_value);
@@ -388,7 +401,6 @@ static int imx_ahci_probe(struct platform_device *pdev)IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |IMX6Q_GPR13_SATA_SPD_MODE_3P0G | -IMX6Q_GPR13_SATA_MPLL_SS_EN | reg_value; }
Signature · 1 line
1.8.3.1
PATCH 143/222 imx-drm: imx-drm-core: fix imx_drm_encoder_get_mux_id
In reply to Russell King - ARM LinuxFrom: Philipp Zabel <[email protected]>
To: linux-arm-kernel at lists.infradead.org
The decoder mux id is equal to the port id of the encoder's input port that is connected to the given crtc, not to the endpoint id (which is arbitrary and usually zero).
--- drivers/staging/imx-drm/imx-drm-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/imx-drm/imx-drm-core.c +1 -1
@@ -517,7 +517,7 @@ int imx_drm_encoder_get_mux_id(struct device_node *node,of_node_put (port);if (port == imx_crtc->port) { ret =of_graph_parse_endpoint (ep, &endpoint); -return ret ? ret : endpoint.id; +return ret ? ret : endpoint.port; } }while (ep);
Signature · 1 line
1.8.3.1
PATCH 144/222 imx-drm: imx-drm-core: skip components whose parent device is disabled
In reply to Russell King - ARM LinuxFrom: Shawn Guo <[email protected]>
To: linux-arm-kernel at lists.infradead.org
In a board setup which disables LDB device node completely by changing status to 'disabled', and only enables HDMI device, we're running into the problem that imx-drm master never succeeds in binding, and hence HDMI does not come up either.
&ldb {
status = "disabled";
lvds-channel at 1 {
...
status = "okay";
};
};The imx-drm-core should really skip the LVDS channels no matter what lvds-channel's status is, if LDB device is disabled. Let's consider such setup a misconfiguration, give a warning in there and not add the component.
--- drivers/staging/imx-drm/imx-drm-core.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/staging/imx-drm/imx-drm-core.c +5 -0
@@ -675,6 +675,11 @@ static int imx_drm_platform_probe(struct platform_device *pdev)if (!remote || !of_device_is_available (remote)) {of_node_put (remote);continue ; + }else if (!of_device_is_available (remote->parent)) { +dev_warn (&pdev->dev,"parent device of %s is not available\n" , + remote->full_name); +of_node_put (remote); +continue ; } ret =imx_drm_add_component (&pdev->dev, remote);
Signature · 1 line
1.8.3.1
PATCH 145/222 imx-drm: imx-ldb: add drm_panel support
In reply to Russell King - ARM LinuxFrom: Philipp Zabel <[email protected]>
To: linux-arm-kernel at lists.infradead.org
This patch allows to optionally attach the lvds-channel to a panel supported by a drm_panel driver instead of supplying the modes via device tree.
Before:
ldb {
...
lvds-channel at 0 {
...
display-timings {
native-timing = <&timing1>;
timing1: etm0700g0dh6 {
hactive = <800>;
vactive = <480>;
clock-frequency = <33260000>;
hsync-len = <128>;
hback-porch = <88>;
hfront-porch = <40>;
vsync-len = <2>;
vback-porch = <33>;
vfront-porch = <10>;
hsync-active = <0>;
vsync-active = <0>;
...
};
};
...
};
};After:
ldb {
...
lvds-channel at 0 {
fsl,panel = <&panel>;
...
};
};
panel: panel {
compatible = "edt,etm0700g0dh6", "simple-panel";
};--- drivers/staging/imx-drm/Kconfig | 1 + drivers/staging/imx-drm/imx-ldb.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+)
drivers/staging/imx-drm/Kconfig +1 -0
@@ -35,6 +35,7 @@ config DRM_IMX_TVE config DRM_IMX_LDB tristate "Support for LVDS displays" depends on DRM_IMX && MFD_SYSCON + select DRM_PANEL help Choose this to enable the internal LVDS Display Bridge (LDB) found on i.MX53 and i.MX6 processors.
drivers/staging/imx-drm/imx-ldb.c +21 -0
@@ -24,6 +24,7 @@#include <drm/drmP.h> #include <drm/drm_fb_helper.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_panel.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <linux/of_address.h>
@@ -60,6 +61,7 @@ struct imx_ldb_channel {struct imx_ldb *ldb;struct drm_connector connector;struct drm_encoder encoder; +struct drm_panel *panel;struct device_node *child;int chno;void *edid;
@@ -96,6 +98,13 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)struct imx_ldb_channel *imx_ldb_ch =con_to_imx_ldb_ch (connector);int num_modes =0 ; +if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs && + imx_ldb_ch->panel->funcs->get_modes) { + num_modes = imx_ldb_ch->panel->funcs->get_modes (imx_ldb_ch->panel); +if (num_modes >0 ) +return num_modes; + } +if (imx_ldb_ch->edid) {drm_mode_connector_update_edid_property (connector, imx_ldb_ch->edid);
@@ -243,6 +252,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder) }regmap_write (ldb->regmap,IOMUXC_GPR2 , ldb->ldb_ctrl); + +drm_panel_enable (imx_ldb_ch->panel); } static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
@@ -294,6 +305,8 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder) (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)return ; +drm_panel_disable (imx_ldb_ch->panel); +if (imx_ldb_ch == &ldb->channel[0 ]) ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK ;else if (imx_ldb_ch == &ldb->channel[1 ])
@@ -379,6 +392,9 @@ static int imx_ldb_register(struct drm_device *drm,drm_connector_init (drm, &imx_ldb_ch->connector, &imx_ldb_connector_funcs,DRM_MODE_CONNECTOR_LVDS ); +if (imx_ldb_ch->panel) +drm_panel_attach (imx_ldb_ch->panel, &imx_ldb_ch->connector); +drm_mode_connector_attach_encoder (&imx_ldb_ch->connector, &imx_ldb_ch->encoder);
@@ -493,6 +509,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)for_each_child_of_node (np, child) {struct imx_ldb_channel *channel; +struct device_node *panel_node; ret =of_property_read_u32 (child,"reg" , &i);if (ret || i <0 || i >1 )
@@ -556,6 +573,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)return -EINVAL ; } + panel_node =of_parse_phandle (child,"fsl,panel" ,0 ); +if (panel_node) + channel->panel =of_drm_find_panel (panel_node); + ret =imx_ldb_register (drm, channel);if (ret)return ret;
Signature · 1 line
1.8.3.1
PATCH 146/222 imx-drm: match ipu_di_signal_cfg's clk_pol with its description.
In reply to Russell King - ARM LinuxFrom: Denis Carikli <[email protected]>
To: linux-arm-kernel at lists.infradead.org
According to the datasheet, setting the di0_polarity_disp_clk field in the GENERAL di register sets the output clock polarity to active high.
--- drivers/staging/imx-drm/ipu-v3/ipu-di.c | 2 +- drivers/staging/imx-drm/ipuv3-crtc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/staging/imx-drm/ipu-v3/ipu-di.c +1 -1
@@ -595,7 +595,7 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) } } -if (!sig->clk_pol) +if (sig->clk_pol) di_gen |=DI_GEN_POLARITY_DISP_CLK ;ipu_di_write (di, di_gen,DI_GENERAL );
drivers/staging/imx-drm/ipuv3-crtc.c +1 -1
@@ -158,7 +158,7 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, sig_cfg.Vsync_pol =1 ; sig_cfg.enable_pol =1 ; - sig_cfg.clk_pol =1 ; + sig_cfg.clk_pol =0 ; sig_cfg.width = mode->hdisplay; sig_cfg.height = mode->vdisplay; sig_cfg.pixel_fmt = out_pixel_fmt;
Signature · 1 line
1.8.3.1
PATCH 147/222 v4l2: add new V4L2_PIX_FMT_RGB666 pixel format.
In reply to Russell King - ARM LinuxFrom: Denis Carikli <[email protected]>
To: linux-arm-kernel at lists.infradead.org
That new macro is needed by the imx_drm staging driver
for supporting the QVGA display of the eukrea-cpuimx51 board.
--- .../DocBook/media/v4l/pixfmt-packed-rgb.xml | 39 ++++++++++++++++++++++ include/uapi/linux/videodev2.h | 1 + 2 files changed, 40 insertions(+)
Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml +39 -0
@@ -279,6 +279,45 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para> <entry></entry> <entry></entry> </row> + <row id="V4L2-PIX-FMT-RGB666"> + <entry><constant>V4L2_PIX_FMT_RGB666</constant></entry> + <entry>'RGBH'</entry> + <entry></entry> + <entry>r<subscript>5</subscript></entry> + <entry>r<subscript>4</subscript></entry> + <entry>r<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + <entry>r<subscript>1</subscript></entry> + <entry>r<subscript>0</subscript></entry> + <entry>g<subscript>5</subscript></entry> + <entry>g<subscript>4</subscript></entry> + <entry></entry> + <entry>g<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + <entry>g<subscript>1</subscript></entry> + <entry>g<subscript>0</subscript></entry> + <entry>b<subscript>5</subscript></entry> + <entry>b<subscript>4</subscript></entry> + <entry>b<subscript>3</subscript></entry> + <entry>b<subscript>2</subscript></entry> + <entry></entry> + <entry>b<subscript>1</subscript></entry> + <entry>b<subscript>0</subscript></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + <entry></entry> + </row> <row id="V4L2-PIX-FMT-BGR24"> <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry> <entry>'BGR3'</entry>
include/uapi/linux/videodev2.h +1 -0
@@ -299,6 +299,7 @@ struct v4l2_pix_format {#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q')/* 16 RGB-5-5-5 BE */ #define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R')/* 16 RGB-5-6-5 BE */ #define V4L2_PIX_FMT_BGR666 v4l2_fourcc('B', 'G', 'R', 'H')/* 18 BGR-6-6-6 */ +#define V4L2_PIX_FMT_RGB666 v4l2_fourcc('R', 'G', 'B', 'H')/* 18 RGB-6-6-6 */ #define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3')/* 24 BGR-8-8-8 */ #define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3')/* 24 RGB-8-8-8 */ #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4')/* 32 BGR-8-8-8-8 */
Signature · 1 line
1.8.3.1
PATCH 148/222 imx-drm: add RGB666 support for parallel display.
In reply to Russell King - ARM LinuxFrom: Denis Carikli <[email protected]>
To: linux-arm-kernel at lists.infradead.org
--- .../devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt | 3 ++- drivers/staging/imx-drm/ipu-v3/ipu-dc.c | 9 +++++++++ drivers/staging/imx-drm/parallel-display.c | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt +2 -1
@@ -60,7 +60,8 @@ Parallel display support - compatible: Should be "fsl,imx-parallel-display" Optional properties: - interface_pix_fmt: How this display is connected to the - display interface. Currently supported types: "rgb24", "rgb565", "bgr666" + display interface. Currently supported types: "rgb24", "rgb565", "bgr666", + "rgb666" - edid: verbatim EDID data block describing attached display. - ddc: phandle describing the i2c bus handling the display data channel
drivers/staging/imx-drm/ipu-v3/ipu-dc.c +9 -0
@@ -92,6 +92,7 @@ enum ipu_dc_map {IPU_DC_MAP_GBR24 ,/* TVEv2 */ IPU_DC_MAP_BGR666 ,IPU_DC_MAP_BGR24 , + IPU_DC_MAP_RGB666, }; struct ipu_dc {
@@ -155,6 +156,8 @@ static int ipu_pixfmt_to_map(u32 fmt)return IPU_DC_MAP_BGR666 ;case V4L2_PIX_FMT_BGR24 :return IPU_DC_MAP_BGR24 ; +case V4L2_PIX_FMT_RGB666 : +return IPU_DC_MAP_RGB666 ;default :return -EINVAL ; }
@@ -404,6 +407,12 @@ int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,ipu_dc_map_config (priv,IPU_DC_MAP_BGR24 ,1 ,15 ,0xff );/* green */ ipu_dc_map_config (priv,IPU_DC_MAP_BGR24 ,0 ,23 ,0xff );/* blue */ +/* rgb666 */ +ipu_dc_map_clear (priv,IPU_DC_MAP_RGB666 ); +ipu_dc_map_config (priv,IPU_DC_MAP_RGB666 ,0 ,5 ,0xfc );/* blue */ +ipu_dc_map_config (priv,IPU_DC_MAP_RGB666 ,1 ,11 ,0xfc );/* green */ +ipu_dc_map_config (priv,IPU_DC_MAP_RGB666 ,2 ,17 ,0xfc );/* red */ +return 0 ; }
drivers/staging/imx-drm/parallel-display.c +2 -0
@@ -219,6 +219,8 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) imxpd->interface_pix_fmt =V4L2_PIX_FMT_RGB565 ; else if (!strcmp(fmt, "bgr666")) imxpd->interface_pix_fmt =V4L2_PIX_FMT_BGR666 ; + else if (!strcmp(fmt, "rgb666")) + imxpd->interface_pix_fmt =V4L2_PIX_FMT_RGB666 ; } panel_node =of_parse_phandle (np,"fsl,panel" ,0 );
Signature · 1 line
1.8.3.1
PATCH 149/222 imx-drm: ipu-common: add ipu_map_irq to request non-IDMAC interrupts
In reply to Russell King - ARM LinuxFrom: Philipp Zabel <[email protected]>
To: linux-arm-kernel at lists.infradead.org
This allows to request the DC related interrupts.
--- drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h | 1 + drivers/staging/imx-drm/ipu-v3/ipu-common.c | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-)
drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h +1 -0
@@ -76,6 +76,7 @@ enum ipu_channel_irq { IPU_IRQ_EOS = 192, }; +int ipu_map_irq (struct ipu_soc *ipu,int irq);int ipu_idmac_channel_irq (struct ipu_soc *ipu,struct ipuv3_channel *channel,enum ipu_channel_irq irq);
drivers/staging/imx-drm/ipu-v3/ipu-common.c +13 -6
@@ -933,15 +933,22 @@ static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc)chained_irq_exit (chip, desc); } -int ipu_idmac_channel_irq (struct ipu_soc *ipu,struct ipuv3_channel *channel, -enum ipu_channel_irq irq_type) +int ipu_map_irq (struct ipu_soc *ipu,int irq) { -int irq =irq_linear_revmap (ipu->domain, irq_type + channel->num); +int virq; -if (!irq) - irq =irq_create_mapping (ipu->domain, irq_type + channel->num); + virq =irq_linear_revmap (ipu->domain, irq); +if (!virq) + virq =irq_create_mapping (ipu->domain, irq); + +return virq; +} +EXPORT_SYMBOL_GPL (ipu_map_irq); -return irq; +int ipu_idmac_channel_irq (struct ipu_soc *ipu,struct ipuv3_channel *channel, +enum ipu_channel_irq irq_type) +{ +return ipu_map_irq (ipu, irq_type + channel->num); }EXPORT_SYMBOL_GPL (ipu_idmac_channel_irq);
Signature · 1 line
1.8.3.1
PATCH 150/222 imx-drm: ipu-common: add helpers to check for a busy IDMAC channel and to busywait for an interrupt
In reply to Russell King - ARM LinuxFrom: Philipp Zabel <[email protected]>
To: linux-arm-kernel at lists.infradead.org
--- drivers/staging/imx-drm/ipu-v3/ipu-common.c | 22 ++++++++++++++++++++++ drivers/staging/imx-drm/ipu-v3/ipu-prv.h | 3 +++ 2 files changed, 25 insertions(+)
drivers/staging/imx-drm/ipu-v3/ipu-common.c +22 -0
@@ -697,6 +697,12 @@ int ipu_idmac_enable_channel(struct ipuv3_channel *channel) }EXPORT_SYMBOL_GPL (ipu_idmac_enable_channel); +bool ipu_idmac_channel_busy (struct ipu_soc *ipu,unsigned int chno) +{ +return (ipu_idmac_read (ipu,IDMAC_CHA_BUSY (chno)) &idma_mask (chno)); +} +EXPORT_SYMBOL_GPL (ipu_idmac_channel_busy); +int ipu_idmac_wait_busy (struct ipuv3_channel *channel,int ms) {struct ipu_soc *ipu = channel->ipu;
@@ -714,6 +720,22 @@ int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms) }EXPORT_SYMBOL_GPL (ipu_idmac_wait_busy); +int ipu_wait_interrupt (struct ipu_soc *ipu,int irq,int ms) +{ +unsigned long timeout; + + timeout = jiffies +msecs_to_jiffies (ms); +ipu_cm_write (ipu,BIT (irq %32 ),IPU_INT_STAT (irq /32 )); +while (!(ipu_cm_read (ipu,IPU_INT_STAT (irq /32 ) &BIT (irq %32 )))) { +if (time_after (jiffies, timeout)) +return -ETIMEDOUT ; +cpu_relax (); + } + +return 0 ; +} +EXPORT_SYMBOL_GPL (ipu_wait_interrupt); +int ipu_idmac_disable_channel (struct ipuv3_channel *channel) {struct ipu_soc *ipu = channel->ipu;
drivers/staging/imx-drm/ipu-v3/ipu-prv.h +3 -0
@@ -185,6 +185,9 @@ void ipu_srm_dp_sync_update(struct ipu_soc *ipu);int ipu_module_enable (struct ipu_soc *ipu,u32 mask);int ipu_module_disable (struct ipu_soc *ipu,u32 mask); +bool ipu_idmac_channel_busy (struct ipu_soc *ipu,unsigned int chno); +int ipu_wait_interrupt (struct ipu_soc *ipu,int irq,int ms); +int ipu_di_init (struct ipu_soc *ipu,struct device *dev,int id,unsigned long base,u32 module,struct clk *ipu_clk);void ipu_di_exit (struct ipu_soc *ipu,int id);
Signature · 1 line
1.8.3.1
PATCH 151/222 imx-drm: ipu-dmfc: wait for FIFOs to run empty before disabling
In reply to Russell King - ARM LinuxFrom: Philipp Zabel <[email protected]>
To: linux-arm-kernel at lists.infradead.org
Disabling the DMFC module while there is still data in the FIFOs could cause the "new frame before end of frame" error state when the DMFC is enabled again.
--- drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c +23 -2
@@ -28,7 +28,12 @@#define DMFC_GENERAL1 0x0014#define DMFC_GENERAL2 0x0018#define DMFC_IC_CTRL 0x001c -#define DMFC_STAT 0x0020 +#define DMFC_WR_CHAN_ALT 0x0020 +#define DMFC_WR_CHAN_DEF_ALT 0x0024 +#define DMFC_DP_CHAN_ALT 0x0028 +#define DMFC_DP_CHAN_DEF_ALT 0x002c +#define DMFC_GENERAL1_ALT 0x0030 +#define DMFC_STAT 0x0034#define DMFC_WR_CHAN_1_28 0#define DMFC_WR_CHAN_2_41 8
@@ -133,6 +138,20 @@ int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc) }EXPORT_SYMBOL_GPL (ipu_dmfc_enable_channel); +static void ipu_dmfc_wait_fifos (struct ipu_dmfc_priv *priv) +{ +unsigned long timeout = jiffies +msecs_to_jiffies (1000 ); + +while ((readl (priv->base +DMFC_STAT ) &0x02fff000 ) !=0x02fff000 ) { +if (time_after (jiffies, timeout)) { +dev_warn (priv->dev, +"Timeout waiting for DMFC FIFOs to clear\n" ); +break ; + } +cpu_relax (); + } +} +void ipu_dmfc_disable_channel (struct dmfc_channel *dmfc) {struct ipu_dmfc_priv *priv = dmfc->priv;
@@ -141,8 +160,10 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc) priv->use_count--; -if (!priv->use_count) +if (!priv->use_count) { +ipu_dmfc_wait_fifos (priv);ipu_module_disable (priv->ipu,IPU_CONF_DMFC_EN ); + }if (priv->use_count <0 ) priv->use_count =0 ;
Signature · 1 line
1.8.3.1