* [PATCH] ARM: errata: pl310 cache sync operation may be faulty
From: srinidhi kasagar @ 2011-02-15 11:18 UTC (permalink / raw)
To: linux-arm-kernel
The effect of cache sync operation is to drain the store
buffer and wait for all internal buffers to be empty. In
normal conditions, store buffer is able to merge the
normal memory writes within its 32-byte data buffers.
Due to this erratum present in r3p0, 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.
This can severely affect performance on the write traffic
esp. on Normal memory NC one.
The proposed workaround is to replace the normal offset of
cache sync operation(0x730) by another offset targeting an
unmapped PL310 register 0x740.
Signed-off-by: srinidhi kasagar <srinidhi.kasagar@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
---
arch/arm/Kconfig | 15 +++++++++++++++
arch/arm/mm/cache-l2x0.c | 8 ++++++++
2 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d5eb308..f1946e4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1186,6 +1186,21 @@ config ARM_ERRATA_743622
visible impact on the overall performance or power consumption of the
processor.
+config ARM_ERRATA_753970
+ bool "ARM errata: cache sync operation may be faulty"
+ depends on CACHE_PL310
+ help
+ This option enables the workaround for the 753970 PL310 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.
+
endmenu
source "arch/arm/common/Kconfig"
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 170c9bb..998d521 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -49,8 +49,16 @@ static inline void cache_wait(void __iomem *reg, unsigned long mask)
static inline void cache_sync(void)
{
void __iomem *base = l2x0_base;
+
+#ifdef ARM_ERRATA_753970
+#define L2X0_DUMMY_REG 0x740
+ /* write to an unmmapped register */
+ writel_relaxed(0, base + L2X0_DUMMY_REG);
+ cache_wait(base + L2X0_CACHE_SYNC, 1);
+#else
writel_relaxed(0, base + L2X0_CACHE_SYNC);
cache_wait(base + L2X0_CACHE_SYNC, 1);
+#endif
}
static inline void l2x0_clean_line(unsigned long addr)
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/6] ARM: pm: add generic CPU suspend/resume support
From: Russell King - ARM Linux @ 2011-02-15 11:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTinL0HgSsFmoxyiBuRA6JiWKsHTLW4wFnVDJf_1w@mail.gmail.com>
On Fri, Feb 11, 2011 at 06:50:57PM -0800, Colin Cross wrote:
> > +ENDPROC(cpu_resume_turn_mmu_on)
> > +cpu_resume_after_mmu:
> > + ? ? ? str ? ? r5, [r2, r4, lsl #2] ? ?@ restore old mapping
> > +#ifdef MULTI_CACHE
> > + ? ? ? ldr ? ? r10, =cpu_cache
> > + ? ? ? ldr ? ? pc, [r10, #CACHE_FLUSH_KERN_ALL]
> > +#else
> > + ? ? ? b ? ? ? __cpuc_flush_kern_all
> > +#endif
I think we can eliminate this cache flush by delaying the cache enable
as below. Could you see whether Tegra 2 survives this please?
Thanks.
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index bed1876..193be5f 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -4,6 +4,7 @@
#include <asm/assembler.h>
#include <asm/glue-cache.h>
#include <asm/glue-proc.h>
+#include <asm/system.h>
.text
/*
@@ -81,25 +82,22 @@ ENTRY(cpu_resume_mmu)
str r3, [r2, r4, lsl #2] @ setup 1:1 mapping for mmu code
sub r2, r2, r1
ldr r3, =cpu_resume_after_mmu
+ bic r1, r0, #CR_C @ ensure D-cache is disabled
b cpu_resume_turn_mmu_on
ENDPROC(cpu_resume_mmu)
.ltorg
.align 5
cpu_resume_turn_mmu_on:
- mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, caches, etc
- mrc p15, 0, r0, c0, c0, 0 @ read id reg
- mov r0, r0
- mov r0, r0
+ mcr p15, 0, r1, c1, c0, 0 @ turn on MMU, I-cache, etc
+ mrc p15, 0, r1, c0, c0, 0 @ read id reg
+ mov r1, r1
+ mov r1, r1
mov pc, r3 @ jump to virtual address
ENDPROC(cpu_resume_turn_mmu_on)
cpu_resume_after_mmu:
str r5, [r2, r4, lsl #2] @ restore old mapping
-#ifdef MULTI_CACHE
- ldr r10, =cpu_cache
- ldr pc, [r10, #CACHE_FLUSH_KERN_ALL]
-#else
- b __cpuc_flush_kern_all
-#endif
+ mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache
+ mov pc, lr
/*
* Note: Yes, part of the following code is located into the .data section.
^ permalink raw reply related
* [RFC PATCH 2/2] ARMv7: Invalidate the TLB before freeing page tables
From: Catalin Marinas @ 2011-02-15 11:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110215103127.GC4152@n2100.arm.linux.org.uk>
On Tue, 2011-02-15 at 10:31 +0000, Russell King - ARM Linux wrote:
> On Mon, Feb 14, 2011 at 05:39:58PM +0000, Catalin Marinas wrote:
> > Newer processors like Cortex-A15 may cache entries in the higher page
> > table levels. These cached entries are ASID-tagged and are invalidated
> > during normal TLB operations.
> >
> > When a level 2 (pte) page table is removed, the current code sequence
> > first clears the level 1 (pmd) entry, flushes the cache, frees the level
> > 2 table and then invalidates the TLB. Because of the caching of the
> > higher page table entries, the processor may speculatively create a TLB
> > entry after the level 2 page table has been freed but before the TLB
> > invalidation. If such speculative PTW accesses random data, it could
> > create a global TLB entry that gets used for subsequent user space
> > accesses.
> >
> > The patch ensures that the TLB is invalidated before the page table is
> > freed (pte_free_tlb). Since pte_free_tlb() does not get a vma structure,
> > the patch also introduces flush_tlb_user_page() which takes an mm_struct
> > rather than vma_struct. The original flush_tlb_page() is implemented as
> > a call to flush_tlb_user_page().
>
> We already have support for doing this, and Peter Zijlstra posted patches
> to convert ARM to use a generic implementation of the TLB shootdown code.
>
> http://marc.info/?l=linux-kernel&m=129604765010347&w=2
>
> Does this patch solve your problem?
I don't think it does. Peter's patch moves the ARM TLB support to the
generic one which is a good clean-up, however it doesn't look like
anything is invalidating the TLB entry between pmd_clear() and
pte_free(), only after. This is too late because we may speculatively
get a global TLB entry (which isn't invalidated by the ASID TLB
operations). So with Peter's patch we still have to implement
__pte_free_tlb().
An alternative would be that flush_tlb_page() flushes all the ASIDs for
the corresponding user address and this would include any speculatively
fetched global TLB entries.
--
Catalin
^ permalink raw reply
* [PATCH] ARM: S5PC210: add support for i2c PMICs on Universal_C210 board
From: Marek Szyprowski @ 2011-02-15 10:59 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds basic definitions for MAX8952 & LP3974 (MAX8998
compatible) PMICs for UniversalC210 board. Power consumers for the
device drivers will be added later. These two PMICs occupy I2C5 bus.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pv310/Kconfig | 2 +
arch/arm/mach-s5pv310/mach-universal_c210.c | 443 +++++++++++++++++++++++++++
2 files changed, 445 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
index b2a9acc..a8b0425 100644
--- a/arch/arm/mach-s5pv310/Kconfig
+++ b/arch/arm/mach-s5pv310/Kconfig
@@ -102,7 +102,9 @@ config MACH_UNIVERSAL_C210
select S3C_DEV_HSMMC3
select S5PV310_SETUP_SDHCI
select S3C_DEV_I2C1
+ select S3C_DEV_I2C5
select S5PV310_SETUP_I2C1
+ select S5PV310_SETUP_I2C5
help
Machine support for Samsung Mobile Universal S5PC210 Reference
Board. S5PC210(MCP) is one of package option of S5PV310
diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c
index 36bc3cf..cad55d3 100644
--- a/arch/arm/mach-s5pv310/mach-universal_c210.c
+++ b/arch/arm/mach-s5pv310/mach-universal_c210.c
@@ -27,6 +27,13 @@
#include <plat/sdhci.h>
#include <mach/map.h>
+#include <mach/gpio.h>
+
+#include <linux/i2c.h>
+#include <plat/iic.h>
+
+#include <linux/regulator/max8952.h>
+#include <linux/mfd/max8998.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define UNIVERSAL_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -69,6 +76,438 @@ static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
},
};
+static struct regulator_consumer_supply max8952_consumer =
+ REGULATOR_SUPPLY("vddarm", NULL);
+
+static struct max8952_platform_data universal_max8952_pdata __initdata = {
+ .gpio_vid0 = S5PV310_GPX0(3),
+ .gpio_vid1 = S5PV310_GPX0(4),
+ .gpio_en = -1, /* Not controllable, set "Always High" */
+ .default_mode = 0, /* vid0 = 0, vid1 = 0 */
+ .dvs_mode = { 48, 32, 28, 18 }, /* 1.25, 1.20, 1.05, 0.95V */
+ .sync_freq = 0, /* default: fastest */
+ .ramp_speed = 0, /* default: fastest */
+
+ .reg_data = {
+ .constraints = {
+ .name = "VARM_1.2V",
+ .min_uV = 770000,
+ .max_uV = 1400000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &max8952_consumer,
+ },
+};
+
+static struct regulator_consumer_supply lp3974_buck1_consumer =
+ REGULATOR_SUPPLY("vddint", NULL);
+
+static struct regulator_consumer_supply lp3974_buck2_consumer =
+ REGULATOR_SUPPLY("vddg3d", NULL);
+
+static struct regulator_init_data lp3974_buck1_data = {
+ .constraints = {
+ .name = "VINT_1.1V",
+ .min_uV = 750000,
+ .max_uV = 1500000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &lp3974_buck1_consumer,
+};
+
+static struct regulator_init_data lp3974_buck2_data = {
+ .constraints = {
+ .name = "VG3D_1.1V",
+ .min_uV = 750000,
+ .max_uV = 1500000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &lp3974_buck2_consumer,
+};
+
+static struct regulator_init_data lp3974_buck3_data = {
+ .constraints = {
+ .name = "VCC_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ .disabled = 0,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_buck4_data = {
+ .constraints = {
+ .name = "VMEM_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo2_data = {
+ .constraints = {
+ .name = "VALIVE_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ .disabled = 0,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo3_data = {
+ .constraints = {
+ .name = "VUSB+MIPI_1.1V",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo4_data = {
+ .constraints = {
+ .name = "VADC_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo5_data = {
+ .constraints = {
+ .name = "VTF_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo6_data = {
+ .constraints = {
+ .name = "LDO6",
+ .min_uV = 2000000,
+ .max_uV = 2000000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 0,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo7_data = {
+ .constraints = {
+ .name = "VLCD+VMIPI_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo8_data = {
+ .constraints = {
+ .name = "VUSB+VDAC_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo9_data = {
+ .constraints = {
+ .name = "VCC_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ .disabled = 0,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo10_data = {
+ .constraints = {
+ .name = "VPLL_1.1V",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .boot_on = 1,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo11_data = {
+ .constraints = {
+ .name = "CAM_AF_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo12_data = {
+ .constraints = {
+ .name = "PS_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo13_data = {
+ .constraints = {
+ .name = "VHIC_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo14_data = {
+ .constraints = {
+ .name = "CAM_I_HOST_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo15_data = {
+ .constraints = {
+ .name = "CAM_S_DIG+FM33_CORE_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo16_data = {
+ .constraints = {
+ .name = "CAM_S_ANA_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_ldo17_data = {
+ .constraints = {
+ .name = "VCC_3.0V_LCD",
+ .min_uV = 3000000,
+ .max_uV = 3000000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_32khz_ap_data = {
+ .constraints = {
+ .name = "32KHz AP",
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ .disabled = 0,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_32khz_cp_data = {
+ .constraints = {
+ .name = "32KHz CP",
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_vichg_data = {
+ .constraints = {
+ .name = "VICHG",
+ .state_mem = {
+ .enabled = 0,
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_esafeout1_data = {
+ .constraints = {
+ .name = "SAFEOUT1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 1,
+ .disabled = 0,
+ },
+ },
+};
+
+static struct regulator_init_data lp3974_esafeout2_data = {
+ .constraints = {
+ .name = "SAFEOUT2",
+ .boot_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .enabled = 1,
+ .disabled = 0,
+ },
+ },
+};
+
+static struct max8998_regulator_data lp3974_regulators[] = {
+ { MAX8998_LDO2, &lp3974_ldo2_data },
+ { MAX8998_LDO3, &lp3974_ldo3_data },
+ { MAX8998_LDO4, &lp3974_ldo4_data },
+ { MAX8998_LDO5, &lp3974_ldo5_data },
+ { MAX8998_LDO6, &lp3974_ldo6_data },
+ { MAX8998_LDO7, &lp3974_ldo7_data },
+ { MAX8998_LDO8, &lp3974_ldo8_data },
+ { MAX8998_LDO9, &lp3974_ldo9_data },
+ { MAX8998_LDO10, &lp3974_ldo10_data },
+ { MAX8998_LDO11, &lp3974_ldo11_data },
+ { MAX8998_LDO12, &lp3974_ldo12_data },
+ { MAX8998_LDO13, &lp3974_ldo13_data },
+ { MAX8998_LDO14, &lp3974_ldo14_data },
+ { MAX8998_LDO15, &lp3974_ldo15_data },
+ { MAX8998_LDO16, &lp3974_ldo16_data },
+ { MAX8998_LDO17, &lp3974_ldo17_data },
+ { MAX8998_BUCK1, &lp3974_buck1_data },
+ { MAX8998_BUCK2, &lp3974_buck2_data },
+ { MAX8998_BUCK3, &lp3974_buck3_data },
+ { MAX8998_BUCK4, &lp3974_buck4_data },
+ { MAX8998_EN32KHZ_AP, &lp3974_32khz_ap_data },
+ { MAX8998_EN32KHZ_CP, &lp3974_32khz_cp_data },
+ { MAX8998_ENVICHG, &lp3974_vichg_data },
+ { MAX8998_ESAFEOUT1, &lp3974_esafeout1_data },
+ { MAX8998_ESAFEOUT2, &lp3974_esafeout2_data },
+};
+
+static struct max8998_platform_data universal_lp3974_pdata = {
+ .num_regulators = ARRAY_SIZE(lp3974_regulators),
+ .regulators = lp3974_regulators,
+ .buck1_voltage1 = 1100000, /* INT */
+ .buck1_voltage2 = 1000000,
+ .buck1_voltage3 = 1100000,
+ .buck1_voltage4 = 1000000,
+ .buck1_set1 = S5PV310_GPX0(5),
+ .buck1_set2 = S5PV310_GPX0(6),
+ .buck2_voltage1 = 1200000, /* G3D */
+ .buck2_voltage2 = 1100000,
+ .buck1_default_idx = 0,
+ .buck2_set3 = S5PV310_GPE2(0),
+ .buck2_default_idx = 0,
+ .wakeup = true,
+};
+
+/* GPIO I2C 5 (PMIC) */
+static struct i2c_board_info i2c_devs5[] __initdata = {
+ {
+ I2C_BOARD_INFO("max8952", 0xC0 >> 1),
+ .platform_data = &universal_max8952_pdata,
+ }, {
+ I2C_BOARD_INFO("lp3974", 0xCC >> 1),
+ .platform_data = &universal_lp3974_pdata,
+ },
+};
+
+/* GPIO KEYS */
static struct gpio_keys_button universal_gpio_keys_tables[] = {
{
.code = KEY_VOLUMEUP,
@@ -206,6 +645,7 @@ static struct platform_device *universal_devices[] __initdata = {
/* Universal Devices */
&universal_gpio_keys,
+ &s3c_device_i2c5,
&s5p_device_onenand,
};
@@ -223,6 +663,9 @@ static void __init universal_machine_init(void)
i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+ s3c_i2c5_set_platdata(NULL);
+ i2c_register_board_info(5, i2c_devs5, ARRAY_SIZE(i2c_devs5));
+
/* Last */
platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
}
--
1.7.1.569.g6f426
^ permalink raw reply related
* [PATCH 2/2] omap3: flash: use pr_err instead of printk
From: Sanjeev Premi @ 2011-02-15 10:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297767452-22554-1-git-send-email-premi@ti.com>
Change all occurences of printf() to pr_err().
Includes minor formatting changes as result of
this change.
Signed-off-by: Sanjeev Premi <premi@ti.com>
---
arch/arm/mach-omap2/board-flash.c | 15 ++++++---------
1 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index ce61200..86d1020 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -73,11 +73,11 @@ __init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+ FLASH_SIZE_SDPV1 - 1;
}
if (err < 0) {
- printk(KERN_ERR "NOR: Can't request GPMC CS\n");
+ pr_err("NOR: Can't request GPMC CS\n");
return;
}
if (platform_device_register(&board_nor_device) < 0)
- printk(KERN_ERR "Unable to register NOR device\n");
+ pr_err("Unable to register NOR device\n");
}
#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
@@ -208,7 +208,7 @@ void board_flash_init(struct flash_partitions partition_info[],
*/
idx = get_gpmc0_type();
if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
- printk(KERN_ERR "%s: Invalid chip select: %d\n", __func__, cs);
+ pr_err("%s: Invalid chip select: %d\n", __func__, cs);
return;
}
config_sel = (unsigned char *)(chip_sel_board[idx]);
@@ -232,22 +232,19 @@ void board_flash_init(struct flash_partitions partition_info[],
}
if (norcs > GPMC_CS_NUM)
- printk(KERN_INFO "NOR: Unable to find configuration "
- "in GPMC\n");
+ pr_err("NOR: Unable to find configuration in GPMC\n");
else
board_nor_init(partition_info[0].parts,
partition_info[0].nr_parts, norcs);
if (onenandcs > GPMC_CS_NUM)
- printk(KERN_INFO "OneNAND: Unable to find configuration "
- "in GPMC\n");
+ pr_err("OneNAND: Unable to find configuration in GPMC\n");
else
board_onenand_init(partition_info[1].parts,
partition_info[1].nr_parts, onenandcs);
if (nandcs > GPMC_CS_NUM)
- printk(KERN_INFO "NAND: Unable to find configuration "
- "in GPMC\n");
+ pr_err("NAND: Unable to find configuration in GPMC\n");
else
board_nand_init(partition_info[2].parts,
partition_info[2].nr_parts, nandcs);
--
1.7.2.2
^ permalink raw reply related
* [PATCH 1/2] omap3: fix minor typos
From: Sanjeev Premi @ 2011-02-15 10:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297767452-22554-1-git-send-email-premi@ti.com>
This patch fixes typos that were remaining after
the file and functions were renamed.
Signed-off-by: Sanjeev Premi <premi@ti.com>
---
arch/arm/mach-omap2/board-flash.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index fd38c05..ce61200 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -1,5 +1,5 @@
/*
- * board-sdp-flash.c
+ * board-flash.c
* Modified from mach-omap2/board-3430sdp-flash.c
*
* Copyright (C) 2009 Nokia Corporation
@@ -189,7 +189,7 @@ unmap:
}
/**
- * sdp3430_flash_init - Identify devices connected to GPMC and register.
+ * board_flash_init - Identify devices connected to GPMC and register.
*
* @return - void.
*/
--
1.7.2.2
^ permalink raw reply related
* [PATCH 0/2] omap3: minor clean-up in flash related code
From: Sanjeev Premi @ 2011-02-15 10:57 UTC (permalink / raw)
To: linux-arm-kernel
Changes include:
- fixing typos
- using pr_err() instead of printk
Sanjeev Premi (2):
omap3: fix minor typos
omap3: flash: use pr_err instead of printk
arch/arm/mach-omap2/board-flash.c | 19 ++++++++-----------
1 files changed, 8 insertions(+), 11 deletions(-)
--
1.7.2.2
^ permalink raw reply
* [PATCH 2/6] ARM: pm: add generic CPU suspend/resume support
From: Russell King - ARM Linux @ 2011-02-15 10:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTi=JF1c-aFHpSZ-XECLEPSMsFihXT+w3=NXdYn8L@mail.gmail.com>
On Mon, Feb 14, 2011 at 08:11:23PM -0800, Colin Cross wrote:
> Even with a cache flush, cpu_resume_turn_on_mmu fails because the page
> table modification, done with the cache off, ends up in memory, but
> the L2 contains the old value. When the MMU and cache are enabled,
> the 1:1 mapping disappears. The page table would need to be
> invalidated during suspend.
>
> I can avoid the problem entirely by leaving the MMU on and skipping
> cpu_resume when the CPU does not go through reset.
If you're not losing CPU state, what's the point in calling the suspend
function? It's purpose is to save CPU state ready for the CPU going to
sleep and losing power, and restoring that state when the CPU wakes up
sometime later.
^ permalink raw reply
* [PATCH v4 0/5] ARM: omap[34]: Thumb-2 compatibility fixes
From: Dave Martin @ 2011-02-15 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87zkpyxl64.fsf@ti.com>
On Mon, Feb 14, 2011 at 11:15 PM, Kevin Hilman <khilman@ti.com> wrote:
> Hi Dave,
>
> Dave Martin <dave.martin@linaro.org> writes:
>
>> On Mon, Feb 14, 2011 at 10:00:23AM -0500, Nicolas Pitre wrote:
>>> On Mon, 14 Feb 2011, Dave Martin wrote:
>>>
>>> > @@ -289,8 +297,20 @@ clean_l2:
>>> > ? ? * ?- should be faster and will change with kernel
>>> > ? ? * ?- 'might' have to copy address, load and jump to it
>>> > ? ? */
>>> > +#ifdef CONFIG_THUMB2_KERNEL
>>> > + ?/* kernel is non-interworking : must do this from Thumb */
>>> > + ?adr ? ? r1, . + 1
>>> > + ?bx ? ? ?r1
>>> > + ?.thumb
>>> > +#endif
>>> > ? ?ldr ? ? r1, kernel_flush
>>>
>>> Didn't you mean this instead:
>>>
>>> ? ? ?/* kernel is non-interworking : must do this from Thumb */
>>> ? ? ?adr ? ? r1, 1f + 1
>>> ? ? ?bx ? ? ?r1
>>> ? ? ?.thumb
>>> 1: ? ldr ? ? r1, kernel_flush
>>> ? ? ?...
>>
>> Note that this is intended as an experimental hack, not a real patch
>> (apologies if I didn't make that clear...)
>>
>> Well, actually I meant "add r1, pc, #1" ... which means I was too
>> busy trying to be clever... oops!
>>
>> That is of course exactly equivalent to your code...
>>
>>>
>>> ?
>>>
>>> > ? ?blx ? ? r1
>>> > +#ifdef CONFIG_THUMB2_KERNEL
>>> > + ?.align
>>> > + ?bx ? ? ?pc
>>> > + ?nop
>>> > + ?.arm
>>>
>>> Also here, the .align has the potential to introduce a zero halfword in
>>> the instruction stream before the bx. ?What about:
>>>
>>> ? ? ?adr ? ? r3, 1f
>>> ? ? ?bx ? ? ?r3
>>> ? ? ?.align
>>> ? ? ?.arm
>>> 1: ? ...
>>
>> .align inserts a 16-bit nop when misaligned in Thumb in a text section,
>> and a word-aligned bx pc is a specific architecturally allowed way
>> to do an inline switch to ARM. ?The linker uses this trick for PLT
>> veneers etc.
>>
>> A nicer fix for doing this sort of call from low-level code which
>> might be ARM is to convert arch/arm/mm/*-v7.S to use "bx lr" to return.
>>
>> Generally, we can do this for all arches >= v5, without any
>> incompatibility. ?However, since the need for it will be rare and it
>> will generate patch noise for not much real benefit,
>> I haven't proposed this.
>>
>> Updated patch below.
>
> I tested the updated patch on top of your "dirty" branch I tested with
> last week, and now see off-mode working just fine.
Thanks for testing-- that's great news.
I will have a think about whether the patch can be tidied up to revert
most of the code back to Thumb, though that isn't essential. If I've
understood what's going on correctly, I think only the restore entry
points, SMC call sites and the entry to omap3_sram_configure_core_dpll
could need to be ARM; the rest shouldn't really make any difference...
Cheers
---Dave
^ permalink raw reply
* [PATCH] Ensure predictable endian state on signal handler entry
From: Dave Martin @ 2011-02-15 10:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110214200222.GD31103@n2100.arm.linux.org.uk>
On Mon, Feb 14, 2011 at 08:02:22PM +0000, Russell King - ARM Linux wrote:
> Ensure a predictable endian state when entering signal handlers. This
> avoids programs which use SETEND to momentarily switch their endian
> state from having their signal handlers entered with an unpredictable
> endian state.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> --
>
> arch/arm/kernel/signal.c | 4 +++-
> 1 files changed, 3 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
> index 907d5a6..abaf844 100644
> --- a/arch/arm/kernel/signal.c
> +++ b/arch/arm/kernel/signal.c
> @@ -474,7 +474,9 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
> unsigned long handler = (unsigned long)ka->sa.sa_handler;
> unsigned long retcode;
> int thumb = 0;
> - unsigned long cpsr = regs->ARM_cpsr & ~PSR_f;
> + unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
> +
> + cpsr |= PSR_ENDSTATE;
>
> /*
> * Maybe we need to deliver a 32-bit signal to a 26-bit task.
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Looks sensible to me.
Acked-by: Dave Martin <dave.martin@linaro.org>
Only tested it with little-endian, but it's enough to make my silly
test program not segfault. (Without your patch, it definitely does...)
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
static void handler(int n)
{
unsigned long cpsr;
#define FORMAT "handler: CPSR = 0x%08lX\n"
char buf[sizeof FORMAT - 5 + 8];
asm ("mrs %0, CPSR" : "=r" (cpsr));
snprintf(buf, sizeof buf, FORMAT, cpsr);
write(STDOUT_FILENO, buf, strlen(buf));
}
int main(void)
{
signal(SIGINT, handler);
asm volatile (
"0: setend be\n\t"
" b 0b"
);
}
Cheers
---Dave
^ permalink raw reply
* [RFC PATCH 2/2] ARMv7: Invalidate the TLB before freeing page tables
From: Russell King - ARM Linux @ 2011-02-15 10:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110214173958.21717.30746.stgit@e102109-lin.cambridge.arm.com>
On Mon, Feb 14, 2011 at 05:39:58PM +0000, Catalin Marinas wrote:
> Newer processors like Cortex-A15 may cache entries in the higher page
> table levels. These cached entries are ASID-tagged and are invalidated
> during normal TLB operations.
>
> When a level 2 (pte) page table is removed, the current code sequence
> first clears the level 1 (pmd) entry, flushes the cache, frees the level
> 2 table and then invalidates the TLB. Because of the caching of the
> higher page table entries, the processor may speculatively create a TLB
> entry after the level 2 page table has been freed but before the TLB
> invalidation. If such speculative PTW accesses random data, it could
> create a global TLB entry that gets used for subsequent user space
> accesses.
>
> The patch ensures that the TLB is invalidated before the page table is
> freed (pte_free_tlb). Since pte_free_tlb() does not get a vma structure,
> the patch also introduces flush_tlb_user_page() which takes an mm_struct
> rather than vma_struct. The original flush_tlb_page() is implemented as
> a call to flush_tlb_user_page().
We already have support for doing this, and Peter Zijlstra posted patches
to convert ARM to use a generic implementation of the TLB shootdown code.
http://marc.info/?l=linux-kernel&m=129604765010347&w=2
Does this patch solve your problem?
^ permalink raw reply
* [PATCH v2] ARM: S5PV210: Add GONI board setup for CIF camera support
From: Kukjin Kim @ 2011-02-15 10:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D5A3F31.1070106@samsung.com>
Sylwester Nawrocki wrote:
>
> Hi Kukjin,
>
Hi :)
> > Hmm...looks you don't want to follow my suggestion on 2nd patch.
>
> I've attempted to make a change as you suggested but it turned out
> that all regulators I'm adding supplies for in the second patch are
> also used by the other, high resolution camera. It's not about I don't
> want to follow you suggestions. The argument is that I's like to add
shortly
> support for the other camera and then the patch would be just one line
> per a power supply rather than 4. I really don't mind to adhere to your
> preferred style. But in this case it would be just more work to revert
> things back and forth.
>
Ok, I see, no problem.
> I've boot tested your patch:
> ARM: S5PV210: Use REGULATOR_SUPPLY macro for regulator consumers
> on Aquila and GONI board altogether with my changeset.
>
Thanks :)
> >
> > I'm still wondering why array is needed for just one member in
> > regulator_consumer_supply structure now even though other something will
be
> > added later.
> >
> > Nevertheless will apply your 3 patches but if not required array will be
> > removed later.
>
> Thanks! I am going to post further patches for this board soon so there
> should be no need to change anything. Please use you time for more
important
> things ;)
>
Hehehe, ok and don't worry ;)
> I've noticed one issue with the first patch, i.e. Kyungmin's email address
> is broken. Should I resend the patch or could you please correct this on
your
> side?
>
Oops, ok. I fixed it.
As a note, I received request about common phy control from Marek. So I will
re-think with your mini phy patches, then let you know about that soon.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH] ARM: PXA: Make PXA27x/PXA3xx overlay actually work
From: Russell King - ARM Linux @ 2011-02-15 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTi=AfxN73pSNZ5RiTiTWfxR7PhcyJUyXzzeaYNWw@mail.gmail.com>
On Tue, Feb 15, 2011 at 03:35:44PM +0800, Eric Miao wrote:
> > @@ -720,12 +726,10 @@ static int overlayfb_open(struct fb_info *info, int user)
> > ? ? ? ?if (user == 0)
> > ? ? ? ? ? ? ? ?return -ENODEV;
> >
> > - ? ? ? /* allow only one user at a time */
> > - ? ? ? if (atomic_inc_and_test(&ofb->usage))
> > - ? ? ? ? ? ? ? return -EBUSY;
> > + ? ? ? if (ofb->usage++ == 0)
> > + ? ? ? ? ? ? ? /* unblank the base framebuffer */
> > + ? ? ? ? ? ? ? fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
>
> The change above allows multiple user at a time? Then I guess
> some other places need to be changed accordingly to avoid the
> racing conditions.
You can't prevent multiple users. Think threaded applications which
share the same set of fds.
Any driver which tries to do so by restricting the number of open()s is
simply buggy.
^ permalink raw reply
* [PATCH V6 13/63] ST SPEAr: Updating Clock Support
From: Viresh Kumar @ 2011-02-15 9:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1297763160.git.viresh.kumar@st.com>
- Adding support for divisor per parent clock
- Adding ENABLED_ON_INIT feature in clk
- Adding clk_set_rate, round_rate_index & clk_round_rate
- Simplified clk_recalc functions
- Added/updating clock definitions
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: shiraz hashim <shiraz.hashim@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
---
arch/arm/mach-spear13xx/clock.c | 621 ++++++++++++++++++-
arch/arm/mach-spear13xx/include/mach/misc_regs.h | 101 ++--
arch/arm/mach-spear3xx/clock.c | 431 +++++++++++--
arch/arm/mach-spear3xx/include/mach/misc_regs.h | 5 +-
arch/arm/mach-spear6xx/clock.c | 331 ++++++++---
arch/arm/mach-spear6xx/include/mach/misc_regs.h | 5 +-
arch/arm/plat-spear/clock.c | 705 +++++++++++++++++-----
arch/arm/plat-spear/include/plat/clock.h | 94 +++-
8 files changed, 1918 insertions(+), 375 deletions(-)
diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index 722f634..c39389e 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c
@@ -53,10 +53,10 @@ static struct clk rtc_clk = {
static struct pclk_info pll_pclk_info[] = {
{
.pclk = &osc1_24m_clk,
- .pclk_mask = OSC_24M_MASK,
+ .pclk_val = OSC_24M_VAL,
}, {
.pclk = &osc3_25m_clk,
- .pclk_mask = OSC_25M_MASK,
+ .pclk_val = OSC_25M_VAL,
},
};
@@ -88,16 +88,45 @@ static struct pll_clk_config pll1_config = {
.masks = &pll_masks,
};
+/* pll rate configuration table, in ascending order of rates */
+struct pll_rate_tbl pll_rtbl[] = {
+ /* PCLK 24MHz */
+ {.mode = 0, .m = 0x7D, .n = 0x03, .p = 0x2}, /* 500 MHz */
+ {.mode = 0, .m = 0xA6, .n = 0x03, .p = 0x2}, /* 664 MHz */
+ {.mode = 0, .m = 0xC8, .n = 0x03, .p = 0x2}, /* 800 MHz */
+ {.mode = 0, .m = 0xFA, .n = 0x06, .p = 0x1}, /* 1000 MHz */
+};
+
/* pll1 clock */
static struct clk pll1_clk = {
+ .flags = ENABLED_ON_INIT,
.pclk_sel = &pll_pclk_sel,
.pclk_sel_shift = PLL1_CLK_SHIFT,
.en_reg = PLL1_CTR,
.en_reg_bit = PLL_ENABLE,
+ .calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
+ .set_rate = &pll_clk_set_rate,
+ .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 3},
.private_data = &pll1_config,
};
+/* pll1div2 clock */
+static struct clk pll1div2_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &pll1_clk,
+ .div_factor = 2,
+ .recalc = &follow_parent,
+};
+
+/* pll1div4 clock */
+static struct clk pll1div4_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &pll1_clk,
+ .div_factor = 4,
+ .recalc = &follow_parent,
+};
+
/* pll2 configuration structure */
static struct pll_clk_config pll2_config = {
.mode_reg = PLL2_CTR,
@@ -111,7 +140,10 @@ static struct clk pll2_clk = {
.pclk_sel_shift = PLL2_CLK_SHIFT,
.en_reg = PLL2_CTR,
.en_reg_bit = PLL_ENABLE,
+ .calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
+ .set_rate = &pll_clk_set_rate,
+ .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 3},
.private_data = &pll2_config,
};
@@ -128,7 +160,10 @@ static struct clk pll3_clk = {
.pclk_sel_shift = PLL3_CLK_SHIFT,
.en_reg = PLL3_CTR,
.en_reg_bit = PLL_ENABLE,
+ .calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
+ .set_rate = &pll_clk_set_rate,
+ .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 3},
.private_data = &pll3_config,
};
@@ -139,12 +174,24 @@ static struct pll_clk_config pll4_config = {
.masks = &pll_masks,
};
+/* pll4 rate configuration table, in ascending order of rates */
+struct pll_rate_tbl pll4_rtbl[] = {
+ {.mode = 0, .m = 0x7D, .n = 0x03, .p = 0x2}, /* 500 MHz */
+ {.mode = 0, .m = 0xA6, .n = 0x03, .p = 0x2}, /* 664 MHz */
+ {.mode = 0, .m = 0xC8, .n = 0x03, .p = 0x2}, /* 800 MHz */
+ {.mode = 0, .m = 0xFA, .n = 0x06, .p = 0x1}, /* 1000 MHz */
+};
+
/* pll4 (DDR) clock */
static struct clk pll4_clk = {
+ .flags = ENABLED_ON_INIT,
.pclk = &osc1_24m_clk,
.en_reg = PLL4_CTR,
.en_reg_bit = PLL_ENABLE,
+ .calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
+ .set_rate = &pll_clk_set_rate,
+ .rate_config = {pll4_rtbl, ARRAY_SIZE(pll4_rtbl), 3},
.private_data = &pll4_config,
};
@@ -192,10 +239,10 @@ static struct clk apb_clk = {
static struct pclk_info gpt_pclk_info[] = {
{
.pclk = &osc1_24m_clk,
- .pclk_mask = GPT_OSC24_MASK,
+ .pclk_val = GPT_OSC24_VAL,
}, {
.pclk = &apb_clk,
- .pclk_mask = GPT_APB_MASK,
+ .pclk_val = GPT_APB_VAL,
},
};
@@ -246,15 +293,8 @@ static struct clk gpt3_clk = {
/* watch dog timer clock */
static struct clk wdt_clk = {
.flags = ALWAYS_ENABLED,
- .pclk = &apb_clk,
- .recalc = &follow_parent,
-};
-
-/* smi clock */
-static struct clk smi_clk = {
- .pclk = &ahb_clk,
- .en_reg = PERIP1_CLK_ENB,
- .en_reg_bit = SMI_CLK_ENB,
+ .pclk = &cpu_clk,
+ .div_factor = 2,
.recalc = &follow_parent,
};
@@ -270,22 +310,42 @@ static struct aux_clk_masks aux_masks = {
.yscale_sel_shift = AUX_YSCALE_SHIFT,
};
+/* clocks derived multiple parents (pll1, pll5, synthesizers or others) */
/* uart configurations */
-static struct aux_clk_config uart_config = {
+static struct aux_clk_config uart_synth_config = {
.synth_reg = UART_CLK_SYNT,
.masks = &aux_masks,
};
-/* clocks derived from pll1 or pll5 */
+/* aux rate configuration table, in ascending order of rates */
+struct aux_rate_tbl aux_rtbl[] = {
+ /* For PLL1div2 = 500 MHz */
+ {.xscale = 1, .yscale = 6, .eq = 1}, /* 83 MHz */
+ {.xscale = 1, .yscale = 4, .eq = 1}, /* 125 MHz */
+ {.xscale = 1, .yscale = 3, .eq = 1}, /* 166 MHz */
+ {.xscale = 1, .yscale = 2, .eq = 1}, /* 250 MHz */
+};
+
+/* uart synth clock */
+static struct clk uart_synth_clk = {
+ .en_reg = UART_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1div2_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 0},
+ .private_data = &uart_synth_config,
+};
+
/* uart parents */
static struct pclk_info uart_pclk_info[] = {
{
.pclk = &pll5_clk,
- .pclk_mask = AUX_CLK_PLL5_MASK,
+ .pclk_val = AUX_CLK_PLL5_VAL,
}, {
- .pclk = &pll1_clk,
- .pclk_mask = AUX_CLK_PLL1_MASK,
- .scalable = 1,
+ .pclk = &uart_synth_clk,
+ .pclk_val = AUX_CLK_SYNT_VAL,
},
};
@@ -303,10 +363,469 @@ static struct clk uart_clk = {
.en_reg_bit = UART_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
+ .recalc = &follow_parent,
+};
+
+/* sdhci configurations */
+static struct aux_clk_config sdhci_synth_config = {
+ .synth_reg = SDHCI_CLK_SYNT,
+ .masks = &aux_masks,
+};
+
+/* sdhci synth clock */
+static struct clk sdhci_synth_clk = {
+ .en_reg = SDHCI_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1div2_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+ .private_data = &sdhci_synth_config,
+};
+
+/* sdhci clock */
+static struct clk sdhci_clk = {
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = SDHCI_CLK_ENB,
+ .pclk = &sdhci_synth_clk,
+ .recalc = &follow_parent,
+};
+
+/* cfxd configurations */
+static struct aux_clk_config cfxd_synth_config = {
+ .synth_reg = CFXD_CLK_SYNT,
+ .masks = &aux_masks,
+};
+
+/* cfxd synth clock */
+static struct clk cfxd_synth_clk = {
+ .en_reg = CFXD_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1div2_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+ .private_data = &cfxd_synth_config,
+};
+
+/* cfxd clock */
+static struct clk cfxd_clk = {
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = CFXD_CLK_ENB,
+ .pclk = &cfxd_synth_clk,
+ .recalc = &follow_parent,
+};
+
+/* C3 clk configurations */
+static struct aux_clk_config c3_synth_config = {
+ .synth_reg = C3_CLK_SYNT,
+ .masks = &aux_masks,
+};
+
+/* c3 synth clock */
+static struct clk c3_synth_clk = {
+ .en_reg = C3_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1div2_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 0},
+ .private_data = &c3_synth_config,
+};
+
+/* c3 parents */
+static struct pclk_info c3_pclk_info[] = {
+ {
+ .pclk = &pll5_clk,
+ .pclk_val = AUX_CLK_PLL5_VAL,
+ }, {
+ .pclk = &c3_synth_clk,
+ .pclk_val = AUX_CLK_SYNT_VAL,
+ },
+};
+
+/* c3 parent select structure */
+static struct pclk_sel c3_pclk_sel = {
+ .pclk_info = c3_pclk_info,
+ .pclk_count = ARRAY_SIZE(c3_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = C3_CLK_MASK,
+};
+
+/* c3 clock */
+static struct clk c3_clk = {
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = C3_CLK_ENB,
+ .pclk_sel = &c3_pclk_sel,
+ .pclk_sel_shift = C3_CLK_SHIFT,
+ .recalc = &follow_parent,
+};
+
+/* gmac phy clk configurations */
+static struct aux_clk_config gmac_phy_synth_config = {
+ .synth_reg = GMAC_CLK_SYNT,
+ .masks = &aux_masks,
+};
+
+/* gmii external pad clock for phy operation */
+static struct clk gmii_txclk125_pad = {
+ .flags = ALWAYS_ENABLED,
+ .rate = 125000000,
+};
+
+/* gmac phy set of input clks*/
+static struct pclk_info gmac_phy_input_pclk_info[] = {
+ {
+ .pclk = &gmii_txclk125_pad,
+ .pclk_val = GMAC_PHY_PAD_VAL,
+ }, {
+ .pclk = &pll2_clk,
+ .pclk_val = GMAC_PHY_PLL2_VAL,
+ }, {
+ .pclk = &osc3_25m_clk,
+ .pclk_val = GMAC_PHY_OSC3_VAL,
+ },
+};
+
+static struct pclk_sel gmac_phy_input_pclk_sel = {
+ .pclk_info = gmac_phy_input_pclk_info,
+ .pclk_count = ARRAY_SIZE(gmac_phy_input_pclk_info),
+ .pclk_sel_reg = GMAC_CLK_CFG,
+ .pclk_sel_mask = GMAC_PHY_INPUT_CLK_MASK,
+};
+
+static struct clk gmac_phy_input_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk_sel = &gmac_phy_input_pclk_sel,
+ .pclk_sel_shift = GMAC_PHY_INPUT_CLK_SHIFT,
+ .recalc = &follow_parent,
+};
+
+/* gmac rate configuration table, in ascending order of rates */
+struct aux_rate_tbl gmac_rtbl[] = {
+ /* For gmac phy input clk */
+ {.xscale = 1, .yscale = 6, .eq = 1}, /* divided by 6 */
+ {.xscale = 1, .yscale = 4, .eq = 1}, /* divided by 4 */
+ {.xscale = 1, .yscale = 3, .eq = 1}, /* divided by 3 */
+ {.xscale = 1, .yscale = 2, .eq = 1}, /* divided by 2 */
+};
+
+static struct clk gmac_phy_synth_clk = {
+ .en_reg = GMAC_CLK_CFG,
+ .en_reg_bit = GMAC_PHY_SYNT_ENB,
+ .pclk = &gmac_phy_input_clk,
+ .calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
- .private_data = &uart_config,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {gmac_rtbl, ARRAY_SIZE(gmac_rtbl), 0},
+ .private_data = &gmac_phy_synth_config,
+};
+
+/* gmac phy parents */
+static struct pclk_info gmac_phy_pclk_info[] = {
+ {
+ .pclk = &gmac_phy_input_clk,
+ .pclk_val = 0,
+ }, {
+ .pclk = &gmac_phy_synth_clk,
+ .pclk_val = 1,
+ }
+};
+
+/* gmac phy parent select structure */
+static struct pclk_sel gmac_phy_pclk_sel = {
+ .pclk_info = gmac_phy_pclk_info,
+ .pclk_count = ARRAY_SIZE(gmac_phy_pclk_info),
+ .pclk_sel_reg = GMAC_CLK_CFG,
+ .pclk_sel_mask = GMAC_PHY_CLK_MASK,
+};
+
+/* gmac phy clock */
+static struct clk gmac_phy_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk_sel = &gmac_phy_pclk_sel,
+ .pclk_sel_shift = GMAC_PHY_CLK_SHIFT,
+ .recalc = &follow_parent,
+};
+
+/* clcd synthesizers masks */
+static struct clcd_synth_masks clcd_masks = {
+ .div_factor_mask = CLCD_SYNT_DIV_FACTOR_MASK,
+ .div_factor_shift = CLCD_SYNT_DIV_FACTOR_SHIFT,
+};
+
+static struct clcd_clk_config clcd_synth_config = {
+ .synth_reg = CLCD_CLK_SYNT,
+ .masks = &clcd_masks,
+};
+
+/* clcd synth parents */
+static struct pclk_info clcd_synth_pclk_info[] = {
+ {
+ .pclk = &pll1div4_clk,
+ .pclk_val = CLCD_SYNT_PLL1_DIV4_VAL,
+ }, {
+ .pclk = &pll2_clk,
+ .pclk_val = CLCD_SYNT_PLL2_VAL,
+ },
+};
+
+/* clcd synth parent select structure */
+static struct pclk_sel clcd_synth_pclk_sel = {
+ .pclk_info = clcd_synth_pclk_info,
+ .pclk_count = ARRAY_SIZE(clcd_synth_pclk_info),
+ .pclk_sel_reg = PLL_CFG,
+ .pclk_sel_mask = CLCD_SYNT_CLK_MASK,
+};
+
+/* clcd rate configuration table, in ascending order of rates */
+struct clcd_rate_tbl clcd_rtbl[] = {
+ /* For pll1div4 = 250 MHz */
+ {.div = 0x4000}, /* 62.5 MHz */
+ {.div = 0x2000}, /* 125 MHz */
+};
+
+/* clcd synth clock */
+static struct clk clcd_synth_clk = {
+ .en_reg = CLCD_CLK_SYNT,
+ .en_reg_bit = CLCD_SYNT_ENB,
+ .pclk_sel = &clcd_synth_pclk_sel,
+ .pclk_sel_shift = CLCD_SYNT_CLK_SHIFT,
+ .calc_rate = &clcd_calc_rate,
+ .recalc = &clcd_clk_recalc,
+ .set_rate = &clcd_clk_set_rate,
+ .rate_config = {clcd_rtbl, ARRAY_SIZE(clcd_rtbl), 1},
+ .private_data = &clcd_synth_config,
+};
+
+/* clcd clock parents */
+static struct pclk_info clcd_pclk_info[] = {
+ {
+ .pclk = &pll5_clk,
+ .pclk_val = AUX_CLK_PLL5_VAL,
+ }, {
+ .pclk = &clcd_synth_clk,
+ .pclk_val = AUX_CLK_SYNT_VAL,
+ },
+};
+
+/* clcd parent select structure */
+static struct pclk_sel clcd_pclk_sel = {
+ .pclk_info = clcd_pclk_info,
+ .pclk_count = ARRAY_SIZE(clcd_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = CLCD_CLK_MASK,
+};
+
+/* clcd clock */
+static struct clk clcd_clk = {
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = CLCD_CLK_ENB,
+ .pclk_sel = &clcd_pclk_sel,
+ .pclk_sel_shift = CLCD_CLK_SHIFT,
+ .recalc = &follow_parent,
+};
+
+/* clock derived from ahb clk */
+
+/* i2c clock */
+static struct clk i2c_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = I2C_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* dma clock */
+static struct clk dma0_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = DMA0_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+static struct clk dma1_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = DMA1_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* jpeg clock */
+static struct clk jpeg_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = JPEG_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* gmac clock */
+static struct clk gmac_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = GMAC_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* fsmc clock */
+static struct clk fsmc_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = FSMC_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* smi clock */
+static struct clk smi_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = SMI_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* uhc0 clock */
+static struct clk uhci0_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = UHC0_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* uhc1 clock */
+static struct clk uhci1_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = UHC1_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* usbd clock */
+static struct clk usbd_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = USBD_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* pci clocks */
+static struct clk pcie0_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = PCIE0_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+static struct clk pcie1_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = PCIE1_CLK_ENB,
+ .recalc = &follow_parent,
};
+static struct clk pcie2_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = PCIE2_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* sysram clocks */
+static struct clk sysram0_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = SYSRAM0_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+static struct clk sysram1_clk = {
+ .pclk = &ahb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = SYSRAM1_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* clock derived from apb clk */
+/* adc clock */
+static struct clk adc_clk = {
+ .pclk = &apb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = ADC_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* ssp clock */
+static struct clk ssp_clk = {
+ .pclk = &apb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = SSP_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* gpio clock */
+static struct clk gpio0_clk = {
+ .pclk = &apb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = GPIO0_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* gpio clock */
+static struct clk gpio1_clk = {
+ .pclk = &apb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = GPIO1_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* i2s0 clock */
+static struct clk i2s0_clk = {
+ .pclk = &apb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = I2S0_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* i2s1 clock */
+static struct clk i2s1_clk = {
+ .pclk = &apb_clk,
+ .en_reg = PERIP1_CLK_ENB,
+ .en_reg_bit = I2S1_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* keyboard clock */
+static struct clk kbd_clk = {
+ .pclk = &apb_clk,
+ .en_reg = PERIP2_CLK_ENB,
+ .en_reg_bit = KBD_CLK_ENB,
+ .recalc = &follow_parent,
+};
+
+/* spear1300 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR1300
+
+#endif
+
+/* spear1310 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR1310
+/* can0 clock */
+static struct clk can0_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* can1 clock */
+static struct clk can1_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+#endif
+
/* array of all spear 13xx clock lookups */
static struct clk_lookup spear_clk_lookups[] = {
/* root clks */
@@ -315,7 +834,7 @@ static struct clk_lookup spear_clk_lookups[] = {
{.con_id = "osc3_25m_clk", .clk = &osc3_25m_clk},
/* clock derived from 32 KHz osc clk */
- {.dev_id = "rtc", .clk = &rtc_clk},
+ {.dev_id = "rtc-spear", .clk = &rtc_clk},
/* clock derived from 24/25 MHz osc1/osc3 clk */
{.con_id = "pll1_clk", .clk = &pll1_clk},
@@ -328,18 +847,68 @@ static struct clk_lookup spear_clk_lookups[] = {
/* clock derived from pll1 clk */
{.con_id = "cpu_clk", .clk = &cpu_clk},
{.con_id = "ahb_clk", .clk = &ahb_clk},
- { .con_id = "apb_clk", .clk = &apb_clk},
+ {.con_id = "apb_clk", .clk = &apb_clk},
+
+ /* synthesizers/prescaled clocks */
+ {.con_id = "pll1div2_clk", .clk = &pll1div2_clk},
+ {.con_id = "pll1div4_clk", .clk = &pll1div4_clk},
+ {.con_id = "c3_synth_clk", .clk = &c3_synth_clk},
+ {.con_id = "gmii_txclk123_pad_clk", .clk = &gmii_txclk125_pad},
+ {.con_id = "clcd_synth_clk", .clk = &clcd_synth_clk},
+ {.con_id = "uart_synth_clk", .clk = &uart_synth_clk},
+ {.con_id = "sdhci_synth_clk", .clk = &sdhci_synth_clk},
+ {.con_id = "cfxd_synth_clk", .clk = &cfxd_synth_clk},
+ {.con_id = "gmac_phy_input_clk", .clk = &gmac_phy_input_clk},
+ {.con_id = "gmac_phy_synth_clk", .clk = &gmac_phy_synth_clk},
+ {.con_id = "gmac_phy_clk", .clk = &gmac_phy_clk},
/* clocks having multiple parent source from above clocks */
- {.dev_id = "uart", .clk = &uart_clk},
+ {.dev_id = "clcd", .clk = &clcd_clk},
{.dev_id = "gpt0", .clk = &gpt0_clk},
{.dev_id = "gpt1", .clk = &gpt1_clk},
{.dev_id = "gpt2", .clk = &gpt2_clk},
{.dev_id = "gpt3", .clk = &gpt3_clk},
+ {.dev_id = "uart", .clk = &uart_clk},
- /* clock derived from ahb/apb clk */
- { .dev_id = "smi", .clk = &smi_clk},
- { .dev_id = "wdt", .clk = &wdt_clk},
+ /* clock derived from ahb clk */
+ {.dev_id = "smi", .clk = &smi_clk},
+ {.con_id = "usbh.0_clk", .clk = &uhci0_clk},
+ {.con_id = "usbh.1_clk", .clk = &uhci1_clk},
+ {.dev_id = "usbd", .clk = &usbd_clk},
+ {.dev_id = "i2c_designware.0", .clk = &i2c_clk},
+ {.dev_id = "dma0", .clk = &dma0_clk},
+ {.dev_id = "dma1", .clk = &dma1_clk},
+ {.dev_id = "jpeg", .clk = &jpeg_clk},
+ {.dev_id = "gmac", .clk = &gmac_clk},
+ {.dev_id = "c3", .clk = &c3_clk},
+ {.dev_id = "pcie0", .clk = &pcie0_clk},
+ {.dev_id = "pcie1", .clk = &pcie1_clk},
+ {.dev_id = "pcie2", .clk = &pcie2_clk},
+ {.dev_id = "cfxd", .clk = &cfxd_clk},
+ {.dev_id = "sdhci", .clk = &sdhci_clk},
+ {.con_id = "fsmc", .clk = &fsmc_clk},
+ {.dev_id = "sysram0", .clk = &sysram0_clk},
+ {.dev_id = "sysram1", .clk = &sysram1_clk},
+
+ /* clock derived from apb clk */
+ {.dev_id = "i2s0", .clk = &i2s0_clk},
+ {.dev_id = "i2s1", .clk = &i2s1_clk},
+ {.dev_id = "adc", .clk = &adc_clk},
+ {.dev_id = "ssp-pl022", .clk = &ssp_clk},
+ {.dev_id = "gpio0", .clk = &gpio0_clk},
+ {.dev_id = "gpio1", .clk = &gpio1_clk},
+ {.dev_id = "keyboard", .clk = &kbd_clk},
+ {.dev_id = "wdt", .clk = &wdt_clk},
+
+ /* spear1300 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR1300
+#endif
+
+ /* spear1310 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR1310
+ {.dev_id = "c_can_platform.0", .clk = &can0_clk},
+ {.dev_id = "c_can_platform.1", .clk = &can1_clk},
+#endif
};
void __init clk_init(void)
diff --git a/arch/arm/mach-spear13xx/include/mach/misc_regs.h b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
index 56ffa4e..0a9c86a 100644
--- a/arch/arm/mach-spear13xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
@@ -36,12 +36,16 @@
/* PLL related registers and bit values */
#define PLL_CFG (MISC_BASE + 0x210)
/* PLL_CFG bit values */
- #define OSC_24M_MASK 0
- #define OSC_25M_MASK 1
- #define PLL_CLK_MASK 3
- #define PLL1_CLK_SHIFT 20
- #define PLL2_CLK_SHIFT 22
- #define PLL3_CLK_SHIFT 24
+ #define OSC_24M_VAL 0
+ #define OSC_25M_VAL 1
+ #define PLL_CLK_MASK 3
+ #define PLL1_CLK_SHIFT 20
+ #define PLL2_CLK_SHIFT 22
+ #define PLL3_CLK_SHIFT 24
+ #define CLCD_SYNT_PLL1_DIV4_VAL 0
+ #define CLCD_SYNT_PLL2_VAL 1
+ #define CLCD_SYNT_CLK_MASK 1
+ #define CLCD_SYNT_CLK_SHIFT 31
#define PLL1_CTR (MISC_BASE + 0x214)
#define PLL1_FRQ (MISC_BASE + 0x218)
@@ -77,30 +81,53 @@
#define PERIP_CLK_CFG (MISC_BASE + 0x244)
/* PERIP_CLK_CFG bit values */
- #define GPT_OSC24_MASK 0
- #define GPT_APB_MASK 1
- #define GPT_CLK_MASK 1
- #define GPT0_CLK_SHIFT 8
- #define GPT1_CLK_SHIFT 9
- #define GPT2_CLK_SHIFT 12
- #define GPT3_CLK_SHIFT 13
- #define AUX_CLK_PLL1_MASK 1
- #define AUX_CLK_PLL5_MASK 0
+ #define GPT_OSC24_VAL 0
+ #define GPT_APB_VAL 1
+ #define GPT_CLK_MASK 1
+ #define GPT0_CLK_SHIFT 8
+ #define GPT1_CLK_SHIFT 9
+ #define GPT2_CLK_SHIFT 12
+ #define GPT3_CLK_SHIFT 13
+ #define AUX_CLK_PLL5_VAL 0
+ #define AUX_CLK_SYNT_VAL 1
#define UART_CLK_MASK 1
#define UART_CLK_SHIFT 4
+ #define CLCD_PLL5_VAL 0
+ #define CLCD_SYNT_MASK 1
+ #define CLCD_CLK_MASK 3
+ #define CLCD_CLK_SHIFT 2
+ #define C3_CLK_MASK 1
+ #define C3_CLK_SHIFT 1
#define GMAC_CLK_CFG (MISC_BASE + 0x248)
-#define C3_CLK_SYNTH (MISC_BASE + 0x24c)
+
+ #define GMAC_PHY_PAD_VAL 0
+ #define GMAC_PHY_PLL2_VAL 1
+ #define GMAC_PHY_OSC3_VAL 2
+ #define GMAC_PHY_INPUT_CLK_MASK 3
+ #define GMAC_PHY_INPUT_CLK_SHIFT 1
+ #define GMAC_PHY_SYNT_ENB 3
+ #define GMAC_PHY_CLK_MASK 1
+ #define GMAC_PHY_CLK_SHIFT 3
+ #define GMAC_PHY_SYNT_ENB_VAL 4
+
+#define C3_CLK_SYNT (MISC_BASE + 0x24c)
#define CLCD_CLK_SYNT (MISC_BASE + 0x250)
+ /* CLCD synth reg masks */
+ #define CLCD_SYNT_ENB 31
+ #define CLCD_SYNT_DIV_FACTOR_MASK 0x1ffff
+ #define CLCD_SYNT_DIV_FACTOR_SHIFT 0
+
#define UART_CLK_SYNT (MISC_BASE + 0x254)
#define GMAC_CLK_SYNT (MISC_BASE + 0x258)
-#define MCIF_SD_CLK_SYNT (MISC_BASE + 0x25c)
-#define MCIF_CFXD_CLK_SYNT (MISC_BASE + 0x260)
+#define SDHCI_CLK_SYNT (MISC_BASE + 0x25c)
+#define CFXD_CLK_SYNT (MISC_BASE + 0x260)
#define RAS_CLK_SYNT0 (MISC_BASE + 0x264)
#define RAS_CLK_SYNT1 (MISC_BASE + 0x268)
#define RAS_CLK_SYNT2 (MISC_BASE + 0x26c)
#define RAS_CLK_SYNT3 (MISC_BASE + 0x270)
/* aux clk synthesizer register masks */
+ #define AUX_SYNT_ENB 31
#define AUX_EQ_SEL_SHIFT 30
#define AUX_EQ_SEL_MASK 1
#define AUX_EQ1_SEL 0
@@ -114,32 +141,32 @@
/* PERIP1_CLK_ENB register masks */
#define BUS_CLK_ENB 0
#define SYSROM_CLK_ENB 1
- #define AORAM_CLK_ENB 2
- #define SYSRAM_CLK_ENB 3
+ #define SYSRAM1_CLK_ENB 2
+ #define SYSRAM0_CLK_ENB 3
#define FSMC_CLK_ENB 4
#define SMI_CLK_ENB 5
- #define SD_CLK_ENB 6
- #define CF_XD_CLK_ENB 7
- #define GETH_CLK_ENB 8
+ #define SDHCI_CLK_ENB 6
+ #define CFXD_CLK_ENB 7
+ #define GMAC_CLK_ENB 8
#define UHC0_CLK_ENB 9
#define UHC1_CLK_ENB 10
- #define UDC_UPD_CLK_ENB 11
- #define PCI0_CLK_ENB 12
- #define PCI1_CLK_ENB 13
- #define PCI2_CLK_ENB 14
+ #define USBD_CLK_ENB 11
+ #define PCIE0_CLK_ENB 12
+ #define PCIE1_CLK_ENB 13
+ #define PCIE2_CLK_ENB 14
#define UART_CLK_ENB 15
#define SSP_CLK_ENB 17
#define I2C_CLK_ENB 18
- #define I2S_SLV_CLK_ENB 19
- #define I2S_MST_CLK_ENB 20
+ #define I2S0_CLK_ENB 19
+ #define I2S1_CLK_ENB 20
#define GPT0_CLK_ENB 21
#define GPT1_CLK_ENB 22
- #define GPIOA_CLK_ENB 23
- #define GPIOB_CLK_ENB 24
+ #define GPIO0_CLK_ENB 23
+ #define GPIO1_CLK_ENB 24
#define DMA0_CLK_ENB 25
#define DMA1_CLK_ENB 26
#define CLCD_CLK_ENB 27
- #define JPEGC_CLK_ENB 28
+ #define JPEG_CLK_ENB 28
#define C3_CLK_ENB 29
#define ADC_CLK_ENB 30
#define RTC_CLK_ENB 31
@@ -219,11 +246,11 @@
#define THSENS_CFG (MISC_BASE + 0x6c4)
/* Compensation Configuration Registers */
-#define COMP_1V8_2V5_3V3__1_CFG (MISC_BASE + 0x700)
-#define COMP_1V8_2V5_3V3__2_CFG (MISC_BASE + 0x704)
-#define COMP_3V3_1_CFG (MISC_BASE + 0x708)
-#define COMP_3V3_2_CFG (MISC_BASE + 0x70c)
-#define COMP_DDR_CFG (MISC_BASE + 0x710)
+#define COMP_1V8_2V5_3V3__1_CFG (MISC_BASE + 0x700)
+#define COMP_1V8_2V5_3V3__2_CFG (MISC_BASE + 0x704)
+#define COMP_3V3_1_CFG (MISC_BASE + 0x708)
+#define COMP_3V3_2_CFG (MISC_BASE + 0x70c)
+#define COMP_DDR_CFG (MISC_BASE + 0x710)
/* OTP Programming Registers */
#define OTP_PROG_CTR (MISC_BASE + 0x800)
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 7ea8749..8ae4ad0 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -60,12 +60,22 @@ static struct pll_clk_config pll1_config = {
.masks = &pll1_masks,
};
+/* pll rate configuration table, in ascending order of rates */
+struct pll_rate_tbl pll_rtbl[] = {
+ {.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
+ {.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
+};
+
/* PLL1 clock */
static struct clk pll1_clk = {
+ .flags = ENABLED_ON_INIT,
.pclk = &osc_24m_clk,
.en_reg = PLL1_CTR,
.en_reg_bit = PLL_ENABLE,
+ .calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
+ .set_rate = &pll_clk_set_rate,
+ .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
.private_data = &pll1_config,
};
@@ -103,11 +113,22 @@ static struct bus_clk_config ahb_config = {
.masks = &ahb_masks,
};
+/* ahb rate configuration table, in ascending order of rates */
+struct bus_rate_tbl bus_rtbl[] = {
+ {.div = 3}, /* == parent divided by 4 */
+ {.div = 2}, /* == parent divided by 3 */
+ {.div = 1}, /* == parent divided by 2 */
+ {.div = 0}, /* == parent divided by 1 */
+};
+
/* ahb clock */
static struct clk ahb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
+ .calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
+ .set_rate = &bus_clk_set_rate,
+ .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &ahb_config,
};
@@ -123,22 +144,40 @@ static struct aux_clk_masks aux_masks = {
.yscale_sel_shift = AUX_YSCALE_SHIFT,
};
-/* uart configurations */
-static struct aux_clk_config uart_config = {
+/* uart synth configurations */
+static struct aux_clk_config uart_synth_config = {
.synth_reg = UART_CLK_SYNT,
.masks = &aux_masks,
};
+/* aux rate configuration table, in ascending order of rates */
+struct aux_rate_tbl aux_rtbl[] = {
+ /* For PLL1 = 332 MHz */
+ {.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
+ {.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
+ {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
+};
+
+/* uart synth clock */
+static struct clk uart_synth_clk = {
+ .en_reg = UART_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
+ .private_data = &uart_synth_config,
+};
+
/* uart parents */
static struct pclk_info uart_pclk_info[] = {
{
- .pclk = &pll1_clk,
- .pclk_mask = AUX_CLK_PLL1_MASK,
- .scalable = 1,
+ .pclk = &uart_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
- .pclk_mask = AUX_CLK_PLL3_MASK,
- .scalable = 0,
+ .pclk_val = AUX_CLK_PLL3_VAL,
},
};
@@ -156,26 +195,35 @@ static struct clk uart_clk = {
.en_reg_bit = UART_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
- .recalc = &aux_clk_recalc,
- .private_data = &uart_config,
+ .recalc = &follow_parent,
};
/* firda configurations */
-static struct aux_clk_config firda_config = {
+static struct aux_clk_config firda_synth_config = {
.synth_reg = FIRDA_CLK_SYNT,
.masks = &aux_masks,
};
+/* firda synth clock */
+static struct clk firda_synth_clk = {
+ .en_reg = FIRDA_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
+ .private_data = &firda_synth_config,
+};
+
/* firda parents */
static struct pclk_info firda_pclk_info[] = {
{
- .pclk = &pll1_clk,
- .pclk_mask = AUX_CLK_PLL1_MASK,
- .scalable = 1,
+ .pclk = &firda_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
- .pclk_mask = AUX_CLK_PLL3_MASK,
- .scalable = 0,
+ .pclk_val = AUX_CLK_PLL3_VAL,
},
};
@@ -193,84 +241,155 @@ static struct clk firda_clk = {
.en_reg_bit = FIRDA_CLK_ENB,
.pclk_sel = &firda_pclk_sel,
.pclk_sel_shift = FIRDA_CLK_SHIFT,
- .recalc = &aux_clk_recalc,
- .private_data = &firda_config,
+ .recalc = &follow_parent,
+};
+
+/* gpt synthesizer masks */
+static struct gpt_clk_masks gpt_masks = {
+ .mscale_sel_mask = GPT_MSCALE_MASK,
+ .mscale_sel_shift = GPT_MSCALE_SHIFT,
+ .nscale_sel_mask = GPT_NSCALE_MASK,
+ .nscale_sel_shift = GPT_NSCALE_SHIFT,
+};
+
+/* gpt rate configuration table, in ascending order of rates */
+struct gpt_rate_tbl gpt_rtbl[] = {
+ /* For pll1 = 332 MHz */
+ {.mscale = 4, .nscale = 0}, /* 41.5 MHz */
+ {.mscale = 2, .nscale = 0}, /* 55.3 MHz */
+ {.mscale = 1, .nscale = 0}, /* 83 MHz */
+};
+
+/* gpt0 synth clk config*/
+static struct gpt_clk_config gpt0_synth_config = {
+ .synth_reg = PRSC1_CLK_CFG,
+ .masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt0_synth_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &pll1_clk,
+ .calc_rate = &gpt_calc_rate,
+ .recalc = &gpt_clk_recalc,
+ .set_rate = &gpt_clk_set_rate,
+ .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+ .private_data = &gpt0_synth_config,
};
/* gpt parents */
-static struct pclk_info gpt_pclk_info[] = {
+static struct pclk_info gpt0_pclk_info[] = {
{
- .pclk = &pll1_clk,
- .pclk_mask = AUX_CLK_PLL1_MASK,
- .scalable = 1,
+ .pclk = &gpt0_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
- .pclk_mask = AUX_CLK_PLL3_MASK,
- .scalable = 0,
+ .pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
-static struct pclk_sel gpt_pclk_sel = {
- .pclk_info = gpt_pclk_info,
- .pclk_count = ARRAY_SIZE(gpt_pclk_info),
+static struct pclk_sel gpt0_pclk_sel = {
+ .pclk_info = gpt0_pclk_info,
+ .pclk_count = ARRAY_SIZE(gpt0_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
-/* gpt synthesizer masks */
-static struct gpt_clk_masks gpt_masks = {
- .mscale_sel_mask = GPT_MSCALE_MASK,
- .mscale_sel_shift = GPT_MSCALE_SHIFT,
- .nscale_sel_mask = GPT_NSCALE_MASK,
- .nscale_sel_shift = GPT_NSCALE_SHIFT,
+/* gpt0 timer clock */
+static struct clk gpt0_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk_sel = &gpt0_pclk_sel,
+ .pclk_sel_shift = GPT0_CLK_SHIFT,
+ .recalc = &follow_parent,
};
-/* gpt0 configurations */
-static struct gpt_clk_config gpt0_config = {
- .synth_reg = PRSC1_CLK_CFG,
+/* gpt1 synth clk configurations */
+static struct gpt_clk_config gpt1_synth_config = {
+ .synth_reg = PRSC2_CLK_CFG,
.masks = &gpt_masks,
};
-/* gpt0 timer clock */
-static struct clk gpt0_clk = {
+/* gpt1 synth clock */
+static struct clk gpt1_synth_clk = {
.flags = ALWAYS_ENABLED,
- .pclk_sel = &gpt_pclk_sel,
- .pclk_sel_shift = GPT0_CLK_SHIFT,
+ .pclk = &pll1_clk,
+ .calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
- .private_data = &gpt0_config,
+ .set_rate = &gpt_clk_set_rate,
+ .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+ .private_data = &gpt1_synth_config,
};
-/* gpt1 configurations */
-static struct gpt_clk_config gpt1_config = {
- .synth_reg = PRSC2_CLK_CFG,
- .masks = &gpt_masks,
+static struct pclk_info gpt1_pclk_info[] = {
+ {
+ .pclk = &gpt1_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
+ }, {
+ .pclk = &pll3_48m_clk,
+ .pclk_val = AUX_CLK_PLL3_VAL,
+ },
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt1_pclk_sel = {
+ .pclk_info = gpt1_pclk_info,
+ .pclk_count = ARRAY_SIZE(gpt1_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt1 timer clock */
static struct clk gpt1_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPT1_CLK_ENB,
- .pclk_sel = &gpt_pclk_sel,
+ .pclk_sel = &gpt1_pclk_sel,
.pclk_sel_shift = GPT1_CLK_SHIFT,
- .recalc = &gpt_clk_recalc,
- .private_data = &gpt1_config,
+ .recalc = &follow_parent,
};
-/* gpt2 configurations */
-static struct gpt_clk_config gpt2_config = {
+/* gpt2 synth clk configurations */
+static struct gpt_clk_config gpt2_synth_config = {
.synth_reg = PRSC3_CLK_CFG,
.masks = &gpt_masks,
};
+/* gpt1 synth clock */
+static struct clk gpt2_synth_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &pll1_clk,
+ .calc_rate = &gpt_calc_rate,
+ .recalc = &gpt_clk_recalc,
+ .set_rate = &gpt_clk_set_rate,
+ .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+ .private_data = &gpt2_synth_config,
+};
+
+static struct pclk_info gpt2_pclk_info[] = {
+ {
+ .pclk = &gpt2_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
+ }, {
+ .pclk = &pll3_48m_clk,
+ .pclk_val = AUX_CLK_PLL3_VAL,
+ },
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt2_pclk_sel = {
+ .pclk_info = gpt2_pclk_info,
+ .pclk_count = ARRAY_SIZE(gpt2_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = GPT_CLK_MASK,
+};
+
/* gpt2 timer clock */
static struct clk gpt2_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPT2_CLK_ENB,
- .pclk_sel = &gpt_pclk_sel,
+ .pclk_sel = &gpt2_pclk_sel,
.pclk_sel_shift = GPT2_CLK_SHIFT,
- .recalc = &gpt_clk_recalc,
- .private_data = &gpt2_config,
+ .recalc = &follow_parent,
};
/* clock derived from pll3 clk */
@@ -290,13 +409,6 @@ static struct clk usbd_clk = {
.recalc = &follow_parent,
};
-/* clcd clock */
-static struct clk clcd_clk = {
- .flags = ALWAYS_ENABLED,
- .pclk = &pll3_48m_clk,
- .recalc = &follow_parent,
-};
-
/* clock derived from ahb clk */
/* apb masks structure */
static struct bus_clk_masks apb_masks = {
@@ -314,7 +426,10 @@ static struct bus_clk_config apb_config = {
static struct clk apb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
+ .calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
+ .set_rate = &bus_clk_set_rate,
+ .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &apb_config,
};
@@ -375,8 +490,17 @@ static struct clk adc_clk = {
.recalc = &follow_parent,
};
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+/* emi clock */
+static struct clk emi_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &ahb_clk,
+ .recalc = &follow_parent,
+};
+#endif
+
/* ssp clock */
-static struct clk ssp_clk = {
+static struct clk ssp0_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP_CLK_ENB,
@@ -393,6 +517,137 @@ static struct clk gpio_clk = {
static struct clk dummy_apb_pclk;
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
+ defined(CONFIG_MACH_SPEAR320)
+/* fsmc clock */
+static struct clk fsmc_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &ahb_clk,
+ .recalc = &follow_parent,
+};
+#endif
+
+/* common clocks to spear310 and spear320 */
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+/* uart1 clock */
+static struct clk uart1_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* uart2 clock */
+static struct clk uart2_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
+
+/* common clocks to spear300 and spear320 */
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
+/* clcd clock */
+static struct clk clcd_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &pll3_48m_clk,
+ .recalc = &follow_parent,
+};
+
+/* sdhci clock */
+static struct clk sdhci_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &ahb_clk,
+ .recalc = &follow_parent,
+};
+#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
+
+/* spear300 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR300
+/* gpio1 clock */
+static struct clk gpio1_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* keyboard clock */
+static struct clk kbd_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+#endif
+
+/* spear310 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR310
+/* uart3 clock */
+static struct clk uart3_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* uart4 clock */
+static struct clk uart4_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* uart5 clock */
+static struct clk uart5_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+#endif
+
+/* spear320 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR320
+/* can0 clock */
+static struct clk can0_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* can1 clock */
+static struct clk can1_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* i2c1 clock */
+static struct clk i2c1_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &ahb_clk,
+ .recalc = &follow_parent,
+};
+
+/* ssp1 clock */
+static struct clk ssp1_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* ssp2 clock */
+static struct clk ssp2_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+
+/* pwm clock */
+static struct clk pwm_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &apb_clk,
+ .recalc = &follow_parent,
+};
+#endif
+
/* array of all spear 3xx clock lookups */
static struct clk_lookup spear_clk_lookups[] = {
{ .con_id = "apb_pclk", .clk = &dummy_apb_pclk},
@@ -400,7 +655,7 @@ static struct clk_lookup spear_clk_lookups[] = {
{ .con_id = "osc_32k_clk", .clk = &osc_32k_clk},
{ .con_id = "osc_24m_clk", .clk = &osc_24m_clk},
/* clock derived from 32 KHz osc clk */
- { .dev_id = "rtc", .clk = &rtc_clk},
+ { .dev_id = "rtc-spear", .clk = &rtc_clk},
/* clock derived from 24 MHz osc clk */
{ .con_id = "pll1_clk", .clk = &pll1_clk},
{ .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk},
@@ -408,18 +663,22 @@ static struct clk_lookup spear_clk_lookups[] = {
/* clock derived from pll1 clk */
{ .con_id = "cpu_clk", .clk = &cpu_clk},
{ .con_id = "ahb_clk", .clk = &ahb_clk},
+ { .con_id = "uart_synth_clk", .clk = &uart_synth_clk},
+ { .con_id = "firda_synth_clk", .clk = &firda_synth_clk},
+ { .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk},
+ { .con_id = "gpt1_synth_clk", .clk = &gpt1_synth_clk},
+ { .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk},
{ .dev_id = "uart", .clk = &uart_clk},
{ .dev_id = "firda", .clk = &firda_clk},
{ .dev_id = "gpt0", .clk = &gpt0_clk},
{ .dev_id = "gpt1", .clk = &gpt1_clk},
{ .dev_id = "gpt2", .clk = &gpt2_clk},
/* clock derived from pll3 clk */
- { .dev_id = "usbh", .clk = &usbh_clk},
+ { .con_id = "usbh_clk", .clk = &usbh_clk},
{ .dev_id = "usbd", .clk = &usbd_clk},
- { .dev_id = "clcd", .clk = &clcd_clk},
/* clock derived from ahb clk */
{ .con_id = "apb_clk", .clk = &apb_clk},
- { .dev_id = "i2c", .clk = &i2c_clk},
+ { .dev_id = "i2c_designware.0", .clk = &i2c_clk},
{ .dev_id = "dma", .clk = &dma_clk},
{ .dev_id = "jpeg", .clk = &jpeg_clk},
{ .dev_id = "gmac", .clk = &gmac_clk},
@@ -427,8 +686,50 @@ static struct clk_lookup spear_clk_lookups[] = {
{ .dev_id = "c3", .clk = &c3_clk},
/* clock derived from apb clk */
{ .dev_id = "adc", .clk = &adc_clk},
- { .dev_id = "ssp", .clk = &ssp_clk},
+ { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk},
{ .dev_id = "gpio", .clk = &gpio_clk},
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+ { .dev_id = "physmap-flash", .clk = &emi_clk},
+#endif
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
+ defined(CONFIG_MACH_SPEAR320)
+ { .con_id = "fsmc", .clk = &fsmc_clk},
+#endif
+
+/* common clocks to spear310 and spear320 */
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+ { .dev_id = "uart1", .clk = &uart1_clk},
+ { .dev_id = "uart2", .clk = &uart2_clk},
+#endif
+
+ /* common clock to spear300 and spear320 */
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
+ { .dev_id = "clcd", .clk = &clcd_clk},
+ { .dev_id = "sdhci", .clk = &sdhci_clk},
+#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
+
+ /* spear300 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR300
+ { .dev_id = "gpio1", .clk = &gpio1_clk},
+ { .dev_id = "keyboard", .clk = &kbd_clk},
+#endif
+
+ /* spear310 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR310
+ { .dev_id = "uart3", .clk = &uart3_clk},
+ { .dev_id = "uart4", .clk = &uart4_clk},
+ { .dev_id = "uart5", .clk = &uart5_clk},
+
+#endif
+ /* spear320 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR320
+ { .dev_id = "c_can_platform.0", .clk = &can0_clk},
+ { .dev_id = "c_can_platform.1", .clk = &can1_clk},
+ { .dev_id = "i2c_designware.1", .clk = &i2c1_clk},
+ { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk},
+ { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk},
+ { .dev_id = "pwm", .clk = &pwm_clk},
+#endif
};
void __init clk_init(void)
diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
index 6c919e1..0b93347 100644
--- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
@@ -63,8 +63,8 @@
#define GPT1_CLK_SHIFT 11
#define GPT2_CLK_SHIFT 12
#define GPT_CLK_MASK 0x1
-#define AUX_CLK_PLL3_MASK 0
-#define AUX_CLK_PLL1_MASK 1
+#define AUX_CLK_PLL3_VAL 0
+#define AUX_CLK_PLL1_VAL 1
#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
/* PERIP1_CLK_ENB register masks */
@@ -113,6 +113,7 @@
#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
/* aux clk synthesiser register masks for irda to ras4 */
+#define AUX_SYNT_ENB 31
#define AUX_EQ_SEL_SHIFT 30
#define AUX_EQ_SEL_MASK 1
#define AUX_EQ1_SEL 0
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index ef88922..9171952 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -60,12 +60,22 @@ static struct pll_clk_config pll1_config = {
.masks = &pll1_masks,
};
+/* pll rate configuration table, in ascending order of rates */
+struct pll_rate_tbl pll_rtbl[] = {
+ {.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
+ {.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
+};
+
/* PLL1 clock */
static struct clk pll1_clk = {
+ .flags = ENABLED_ON_INIT,
.pclk = &osc_30m_clk,
.en_reg = PLL1_CTR,
.en_reg_bit = PLL_ENABLE,
+ .calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
+ .set_rate = &pll_clk_set_rate,
+ .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
.private_data = &pll1_config,
};
@@ -103,35 +113,25 @@ static struct bus_clk_config ahb_config = {
.masks = &ahb_masks,
};
+/* ahb rate configuration table, in ascending order of rates */
+struct bus_rate_tbl bus_rtbl[] = {
+ {.div = 3}, /* == parent divided by 4 */
+ {.div = 2}, /* == parent divided by 3 */
+ {.div = 1}, /* == parent divided by 2 */
+ {.div = 0}, /* == parent divided by 1 */
+};
+
/* ahb clock */
static struct clk ahb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
+ .calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
+ .set_rate = &bus_clk_set_rate,
+ .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &ahb_config,
};
-/* uart parents */
-static struct pclk_info uart_pclk_info[] = {
- {
- .pclk = &pll1_clk,
- .pclk_mask = AUX_CLK_PLL1_MASK,
- .scalable = 1,
- }, {
- .pclk = &pll3_48m_clk,
- .pclk_mask = AUX_CLK_PLL3_MASK,
- .scalable = 0,
- },
-};
-
-/* uart parent select structure */
-static struct pclk_sel uart_pclk_sel = {
- .pclk_info = uart_pclk_info,
- .pclk_count = ARRAY_SIZE(uart_pclk_info),
- .pclk_sel_reg = PERIP_CLK_CFG,
- .pclk_sel_mask = UART_CLK_MASK,
-};
-
/* auxiliary synthesizers masks */
static struct aux_clk_masks aux_masks = {
.eq_sel_mask = AUX_EQ_SEL_MASK,
@@ -145,19 +145,57 @@ static struct aux_clk_masks aux_masks = {
};
/* uart configurations */
-static struct aux_clk_config uart_config = {
+static struct aux_clk_config uart_synth_config = {
.synth_reg = UART_CLK_SYNT,
.masks = &aux_masks,
};
+/* aux rate configuration table, in ascending order of rates */
+struct aux_rate_tbl aux_rtbl[] = {
+ /* For PLL1 = 332 MHz */
+ {.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
+ {.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
+ {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
+};
+
+/* uart synth clock */
+static struct clk uart_synth_clk = {
+ .en_reg = UART_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+ .private_data = &uart_synth_config,
+};
+
+/* uart parents */
+static struct pclk_info uart_pclk_info[] = {
+ {
+ .pclk = &uart_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
+ }, {
+ .pclk = &pll3_48m_clk,
+ .pclk_val = AUX_CLK_PLL3_VAL,
+ },
+};
+
+/* uart parent select structure */
+static struct pclk_sel uart_pclk_sel = {
+ .pclk_info = uart_pclk_info,
+ .pclk_count = ARRAY_SIZE(uart_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = UART_CLK_MASK,
+};
+
/* uart0 clock */
static struct clk uart0_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = UART0_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
- .recalc = &aux_clk_recalc,
- .private_data = &uart_config,
+ .recalc = &follow_parent,
};
/* uart1 clock */
@@ -166,26 +204,35 @@ static struct clk uart1_clk = {
.en_reg_bit = UART1_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
- .recalc = &aux_clk_recalc,
- .private_data = &uart_config,
+ .recalc = &follow_parent,
};
/* firda configurations */
-static struct aux_clk_config firda_config = {
+static struct aux_clk_config firda_synth_config = {
.synth_reg = FIRDA_CLK_SYNT,
.masks = &aux_masks,
};
+/* firda synth clock */
+static struct clk firda_synth_clk = {
+ .en_reg = FIRDA_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+ .private_data = &firda_synth_config,
+};
+
/* firda parents */
static struct pclk_info firda_pclk_info[] = {
{
- .pclk = &pll1_clk,
- .pclk_mask = AUX_CLK_PLL1_MASK,
- .scalable = 1,
+ .pclk = &firda_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
- .pclk_mask = AUX_CLK_PLL3_MASK,
- .scalable = 0,
+ .pclk_val = AUX_CLK_PLL3_VAL,
},
};
@@ -203,26 +250,35 @@ static struct clk firda_clk = {
.en_reg_bit = FIRDA_CLK_ENB,
.pclk_sel = &firda_pclk_sel,
.pclk_sel_shift = FIRDA_CLK_SHIFT,
- .recalc = &aux_clk_recalc,
- .private_data = &firda_config,
+ .recalc = &follow_parent,
};
/* clcd configurations */
-static struct aux_clk_config clcd_config = {
+static struct aux_clk_config clcd_synth_config = {
.synth_reg = CLCD_CLK_SYNT,
.masks = &aux_masks,
};
+/* firda synth clock */
+static struct clk clcd_synth_clk = {
+ .en_reg = CLCD_CLK_SYNT,
+ .en_reg_bit = AUX_SYNT_ENB,
+ .pclk = &pll1_clk,
+ .calc_rate = &aux_calc_rate,
+ .recalc = &aux_clk_recalc,
+ .set_rate = &aux_clk_set_rate,
+ .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+ .private_data = &clcd_synth_config,
+};
+
/* clcd parents */
static struct pclk_info clcd_pclk_info[] = {
{
- .pclk = &pll1_clk,
- .pclk_mask = AUX_CLK_PLL1_MASK,
- .scalable = 1,
+ .pclk = &clcd_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
- .pclk_mask = AUX_CLK_PLL3_MASK,
- .scalable = 0,
+ .pclk_val = AUX_CLK_PLL3_VAL,
},
};
@@ -240,29 +296,7 @@ static struct clk clcd_clk = {
.en_reg_bit = CLCD_CLK_ENB,
.pclk_sel = &clcd_pclk_sel,
.pclk_sel_shift = CLCD_CLK_SHIFT,
- .recalc = &aux_clk_recalc,
- .private_data = &clcd_config,
-};
-
-/* gpt parents */
-static struct pclk_info gpt_pclk_info[] = {
- {
- .pclk = &pll1_clk,
- .pclk_mask = AUX_CLK_PLL1_MASK,
- .scalable = 1,
- }, {
- .pclk = &pll3_48m_clk,
- .pclk_mask = AUX_CLK_PLL3_MASK,
- .scalable = 0,
- },
-};
-
-/* gpt parent select structure */
-static struct pclk_sel gpt_pclk_sel = {
- .pclk_info = gpt_pclk_info,
- .pclk_count = ARRAY_SIZE(gpt_pclk_info),
- .pclk_sel_reg = PERIP_CLK_CFG,
- .pclk_sel_mask = GPT_CLK_MASK,
+ .recalc = &follow_parent,
};
/* gpt synthesizer masks */
@@ -273,60 +307,162 @@ static struct gpt_clk_masks gpt_masks = {
.nscale_sel_shift = GPT_NSCALE_SHIFT,
};
-/* gpt0_1 configurations */
-static struct gpt_clk_config gpt0_1_config = {
+/* gpt rate configuration table, in ascending order of rates */
+struct gpt_rate_tbl gpt_rtbl[] = {
+ /* For pll1 = 332 MHz */
+ {.mscale = 4, .nscale = 0}, /* 41.5 MHz */
+ {.mscale = 2, .nscale = 0}, /* 55.3 MHz */
+ {.mscale = 1, .nscale = 0}, /* 83 MHz */
+};
+
+/* gpt0 synth clk config*/
+static struct gpt_clk_config gpt0_synth_config = {
.synth_reg = PRSC1_CLK_CFG,
.masks = &gpt_masks,
};
+/* gpt synth clock */
+static struct clk gpt0_synth_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &pll1_clk,
+ .calc_rate = &gpt_calc_rate,
+ .recalc = &gpt_clk_recalc,
+ .set_rate = &gpt_clk_set_rate,
+ .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+ .private_data = &gpt0_synth_config,
+};
+
+/* gpt parents */
+static struct pclk_info gpt0_pclk_info[] = {
+ {
+ .pclk = &gpt0_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
+ }, {
+ .pclk = &pll3_48m_clk,
+ .pclk_val = AUX_CLK_PLL3_VAL,
+ },
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt0_pclk_sel = {
+ .pclk_info = gpt0_pclk_info,
+ .pclk_count = ARRAY_SIZE(gpt0_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = GPT_CLK_MASK,
+};
+
/* gpt0 ARM1 subsystem timer clock */
static struct clk gpt0_clk = {
.flags = ALWAYS_ENABLED,
- .pclk_sel = &gpt_pclk_sel,
+ .pclk_sel = &gpt0_pclk_sel,
.pclk_sel_shift = GPT0_CLK_SHIFT,
- .recalc = &gpt_clk_recalc,
- .private_data = &gpt0_1_config,
+ .recalc = &follow_parent,
+};
+
+
+/* Note: gpt0 and gpt1 share same parent clocks */
+/* gpt parent select structure */
+static struct pclk_sel gpt1_pclk_sel = {
+ .pclk_info = gpt0_pclk_info,
+ .pclk_count = ARRAY_SIZE(gpt0_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt1 timer clock */
static struct clk gpt1_clk = {
.flags = ALWAYS_ENABLED,
- .pclk_sel = &gpt_pclk_sel,
+ .pclk_sel = &gpt1_pclk_sel,
.pclk_sel_shift = GPT1_CLK_SHIFT,
- .recalc = &gpt_clk_recalc,
- .private_data = &gpt0_1_config,
+ .recalc = &follow_parent,
};
-/* gpt2 configurations */
-static struct gpt_clk_config gpt2_config = {
+/* gpt2 synth clk config*/
+static struct gpt_clk_config gpt2_synth_config = {
.synth_reg = PRSC2_CLK_CFG,
.masks = &gpt_masks,
};
+/* gpt synth clock */
+static struct clk gpt2_synth_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &pll1_clk,
+ .calc_rate = &gpt_calc_rate,
+ .recalc = &gpt_clk_recalc,
+ .set_rate = &gpt_clk_set_rate,
+ .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+ .private_data = &gpt2_synth_config,
+};
+
+/* gpt parents */
+static struct pclk_info gpt2_pclk_info[] = {
+ {
+ .pclk = &gpt2_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
+ }, {
+ .pclk = &pll3_48m_clk,
+ .pclk_val = AUX_CLK_PLL3_VAL,
+ },
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt2_pclk_sel = {
+ .pclk_info = gpt2_pclk_info,
+ .pclk_count = ARRAY_SIZE(gpt2_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = GPT_CLK_MASK,
+};
+
/* gpt2 timer clock */
static struct clk gpt2_clk = {
- .en_reg = PERIP1_CLK_ENB,
- .en_reg_bit = GPT2_CLK_ENB,
- .pclk_sel = &gpt_pclk_sel,
+ .flags = ALWAYS_ENABLED,
+ .pclk_sel = &gpt2_pclk_sel,
.pclk_sel_shift = GPT2_CLK_SHIFT,
- .recalc = &gpt_clk_recalc,
- .private_data = &gpt2_config,
+ .recalc = &follow_parent,
};
-/* gpt3 configurations */
-static struct gpt_clk_config gpt3_config = {
+/* gpt3 synth clk config*/
+static struct gpt_clk_config gpt3_synth_config = {
.synth_reg = PRSC3_CLK_CFG,
.masks = &gpt_masks,
};
+/* gpt synth clock */
+static struct clk gpt3_synth_clk = {
+ .flags = ALWAYS_ENABLED,
+ .pclk = &pll1_clk,
+ .calc_rate = &gpt_calc_rate,
+ .recalc = &gpt_clk_recalc,
+ .set_rate = &gpt_clk_set_rate,
+ .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+ .private_data = &gpt3_synth_config,
+};
+
+/* gpt parents */
+static struct pclk_info gpt3_pclk_info[] = {
+ {
+ .pclk = &gpt3_synth_clk,
+ .pclk_val = AUX_CLK_PLL1_VAL,
+ }, {
+ .pclk = &pll3_48m_clk,
+ .pclk_val = AUX_CLK_PLL3_VAL,
+ },
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt3_pclk_sel = {
+ .pclk_info = gpt3_pclk_info,
+ .pclk_count = ARRAY_SIZE(gpt3_pclk_info),
+ .pclk_sel_reg = PERIP_CLK_CFG,
+ .pclk_sel_mask = GPT_CLK_MASK,
+};
+
/* gpt3 timer clock */
static struct clk gpt3_clk = {
- .en_reg = PERIP1_CLK_ENB,
- .en_reg_bit = GPT3_CLK_ENB,
- .pclk_sel = &gpt_pclk_sel,
+ .flags = ALWAYS_ENABLED,
+ .pclk_sel = &gpt3_pclk_sel,
.pclk_sel_shift = GPT3_CLK_SHIFT,
- .recalc = &gpt_clk_recalc,
- .private_data = &gpt3_config,
+ .recalc = &follow_parent,
};
/* clock derived from pll3 clk */
@@ -371,7 +507,10 @@ static struct bus_clk_config apb_config = {
static struct clk apb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
+ .calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
+ .set_rate = &bus_clk_set_rate,
+ .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &apb_config,
};
@@ -488,7 +627,7 @@ static struct clk_lookup spear_clk_lookups[] = {
{ .con_id = "osc_32k_clk", .clk = &osc_32k_clk},
{ .con_id = "osc_30m_clk", .clk = &osc_30m_clk},
/* clock derived from 32 KHz os clk */
- { .dev_id = "rtc", .clk = &rtc_clk},
+ { .dev_id = "rtc-spear", .clk = &rtc_clk},
/* clock derived from 30 MHz os clk */
{ .con_id = "pll1_clk", .clk = &pll1_clk},
{ .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk},
@@ -496,6 +635,12 @@ static struct clk_lookup spear_clk_lookups[] = {
/* clock derived from pll1 clk */
{ .con_id = "cpu_clk", .clk = &cpu_clk},
{ .con_id = "ahb_clk", .clk = &ahb_clk},
+ { .con_id = "uart_synth_clk", .clk = &uart_synth_clk},
+ { .con_id = "firda_synth_clk", .clk = &firda_synth_clk},
+ { .con_id = "clcd_synth_clk", .clk = &clcd_synth_clk},
+ { .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk},
+ { .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk},
+ { .con_id = "gpt3_synth_clk", .clk = &gpt3_synth_clk},
{ .dev_id = "uart0", .clk = &uart0_clk},
{ .dev_id = "uart1", .clk = &uart1_clk},
{ .dev_id = "firda", .clk = &firda_clk},
@@ -505,22 +650,22 @@ static struct clk_lookup spear_clk_lookups[] = {
{ .dev_id = "gpt2", .clk = &gpt2_clk},
{ .dev_id = "gpt3", .clk = &gpt3_clk},
/* clock derived from pll3 clk */
- { .dev_id = "usbh0", .clk = &usbh0_clk},
- { .dev_id = "usbh1", .clk = &usbh1_clk},
+ { .con_id = "usbh.0_clk", .clk = &usbh0_clk},
+ { .con_id = "usbh.1_clk", .clk = &usbh1_clk},
{ .dev_id = "usbd", .clk = &usbd_clk},
/* clock derived from ahb clk */
{ .con_id = "apb_clk", .clk = &apb_clk},
- { .dev_id = "i2c", .clk = &i2c_clk},
+ { .dev_id = "i2c_designware.0", .clk = &i2c_clk},
{ .dev_id = "dma", .clk = &dma_clk},
{ .dev_id = "jpeg", .clk = &jpeg_clk},
{ .dev_id = "gmac", .clk = &gmac_clk},
{ .dev_id = "smi", .clk = &smi_clk},
- { .dev_id = "fsmc", .clk = &fsmc_clk},
+ { .con_id = "fsmc", .clk = &fsmc_clk},
/* clock derived from apb clk */
{ .dev_id = "adc", .clk = &adc_clk},
- { .dev_id = "ssp0", .clk = &ssp0_clk},
- { .dev_id = "ssp1", .clk = &ssp1_clk},
- { .dev_id = "ssp2", .clk = &ssp2_clk},
+ { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk},
+ { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk},
+ { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk},
{ .dev_id = "gpio0", .clk = &gpio0_clk},
{ .dev_id = "gpio1", .clk = &gpio1_clk},
{ .dev_id = "gpio2", .clk = &gpio2_clk},
diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
index d153177..45571c1 100644
--- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
@@ -66,8 +66,8 @@
#define GPT2_CLK_SHIFT 11
#define GPT3_CLK_SHIFT 12
#define GPT_CLK_MASK 0x1
-#define AUX_CLK_PLL3_MASK 0
-#define AUX_CLK_PLL1_MASK 1
+#define AUX_CLK_PLL3_VAL 0
+#define AUX_CLK_PLL1_VAL 1
#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
/* PERIP1_CLK_ENB register masks */
@@ -123,6 +123,7 @@
#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
/* aux clk synthesiser register masks for irda to ras4 */
+#define AUX_SYNT_ENB 31
#define AUX_EQ_SEL_SHIFT 30
#define AUX_EQ_SEL_MASK 1
#define AUX_EQ1_SEL 0
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index f1cf832..7e7ab60 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -12,6 +12,7 @@
*/
#include <linux/bug.h>
+#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/list.h>
@@ -22,7 +23,7 @@
static DEFINE_SPINLOCK(clocks_lock);
static LIST_HEAD(root_clks);
-static void propagate_rate(struct list_head *);
+static void propagate_rate(struct clk *, int on_init);
static int generic_clk_enable(struct clk *clk)
{
@@ -64,6 +65,100 @@ static struct clkops generic_clkops = {
.disable = generic_clk_disable,
};
+/* returns current programmed clocks clock info structure */
+static struct pclk_info *pclk_info_get(struct clk *clk)
+{
+ unsigned int val, i;
+ struct pclk_info *info = NULL;
+
+ val = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift)
+ & clk->pclk_sel->pclk_sel_mask;
+
+ for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
+ if (clk->pclk_sel->pclk_info[i].pclk_val == val)
+ info = &clk->pclk_sel->pclk_info[i];
+ }
+
+ return info;
+}
+
+/*
+ * Set Update pclk, and pclk_info of clk and add clock sibling node to current
+ * parents children list
+ */
+static void clk_reparent(struct clk *clk, struct pclk_info *pclk_info)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ list_del(&clk->sibling);
+ list_add(&clk->sibling, &pclk_info->pclk->children);
+
+ clk->pclk = pclk_info->pclk;
+ spin_unlock_irqrestore(&clocks_lock, flags);
+}
+
+static void do_clk_disable(struct clk *clk)
+{
+ if (!clk)
+ return;
+
+ if (!clk->usage_count) {
+ WARN_ON(1);
+ return;
+ }
+
+ clk->usage_count--;
+
+ if (clk->usage_count == 0) {
+ /*
+ * Surely, there are no active childrens or direct users
+ * of this clock
+ */
+ if (clk->pclk)
+ do_clk_disable(clk->pclk);
+
+ if (clk->ops && clk->ops->disable)
+ clk->ops->disable(clk);
+ }
+}
+
+static int do_clk_enable(struct clk *clk)
+{
+ int ret = 0;
+
+ if (!clk)
+ return -EFAULT;
+
+ if (clk->usage_count == 0) {
+ if (clk->pclk) {
+ ret = do_clk_enable(clk->pclk);
+ if (ret)
+ goto err;
+ }
+ if (clk->ops && clk->ops->enable) {
+ ret = clk->ops->enable(clk);
+ if (ret) {
+ if (clk->pclk)
+ do_clk_disable(clk->pclk);
+ goto err;
+ }
+ }
+ /*
+ * Since the clock is going to be used for the first
+ * time please reclac
+ */
+ if (clk->recalc) {
+ ret = clk->recalc(clk);
+ if (ret)
+ goto err;
+ }
+ }
+ clk->usage_count++;
+err:
+ return ret;
+}
+
/*
* clk_enable - inform the system when the clock source should be running.
* @clk: clock source
@@ -77,17 +172,9 @@ int clk_enable(struct clk *clk)
unsigned long flags;
int ret = 0;
- if (!clk || IS_ERR(clk))
- return -EFAULT;
-
spin_lock_irqsave(&clocks_lock, flags);
- if (clk->usage_count == 0) {
- if (clk->ops && clk->ops->enable)
- ret = clk->ops->enable(clk);
- }
- clk->usage_count++;
+ ret = do_clk_enable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
-
return ret;
}
EXPORT_SYMBOL(clk_enable);
@@ -108,17 +195,8 @@ void clk_disable(struct clk *clk)
{
unsigned long flags;
- if (!clk || IS_ERR(clk))
- return;
-
- WARN_ON(clk->usage_count == 0);
-
spin_lock_irqsave(&clocks_lock, flags);
- clk->usage_count--;
- if (clk->usage_count == 0) {
- if (clk->ops && clk->ops->disable)
- clk->ops->disable(clk);
- }
+ do_clk_disable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
@@ -152,15 +230,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
int i, found = 0, val = 0;
unsigned long flags;
- if (!clk || IS_ERR(clk) || !parent || IS_ERR(parent))
+ if (!clk || !parent)
return -EFAULT;
- if (clk->usage_count)
- return -EBUSY;
- if (!clk->pclk_sel)
- return -EPERM;
if (clk->pclk == parent)
return 0;
+ if (!clk->pclk_sel)
+ return -EPERM;
+ /* check if requested parent is in clk parent list */
for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
if (clk->pclk_sel->pclk_info[i].pclk == parent) {
found = 1;
@@ -175,13 +252,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
/* reflect parent change in hardware */
val = readl(clk->pclk_sel->pclk_sel_reg);
val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift);
- val |= clk->pclk_sel->pclk_info[i].pclk_mask << clk->pclk_sel_shift;
+ val |= clk->pclk_sel->pclk_info[i].pclk_val << clk->pclk_sel_shift;
writel(val, clk->pclk_sel->pclk_sel_reg);
spin_unlock_irqrestore(&clocks_lock, flags);
/* reflect parent change in software */
- clk->recalc(clk);
- propagate_rate(&clk->children);
+ clk_reparent(clk, &clk->pclk_sel->pclk_info[i]);
+
+ propagate_rate(clk, 0);
return 0;
}
EXPORT_SYMBOL(clk_set_parent);
@@ -195,19 +273,37 @@ EXPORT_SYMBOL(clk_set_parent);
*/
int clk_set_rate(struct clk *clk, unsigned long rate)
{
- /* TODO */
- return -EINVAL;
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (!clk || !rate)
+ return -EFAULT;
+
+ if (clk->set_rate) {
+ spin_lock_irqsave(&clocks_lock, flags);
+ ret = clk->set_rate(clk, rate);
+ if (!ret)
+ /* if successful -> propagate */
+ propagate_rate(clk, 0);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+ } else if (clk->pclk) {
+ u32 mult = clk->div_factor ? clk->div_factor : 1;
+ ret = clk_set_rate(clk->pclk, mult * rate);
+ }
+
+ return ret;
}
EXPORT_SYMBOL(clk_set_rate);
/* registers clock in platform clock framework */
void clk_register(struct clk_lookup *cl)
{
- struct clk *clk = cl->clk;
+ struct clk *clk;
unsigned long flags;
- if (!clk || IS_ERR(clk))
+ if (!cl || !cl->clk)
return;
+ clk = cl->clk;
spin_lock_irqsave(&clocks_lock, flags);
@@ -220,15 +316,24 @@ void clk_register(struct clk_lookup *cl)
/* root clock don't have any parents */
if (!clk->pclk && !clk->pclk_sel) {
list_add(&clk->sibling, &root_clks);
- /* add clocks with only one parent to parent's children list */
} else if (clk->pclk && !clk->pclk_sel) {
+ /* add clocks with only one parent to parent's children list */
list_add(&clk->sibling, &clk->pclk->children);
} else {
- /* add clocks with > 1 parent to 1st parent's children list */
- clk->pclk = clk->pclk_sel->pclk_info[0].pclk;
- list_add(&clk->sibling,
- &clk->pclk_sel->pclk_info[0].pclk->children);
+ /* clocks with more than one parent */
+ struct pclk_info *pclk_info;
+
+ pclk_info = pclk_info_get(clk);
+ if (!pclk_info) {
+ pr_err("CLKDEV: invalid pclk info of clk with"
+ " %s dev_id and %s con_id\n",
+ cl->dev_id, cl->con_id);
+ } else {
+ clk->pclk = pclk_info->pclk;
+ list_add(&clk->sibling, &pclk_info->pclk->children);
+ }
}
+
spin_unlock_irqrestore(&clocks_lock, flags);
/* add clock to arm clockdev framework */
@@ -236,56 +341,142 @@ void clk_register(struct clk_lookup *cl)
}
/**
- * propagate_rate - recalculate and propagate all clocks in list head
+ * propagate_rate - recalculate and propagate all clocks to children
+ * @pclk: parent clock required to be propogated
+ * @on_init: flag for enabling clocks which are ENABLED_ON_INIT.
*
- * Recalculates all root clocks in list head, which if the clock's .recalc is
- * set correctly, should also propagate their rates.
+ * Recalculates all children clocks
*/
-static void propagate_rate(struct list_head *lhead)
+void propagate_rate(struct clk *pclk, int on_init)
{
- struct clk *clkp, *_temp;
+ struct clk *clk, *_temp;
+ int ret = 0;
+
+ list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) {
+ if (clk->recalc) {
+ ret = clk->recalc(clk);
+ /*
+ * recalc will return error if clk out is not programmed
+ * In this case configure default rate.
+ */
+ if (ret && clk->set_rate)
+ clk->set_rate(clk, 0);
+ }
+ propagate_rate(clk, on_init);
+
+ if (!on_init)
+ continue;
- list_for_each_entry_safe(clkp, _temp, lhead, sibling) {
- if (clkp->recalc)
- clkp->recalc(clkp);
- propagate_rate(&clkp->children);
+ /* Enable clks enabled on init, in software view */
+ if (clk->flags & ENABLED_ON_INIT)
+ do_clk_enable(clk);
}
}
-/* returns current programmed clocks clock info structure */
-static struct pclk_info *pclk_info_get(struct clk *clk)
+/**
+ * round_rate_index - return closest programmable rate index in rate_config tbl
+ * @clk: ptr to clock structure
+ * @drate: desired rate
+ * @rate: final rate will be returned in this variable only.
+ *
+ * Finds index in rate_config for highest clk rate which is less than
+ * requested rate. If there is no clk rate lesser than requested rate then
+ * -EINVAL is returned. This routine assumes that rate_config is written
+ * in incrementing order of clk rates.
+ * If drate passed is zero then default rate is programmed.
+ */
+static int
+round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate)
{
- unsigned int mask, i;
- unsigned long flags;
- struct pclk_info *info = NULL;
+ unsigned long tmp = 0, prev_rate = 0;
+ int index;
- spin_lock_irqsave(&clocks_lock, flags);
- mask = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift)
- & clk->pclk_sel->pclk_sel_mask;
+ if (!clk->calc_rate)
+ return -EFAULT;
- for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
- if (clk->pclk_sel->pclk_info[i].pclk_mask == mask)
- info = &clk->pclk_sel->pclk_info[i];
+ if (!drate)
+ return -EINVAL;
+
+ /*
+ * This loops ends on two conditions:
+ * - as soon as clk is found with rate greater than requested rate.
+ * - if all clks in rate_config are smaller than requested rate.
+ */
+ for (index = 0; index < clk->rate_config.count; index++) {
+ prev_rate = tmp;
+ tmp = clk->calc_rate(clk, index);
+ if (drate < tmp) {
+ index--;
+ break;
+ }
}
- spin_unlock_irqrestore(&clocks_lock, flags);
+ /* return if can't find suitable clock */
+ if (index < 0) {
+ index = -EINVAL;
+ *rate = 0;
+ } else if (index == clk->rate_config.count) {
+ /* program with highest clk rate possible */
+ index = clk->rate_config.count - 1;
+ *rate = tmp;
+ } else
+ *rate = prev_rate;
- return info;
+ return index;
}
-/*
- * Set pclk as cclk's parent and add clock sibling node to current parents
- * children list
+/**
+ * clk_round_rate - adjust a rate to the exact rate a clock can provide
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ *
+ * Returns rounded clock rate in Hz, or negative errno.
*/
-static void change_parent(struct clk *cclk, struct clk *pclk)
+long clk_round_rate(struct clk *clk, unsigned long drate)
{
- unsigned long flags;
+ long rate = 0;
+ int index;
+
+ /*
+ * propagate call to parent who supports calc_rate. Similar approach is
+ * used in clk_set_rate.
+ */
+ if (!clk->calc_rate) {
+ u32 mult;
+ if (!clk->pclk)
+ return clk->rate;
+
+ mult = clk->div_factor ? clk->div_factor : 1;
+ return clk_round_rate(clk->pclk, mult * drate) / mult;
+ }
- spin_lock_irqsave(&clocks_lock, flags);
- list_del(&cclk->sibling);
- list_add(&cclk->sibling, &pclk->children);
+ index = round_rate_index(clk, drate, &rate);
+ if (index >= 0)
+ return rate;
+ else
+ return index;
+}
+EXPORT_SYMBOL(clk_round_rate);
- cclk->pclk = pclk;
- spin_unlock_irqrestore(&clocks_lock, flags);
+/*All below functions are called with lock held */
+
+/*
+ * Calculates pll clk rate for specific value of mode, m, n and p
+ *
+ * In normal mode
+ * rate = (2 * M[15:8] * Fin)/(N * 2^P)
+ *
+ * In Dithered mode
+ * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
+ */
+unsigned long pll_calc_rate(struct clk *clk, int index)
+{
+ unsigned long rate = clk->pclk->rate;
+ struct pll_rate_tbl *tbls = clk->rate_config.tbls;
+ unsigned int mode;
+
+ mode = tbls[index].mode ? 256 : 1;
+ return (((2 * rate / 10000) * tbls[index].m) /
+ (mode * tbls[index].n * (1 << tbls[index].p))) * 10000;
}
/*
@@ -297,13 +488,11 @@ static void change_parent(struct clk *cclk, struct clk *pclk)
* In Dithered mode
* rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
*/
-void pll_clk_recalc(struct clk *clk)
+int pll_clk_recalc(struct clk *clk)
{
struct pll_clk_config *config = clk->private_data;
unsigned int num = 2, den = 0, val, mode = 0;
- unsigned long flags;
- spin_lock_irqsave(&clocks_lock, flags);
mode = (readl(config->mode_reg) >> config->masks->mode_shift) &
config->masks->mode_mask;
@@ -325,22 +514,120 @@ void pll_clk_recalc(struct clk *clk)
den *= 256;
}
+ if (!den)
+ return -EINVAL;
+
clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
- spin_unlock_irqrestore(&clocks_lock, flags);
+ return 0;
+}
+
+/*
+ * Configures new clock rate of pll
+ */
+int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+ struct pll_rate_tbl *tbls = clk->rate_config.tbls;
+ struct pll_clk_config *config = clk->private_data;
+ unsigned long val, rate;
+ int i;
+
+ i = round_rate_index(clk, desired_rate, &rate);
+ if (i < 0)
+ return i;
+
+ val = readl(config->mode_reg) &
+ ~(config->masks->mode_mask << config->masks->mode_shift);
+ val |= (tbls[i].mode & config->masks->mode_mask) <<
+ config->masks->mode_shift;
+ writel(val, config->mode_reg);
+
+ val = readl(config->cfg_reg) &
+ ~(config->masks->div_p_mask << config->masks->div_p_shift);
+ val |= (tbls[i].p & config->masks->div_p_mask) <<
+ config->masks->div_p_shift;
+ val &= ~(config->masks->div_n_mask << config->masks->div_n_shift);
+ val |= (tbls[i].n & config->masks->div_n_mask) <<
+ config->masks->div_n_shift;
+ val &= ~(config->masks->dith_fdbk_m_mask <<
+ config->masks->dith_fdbk_m_shift);
+ if (tbls[i].mode)
+ val |= (tbls[i].m & config->masks->dith_fdbk_m_mask) <<
+ config->masks->dith_fdbk_m_shift;
+ else
+ val |= (tbls[i].m & config->masks->norm_fdbk_m_mask) <<
+ config->masks->norm_fdbk_m_shift;
+
+ writel(val, config->cfg_reg);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+/*
+ * Calculates ahb, apb clk rate for specific value of div
+ */
+unsigned long bus_calc_rate(struct clk *clk, int index)
+{
+ unsigned long rate = clk->pclk->rate;
+ struct bus_rate_tbl *tbls = clk->rate_config.tbls;
+
+ return rate / (tbls[index].div + 1);
}
/* calculates current programmed rate of ahb or apb bus */
-void bus_clk_recalc(struct clk *clk)
+int bus_clk_recalc(struct clk *clk)
{
struct bus_clk_config *config = clk->private_data;
unsigned int div;
- unsigned long flags;
- spin_lock_irqsave(&clocks_lock, flags);
div = ((readl(config->reg) >> config->masks->shift) &
config->masks->mask) + 1;
+
+ if (!div)
+ return -EINVAL;
+
clk->rate = (unsigned long)clk->pclk->rate / div;
- spin_unlock_irqrestore(&clocks_lock, flags);
+ return 0;
+}
+
+/* Configures new clock rate of AHB OR APB bus */
+int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+ struct bus_rate_tbl *tbls = clk->rate_config.tbls;
+ struct bus_clk_config *config = clk->private_data;
+ unsigned long val, rate;
+ int i;
+
+ i = round_rate_index(clk, desired_rate, &rate);
+ if (i < 0)
+ return i;
+
+ val = readl(config->reg) &
+ ~(config->masks->mask << config->masks->shift);
+ val |= (tbls[i].div & config->masks->mask) << config->masks->shift;
+ writel(val, config->reg);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+/*
+ * gives rate for different values of eq, x and y
+ *
+ * Fout from synthesizer can be given from two equations:
+ * Fout1 = (Fin * X/Y)/2 EQ1
+ * Fout2 = Fin * X/Y EQ2
+ */
+unsigned long aux_calc_rate(struct clk *clk, int index)
+{
+ unsigned long rate = clk->pclk->rate;
+ struct aux_rate_tbl *tbls = clk->rate_config.tbls;
+ u8 eq = tbls[index].eq ? 1 : 2;
+
+ return (((rate/10000) * tbls[index].xscale) /
+ (tbls[index].yscale * eq)) * 10000;
}
/*
@@ -353,47 +640,76 @@ void bus_clk_recalc(struct clk *clk)
*
* Selection of eqn 1 or 2 is programmed in register
*/
-void aux_clk_recalc(struct clk *clk)
+int aux_clk_recalc(struct clk *clk)
{
struct aux_clk_config *config = clk->private_data;
- struct pclk_info *pclk_info = NULL;
unsigned int num = 1, den = 1, val, eqn;
- unsigned long flags;
- /* get current programmed parent */
- pclk_info = pclk_info_get(clk);
- if (!pclk_info) {
- spin_lock_irqsave(&clocks_lock, flags);
- clk->pclk = NULL;
- clk->rate = 0;
- spin_unlock_irqrestore(&clocks_lock, flags);
- return;
- }
+ val = readl(config->synth_reg);
- change_parent(clk, pclk_info->pclk);
+ eqn = (val >> config->masks->eq_sel_shift) &
+ config->masks->eq_sel_mask;
+ if (eqn == config->masks->eq1_mask)
+ den *= 2;
- spin_lock_irqsave(&clocks_lock, flags);
- if (pclk_info->scalable) {
- val = readl(config->synth_reg);
-
- eqn = (val >> config->masks->eq_sel_shift) &
- config->masks->eq_sel_mask;
- if (eqn == config->masks->eq1_mask)
- den *= 2;
-
- /* calculate numerator */
- num = (val >> config->masks->xscale_sel_shift) &
- config->masks->xscale_sel_mask;
-
- /* calculate denominator */
- den *= (val >> config->masks->yscale_sel_shift) &
- config->masks->yscale_sel_mask;
- val = (((clk->pclk->rate/10000) * num) / den) * 10000;
- } else
- val = clk->pclk->rate;
+ /* calculate numerator */
+ num = (val >> config->masks->xscale_sel_shift) &
+ config->masks->xscale_sel_mask;
- clk->rate = val;
- spin_unlock_irqrestore(&clocks_lock, flags);
+ /* calculate denominator */
+ den *= (val >> config->masks->yscale_sel_shift) &
+ config->masks->yscale_sel_mask;
+
+ if (!den)
+ return -EINVAL;
+
+ clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
+ return 0;
+}
+
+/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
+int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+ struct aux_rate_tbl *tbls = clk->rate_config.tbls;
+ struct aux_clk_config *config = clk->private_data;
+ unsigned long val, rate;
+ int i;
+
+ i = round_rate_index(clk, desired_rate, &rate);
+ if (i < 0)
+ return i;
+
+ val = readl(config->synth_reg) &
+ ~(config->masks->eq_sel_mask << config->masks->eq_sel_shift);
+ val |= (tbls[i].eq & config->masks->eq_sel_mask) <<
+ config->masks->eq_sel_shift;
+ val &= ~(config->masks->xscale_sel_mask <<
+ config->masks->xscale_sel_shift);
+ val |= (tbls[i].xscale & config->masks->xscale_sel_mask) <<
+ config->masks->xscale_sel_shift;
+ val &= ~(config->masks->yscale_sel_mask <<
+ config->masks->yscale_sel_shift);
+ val |= (tbls[i].yscale & config->masks->yscale_sel_mask) <<
+ config->masks->yscale_sel_shift;
+ writel(val, config->synth_reg);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+/*
+ * Calculates gpt clk rate for different values of mscale and nscale
+ *
+ * Fout= Fin/((2 ^ (N+1)) * (M+1))
+ */
+unsigned long gpt_calc_rate(struct clk *clk, int index)
+{
+ unsigned long rate = clk->pclk->rate;
+ struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
+
+ return rate / ((1 << (tbls[index].nscale + 1)) *
+ (tbls[index].mscale + 1));
}
/*
@@ -401,49 +717,142 @@ void aux_clk_recalc(struct clk *clk)
* Fout from synthesizer can be given from below equations:
* Fout= Fin/((2 ^ (N+1)) * (M+1))
*/
-void gpt_clk_recalc(struct clk *clk)
+int gpt_clk_recalc(struct clk *clk)
{
struct gpt_clk_config *config = clk->private_data;
- struct pclk_info *pclk_info = NULL;
unsigned int div = 1, val;
- unsigned long flags;
- pclk_info = pclk_info_get(clk);
- if (!pclk_info) {
- spin_lock_irqsave(&clocks_lock, flags);
- clk->pclk = NULL;
- clk->rate = 0;
- spin_unlock_irqrestore(&clocks_lock, flags);
- return;
- }
+ val = readl(config->synth_reg);
+ div += (val >> config->masks->mscale_sel_shift) &
+ config->masks->mscale_sel_mask;
+ div *= 1 << (((val >> config->masks->nscale_sel_shift) &
+ config->masks->nscale_sel_mask) + 1);
- change_parent(clk, pclk_info->pclk);
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (pclk_info->scalable) {
- val = readl(config->synth_reg);
- div += (val >> config->masks->mscale_sel_shift) &
- config->masks->mscale_sel_mask;
- div *= 1 << (((val >> config->masks->nscale_sel_shift) &
- config->masks->nscale_sel_mask) + 1);
- }
+ if (!div)
+ return -EINVAL;
clk->rate = (unsigned long)clk->pclk->rate / div;
- spin_unlock_irqrestore(&clocks_lock, flags);
+ return 0;
+}
+
+/* Configures new clock rate of gptiliary synthesizers used by: UART, FIRDA*/
+int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+ struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
+ struct gpt_clk_config *config = clk->private_data;
+ unsigned long val, rate;
+ int i;
+
+ i = round_rate_index(clk, desired_rate, &rate);
+ if (i < 0)
+ return i;
+
+ val = readl(config->synth_reg) & ~(config->masks->mscale_sel_mask <<
+ config->masks->mscale_sel_shift);
+ val |= (tbls[i].mscale & config->masks->mscale_sel_mask) <<
+ config->masks->mscale_sel_shift;
+ val &= ~(config->masks->nscale_sel_mask <<
+ config->masks->nscale_sel_shift);
+ val |= (tbls[i].nscale & config->masks->nscale_sel_mask) <<
+ config->masks->nscale_sel_shift;
+ writel(val, config->synth_reg);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+/*
+ * Calculates clcd clk rate for different values of div
+ *
+ * Fout from synthesizer can be given from below equation:
+ * Fout= Fin/2*div (division factor)
+ * div is 17 bits:-
+ * 0-13 (fractional part)
+ * 14-16 (integer part)
+ * To calculate Fout we left shift val by 14 bits and divide Fin by
+ * complete div (including fractional part) and then right shift the
+ * result by 14 places.
+ */
+unsigned long clcd_calc_rate(struct clk *clk, int index)
+{
+ unsigned long rate = clk->pclk->rate;
+ struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
+
+ rate /= 1000;
+ rate <<= 12;
+ rate /= (2 * tbls[index].div);
+ rate >>= 12;
+ rate *= 1000;
+
+ return rate;
+}
+
+/*
+ * calculates current programmed rate of clcd synthesizer
+ * Fout from synthesizer can be given from below equation:
+ * Fout= Fin/2*div (division factor)
+ * div is 17 bits:-
+ * 0-13 (fractional part)
+ * 14-16 (integer part)
+ * To calculate Fout we left shift val by 14 bits and divide Fin by
+ * complete div (including fractional part) and then right shift the
+ * result by 14 places.
+ */
+int clcd_clk_recalc(struct clk *clk)
+{
+ struct clcd_clk_config *config = clk->private_data;
+ unsigned int div = 1;
+ unsigned long prate;
+ unsigned int val;
+
+ val = readl(config->synth_reg);
+ div = (val >> config->masks->div_factor_shift) &
+ config->masks->div_factor_mask;
+
+ if (!div)
+ return -EINVAL;
+
+ prate = clk->pclk->rate / 1000; /* first level division, make it KHz */
+
+ clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
+ clk->rate *= 1000;
+ return 0;
+}
+
+/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
+int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+ struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
+ struct clcd_clk_config *config = clk->private_data;
+ unsigned long val, rate;
+ int i;
+
+ i = round_rate_index(clk, desired_rate, &rate);
+ if (i < 0)
+ return i;
+
+ val = readl(config->synth_reg) & ~(config->masks->div_factor_mask <<
+ config->masks->div_factor_shift);
+ val |= (tbls[i].div & config->masks->div_factor_mask) <<
+ config->masks->div_factor_shift;
+ writel(val, config->synth_reg);
+
+ clk->rate = rate;
+
+ return 0;
}
/*
* Used for clocks that always have value as the parent clock divided by a
* fixed divisor
*/
-void follow_parent(struct clk *clk)
+int follow_parent(struct clk *clk)
{
- unsigned long flags;
unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor;
- spin_lock_irqsave(&clocks_lock, flags);
clk->rate = clk->pclk->rate/div_factor;
- spin_unlock_irqrestore(&clocks_lock, flags);
+ return 0;
}
/**
@@ -454,5 +863,25 @@ void follow_parent(struct clk *clk)
*/
void recalc_root_clocks(void)
{
- propagate_rate(&root_clks);
+ struct clk *pclk;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ list_for_each_entry(pclk, &root_clks, sibling) {
+ if (pclk->recalc) {
+ ret = pclk->recalc(pclk);
+ /*
+ * recalc will return error if clk out is not programmed
+ * In this case configure default clock.
+ */
+ if (ret && pclk->set_rate)
+ pclk->set_rate(pclk, 0);
+ }
+ propagate_rate(pclk, 1);
+ /* Enable clks enabled on init, in software view */
+ if (pclk->flags & ENABLED_ON_INIT)
+ do_clk_enable(pclk);
+ }
+ spin_unlock_irqrestore(&clocks_lock, flags);
}
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index 863d9e9..5a601d8 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -21,6 +21,7 @@
/* clk structure flags */
#define ALWAYS_ENABLED (1 << 0) /* clock always enabled */
#define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */
+#define ENABLED_ON_INIT (1 << 2) /* clocks enabled@init */
/**
* struct clkops - clock operations
@@ -35,13 +36,11 @@ struct clkops {
/**
* struct pclk_info - parents info
* @pclk: pointer to parent clk
- * @pclk_mask: value to be written for selecting this parent
- * @scalable: Is parent scalable (1 - YES, 0 - NO)
+ * @pclk_val: value to be written for selecting this parent
*/
struct pclk_info {
struct clk *pclk;
- u8 pclk_mask;
- u8 scalable;
+ u8 pclk_val;
};
/**
@@ -59,6 +58,18 @@ struct pclk_sel {
};
/**
+ * struct rate_config - clk rate configurations
+ * @tbls: array of device specific clk rate tables, in ascending order of rates
+ * @count: size of tbls array
+ * @default_index: default setting when originally disabled
+ */
+struct rate_config {
+ void *tbls;
+ u8 count;
+ u8 default_index;
+};
+
+/**
* struct clk - clock structure
* @usage_count: num of users who enabled this clock
* @flags: flags for clock properties
@@ -67,7 +78,10 @@ struct pclk_sel {
* @en_reg_bit: clk enable/disable bit
* @ops: clk enable/disable ops - generic_clkops selected if NULL
* @recalc: pointer to clock rate recalculate function
- * @div_factor: division factor to parent clock. Only for recalc = follow_parent
+ * @set_rate: pointer to clock set rate function
+ * @calc_rate: pointer to clock get rate function for index
+ * @rate_config: rate configuration information, used by set_rate
+ * @div_factor: division factor to parent clock.
* @pclk: current parent clk
* @pclk_sel: pointer to parent selection structure
* @pclk_sel_shift: register shift for selecting parent of this clock
@@ -82,7 +96,10 @@ struct clk {
void __iomem *en_reg;
u8 en_reg_bit;
const struct clkops *ops;
- void (*recalc) (struct clk *);
+ int (*recalc) (struct clk *);
+ int (*set_rate) (struct clk *, unsigned long rate);
+ unsigned long (*calc_rate)(struct clk *, int index);
+ struct rate_config rate_config;
unsigned int div_factor;
struct clk *pclk;
@@ -115,6 +132,14 @@ struct pll_clk_config {
struct pll_clk_masks *masks;
};
+/* pll clk rate config structure */
+struct pll_rate_tbl {
+ u8 mode;
+ u16 m;
+ u8 n;
+ u8 p;
+};
+
/* ahb and apb bus configuration structure */
struct bus_clk_masks {
u32 mask;
@@ -126,6 +151,11 @@ struct bus_clk_config {
struct bus_clk_masks *masks;
};
+/* ahb and apb clk bus rate config structure */
+struct bus_rate_tbl {
+ u8 div;
+};
+
/* Aux clk configuration structure: applicable to UART and FIRDA */
struct aux_clk_masks {
u32 eq_sel_mask;
@@ -143,6 +173,13 @@ struct aux_clk_config {
struct aux_clk_masks *masks;
};
+/* aux clk rate config structure */
+struct aux_rate_tbl {
+ u16 xscale;
+ u16 yscale;
+ u8 eq;
+};
+
/* GPT clk configuration structure */
struct gpt_clk_masks {
u32 mscale_sel_mask;
@@ -156,15 +193,48 @@ struct gpt_clk_config {
struct gpt_clk_masks *masks;
};
+/* gpt clk rate config structure */
+struct gpt_rate_tbl {
+ u16 mscale;
+ u16 nscale;
+};
+
+/* clcd clk configuration structure */
+struct clcd_synth_masks {
+ u32 div_factor_mask;
+ u32 div_factor_shift;
+};
+
+struct clcd_clk_config {
+ void __iomem *synth_reg;
+ struct clcd_synth_masks *masks;
+};
+
+/* clcd clk rate config structure */
+struct clcd_rate_tbl {
+ u16 div;
+};
+
/* platform specific clock functions */
void clk_register(struct clk_lookup *cl);
void recalc_root_clocks(void);
-/* clock recalc functions */
-void follow_parent(struct clk *clk);
-void pll_clk_recalc(struct clk *clk);
-void bus_clk_recalc(struct clk *clk);
-void gpt_clk_recalc(struct clk *clk);
-void aux_clk_recalc(struct clk *clk);
+/* clock recalc & set rate functions */
+int follow_parent(struct clk *clk);
+unsigned long pll_calc_rate(struct clk *clk, int index);
+int pll_clk_recalc(struct clk *clk);
+int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long bus_calc_rate(struct clk *clk, int index);
+int bus_clk_recalc(struct clk *clk);
+int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long gpt_calc_rate(struct clk *clk, int index);
+int gpt_clk_recalc(struct clk *clk);
+int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long aux_calc_rate(struct clk *clk, int index);
+int aux_clk_recalc(struct clk *clk);
+int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long clcd_calc_rate(struct clk *clk, int index);
+int clcd_clk_recalc(struct clk *clk);
+int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
#endif /* __PLAT_CLOCK_H */
--
1.7.2.2
^ permalink raw reply related
* [RFC,PATCH 1/3] Add a common struct clk
From: Jeremy Kerr @ 2011-02-15 9:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110215083759.GA4152@n2100.arm.linux.org.uk>
Hi Russell,
> > Why is that? Consider two devices using one clock; one does some
> > initialisation based on the return value of clk_get_rate(), the other
> > calls clk_set_rate() some time later. Now the first device is
> > incorrectly initialised.
>
> What about a clock sourced from a PLL which provides the dotclock for a
> framebuffer device? On every mode set, should the clk have to be disabled,
> unprepared, rate set, re-prepared and re-enabled?
Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.
Other options are:
* Require that the driver has called clk_prepare, and that prepare_count
is 1 during the set_rate call (indicating that this is the only user); or
* Leave the set_rate and set_parent semantics as-is and assume that anything
calling either knows what it's doing (and that it won't affect other
devices)
Are you OK if we address this separately to the API unification though?
Cheers,
Jeremy
^ permalink raw reply
* [PATCH 3/5] ARM: l2x0: Errata fix for flush by Way operation can cause data corruption
From: Santosh Shilimkar @ 2011-02-15 9:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTinSOUPZuDikusgnT99Qmqv8p+DNQu2Hu42N=yJb@mail.gmail.com>
> -----Original Message-----
> From: Andrei Warkentin [mailto:andreiw at motorola.com]
> Sent: Tuesday, February 15, 2011 2:40 PM
> To: Santosh Shilimkar
> Cc: linux-arm-kernel at lists.infradead.org; linux-
> omap at vger.kernel.org; Kevin Hilman; tony at atomide.com; Catalin
> Marinas
> Subject: Re: [PATCH 3/5] ARM: l2x0: Errata fix for flush by Way
> operation can cause data corruption
>
> On Tue, Feb 15, 2011 at 1:14 AM, Santosh Shilimkar
> <santosh.shilimkar@ti.com> wrote:
> >> -----Original Message-----
> >> From: Santosh Shilimkar [mailto:santosh.shilimkar at ti.com]
> >> Sent: Monday, February 14, 2011 10:39 AM
> >> To: Andrei Warkentin
> >> Cc: linux-omap at vger.kernel.org; Kevin Hilman; tony at atomide.com;
> >> linux-arm-kernel at lists.infradead.org; Catalin Marinas
> >> Subject: RE: [PATCH 3/5] ARM: l2x0: Errata fix for flush by Way
> >> operation can cause data corruption
> >>
> >
[....]
> >
>
> Why set by default to NULL, why not have a normal l2x0_set_debug
> which
> just does a write to L2X0_DEBUG_CTRL, and then just invoke the
> function pointer when you wish to manipulate the DCR? That way you
> don't need the runtime check, and it's just clearer, I think.
>
I though about it. There more changes in the file and hence I
avoided it. This can be done though.
> Also, why not do something like -
> ....
> do_stuff();
> #ifdef CONFIG_NEED_ERRATA_1234
> do_errata_stuff();
> #endif
> do_more_stuff();
> ...
>
Which makes code completely ugly.
> instead of -
>
> ...
> #ifdef CONFIG_NEED_ERRATA_1234
> do_some_stuf() {
> bar();
> }
> #else
> {
> do_some_stuff() {
> }
> // nothing
> }
>
We have already discussed this. The code becomes ugly. If you
are interested in the reasoning, please check archives.
Russell and Catalin has suggested above.
If you understand the errata in first place, you could
understand the comment.
I let Catalin, Russell comment on it more, but unnecessary
CONFIG options and polluting every function with #If, else
checks don't make sense. Rest of your comments are related
to this.
Regards,
Santosh
^ permalink raw reply
* [PATCH V5 resend 39/63] SPEAr CPU freq: Adding support for CPU Freq framework
From: viresh kumar @ 2011-02-15 9:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D5A4200.3000303@windriver.com>
On 02/15/2011 02:36 PM, stanley.miao wrote:
> Viresh Kumar wrote:
>> > From: Deepak Sikri <deepak.sikri@st.com>
>> >
>> > <snip>
>> > +
>> > + newfreq = clk_round_rate(cpu_clk, spear_cpu_freq[index] * 1000);
>> > + if (newfreq < 0) {
>> > + pr_err("CPU Freq: clk_round_rate failed: %ld\n", newfreq);
>> > + return newfreq;
>> > + }
>> >
> clk_round_rate will call round_rate_index();
> --------------------------
>
> static int
> round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate)
> {
> unsigned long tmp = 0, prev_rate = 0;
> int index;
>
> if (!clk->calc_rate)
> return -EFAULT;
>
> ------------------------------------------
>
> The cpu_clk don't have calc_rate, clk_round_rate always return fault.
I will resend this patch with this issue resolved.
--
viresh
^ permalink raw reply
* [PATCH] ARM: Samsung: change suspend/resume code to depend on CONFIG_SUSPEND
From: Marek Szyprowski @ 2011-02-15 9:15 UTC (permalink / raw)
To: linux-arm-kernel
Most suspend/resume code depends on CONFIG_PM. This causes problems
if one wants to enable Runtime PM (to control power domains for example),
but doesn't need system suspend/resume feature. This also enables to use
Runtime PM feature on S5PV310 which doesn't implement system suspend/resume
callbacks yet.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s3c2410/mach-bast.c | 2 +-
arch/arm/mach-s3c2412/mach-jive.c | 2 +-
arch/arm/mach-s3c2440/mach-osiris.c | 2 +-
arch/arm/mach-s3c2440/s3c244x.c | 2 +-
arch/arm/mach-s3c64xx/Makefile | 6 +++---
arch/arm/mach-s5pv210/cpufreq.c | 4 ++--
arch/arm/mach-s5pv310/cpufreq.c | 4 ++--
arch/arm/mach-s5pv310/irq-eint.c | 2 +-
arch/arm/plat-s3c24xx/Makefile | 6 +++---
arch/arm/plat-s3c24xx/cpu-freq.c | 2 +-
arch/arm/plat-s3c24xx/dma.c | 2 +-
arch/arm/plat-s3c24xx/include/plat/irq.h | 2 +-
arch/arm/plat-s5p/Makefile | 4 ++--
arch/arm/plat-s5p/irq-eint.c | 4 ++--
arch/arm/plat-samsung/Makefile | 4 ++--
arch/arm/plat-samsung/adc.c | 2 +-
arch/arm/plat-samsung/gpio.c | 2 +-
arch/arm/plat-samsung/include/plat/gpio-core.h | 6 +++---
arch/arm/plat-samsung/include/plat/pm.h | 4 ++--
arch/arm/plat-samsung/pwm.c | 2 +-
20 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 2970ea9..18187a4 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -213,7 +213,7 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
/* NAND Flash on BAST board */
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static int bast_pm_suspend(struct sys_device *sd, pm_message_t state)
{
/* ensure that an nRESET is not generated on resume. */
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 923e01b..10643ef8 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -485,7 +485,7 @@ static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = {
/* Jive power management device */
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static int jive_pm_suspend(struct sys_device *sd, pm_message_t state)
{
/* Write the magic value u-boot uses to check for resume into
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 14dc678..06d115a 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -281,7 +281,7 @@ static struct platform_device osiris_pcmcia = {
/* Osiris power management device */
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static unsigned char pm_osiris_ctrl0;
static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
diff --git a/arch/arm/mach-s3c2440/s3c244x.c b/arch/arm/mach-s3c2440/s3c244x.c
index 90c1707..7e693a0 100644
--- a/arch/arm/mach-s3c2440/s3c244x.c
+++ b/arch/arm/mach-s3c2440/s3c244x.c
@@ -134,7 +134,7 @@ void __init s3c244x_init_clocks(int xtal)
s3c2410_baseclk_add();
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static struct sleep_save s3c244x_sleep[] = {
SAVE_ITEM(S3C2440_DSC0),
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 4657363..183ebb3 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -43,9 +43,9 @@ obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
# PM
-obj-$(CONFIG_PM) += pm.o
-obj-$(CONFIG_PM) += sleep.o
-obj-$(CONFIG_PM) += irq-pm.o
+obj-$(CONFIG_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += sleep.o
+obj-$(CONFIG_SUSPEND) += irq-pm.o
# Machine support
diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c
index a6f2292..7e697cd 100644
--- a/arch/arm/mach-s5pv210/cpufreq.c
+++ b/arch/arm/mach-s5pv210/cpufreq.c
@@ -389,7 +389,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy,
pm_message_t pmsg)
{
@@ -470,7 +470,7 @@ static struct cpufreq_driver s5pv210_driver = {
.get = s5pv210_getspeed,
.init = s5pv210_cpu_init,
.name = "s5pv210",
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
.suspend = s5pv210_cpufreq_suspend,
.resume = s5pv210_cpufreq_resume,
#endif
diff --git a/arch/arm/mach-s5pv310/cpufreq.c b/arch/arm/mach-s5pv310/cpufreq.c
index b04cbc7..8493b6d 100644
--- a/arch/arm/mach-s5pv310/cpufreq.c
+++ b/arch/arm/mach-s5pv310/cpufreq.c
@@ -457,7 +457,7 @@ static int s5pv310_target(struct cpufreq_policy *policy,
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static int s5pv310_cpufreq_suspend(struct cpufreq_policy *policy,
pm_message_t pmsg)
{
@@ -497,7 +497,7 @@ static struct cpufreq_driver s5pv310_driver = {
.get = s5pv310_getspeed,
.init = s5pv310_cpufreq_cpu_init,
.name = "s5pv310_cpufreq",
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
.suspend = s5pv310_cpufreq_suspend,
.resume = s5pv310_cpufreq_resume,
#endif
diff --git a/arch/arm/mach-s5pv310/irq-eint.c b/arch/arm/mach-s5pv310/irq-eint.c
index 477bd9e..39c7f7b 100644
--- a/arch/arm/mach-s5pv310/irq-eint.c
+++ b/arch/arm/mach-s5pv310/irq-eint.c
@@ -152,7 +152,7 @@ static struct irq_chip s5pv310_irq_eint = {
.irq_mask_ack = s5pv310_irq_eint_maskack,
.irq_ack = s5pv310_irq_eint_ack,
.irq_set_type = s5pv310_irq_eint_set_type,
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
.irq_set_wake = s3c_irqext_wake,
#endif
};
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
index c2064c3..763b7bb 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -26,9 +26,9 @@ obj-$(CONFIG_CPU_FREQ_S3C24XX_DEBUGFS) += cpu-freq-debugfs.o
# Architecture dependant builds
obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
-obj-$(CONFIG_PM) += pm.o
-obj-$(CONFIG_PM) += irq-pm.o
-obj-$(CONFIG_PM) += sleep.o
+obj-$(CONFIG_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += irq-pm.o
+obj-$(CONFIG_SUSPEND) += sleep.o
obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
obj-$(CONFIG_S3C2443_CLOCK) += s3c2443-clock.o
obj-$(CONFIG_S3C2410_DMA) += dma.o
diff --git a/arch/arm/plat-s3c24xx/cpu-freq.c b/arch/arm/plat-s3c24xx/cpu-freq.c
index 25a8fc7..1d38db5 100644
--- a/arch/arm/plat-s3c24xx/cpu-freq.c
+++ b/arch/arm/plat-s3c24xx/cpu-freq.c
@@ -429,7 +429,7 @@ static int s3c_cpufreq_verify(struct cpufreq_policy *policy)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static struct cpufreq_frequency_table suspend_pll;
static unsigned int suspend_freq;
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 6ad274e..6199b6e 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1202,7 +1202,7 @@ static inline struct s3c2410_dma_chan *to_dma_chan(struct sys_device *dev)
/* system device class */
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
{
diff --git a/arch/arm/plat-s3c24xx/include/plat/irq.h b/arch/arm/plat-s3c24xx/include/plat/irq.h
index ec087d6..ca6354f 100644
--- a/arch/arm/plat-s3c24xx/include/plat/irq.h
+++ b/arch/arm/plat-s3c24xx/include/plat/irq.h
@@ -106,7 +106,7 @@ s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
/* exported for use in arch/arm/mach-s3c2410 */
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
#else
#define s3c_irq_wake NULL
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index 4bd5cf9..ce5a0a7 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -20,8 +20,8 @@ obj-y += irq.o
obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o
obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.o
-obj-$(CONFIG_PM) += pm.o
-obj-$(CONFIG_PM) += irq-pm.o
+obj-$(CONFIG_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += irq-pm.o
# devices
diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c
index 225aa25..e203a65 100644
--- a/arch/arm/plat-s5p/irq-eint.c
+++ b/arch/arm/plat-s5p/irq-eint.c
@@ -125,7 +125,7 @@ static struct irq_chip s5p_irq_eint = {
.irq_mask_ack = s5p_irq_eint_maskack,
.irq_ack = s5p_irq_eint_ack,
.irq_set_type = s5p_irq_eint_set_type,
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
.irq_set_wake = s3c_irqext_wake,
#endif
};
@@ -195,7 +195,7 @@ static struct irq_chip s5p_irq_vic_eint = {
.irq_mask_ack = s5p_irq_vic_eint_maskack,
.irq_ack = s5p_irq_vic_eint_ack,
.irq_set_type = s5p_irq_eint_set_type,
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
.irq_set_wake = s3c_irqext_wake,
#endif
};
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 29932f8..7e92457 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -68,8 +68,8 @@ obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o
# PM support
-obj-$(CONFIG_PM) += pm.o
-obj-$(CONFIG_PM) += pm-gpio.o
+obj-$(CONFIG_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += pm-gpio.o
obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o
obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index e8f2be2..d818405 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -412,7 +412,7 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct adc_device *adc = platform_get_drvdata(pdev);
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c
index 7743c4b..4f3700f 100644
--- a/arch/arm/plat-samsung/gpio.c
+++ b/arch/arm/plat-samsung/gpio.c
@@ -143,7 +143,7 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
if (!gc->get)
gc->get = s3c_gpiolib_get;
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
if (chip->pm != NULL) {
if (!chip->pm->save || !chip->pm->resume)
printk(KERN_ERR "gpio: %s has missing PM functions\n",
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index dac35d0..8b5209b 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -68,7 +68,7 @@ struct s3c_gpio_chip {
int irq_base;
int group;
spinlock_t lock;
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
u32 pm_save[4];
#endif
};
@@ -153,7 +153,7 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
#endif
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
@@ -164,7 +164,7 @@ extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
#define s3c_gpio_pm_4bit NULL
#define __gpio_pm(x) NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_SUSPEND */
/* locking wrappers to deal with multiple access to the same gpio bank */
#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 30518cc..69f4cc8 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -19,7 +19,7 @@
struct sys_device;
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
extern __init int s3c_pm_init(void);
@@ -103,7 +103,7 @@ extern void s3c_pm_do_save(struct sleep_save *ptr, int count);
extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
extern int s3c24xx_irq_resume(struct sys_device *dev);
diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c
index 2eeb49f..926f08d 100644
--- a/arch/arm/plat-samsung/pwm.c
+++ b/arch/arm/plat-samsung/pwm.c
@@ -380,7 +380,7 @@ static int __devexit s3c_pwm_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_SUSPEND
static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state)
{
struct pwm_device *pwm = platform_get_drvdata(pdev);
--
1.7.1.569.g6f426
^ permalink raw reply related
* [PATCH 3/5] ARM: l2x0: Errata fix for flush by Way operation can cause data corruption
From: Andrei Warkentin @ 2011-02-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4dfaffa99292bf8e36791ea9a68de75e@mail.gmail.com>
On Tue, Feb 15, 2011 at 1:14 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
>> -----Original Message-----
>> From: Santosh Shilimkar [mailto:santosh.shilimkar at ti.com]
>> Sent: Monday, February 14, 2011 10:39 AM
>> To: Andrei Warkentin
>> Cc: linux-omap at vger.kernel.org; Kevin Hilman; tony at atomide.com;
>> linux-arm-kernel at lists.infradead.org; Catalin Marinas
>> Subject: RE: [PATCH 3/5] ARM: l2x0: Errata fix for flush by Way
>> operation can cause data corruption
>>
>
> [....]
>
>> > ...
>> I understood that from first comment. But I am not in favor
>> of polluting common ARM files with SOC specific #ifdeffery.
>> We have gone over this when first errata support
>> was added for PL310
>>
>> I have a better way to handle this scenario.
>> Expect an updated patch for this.
>>
>
> Below is the updated version which should remove any
> OMAP dependency on these errata's. Attached same.
>
> ----
> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Date: Fri, 14 Jan 2011 14:16:04 +0530
> Subject: [v2 PATCH 3/5] ARM: l2x0: Errata fix for flush by Way operation
> can cause data corruption
>
> 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.
>
> Workaround:
> Disable Write-Back and Cache Linefill (Debug Control Register)
> Clean & Invalidate by Way (0x7FC)
> Re-enable Write-Back and Cache Linefill (Debug Control Register)
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> ---
> ?arch/arm/Kconfig ? ? ? ? ? ? ? ? ? | ? 13 ++++++++++++-
> ?arch/arm/include/asm/outercache.h ?| ? ?1 +
> ?arch/arm/mach-omap2/Kconfig ? ? ? ?| ? ?3 +++
> ?arch/arm/mach-omap2/omap4-common.c | ? ?7 +++++++
> ?arch/arm/mm/cache-l2x0.c ? ? ? ? ? | ? 28 +++++++++++++++-------------
> ?5 files changed, 38 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 5cff165..ebadd95 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1140,7 +1140,7 @@ config ARM_ERRATA_742231
>
> ?config PL310_ERRATA_588369
> ? ? ? ?bool "Clean & Invalidate maintenance operations do not invalidate
> clean lines"
> - ? ? ? depends on CACHE_L2X0 && ARCH_OMAP4
> + ? ? ? depends on CACHE_L2X0 && CACHE_PL310
> ? ? ? ?help
> ? ? ? ? ? The PL310 L2 cache controller implements three types of Clean &
> ? ? ? ? ? Invalidate maintenance operations: by Physical Address
> @@ -1177,6 +1177,17 @@ config ARM_ERRATA_743622
> ? ? ? ? ?visible impact on the overall performance or power consumption
> of the
> ? ? ? ? ?processor.
>
> +config PL310_ERRATA_727915
> + ? ? ? bool "Background Clean & Invalidate by Way operation can cause
> data corruption"
> + ? ? ? depends on CACHE_L2X0 && CACHE_PL310
> + ? ? ? 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 Note that this errata uses Texas
> + ? ? ? ? Instrument's secure monitor api to implement the work around.
> ?endmenu
>
> ?source "arch/arm/common/Kconfig"
> diff --git a/arch/arm/include/asm/outercache.h
> b/arch/arm/include/asm/outercache.h
> index fc19009..348d513 100644
> --- a/arch/arm/include/asm/outercache.h
> +++ b/arch/arm/include/asm/outercache.h
> @@ -31,6 +31,7 @@ struct outer_cache_fns {
> ?#ifdef CONFIG_OUTER_CACHE_SYNC
> ? ? ? ?void (*sync)(void);
> ?#endif
> + ? ? ? void (*set_debug)(unsigned long);
> ?};
>
> ?#ifdef CONFIG_OUTER_CACHE
> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
> index f285dd7..fd11ab4 100644
> --- a/arch/arm/mach-omap2/Kconfig
> +++ b/arch/arm/mach-omap2/Kconfig
> @@ -45,7 +45,10 @@ config ARCH_OMAP4
> ? ? ? ?select CPU_V7
> ? ? ? ?select ARM_GIC
> ? ? ? ?select LOCAL_TIMERS
> + ? ? ? select CACHE_L2X0
> + ? ? ? select CACHE_PL310
> ? ? ? ?select PL310_ERRATA_588369
> + ? ? ? select PL310_ERRATA_727915
> ? ? ? ?select ARM_ERRATA_720789
> ? ? ? ?select ARCH_HAS_OPP
> ? ? ? ?select PM_OPP if PM
> diff --git a/arch/arm/mach-omap2/omap4-common.c
> b/arch/arm/mach-omap2/omap4-common.c
> index 1926864..9ef8c29 100644
> --- a/arch/arm/mach-omap2/omap4-common.c
> +++ b/arch/arm/mach-omap2/omap4-common.c
> @@ -52,6 +52,12 @@ static void omap4_l2x0_disable(void)
> ? ? ? ?omap_smc1(0x102, 0x0);
> ?}
>
> +static void omap4_l2x0_set_debug(unsigned long val)
> +{
> + ? ? ? /* Program PL310 L2 Cache controller debug register */
> + ? ? ? omap_smc1(0x100, val);
> +}
> +
> ?static int __init omap_l2_cache_init(void)
> ?{
> ? ? ? ?u32 aux_ctrl = 0;
> @@ -99,6 +105,7 @@ static int __init omap_l2_cache_init(void)
> ? ? ? ? * specific one
> ? ? ? ?*/
> ? ? ? ?outer_cache.disable = omap4_l2x0_disable;
> + ? ? ? outer_cache.set_debug = omap4_l2x0_set_debug;
>
> ? ? ? ?return 0;
> ?}
> diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
> index 170c9bb..a8caee4 100644
> --- a/arch/arm/mm/cache-l2x0.c
> +++ b/arch/arm/mm/cache-l2x0.c
> @@ -67,18 +67,22 @@ static inline void l2x0_inv_line(unsigned long addr)
> ? ? ? ?writel_relaxed(addr, base + L2X0_INV_LINE_PA);
> ?}
>
> -#ifdef CONFIG_PL310_ERRATA_588369
> +#if defined(CONFIG_PL310_ERRATA_588369) ||
> defined(CONFIG_PL310_ERRATA_727915)
> ?static void debug_writel(unsigned long val)
> ?{
> - ? ? ? extern void omap_smc1(u32 fn, u32 arg);
> -
> - ? ? ? /*
> - ? ? ? ?* Texas Instrument secure monitor api to modify the
> - ? ? ? ?* PL310 Debug Control Register.
> - ? ? ? ?*/
> - ? ? ? omap_smc1(0x100, val);
> + ? ? ? if (outer_cache.set_debug)
> + ? ? ? ? ? ? ? outer_cache.set_debug(val);
> + ? ? ? else
> + ? ? ? ? ? ? ? writel(val, l2x0_base + L2X0_DEBUG_CTRL);
> +}
> +#else
> +/* Optimised out for non-errata case */
> +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;
> @@ -91,11 +95,6 @@ static inline void l2x0_flush_line(unsigned long addr)
> ?}
> ?#else
>
> -/* Optimised out for non-errata case */
> -static inline void debug_writel(unsigned long val)
> -{
> -}
> -
> ?static inline void l2x0_flush_line(unsigned long addr)
> ?{
> ? ? ? ?void __iomem *base = l2x0_base;
> @@ -119,9 +118,11 @@ static void l2x0_flush_all(void)
>
> ? ? ? ?/* clean all ways */
> ? ? ? ?spin_lock_irqsave(&l2x0_lock, flags);
> + ? ? ? 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);
> ? ? ? ?cache_sync();
> + ? ? ? debug_writel(0x00);
> ? ? ? ?spin_unlock_irqrestore(&l2x0_lock, flags);
> ?}
>
> @@ -329,6 +330,7 @@ void __init l2x0_init(void __iomem *base, __u32
> aux_val, __u32 aux_mask)
> ? ? ? ?outer_cache.flush_all = l2x0_flush_all;
> ? ? ? ?outer_cache.inv_all = l2x0_inv_all;
> ? ? ? ?outer_cache.disable = l2x0_disable;
> + ? ? ? outer_cache.set_debug = NULL;
>
> ? ? ? ?printk(KERN_INFO "%s cache controller enabled\n", type);
> ? ? ? ?printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x,
> Cache size: %d B\n",
> --
> 1.6.0.4
>
Why set by default to NULL, why not have a normal l2x0_set_debug which
just does a write to L2X0_DEBUG_CTRL, and then just invoke the
function pointer when you wish to manipulate the DCR? That way you
don't need the runtime check, and it's just clearer, I think.
Also, why not do something like -
....
do_stuff();
#ifdef CONFIG_NEED_ERRATA_1234
do_errata_stuff();
#endif
do_more_stuff();
...
instead of -
...
#ifdef CONFIG_NEED_ERRATA_1234
do_some_stuf() {
bar();
}
#else
{
do_some_stuff() {
}
// nothing
}
do_stuff();
do_some_stuff();
do_more_stuff();
It's not exactly clear otherwise what's happening and why there are
these extra calls that sometimes are compiled in, and sometimes
aren't. The way I am suggesting, you would just look at a function
block and you can easily tell what is different in the errata case,
and you don't need to jump back and forth to figure that out. I think
it makes for cleaner code.
And it would be nice if the errata had some revision data attached to
them, as in my suggestion patch I sent earlier. It's a nuisance to
look at Kconfig wondering which errata you might be interested in,
especially if your platform spans several generations and revs of
different parts. Then you need to dig up an errata sheet and scan it
yourself. The alternative is to be able to select a known rev for
PL310, for example, which would just pick the errata that apply to
that rev, or at least mention the affected revs in the documentation
for the option.
^ permalink raw reply
* [PATCH 2/2] ARM: S5PC110: add power consumers for hsotg for Goni board
From: Marek Szyprowski @ 2011-02-15 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297760784-8486-1-git-send-email-m.szyprowski@samsung.com>
This patch adds definitions for power consumers for s3c-hsotg driver
on Goni board. The consumers are defined as arrays, because later more
entries for MIPI and ADC will be defined.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pv210/mach-goni.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 10f754b..796625c 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -269,10 +269,18 @@ static void __init goni_tsp_init(void)
/* MAX8998 regulators */
#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
+static struct regulator_consumer_supply goni_ldo3_consumers[] = {
+ REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
+};
+
static struct regulator_consumer_supply goni_ldo5_consumers[] = {
REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
};
+static struct regulator_consumer_supply goni_ldo8_consumers[] = {
+ REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
+};
+
static struct regulator_init_data goni_ldo2_data = {
.constraints = {
.name = "VALIVE_1.1V",
@@ -292,7 +300,10 @@ static struct regulator_init_data goni_ldo3_data = {
.min_uV = 1100000,
.max_uV = 1100000,
.apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
+ .num_consumer_supplies = ARRAY_SIZE(goni_ldo3_consumers),
+ .consumer_supplies = goni_ldo3_consumers,
};
static struct regulator_init_data goni_ldo4_data = {
@@ -341,7 +352,10 @@ static struct regulator_init_data goni_ldo8_data = {
.min_uV = 3300000,
.max_uV = 3300000,
.apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
+ .num_consumer_supplies = ARRAY_SIZE(goni_ldo8_consumers),
+ .consumer_supplies = goni_ldo8_consumers,
};
static struct regulator_init_data goni_ldo9_data = {
--
1.7.1.569.g6f426
^ permalink raw reply related
* [PATCH 1/2] ARM: S5PC110: disable unused power regulators on Goni board
From: Marek Szyprowski @ 2011-02-15 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297760784-8486-1-git-send-email-m.szyprowski@samsung.com>
A lot of power regulator has been enabled by default causing the board
to consume a lot of power. This patch fixes this issue.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pv210/mach-goni.c | 10 +---------
1 files changed, 1 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 43c1c1b..10f754b 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -292,7 +292,6 @@ static struct regulator_init_data goni_ldo3_data = {
.min_uV = 1100000,
.max_uV = 1100000,
.apply_uV = 1,
- .always_on = 1,
},
};
@@ -311,6 +310,7 @@ static struct regulator_init_data goni_ldo5_data = {
.min_uV = 2800000,
.max_uV = 2800000,
.apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers),
.consumer_supplies = goni_ldo5_consumers,
@@ -341,7 +341,6 @@ static struct regulator_init_data goni_ldo8_data = {
.min_uV = 3300000,
.max_uV = 3300000,
.apply_uV = 1,
- .always_on = 1,
},
};
@@ -351,7 +350,6 @@ static struct regulator_init_data goni_ldo9_data = {
.min_uV = 2800000,
.max_uV = 2800000,
.apply_uV = 1,
- .always_on = 1,
},
};
@@ -371,7 +369,6 @@ static struct regulator_init_data goni_ldo11_data = {
.min_uV = 2800000,
.max_uV = 2800000,
.apply_uV = 1,
- .always_on = 1,
},
};
@@ -381,7 +378,6 @@ static struct regulator_init_data goni_ldo12_data = {
.min_uV = 1200000,
.max_uV = 1200000,
.apply_uV = 1,
- .always_on = 1,
},
};
@@ -391,7 +387,6 @@ static struct regulator_init_data goni_ldo13_data = {
.min_uV = 2800000,
.max_uV = 2800000,
.apply_uV = 1,
- .always_on = 1,
},
};
@@ -401,7 +396,6 @@ static struct regulator_init_data goni_ldo14_data = {
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = 1,
- .always_on = 1,
},
};
@@ -411,7 +405,6 @@ static struct regulator_init_data goni_ldo15_data = {
.min_uV = 3300000,
.max_uV = 3300000,
.apply_uV = 1,
- .always_on = 1,
},
};
@@ -421,7 +414,6 @@ static struct regulator_init_data goni_ldo16_data = {
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = 1,
- .always_on = 1,
},
};
--
1.7.1.569.g6f426
^ permalink raw reply related
* [PATCH] Another small regulators update for Goni board
From: Marek Szyprowski @ 2011-02-15 9:06 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
This small patch series updates regulator definitions on Goni board. The
first one disables all unused regulators, the second one add support for
regualtors for s3c-hsotg driver.
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply
* [PATCH V5 00/63] Updating SPEAr Support
From: stanley.miao @ 2011-02-15 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1295499392.git.viresh.kumar@st.com>
Viresh Kumar wrote:
> Following set of patches:
> - updates SPEAr3xx, 6xx support
> - Adds support for SPEAr13xx
> - Removes Multiple defconfigs per machine family
>
> C
I have reviewed all the spear13xx related patches. Please add
Reviewed-by: Stanley.Miao <stanley.miao@windriver.com>
Stanley.
^ permalink raw reply
* [PATCH V5 resend 39/63] SPEAr CPU freq: Adding support for CPU Freq framework
From: stanley.miao @ 2011-02-15 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <01612f9ae6c475b861c2f03cc24a4cb4639e01d1.1295581815.git.viresh.kumar@st.com>
Viresh Kumar wrote:
> From: Deepak Sikri <deepak.sikri@st.com>
>
> <snip>
> +
> + newfreq = clk_round_rate(cpu_clk, spear_cpu_freq[index] * 1000);
> + if (newfreq < 0) {
> + pr_err("CPU Freq: clk_round_rate failed: %ld\n", newfreq);
> + return newfreq;
> + }
>
clk_round_rate will call round_rate_index();
--------------------------
static int
round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate)
{
unsigned long tmp = 0, prev_rate = 0;
int index;
if (!clk->calc_rate)
return -EFAULT;
------------------------------------------
The cpu_clk don't have calc_rate, clk_round_rate always return fault.
Stanley.
^ permalink raw reply
* [PATCH for 2.6.38] ARM: S5PC110: fix regulator names
From: Marek Szyprowski @ 2011-02-15 9:01 UTC (permalink / raw)
To: linux-arm-kernel
Since commit 1130e5b3ff4 regulators are exported to debugfs. The names
of the regulators that contains slash ('/') causes an ops during kernel
boot. This patch fixes this issue.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pv210/mach-aquila.c | 6 +++---
arch/arm/mach-s5pv210/mach-goni.c | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 1236e19..557add4 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -149,7 +149,7 @@ static struct regulator_init_data aquila_ldo2_data = {
static struct regulator_init_data aquila_ldo3_data = {
.constraints = {
- .name = "VUSB/MIPI_1.1V",
+ .name = "VUSB+MIPI_1.1V",
.min_uV = 1100000,
.max_uV = 1100000,
.apply_uV = 1,
@@ -197,7 +197,7 @@ static struct regulator_init_data aquila_ldo7_data = {
static struct regulator_init_data aquila_ldo8_data = {
.constraints = {
- .name = "VUSB/VADC_3.3V",
+ .name = "VUSB+VADC_3.3V",
.min_uV = 3300000,
.max_uV = 3300000,
.apply_uV = 1,
@@ -207,7 +207,7 @@ static struct regulator_init_data aquila_ldo8_data = {
static struct regulator_init_data aquila_ldo9_data = {
.constraints = {
- .name = "VCC/VCAM_2.8V",
+ .name = "VCC+VCAM_2.8V",
.min_uV = 2800000,
.max_uV = 2800000,
.apply_uV = 1,
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 2beeb66..056f5c7 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -288,7 +288,7 @@ static struct regulator_init_data goni_ldo2_data = {
static struct regulator_init_data goni_ldo3_data = {
.constraints = {
- .name = "VUSB/MIPI_1.1V",
+ .name = "VUSB+MIPI_1.1V",
.min_uV = 1100000,
.max_uV = 1100000,
.apply_uV = 1,
@@ -337,7 +337,7 @@ static struct regulator_init_data goni_ldo7_data = {
static struct regulator_init_data goni_ldo8_data = {
.constraints = {
- .name = "VUSB/VADC_3.3V",
+ .name = "VUSB+VADC_3.3V",
.min_uV = 3300000,
.max_uV = 3300000,
.apply_uV = 1,
@@ -347,7 +347,7 @@ static struct regulator_init_data goni_ldo8_data = {
static struct regulator_init_data goni_ldo9_data = {
.constraints = {
- .name = "VCC/VCAM_2.8V",
+ .name = "VCC+VCAM_2.8V",
.min_uV = 2800000,
.max_uV = 2800000,
.apply_uV = 1,
--
1.7.1.569.g6f426
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox