Commit 71f777ed50e9109c235c14604d5e23d2f8e7453c
Exists in
master
and in
16 other branches
Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC fixes from Olof Johansson: "A first set of batches of fixes for 3.13. The diffstat is large mostly because we're adding a defconfig for a family that's been lacking it, and there's some missing clock information added for i.MX and OMAP. The at91 new code is around dealing with RTC/RTT reset at boot to fix possible hangs due to pending wakeup interrupts coming in during early boot" * tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (29 commits) ARM: OMAP2+: Fix build for dra7xx without omap4 and 5 ARM: OMAP2+: omap_device: maintain sane runtime pm status around suspend/resume doc: devicetree: Add bindings documentation for omap-des driver ARM: dts: doc: Document missing compatible property for omap-sham driver ARM: OMAP3: Beagle: fix return value check in beagle_opp_init() ARM: at91: fix hanged boot due to early rtt-interrupt ARM: at91: fix hanged boot due to early rtc-interrupt video: exynos_mipi_dsim: Remove unused variable ARM: highbank: only select errata 764369 if SMP ARM: sti: only select errata 764369 if SMP ARM: tegra: init fuse before setting reset handler ARM: vt8500: add defconfig for v6/v7 chips ARM: integrator_cp: Set LCD{0,1} enable lines when turning on CLCD ARM: OMAP: devicetree: fix SPI node compatible property syntax items pinctrl: single: call pcs_soc->rearm() whenever IRQ mask is changed ARM: OMAP2+: smsc911x: fix return value check in gpmc_smsc911x_init() MAINTAINERS: drop discontinued mailing list ARM: dts: i.MX51: Fix OTG PHY clock ARM: imx: set up pllv3 POWER and BYPASS sequentially ARM: imx: pllv3 needs relock in .set_rate() call ...
Showing 39 changed files Side-by-side Diff
- Documentation/devicetree/bindings/crypto/omap-des.txt
- Documentation/devicetree/bindings/crypto/omap-sham.txt
- Documentation/devicetree/bindings/spi/omap-spi.txt
- MAINTAINERS
- arch/arm/boot/dts/imx51.dtsi
- arch/arm/configs/vt8500_v6_v7_defconfig
- arch/arm/mach-at91/Makefile
- arch/arm/mach-at91/at91sam9260.c
- arch/arm/mach-at91/at91sam9261.c
- arch/arm/mach-at91/at91sam9263.c
- arch/arm/mach-at91/at91sam9g45.c
- arch/arm/mach-at91/at91sam9n12.c
- arch/arm/mach-at91/at91sam9rl.c
- arch/arm/mach-at91/at91sam9x5.c
- arch/arm/mach-at91/generic.h
- arch/arm/mach-at91/include/mach/at91sam9n12.h
- arch/arm/mach-at91/include/mach/at91sam9x5.h
- arch/arm/mach-at91/include/mach/sama5d3.h
- arch/arm/mach-at91/sama5d3.c
- arch/arm/mach-at91/sysirq_mask.c
- arch/arm/mach-highbank/Kconfig
- arch/arm/mach-imx/Makefile
- arch/arm/mach-imx/clk-imx6q.c
- arch/arm/mach-imx/clk-pllv3.c
- arch/arm/mach-imx/common.h
- arch/arm/mach-imx/src.c
- arch/arm/mach-imx/system.c
- arch/arm/mach-integrator/integrator_cp.c
- arch/arm/mach-omap2/Makefile
- arch/arm/mach-omap2/board-omap3beagle.c
- arch/arm/mach-omap2/cclock3xxx_data.c
- arch/arm/mach-omap2/cclock44xx_data.c
- arch/arm/mach-omap2/gpmc-smsc911x.c
- arch/arm/mach-omap2/omap_device.c
- arch/arm/mach-omap2/prm44xx_54xx.h
- arch/arm/mach-sti/Kconfig
- arch/arm/mach-tegra/tegra.c
- drivers/pinctrl/pinctrl-single.c
- drivers/video/exynos/exynos_mipi_dsi.c
Documentation/devicetree/bindings/crypto/omap-des.txt
1 | +OMAP SoC DES crypto Module | |
2 | + | |
3 | +Required properties: | |
4 | + | |
5 | +- compatible : Should contain "ti,omap4-des" | |
6 | +- ti,hwmods: Name of the hwmod associated with the DES module | |
7 | +- reg : Offset and length of the register set for the module | |
8 | +- interrupts : the interrupt-specifier for the DES module | |
9 | +- clocks : A phandle to the functional clock node of the DES module | |
10 | + corresponding to each entry in clock-names | |
11 | +- clock-names : Name of the functional clock, should be "fck" | |
12 | + | |
13 | +Optional properties: | |
14 | +- dmas: DMA specifiers for tx and rx dma. See the DMA client binding, | |
15 | + Documentation/devicetree/bindings/dma/dma.txt | |
16 | + Each entry corresponds to an entry in dma-names | |
17 | +- dma-names: DMA request names should include "tx" and "rx" if present | |
18 | + | |
19 | +Example: | |
20 | + /* DRA7xx SoC */ | |
21 | + des: des@480a5000 { | |
22 | + compatible = "ti,omap4-des"; | |
23 | + ti,hwmods = "des"; | |
24 | + reg = <0x480a5000 0xa0>; | |
25 | + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; | |
26 | + dmas = <&sdma 117>, <&sdma 116>; | |
27 | + dma-names = "tx", "rx"; | |
28 | + clocks = <&l3_iclk_div>; | |
29 | + clock-names = "fck"; | |
30 | + }; |
Documentation/devicetree/bindings/crypto/omap-sham.txt
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | SHAM versions: |
7 | 7 | - "ti,omap2-sham" for OMAP2 & OMAP3. |
8 | 8 | - "ti,omap4-sham" for OMAP4 and AM33XX. |
9 | - Note that these two versions are incompatible. | |
9 | + - "ti,omap5-sham" for OMAP5, DRA7 and AM43XX. | |
10 | 10 | - ti,hwmods: Name of the hwmod associated with the SHAM module |
11 | 11 | - reg : Offset and length of the register set for the module |
12 | 12 | - interrupts : the interrupt-specifier for the SHAM module. |
Documentation/devicetree/bindings/spi/omap-spi.txt
... | ... | @@ -2,8 +2,8 @@ |
2 | 2 | |
3 | 3 | Required properties: |
4 | 4 | - compatible : |
5 | - - "ti,omap2-spi" for OMAP2 & OMAP3. | |
6 | - - "ti,omap4-spi" for OMAP4+. | |
5 | + - "ti,omap2-mcspi" for OMAP2 & OMAP3. | |
6 | + - "ti,omap4-mcspi" for OMAP4+. | |
7 | 7 | - ti,spi-num-cs : Number of chipselect supported by the instance. |
8 | 8 | - ti,hwmods: Name of the hwmod associated to the McSPI |
9 | 9 | - ti,pindir-d0-out-d1-in: Select the D0 pin as output and D1 as |
MAINTAINERS
... | ... | @@ -1070,7 +1070,6 @@ |
1070 | 1070 | ARM/NOMADIK ARCHITECTURE |
1071 | 1071 | M: Alessandro Rubini <rubini@unipv.it> |
1072 | 1072 | M: Linus Walleij <linus.walleij@linaro.org> |
1073 | -M: STEricsson <STEricsson_nomadik_linux@list.st.com> | |
1074 | 1073 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
1075 | 1074 | S: Maintained |
1076 | 1075 | F: arch/arm/mach-nomadik/ |
arch/arm/boot/dts/imx51.dtsi
arch/arm/configs/vt8500_v6_v7_defconfig
1 | +CONFIG_IRQ_DOMAIN_DEBUG=y | |
2 | +CONFIG_NO_HZ=y | |
3 | +CONFIG_HIGH_RES_TIMERS=y | |
4 | +CONFIG_BLK_DEV_INITRD=y | |
5 | +CONFIG_ARCH_MULTI_V6=y | |
6 | +CONFIG_ARCH_WM8750=y | |
7 | +CONFIG_ARCH_WM8850=y | |
8 | +CONFIG_ARM_ERRATA_720789=y | |
9 | +CONFIG_ARM_ERRATA_754322=y | |
10 | +CONFIG_ARM_ERRATA_775420=y | |
11 | +CONFIG_HAVE_ARM_ARCH_TIMER=y | |
12 | +CONFIG_AEABI=y | |
13 | +CONFIG_HIGHMEM=y | |
14 | +CONFIG_HIGHPTE=y | |
15 | +CONFIG_ARM_APPENDED_DTB=y | |
16 | +CONFIG_ARM_ATAG_DTB_COMPAT=y | |
17 | +CONFIG_VFP=y | |
18 | +CONFIG_NEON=y | |
19 | +CONFIG_PM_RUNTIME=y | |
20 | +CONFIG_NET=y | |
21 | +CONFIG_UNIX=y | |
22 | +CONFIG_INET=y | |
23 | +CONFIG_IP_PNP=y | |
24 | +CONFIG_IP_PNP_DHCP=y | |
25 | +CONFIG_DEVTMPFS=y | |
26 | +CONFIG_DEVTMPFS_MOUNT=y | |
27 | +CONFIG_PROC_DEVICETREE=y | |
28 | +CONFIG_EEPROM_93CX6=y | |
29 | +CONFIG_SCSI=y | |
30 | +CONFIG_BLK_DEV_SD=y | |
31 | +CONFIG_NETDEVICES=y | |
32 | +# CONFIG_NET_CADENCE is not set | |
33 | +# CONFIG_NET_VENDOR_BROADCOM is not set | |
34 | +# CONFIG_NET_VENDOR_CIRRUS is not set | |
35 | +# CONFIG_NET_VENDOR_FARADAY is not set | |
36 | +# CONFIG_NET_VENDOR_INTEL is not set | |
37 | +# CONFIG_NET_VENDOR_MARVELL is not set | |
38 | +# CONFIG_NET_VENDOR_MICREL is not set | |
39 | +# CONFIG_NET_VENDOR_NATSEMI is not set | |
40 | +# CONFIG_NET_VENDOR_SEEQ is not set | |
41 | +# CONFIG_NET_VENDOR_SMSC is not set | |
42 | +# CONFIG_NET_VENDOR_STMICRO is not set | |
43 | +CONFIG_VIA_VELOCITY=y | |
44 | +# CONFIG_NET_VENDOR_WIZNET is not set | |
45 | +CONFIG_PHYLIB=y | |
46 | +CONFIG_INPUT_MATRIXKMAP=y | |
47 | +CONFIG_SERIAL_VT8500=y | |
48 | +CONFIG_SERIAL_VT8500_CONSOLE=y | |
49 | +CONFIG_I2C=y | |
50 | +CONFIG_I2C_WMT=y | |
51 | +CONFIG_PINCTRL_SINGLE=y | |
52 | +CONFIG_PINCTRL_WM8750=y | |
53 | +CONFIG_GPIO_GENERIC_PLATFORM=y | |
54 | +CONFIG_POWER_SUPPLY=y | |
55 | +CONFIG_POWER_RESET=y | |
56 | +CONFIG_MFD_SYSCON=y | |
57 | +CONFIG_REGULATOR=y | |
58 | +CONFIG_REGULATOR_FIXED_VOLTAGE=y | |
59 | +CONFIG_REGULATOR_GPIO=y | |
60 | +CONFIG_USB=y | |
61 | +CONFIG_USB_EHCI_HCD=y | |
62 | +CONFIG_USB_EHCI_HCD_PLATFORM=y | |
63 | +CONFIG_USB_UHCI_HCD=y | |
64 | +CONFIG_USB_STORAGE=y | |
65 | +CONFIG_NOP_USB_XCEIV=y | |
66 | +CONFIG_USB_GPIO_VBUS=y | |
67 | +CONFIG_USB_ULPI=y | |
68 | +CONFIG_MMC=y | |
69 | +CONFIG_MMC_DEBUG=y | |
70 | +CONFIG_NEW_LEDS=y | |
71 | +CONFIG_LEDS_CLASS=y | |
72 | +CONFIG_LEDS_TRIGGERS=y | |
73 | +CONFIG_RTC_CLASS=y | |
74 | +CONFIG_RTC_DRV_VT8500=y | |
75 | +CONFIG_DMADEVICES=y | |
76 | +CONFIG_COMMON_CLK_DEBUG=y | |
77 | +# CONFIG_IOMMU_SUPPORT is not set | |
78 | +CONFIG_PWM=y | |
79 | +CONFIG_PWM_VT8500=y | |
80 | +CONFIG_RESET_CONTROLLER=y | |
81 | +CONFIG_GENERIC_PHY=y | |
82 | +CONFIG_EXT4_FS=y | |
83 | +CONFIG_TMPFS=y | |
84 | +CONFIG_NFS_FS=y | |
85 | +CONFIG_NFS_V3_ACL=y | |
86 | +CONFIG_NFS_V4=y | |
87 | +CONFIG_ROOT_NFS=y | |
88 | +CONFIG_PRINTK_TIME=y | |
89 | +CONFIG_DEBUG_KERNEL=y | |
90 | +CONFIG_LOCKUP_DETECTOR=y |
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
... | ... | @@ -330,6 +330,9 @@ |
330 | 330 | arm_pm_idle = at91sam9_idle; |
331 | 331 | arm_pm_restart = at91sam9_alt_restart; |
332 | 332 | |
333 | + at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0); | |
334 | + at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1); | |
335 | + | |
333 | 336 | /* Register GPIO subsystem */ |
334 | 337 | at91_gpio_init(at91sam9263_gpio, 5); |
335 | 338 | } |
arch/arm/mach-at91/at91sam9g45.c
... | ... | @@ -379,6 +379,9 @@ |
379 | 379 | arm_pm_idle = at91sam9_idle; |
380 | 380 | arm_pm_restart = at91sam9g45_restart; |
381 | 381 | |
382 | + at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC); | |
383 | + at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT); | |
384 | + | |
382 | 385 | /* Register GPIO subsystem */ |
383 | 386 | at91_gpio_init(at91sam9g45_gpio, 5); |
384 | 387 | } |
arch/arm/mach-at91/at91sam9n12.c
... | ... | @@ -224,8 +224,14 @@ |
224 | 224 | at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE); |
225 | 225 | } |
226 | 226 | |
227 | +static void __init at91sam9n12_initialize(void) | |
228 | +{ | |
229 | + at91_sysirq_mask_rtc(AT91SAM9N12_BASE_RTC); | |
230 | +} | |
231 | + | |
227 | 232 | AT91_SOC_START(at91sam9n12) |
228 | 233 | .map_io = at91sam9n12_map_io, |
229 | 234 | .register_clocks = at91sam9n12_register_clocks, |
235 | + .init = at91sam9n12_initialize, | |
230 | 236 | AT91_SOC_END |
arch/arm/mach-at91/at91sam9rl.c
... | ... | @@ -296,6 +296,9 @@ |
296 | 296 | arm_pm_idle = at91sam9_idle; |
297 | 297 | arm_pm_restart = at91sam9_alt_restart; |
298 | 298 | |
299 | + at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC); | |
300 | + at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT); | |
301 | + | |
299 | 302 | /* Register GPIO subsystem */ |
300 | 303 | at91_gpio_init(at91sam9rl_gpio, 4); |
301 | 304 | } |
arch/arm/mach-at91/at91sam9x5.c
... | ... | @@ -322,6 +322,11 @@ |
322 | 322 | at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE); |
323 | 323 | } |
324 | 324 | |
325 | +static void __init at91sam9x5_initialize(void) | |
326 | +{ | |
327 | + at91_sysirq_mask_rtc(AT91SAM9X5_BASE_RTC); | |
328 | +} | |
329 | + | |
325 | 330 | /* -------------------------------------------------------------------- |
326 | 331 | * Interrupt initialization |
327 | 332 | * -------------------------------------------------------------------- */ |
... | ... | @@ -329,5 +334,6 @@ |
329 | 334 | AT91_SOC_START(at91sam9x5) |
330 | 335 | .map_io = at91sam9x5_map_io, |
331 | 336 | .register_clocks = at91sam9x5_register_clocks, |
337 | + .init = at91sam9x5_initialize, | |
332 | 338 | AT91_SOC_END |
arch/arm/mach-at91/generic.h
... | ... | @@ -34,6 +34,8 @@ |
34 | 34 | struct device_node *parent); |
35 | 35 | extern int __init at91_aic5_of_init(struct device_node *node, |
36 | 36 | struct device_node *parent); |
37 | +extern void __init at91_sysirq_mask_rtc(u32 rtc_base); | |
38 | +extern void __init at91_sysirq_mask_rtt(u32 rtt_base); | |
37 | 39 | |
38 | 40 | |
39 | 41 | /* Timer */ |
arch/arm/mach-at91/include/mach/at91sam9n12.h
arch/arm/mach-at91/include/mach/at91sam9x5.h
arch/arm/mach-at91/include/mach/sama5d3.h
arch/arm/mach-at91/sama5d3.c
... | ... | @@ -371,8 +371,14 @@ |
371 | 371 | at91_init_sram(0, SAMA5D3_SRAM_BASE, SAMA5D3_SRAM_SIZE); |
372 | 372 | } |
373 | 373 | |
374 | +static void __init sama5d3_initialize(void) | |
375 | +{ | |
376 | + at91_sysirq_mask_rtc(SAMA5D3_BASE_RTC); | |
377 | +} | |
378 | + | |
374 | 379 | AT91_SOC_START(sama5d3) |
375 | 380 | .map_io = sama5d3_map_io, |
376 | 381 | .register_clocks = sama5d3_register_clocks, |
382 | + .init = sama5d3_initialize, | |
377 | 383 | AT91_SOC_END |
arch/arm/mach-at91/sysirq_mask.c
1 | +/* | |
2 | + * sysirq_mask.c - System-interrupt masking | |
3 | + * | |
4 | + * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com> | |
5 | + * | |
6 | + * Functions to disable system interrupts from backup-powered peripherals. | |
7 | + * | |
8 | + * The RTC and RTT-peripherals are generally powered by backup power (VDDBU) | |
9 | + * and are not reset on wake-up, user, watchdog or software reset. This means | |
10 | + * that their interrupts may be enabled during early boot (e.g. after a user | |
11 | + * reset). | |
12 | + * | |
13 | + * As the RTC and RTT share the system-interrupt line with the PIT, an | |
14 | + * interrupt occurring before a handler has been installed would lead to the | |
15 | + * system interrupt being disabled and prevent the system from booting. | |
16 | + * | |
17 | + * This program is free software; you can redistribute it and/or modify | |
18 | + * it under the terms of the GNU General Public License as published by | |
19 | + * the Free Software Foundation; either version 2 of the License, or | |
20 | + * (at your option) any later version. | |
21 | + */ | |
22 | + | |
23 | +#include <linux/io.h> | |
24 | +#include <mach/at91_rtt.h> | |
25 | + | |
26 | +#include "generic.h" | |
27 | + | |
28 | +#define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ | |
29 | +#define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */ | |
30 | + | |
31 | +void __init at91_sysirq_mask_rtc(u32 rtc_base) | |
32 | +{ | |
33 | + void __iomem *base; | |
34 | + u32 mask; | |
35 | + | |
36 | + base = ioremap(rtc_base, 64); | |
37 | + if (!base) | |
38 | + return; | |
39 | + | |
40 | + mask = readl_relaxed(base + AT91_RTC_IMR); | |
41 | + if (mask) { | |
42 | + pr_info("AT91: Disabling rtc irq\n"); | |
43 | + writel_relaxed(mask, base + AT91_RTC_IDR); | |
44 | + (void)readl_relaxed(base + AT91_RTC_IMR); /* flush */ | |
45 | + } | |
46 | + | |
47 | + iounmap(base); | |
48 | +} | |
49 | + | |
50 | +void __init at91_sysirq_mask_rtt(u32 rtt_base) | |
51 | +{ | |
52 | + void __iomem *base; | |
53 | + void __iomem *reg; | |
54 | + u32 mode; | |
55 | + | |
56 | + base = ioremap(rtt_base, 16); | |
57 | + if (!base) | |
58 | + return; | |
59 | + | |
60 | + reg = base + AT91_RTT_MR; | |
61 | + | |
62 | + mode = readl_relaxed(reg); | |
63 | + if (mode & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)) { | |
64 | + pr_info("AT91: Disabling rtt irq\n"); | |
65 | + mode &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | |
66 | + writel_relaxed(mode, reg); | |
67 | + (void)readl_relaxed(reg); /* flush */ | |
68 | + } | |
69 | + | |
70 | + iounmap(base); | |
71 | +} |
arch/arm/mach-highbank/Kconfig
arch/arm/mach-imx/Makefile
... | ... | @@ -102,8 +102,8 @@ |
102 | 102 | |
103 | 103 | ifeq ($(CONFIG_PM),y) |
104 | 104 | obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o |
105 | -# i.MX6SL reuses pm-imx6q.c | |
106 | -obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o | |
105 | +# i.MX6SL reuses i.MX6Q code | |
106 | +obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o | |
107 | 107 | endif |
108 | 108 | |
109 | 109 | # i.MX5 based machines |
arch/arm/mach-imx/clk-imx6q.c
... | ... | @@ -122,13 +122,14 @@ |
122 | 122 | { .val = 1, .div = 10, }, |
123 | 123 | { .val = 2, .div = 5, }, |
124 | 124 | { .val = 3, .div = 4, }, |
125 | + { /* sentinel */ } | |
125 | 126 | }; |
126 | 127 | |
127 | 128 | static struct clk_div_table post_div_table[] = { |
128 | 129 | { .val = 2, .div = 1, }, |
129 | 130 | { .val = 1, .div = 2, }, |
130 | 131 | { .val = 0, .div = 4, }, |
131 | - { } | |
132 | + { /* sentinel */ } | |
132 | 133 | }; |
133 | 134 | |
134 | 135 | static struct clk_div_table video_div_table[] = { |
... | ... | @@ -136,7 +137,7 @@ |
136 | 137 | { .val = 1, .div = 2, }, |
137 | 138 | { .val = 2, .div = 1, }, |
138 | 139 | { .val = 3, .div = 4, }, |
139 | - { } | |
140 | + { /* sentinel */ } | |
140 | 141 | }; |
141 | 142 | |
142 | 143 | static void __init imx6q_clocks_init(struct device_node *ccm_node) |
... | ... | @@ -298,7 +299,7 @@ |
298 | 299 | clk[asrc_podf] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3); |
299 | 300 | clk[spdif_pred] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3); |
300 | 301 | clk[spdif_podf] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3); |
301 | - clk[can_root] = imx_clk_divider("can_root", "pll3_usb_otg", base + 0x20, 2, 6); | |
302 | + clk[can_root] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6); | |
302 | 303 | clk[ecspi_root] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6); |
303 | 304 | clk[gpu2d_core_podf] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3); |
304 | 305 | clk[gpu3d_core_podf] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3); |
arch/arm/mach-imx/clk-pllv3.c
... | ... | @@ -12,6 +12,7 @@ |
12 | 12 | |
13 | 13 | #include <linux/clk.h> |
14 | 14 | #include <linux/clk-provider.h> |
15 | +#include <linux/delay.h> | |
15 | 16 | #include <linux/io.h> |
16 | 17 | #include <linux/slab.h> |
17 | 18 | #include <linux/jiffies.h> |
18 | 19 | |
19 | 20 | |
20 | 21 | |
21 | 22 | |
22 | 23 | |
... | ... | @@ -45,33 +46,49 @@ |
45 | 46 | |
46 | 47 | #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) |
47 | 48 | |
49 | +static int clk_pllv3_wait_lock(struct clk_pllv3 *pll) | |
50 | +{ | |
51 | + unsigned long timeout = jiffies + msecs_to_jiffies(10); | |
52 | + u32 val = readl_relaxed(pll->base) & BM_PLL_POWER; | |
53 | + | |
54 | + /* No need to wait for lock when pll is not powered up */ | |
55 | + if ((pll->powerup_set && !val) || (!pll->powerup_set && val)) | |
56 | + return 0; | |
57 | + | |
58 | + /* Wait for PLL to lock */ | |
59 | + do { | |
60 | + if (readl_relaxed(pll->base) & BM_PLL_LOCK) | |
61 | + break; | |
62 | + if (time_after(jiffies, timeout)) | |
63 | + break; | |
64 | + usleep_range(50, 500); | |
65 | + } while (1); | |
66 | + | |
67 | + return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT; | |
68 | +} | |
69 | + | |
48 | 70 | static int clk_pllv3_prepare(struct clk_hw *hw) |
49 | 71 | { |
50 | 72 | struct clk_pllv3 *pll = to_clk_pllv3(hw); |
51 | - unsigned long timeout; | |
52 | 73 | u32 val; |
74 | + int ret; | |
53 | 75 | |
54 | 76 | val = readl_relaxed(pll->base); |
55 | - val &= ~BM_PLL_BYPASS; | |
56 | 77 | if (pll->powerup_set) |
57 | 78 | val |= BM_PLL_POWER; |
58 | 79 | else |
59 | 80 | val &= ~BM_PLL_POWER; |
60 | 81 | writel_relaxed(val, pll->base); |
61 | 82 | |
62 | - timeout = jiffies + msecs_to_jiffies(10); | |
63 | - /* Wait for PLL to lock */ | |
64 | - do { | |
65 | - if (readl_relaxed(pll->base) & BM_PLL_LOCK) | |
66 | - break; | |
67 | - if (time_after(jiffies, timeout)) | |
68 | - break; | |
69 | - } while (1); | |
83 | + ret = clk_pllv3_wait_lock(pll); | |
84 | + if (ret) | |
85 | + return ret; | |
70 | 86 | |
71 | - if (readl_relaxed(pll->base) & BM_PLL_LOCK) | |
72 | - return 0; | |
73 | - else | |
74 | - return -ETIMEDOUT; | |
87 | + val = readl_relaxed(pll->base); | |
88 | + val &= ~BM_PLL_BYPASS; | |
89 | + writel_relaxed(val, pll->base); | |
90 | + | |
91 | + return 0; | |
75 | 92 | } |
76 | 93 | |
77 | 94 | static void clk_pllv3_unprepare(struct clk_hw *hw) |
... | ... | @@ -146,7 +163,7 @@ |
146 | 163 | val |= div; |
147 | 164 | writel_relaxed(val, pll->base); |
148 | 165 | |
149 | - return 0; | |
166 | + return clk_pllv3_wait_lock(pll); | |
150 | 167 | } |
151 | 168 | |
152 | 169 | static const struct clk_ops clk_pllv3_ops = { |
... | ... | @@ -202,7 +219,7 @@ |
202 | 219 | val |= div; |
203 | 220 | writel_relaxed(val, pll->base); |
204 | 221 | |
205 | - return 0; | |
222 | + return clk_pllv3_wait_lock(pll); | |
206 | 223 | } |
207 | 224 | |
208 | 225 | static const struct clk_ops clk_pllv3_sys_ops = { |
... | ... | @@ -276,7 +293,7 @@ |
276 | 293 | writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); |
277 | 294 | writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); |
278 | 295 | |
279 | - return 0; | |
296 | + return clk_pllv3_wait_lock(pll); | |
280 | 297 | } |
281 | 298 | |
282 | 299 | static const struct clk_ops clk_pllv3_av_ops = { |
arch/arm/mach-imx/common.h
... | ... | @@ -127,11 +127,6 @@ |
127 | 127 | static inline void imx_scu_standby_enable(void) {} |
128 | 128 | #endif |
129 | 129 | void imx_src_init(void); |
130 | -#ifdef CONFIG_HAVE_IMX_SRC | |
131 | -void imx_src_prepare_restart(void); | |
132 | -#else | |
133 | -static inline void imx_src_prepare_restart(void) {} | |
134 | -#endif | |
135 | 130 | void imx_gpc_init(void); |
136 | 131 | void imx_gpc_pre_suspend(void); |
137 | 132 | void imx_gpc_post_resume(void); |
arch/arm/mach-imx/src.c
... | ... | @@ -115,21 +115,6 @@ |
115 | 115 | writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4); |
116 | 116 | } |
117 | 117 | |
118 | -void imx_src_prepare_restart(void) | |
119 | -{ | |
120 | - u32 val; | |
121 | - | |
122 | - /* clear enable bits of secondary cores */ | |
123 | - spin_lock(&scr_lock); | |
124 | - val = readl_relaxed(src_base + SRC_SCR); | |
125 | - val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE); | |
126 | - writel_relaxed(val, src_base + SRC_SCR); | |
127 | - spin_unlock(&scr_lock); | |
128 | - | |
129 | - /* clear persistent entry register of primary core */ | |
130 | - writel_relaxed(0, src_base + SRC_GPR1); | |
131 | -} | |
132 | - | |
133 | 118 | void __init imx_src_init(void) |
134 | 119 | { |
135 | 120 | struct device_node *np; |
arch/arm/mach-imx/system.c
... | ... | @@ -42,9 +42,6 @@ |
42 | 42 | { |
43 | 43 | unsigned int wcr_enable; |
44 | 44 | |
45 | - if (cpu_is_imx6q() || cpu_is_imx6dl()) | |
46 | - imx_src_prepare_restart(); | |
47 | - | |
48 | 45 | if (wdog_clk) |
49 | 46 | clk_enable(wdog_clk); |
50 | 47 | |
... | ... | @@ -55,7 +52,14 @@ |
55 | 52 | |
56 | 53 | /* Assert SRS signal */ |
57 | 54 | __raw_writew(wcr_enable, wdog_base); |
58 | - /* write twice to ensure the request will not get ignored */ | |
55 | + /* | |
56 | + * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be | |
57 | + * written twice), we add another two writes to ensure there must be at | |
58 | + * least two writes happen in the same one 32kHz clock period. We save | |
59 | + * the target check here, since the writes shouldn't be a huge burden | |
60 | + * for other platforms. | |
61 | + */ | |
62 | + __raw_writew(wcr_enable, wdog_base); | |
59 | 63 | __raw_writew(wcr_enable, wdog_base); |
60 | 64 | |
61 | 65 | /* wait for reset to assert... */ |
arch/arm/mach-integrator/integrator_cp.c
... | ... | @@ -198,7 +198,8 @@ |
198 | 198 | static void cp_clcd_enable(struct clcd_fb *fb) |
199 | 199 | { |
200 | 200 | struct fb_var_screeninfo *var = &fb->fb.var; |
201 | - u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2; | |
201 | + u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2 | |
202 | + | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1; | |
202 | 203 | |
203 | 204 | if (var->bits_per_pixel <= 8 || |
204 | 205 | (var->bits_per_pixel == 16 && var->green.length == 5)) |
arch/arm/mach-omap2/Makefile
... | ... | @@ -40,7 +40,7 @@ |
40 | 40 | obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-common) $(smp-y) sleep44xx.o |
41 | 41 | obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-common) $(smp-y) sleep44xx.o |
42 | 42 | obj-$(CONFIG_SOC_AM43XX) += $(omap-4-5-common) |
43 | -obj-$(CONFIG_SOC_DRA7XX) += $(omap-4-5-common) $(smp-y) | |
43 | +obj-$(CONFIG_SOC_DRA7XX) += $(omap-4-5-common) $(smp-y) sleep44xx.o | |
44 | 44 | |
45 | 45 | plus_sec := $(call as-instr,.arch_extension sec,+sec) |
46 | 46 | AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec) |
arch/arm/mach-omap2/board-omap3beagle.c
... | ... | @@ -510,7 +510,7 @@ |
510 | 510 | mpu_dev = get_cpu_device(0); |
511 | 511 | iva_dev = omap_device_get_by_hwmod_name("iva"); |
512 | 512 | |
513 | - if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) { | |
513 | + if (!mpu_dev || IS_ERR(iva_dev)) { | |
514 | 514 | pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n", |
515 | 515 | __func__, mpu_dev, iva_dev); |
516 | 516 | return -ENODEV; |
arch/arm/mach-omap2/cclock3xxx_data.c
... | ... | @@ -381,6 +381,42 @@ |
381 | 381 | |
382 | 382 | DEFINE_STRUCT_CLK(dpll4_ck, dpll3_ck_parent_names, dpll4_ck_ops); |
383 | 383 | |
384 | +static const struct clk_div_table dpll4_mx_ck_div_table[] = { | |
385 | + { .div = 1, .val = 1 }, | |
386 | + { .div = 2, .val = 2 }, | |
387 | + { .div = 3, .val = 3 }, | |
388 | + { .div = 4, .val = 4 }, | |
389 | + { .div = 5, .val = 5 }, | |
390 | + { .div = 6, .val = 6 }, | |
391 | + { .div = 7, .val = 7 }, | |
392 | + { .div = 8, .val = 8 }, | |
393 | + { .div = 9, .val = 9 }, | |
394 | + { .div = 10, .val = 10 }, | |
395 | + { .div = 11, .val = 11 }, | |
396 | + { .div = 12, .val = 12 }, | |
397 | + { .div = 13, .val = 13 }, | |
398 | + { .div = 14, .val = 14 }, | |
399 | + { .div = 15, .val = 15 }, | |
400 | + { .div = 16, .val = 16 }, | |
401 | + { .div = 17, .val = 17 }, | |
402 | + { .div = 18, .val = 18 }, | |
403 | + { .div = 19, .val = 19 }, | |
404 | + { .div = 20, .val = 20 }, | |
405 | + { .div = 21, .val = 21 }, | |
406 | + { .div = 22, .val = 22 }, | |
407 | + { .div = 23, .val = 23 }, | |
408 | + { .div = 24, .val = 24 }, | |
409 | + { .div = 25, .val = 25 }, | |
410 | + { .div = 26, .val = 26 }, | |
411 | + { .div = 27, .val = 27 }, | |
412 | + { .div = 28, .val = 28 }, | |
413 | + { .div = 29, .val = 29 }, | |
414 | + { .div = 30, .val = 30 }, | |
415 | + { .div = 31, .val = 31 }, | |
416 | + { .div = 32, .val = 32 }, | |
417 | + { .div = 0 }, | |
418 | +}; | |
419 | + | |
384 | 420 | DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck, 0x0, |
385 | 421 | OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), |
386 | 422 | OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH, |
387 | 423 | |
... | ... | @@ -524,10 +560,10 @@ |
524 | 560 | { .div = 0 } |
525 | 561 | }; |
526 | 562 | |
527 | -DEFINE_CLK_DIVIDER(dpll4_m3_ck, "dpll4_ck", &dpll4_ck, 0x0, | |
563 | +DEFINE_CLK_DIVIDER_TABLE(dpll4_m3_ck, "dpll4_ck", &dpll4_ck, 0x0, | |
528 | 564 | OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), |
529 | 565 | OMAP3430_CLKSEL_TV_SHIFT, OMAP3630_CLKSEL_TV_WIDTH, |
530 | - CLK_DIVIDER_ONE_BASED, NULL); | |
566 | + 0, dpll4_mx_ck_div_table, NULL); | |
531 | 567 | |
532 | 568 | static struct clk dpll4_m3x2_ck; |
533 | 569 | |
534 | 570 | |
... | ... | @@ -847,10 +883,10 @@ |
847 | 883 | |
848 | 884 | DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck, 0x0, 2, 1); |
849 | 885 | |
850 | -DEFINE_CLK_DIVIDER(dpll4_m4_ck, "dpll4_ck", &dpll4_ck, 0x0, | |
886 | +DEFINE_CLK_DIVIDER_TABLE(dpll4_m4_ck, "dpll4_ck", &dpll4_ck, 0x0, | |
851 | 887 | OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL), |
852 | 888 | OMAP3430_CLKSEL_DSS1_SHIFT, OMAP3630_CLKSEL_DSS1_WIDTH, |
853 | - CLK_DIVIDER_ONE_BASED, NULL); | |
889 | + 0, dpll4_mx_ck_div_table, NULL); | |
854 | 890 | |
855 | 891 | static struct clk dpll4_m4x2_ck; |
856 | 892 | |
... | ... | @@ -869,7 +905,8 @@ |
869 | 905 | .clkdm_name = "dpll4_clkdm", |
870 | 906 | }; |
871 | 907 | |
872 | -DEFINE_STRUCT_CLK(dpll4_m4x2_ck, dpll4_m4x2_ck_parent_names, dpll4_m5x2_ck_ops); | |
908 | +DEFINE_STRUCT_CLK_FLAGS(dpll4_m4x2_ck, dpll4_m4x2_ck_parent_names, | |
909 | + dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT); | |
873 | 910 | |
874 | 911 | static struct clk dpll4_m4x2_ck_3630 = { |
875 | 912 | .name = "dpll4_m4x2_ck", |
... | ... | @@ -877,6 +914,7 @@ |
877 | 914 | .parent_names = dpll4_m4x2_ck_parent_names, |
878 | 915 | .num_parents = ARRAY_SIZE(dpll4_m4x2_ck_parent_names), |
879 | 916 | .ops = &dpll4_m5x2_ck_3630_ops, |
917 | + .flags = CLK_SET_RATE_PARENT, | |
880 | 918 | }; |
881 | 919 | |
882 | 920 | DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck, 0x0, |
... | ... | @@ -968,8 +1006,9 @@ |
968 | 1006 | .clkdm_name = "dss_clkdm", |
969 | 1007 | }; |
970 | 1008 | |
971 | -DEFINE_STRUCT_CLK(dss1_alwon_fck_3430es1, dss1_alwon_fck_3430es1_parent_names, | |
972 | - aes2_ick_ops); | |
1009 | +DEFINE_STRUCT_CLK_FLAGS(dss1_alwon_fck_3430es1, | |
1010 | + dss1_alwon_fck_3430es1_parent_names, aes2_ick_ops, | |
1011 | + CLK_SET_RATE_PARENT); | |
973 | 1012 | |
974 | 1013 | static struct clk dss1_alwon_fck_3430es2; |
975 | 1014 | |
... | ... | @@ -983,8 +1022,9 @@ |
983 | 1022 | .clkdm_name = "dss_clkdm", |
984 | 1023 | }; |
985 | 1024 | |
986 | -DEFINE_STRUCT_CLK(dss1_alwon_fck_3430es2, dss1_alwon_fck_3430es1_parent_names, | |
987 | - aes2_ick_ops); | |
1025 | +DEFINE_STRUCT_CLK_FLAGS(dss1_alwon_fck_3430es2, | |
1026 | + dss1_alwon_fck_3430es1_parent_names, aes2_ick_ops, | |
1027 | + CLK_SET_RATE_PARENT); | |
988 | 1028 | |
989 | 1029 | static struct clk dss2_alwon_fck; |
990 | 1030 |
arch/arm/mach-omap2/cclock44xx_data.c
... | ... | @@ -830,7 +830,8 @@ |
830 | 830 | OMAP4430_CM_DSS_DSS_CLKCTRL, |
831 | 831 | OMAP4430_OPTFCLKEN_TV_CLK_SHIFT, 0x0, NULL); |
832 | 832 | |
833 | -DEFINE_CLK_GATE(dss_dss_clk, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, 0x0, | |
833 | +DEFINE_CLK_GATE(dss_dss_clk, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, | |
834 | + CLK_SET_RATE_PARENT, | |
834 | 835 | OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_OPTFCLKEN_DSSCLK_SHIFT, |
835 | 836 | 0x0, NULL); |
836 | 837 |
arch/arm/mach-omap2/gpmc-smsc911x.c
... | ... | @@ -83,7 +83,7 @@ |
83 | 83 | pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id, |
84 | 84 | gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources), |
85 | 85 | &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config)); |
86 | - if (!pdev) { | |
86 | + if (IS_ERR(pdev)) { | |
87 | 87 | pr_err("Unable to register platform device\n"); |
88 | 88 | gpio_free(gpmc_cfg->gpio_reset); |
89 | 89 | goto free2; |
arch/arm/mach-omap2/omap_device.c
... | ... | @@ -621,6 +621,7 @@ |
621 | 621 | |
622 | 622 | if (!ret && !pm_runtime_status_suspended(dev)) { |
623 | 623 | if (pm_generic_runtime_suspend(dev) == 0) { |
624 | + pm_runtime_set_suspended(dev); | |
624 | 625 | omap_device_idle(pdev); |
625 | 626 | od->flags |= OMAP_DEVICE_SUSPENDED; |
626 | 627 | } |
627 | 628 | |
... | ... | @@ -634,10 +635,18 @@ |
634 | 635 | struct platform_device *pdev = to_platform_device(dev); |
635 | 636 | struct omap_device *od = to_omap_device(pdev); |
636 | 637 | |
637 | - if ((od->flags & OMAP_DEVICE_SUSPENDED) && | |
638 | - !pm_runtime_status_suspended(dev)) { | |
638 | + if (od->flags & OMAP_DEVICE_SUSPENDED) { | |
639 | 639 | od->flags &= ~OMAP_DEVICE_SUSPENDED; |
640 | 640 | omap_device_enable(pdev); |
641 | + /* | |
642 | + * XXX: we run before core runtime pm has resumed itself. At | |
643 | + * this point in time, we just restore the runtime pm state and | |
644 | + * considering symmetric operations in resume, we donot expect | |
645 | + * to fail. If we failed, something changed in core runtime_pm | |
646 | + * framework OR some device driver messed things up, hence, WARN | |
647 | + */ | |
648 | + WARN(pm_runtime_set_active(dev), | |
649 | + "Could not set %s runtime state active\n", dev_name(dev)); | |
641 | 650 | pm_generic_runtime_resume(dev); |
642 | 651 | } |
643 | 652 |
arch/arm/mach-omap2/prm44xx_54xx.h
... | ... | @@ -42,7 +42,8 @@ |
42 | 42 | extern void omap4_prm_vcvp_write(u32 val, u8 offset); |
43 | 43 | extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset); |
44 | 44 | |
45 | -#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) | |
45 | +#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \ | |
46 | + defined(CONFIG_SOC_DRA7XX) | |
46 | 47 | void omap44xx_prm_reconfigure_io_chain(void); |
47 | 48 | #else |
48 | 49 | static inline void omap44xx_prm_reconfigure_io_chain(void) |
arch/arm/mach-sti/Kconfig
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 | select HAVE_ARM_SCU if SMP |
13 | 13 | select ARCH_REQUIRE_GPIOLIB |
14 | 14 | select ARM_ERRATA_754322 |
15 | - select ARM_ERRATA_764369 | |
15 | + select ARM_ERRATA_764369 if SMP | |
16 | 16 | select ARM_ERRATA_775420 |
17 | 17 | select PL310_ERRATA_753970 if CACHE_PL310 |
18 | 18 | select PL310_ERRATA_769419 if CACHE_PL310 |
arch/arm/mach-tegra/tegra.c
drivers/pinctrl/pinctrl-single.c
... | ... | @@ -1604,6 +1604,9 @@ |
1604 | 1604 | pcs->write(mask, pcswi->reg); |
1605 | 1605 | raw_spin_unlock(&pcs->lock); |
1606 | 1606 | } |
1607 | + | |
1608 | + if (pcs_soc->rearm) | |
1609 | + pcs_soc->rearm(); | |
1607 | 1610 | } |
1608 | 1611 | |
1609 | 1612 | /** |
... | ... | @@ -1626,8 +1629,6 @@ |
1626 | 1629 | struct pcs_soc_data *pcs_soc = irq_data_get_irq_chip_data(d); |
1627 | 1630 | |
1628 | 1631 | pcs_irq_set(pcs_soc, d->irq, true); |
1629 | - if (pcs_soc->rearm) | |
1630 | - pcs_soc->rearm(); | |
1631 | 1632 | } |
1632 | 1633 | |
1633 | 1634 | /** |
... | ... | @@ -1677,11 +1678,6 @@ |
1677 | 1678 | count++; |
1678 | 1679 | } |
1679 | 1680 | } |
1680 | - | |
1681 | - /* | |
1682 | - * For debugging on omaps, you may want to call pcs_soc->rearm() | |
1683 | - * here to see wake-up interrupts during runtime also. | |
1684 | - */ | |
1685 | 1681 | |
1686 | 1682 | return count; |
1687 | 1683 | } |
drivers/video/exynos/exynos_mipi_dsi.c
... | ... | @@ -141,7 +141,6 @@ |
141 | 141 | |
142 | 142 | static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power) |
143 | 143 | { |
144 | - struct platform_device *pdev = to_platform_device(dsim->dev); | |
145 | 144 | struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; |
146 | 145 | struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; |
147 | 146 |