ARM: arm-soc: SoC updates, take 2
This is the second batch of SoC updates for the 3.8 merge window, containing parts that had dependencies on earlier branches such that we couldn't include them with the first branch. These are general updates for Samsung Exynos, Renesas/shmobile and a topic branch that adds SMP support to Altera's socfpga platform. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQy5gxAAoJEIwa5zzehBx3ab0P/1SSJYLNcn8rieIALLZaSH17 lxVwyv/OMLmRual0eVjXN+mcNuAc05gemLUSNSrdFPrHhEGSqFz8x0C/A6o3Ovw/ OxNNX3rQiZP86vKRVmT/did7yEkMmleKng19uOyBXN2p7f6lh01Y5NFTVE1dWiZG TJPEgWI9mrarUMarL90fBu7AlXPNJwfG0opmT5QWuZmcLlaRXFTqFU2U08e5rPp5 9yrTn3fQCDx+eT7qUBiZfuH6sesMnofYWDNJSvV/aPI4UYsEcK6KyJUL8LBuTLQ7 9LHqsJNHLnlqxDsq6N/B0/pno2rhgdbkPPtl0c0xw35anHWW86IUgWgSCbu16LDZ uKDV31tIsx8yhsm8QkSKwzEjVnablhVYORGByVkNYBVSgMobdxBNFog6iX9NNQxJ 3Z1K0i65YPffDoK7CJorIxcxyvBuBR/KueUFpzEK05xzJlvhPK2NQSY5Je0qEaA3 tZYt0WfMtLC0huhLxEL/xNXuErqvj18kOSal3CHmg2LWVaKCFKNuY/B71yF7xaTc qN3RGJdb5Dyh49CCzXVBSAKJozc+pB8RauGnM//UQf49lmFzQ7oaQjxNjS3zQrjA 3LsbJ8cDbwWVKb8yRvR8BtnJl81yE58D6R/gEPjH33v4jRPLUONLyyhVI57Rf0tV SFjd8wRlsFakOQ4qnG/B =77Ct -----END PGP SIGNATURE----- Merge tag 'soc2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM Soc updates, take 2, from Olof Johansson: "This is the second batch of SoC updates for the 3.8 merge window, containing parts that had dependencies on earlier branches such that we couldn't include them with the first branch. These are general updates for Samsung Exynos, Renesas/shmobile and a topic branch that adds SMP support to Altera's socfpga platform." Fix up conflicts mostly as per Olof. * tag 'soc2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: ARM: EXYNOS: Clock settings for SATA and SATA PHY ARM: EXYNOS: Add ARM down clock support ARM: EXYNOS: Fix i2c suspend/resume for legacy controller ARM: EXYNOS: Add aliases for i2c controller ARM: EXYNOS: Setup legacy i2c controller interrupts sh: clkfwk: fixup unsed variable warning Revert "ARM: shmobile: r8a7779: Replace modify_scu_cpu_psr with scu_power_mode" Revert "ARM: shmobile: sh73a0: Replace modify_scu_cpu_psr with scu_power_mode" Revert "ARM: shmobile: emev2: Replace modify_scu_cpu_psr with scu_power_mode" ARM: highbank: use common debug_ll_io_init ARM: shmobile: sh7372: sh7372_fsiXck_clk become non-global ARM: shmobile: sh7372: remove fsidivx clock ARM: socfpga: mark secondary_trampoline as cpuinit socfpga: map uart into virtual address space so that early_printk() works ARM: socfpga: fix build break for allyesconfig ARM: socfpga: Enable SMP for socfpga ARM: EXYNOS: Add dp clock support for EXYNOS5 ARM: SAMSUNG: call clk_get_rate for debugfs rate files ARM: SAMSUNG: add clock_tree debugfs file in clock
This commit is contained in:
commit
6a57d104c8
|
@ -0,0 +1,11 @@
|
|||
Altera SOCFPGA Reset Manager
|
||||
|
||||
Required properties:
|
||||
- compatible : "altr,rst-mgr"
|
||||
- reg : Should contain 1 register ranges(address and length)
|
||||
|
||||
Example:
|
||||
rstmgr@ffd05000 {
|
||||
compatible = "altr,rst-mgr";
|
||||
reg = <0xffd05000 0x1000>;
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
Altera SOCFPGA System Manager
|
||||
|
||||
Required properties:
|
||||
- compatible : "altr,sys-mgr"
|
||||
- reg : Should contain 1 register ranges(address and length)
|
||||
|
||||
Example:
|
||||
sysmgr@ffd08000 {
|
||||
compatible = "altr,sys-mgr";
|
||||
reg = <0xffd08000 0x1000>;
|
||||
};
|
|
@ -35,6 +35,15 @@
|
|||
mshc1 = &dwmmc_1;
|
||||
mshc2 = &dwmmc_2;
|
||||
mshc3 = &dwmmc_3;
|
||||
i2c0 = &i2c_0;
|
||||
i2c1 = &i2c_1;
|
||||
i2c2 = &i2c_2;
|
||||
i2c3 = &i2c_3;
|
||||
i2c4 = &i2c_4;
|
||||
i2c5 = &i2c_5;
|
||||
i2c6 = &i2c_6;
|
||||
i2c7 = &i2c_7;
|
||||
i2c8 = &i2c_8;
|
||||
};
|
||||
|
||||
gic:interrupt-controller@10481000 {
|
||||
|
@ -119,7 +128,7 @@
|
|||
reg = <0x12170000 0x1ff>;
|
||||
};
|
||||
|
||||
i2c@12C60000 {
|
||||
i2c_0: i2c@12C60000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
reg = <0x12C60000 0x100>;
|
||||
interrupts = <0 56 0>;
|
||||
|
@ -127,7 +136,7 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c@12C70000 {
|
||||
i2c_1: i2c@12C70000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
reg = <0x12C70000 0x100>;
|
||||
interrupts = <0 57 0>;
|
||||
|
@ -135,7 +144,7 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c@12C80000 {
|
||||
i2c_2: i2c@12C80000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
reg = <0x12C80000 0x100>;
|
||||
interrupts = <0 58 0>;
|
||||
|
@ -143,7 +152,7 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c@12C90000 {
|
||||
i2c_3: i2c@12C90000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
reg = <0x12C90000 0x100>;
|
||||
interrupts = <0 59 0>;
|
||||
|
@ -151,7 +160,7 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c@12CA0000 {
|
||||
i2c_4: i2c@12CA0000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
reg = <0x12CA0000 0x100>;
|
||||
interrupts = <0 60 0>;
|
||||
|
@ -159,7 +168,7 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c@12CB0000 {
|
||||
i2c_5: i2c@12CB0000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
reg = <0x12CB0000 0x100>;
|
||||
interrupts = <0 61 0>;
|
||||
|
@ -167,7 +176,7 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c@12CC0000 {
|
||||
i2c_6: i2c@12CC0000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
reg = <0x12CC0000 0x100>;
|
||||
interrupts = <0 62 0>;
|
||||
|
@ -175,7 +184,7 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c@12CD0000 {
|
||||
i2c_7: i2c@12CD0000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
reg = <0x12CD0000 0x100>;
|
||||
interrupts = <0 63 0>;
|
||||
|
@ -183,7 +192,7 @@
|
|||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c@12CE0000 {
|
||||
i2c_8: i2c@12CE0000 {
|
||||
compatible = "samsung,s3c2440-hdmiphy-i2c";
|
||||
reg = <0x12CE0000 0x1000>;
|
||||
interrupts = <0 64 0>;
|
||||
|
|
|
@ -143,5 +143,15 @@
|
|||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
};
|
||||
|
||||
rstmgr@ffd05000 {
|
||||
compatible = "altr,rst-mgr";
|
||||
reg = <0xffd05000 0x1000>;
|
||||
};
|
||||
|
||||
sysmgr@ffd08000 {
|
||||
compatible = "altr,sys-mgr";
|
||||
reg = <0xffd08000 0x4000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -18,9 +18,10 @@ CONFIG_MODULE_UNLOAD=y
|
|||
CONFIG_ARCH_SOCFPGA=y
|
||||
CONFIG_MACH_SOCFPGA_CYCLONE5=y
|
||||
CONFIG_ARM_THUMBEE=y
|
||||
# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
|
||||
# CONFIG_CACHE_L2X0 is not set
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_VMSPLIT_2G=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=2
|
||||
CONFIG_AEABI=y
|
||||
CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||
|
|
|
@ -80,6 +80,8 @@ static struct sleep_save exynos5_clock_save[] = {
|
|||
SAVE_ITEM(EXYNOS5_VPLL_CON0),
|
||||
SAVE_ITEM(EXYNOS5_VPLL_CON1),
|
||||
SAVE_ITEM(EXYNOS5_VPLL_CON2),
|
||||
SAVE_ITEM(EXYNOS5_PWR_CTRL1),
|
||||
SAVE_ITEM(EXYNOS5_PWR_CTRL2),
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -661,15 +663,20 @@ static struct clk exynos5_init_clocks_off[] = {
|
|||
.ctrlbit = (1 << 15),
|
||||
}, {
|
||||
.name = "sata",
|
||||
.devname = "ahci",
|
||||
.devname = "exynos5-sata",
|
||||
.parent = &exynos5_clk_aclk_200.clk,
|
||||
.enable = exynos5_clk_ip_fsys_ctrl,
|
||||
.ctrlbit = (1 << 6),
|
||||
}, {
|
||||
.name = "sata_phy",
|
||||
.name = "sata-phy",
|
||||
.devname = "exynos5-sata-phy",
|
||||
.parent = &exynos5_clk_aclk_200.clk,
|
||||
.enable = exynos5_clk_ip_fsys_ctrl,
|
||||
.ctrlbit = (1 << 24),
|
||||
}, {
|
||||
.name = "sata_phy_i2c",
|
||||
.name = "i2c",
|
||||
.devname = "exynos5-sata-phy-i2c",
|
||||
.parent = &exynos5_clk_aclk_200.clk,
|
||||
.enable = exynos5_clk_ip_fsys_ctrl,
|
||||
.ctrlbit = (1 << 25),
|
||||
}, {
|
||||
|
@ -692,6 +699,11 @@ static struct clk exynos5_init_clocks_off[] = {
|
|||
.devname = "exynos5-mixer",
|
||||
.enable = exynos5_clk_ip_disp1_ctrl,
|
||||
.ctrlbit = (1 << 5),
|
||||
}, {
|
||||
.name = "dp",
|
||||
.devname = "exynos-dp",
|
||||
.enable = exynos5_clk_ip_disp1_ctrl,
|
||||
.ctrlbit = (1 << 4),
|
||||
}, {
|
||||
.name = "jpeg",
|
||||
.enable = exynos5_clk_ip_gen_ctrl,
|
||||
|
@ -1239,6 +1251,16 @@ static struct clksrc_clk exynos5_clksrcs[] = {
|
|||
.sources = &exynos5_clkset_aclk,
|
||||
.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
|
||||
}, {
|
||||
.clk = {
|
||||
.name = "sclk_sata",
|
||||
.devname = "exynos5-sata",
|
||||
.enable = exynos5_clksrc_mask_fsys_ctrl,
|
||||
.ctrlbit = (1 << 24),
|
||||
},
|
||||
.sources = &exynos5_clkset_aclk,
|
||||
.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 24, .size = 1 },
|
||||
.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS0, .shift = 20, .size = 4 },
|
||||
}, {
|
||||
.clk = {
|
||||
.name = "sclk_gscl_wrap",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <asm/suspend.h>
|
||||
#include <asm/unified.h>
|
||||
#include <asm/cpuidle.h>
|
||||
#include <mach/regs-clock.h>
|
||||
#include <mach/regs-pmu.h>
|
||||
#include <mach/pmu.h>
|
||||
|
||||
|
@ -157,12 +158,47 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
|
|||
return exynos4_enter_core0_aftr(dev, drv, new_index);
|
||||
}
|
||||
|
||||
static void __init exynos5_core_down_clk(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
/*
|
||||
* Enable arm clock down (in idle) and set arm divider
|
||||
* ratios in WFI/WFE state.
|
||||
*/
|
||||
tmp = PWR_CTRL1_CORE2_DOWN_RATIO | \
|
||||
PWR_CTRL1_CORE1_DOWN_RATIO | \
|
||||
PWR_CTRL1_DIV2_DOWN_EN | \
|
||||
PWR_CTRL1_DIV1_DOWN_EN | \
|
||||
PWR_CTRL1_USE_CORE1_WFE | \
|
||||
PWR_CTRL1_USE_CORE0_WFE | \
|
||||
PWR_CTRL1_USE_CORE1_WFI | \
|
||||
PWR_CTRL1_USE_CORE0_WFI;
|
||||
__raw_writel(tmp, EXYNOS5_PWR_CTRL1);
|
||||
|
||||
/*
|
||||
* Enable arm clock up (on exiting idle). Set arm divider
|
||||
* ratios when not in idle along with the standby duration
|
||||
* ratios.
|
||||
*/
|
||||
tmp = PWR_CTRL2_DIV2_UP_EN | \
|
||||
PWR_CTRL2_DIV1_UP_EN | \
|
||||
PWR_CTRL2_DUR_STANDBY2_VAL | \
|
||||
PWR_CTRL2_DUR_STANDBY1_VAL | \
|
||||
PWR_CTRL2_CORE2_UP_RATIO | \
|
||||
PWR_CTRL2_CORE1_UP_RATIO;
|
||||
__raw_writel(tmp, EXYNOS5_PWR_CTRL2);
|
||||
}
|
||||
|
||||
static int __init exynos4_init_cpuidle(void)
|
||||
{
|
||||
int i, max_cpuidle_state, cpu_id;
|
||||
struct cpuidle_device *device;
|
||||
struct cpuidle_driver *drv = &exynos4_idle_driver;
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
exynos5_core_down_clk();
|
||||
|
||||
/* Setup cpuidle driver */
|
||||
drv->state_count = (sizeof(exynos4_cpuidle_set) /
|
||||
sizeof(struct cpuidle_state));
|
||||
|
|
|
@ -267,6 +267,9 @@
|
|||
#define EXYNOS5_CLKDIV_STATCPU0 EXYNOS_CLKREG(0x00600)
|
||||
#define EXYNOS5_CLKDIV_STATCPU1 EXYNOS_CLKREG(0x00604)
|
||||
|
||||
#define EXYNOS5_PWR_CTRL1 EXYNOS_CLKREG(0x01020)
|
||||
#define EXYNOS5_PWR_CTRL2 EXYNOS_CLKREG(0x01024)
|
||||
|
||||
#define EXYNOS5_MPLL_CON0 EXYNOS_CLKREG(0x04100)
|
||||
#define EXYNOS5_CLKSRC_CORE1 EXYNOS_CLKREG(0x04204)
|
||||
|
||||
|
@ -344,6 +347,22 @@
|
|||
|
||||
#define EXYNOS5_EPLLCON0_LOCKED_SHIFT (29)
|
||||
|
||||
#define PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28)
|
||||
#define PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16)
|
||||
#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
|
||||
#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
|
||||
#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
|
||||
#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
|
||||
#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
|
||||
#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
|
||||
|
||||
#define PWR_CTRL2_DIV2_UP_EN (1 << 25)
|
||||
#define PWR_CTRL2_DIV1_UP_EN (1 << 24)
|
||||
#define PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16)
|
||||
#define PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8)
|
||||
#define PWR_CTRL2_CORE2_UP_RATIO (1 << 4)
|
||||
#define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
|
||||
|
||||
/* Compatibility defines and inclusion */
|
||||
|
||||
#include <mach/regs-pmu.h>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <mach/map.h>
|
||||
|
||||
#define S5P_PMUREG(x) (S5P_VA_PMU + (x))
|
||||
#define S5P_SYSREG(x) (S3C_VA_SYS + (x))
|
||||
|
||||
#define S5P_CENTRAL_SEQ_CONFIGURATION S5P_PMUREG(0x0200)
|
||||
|
||||
|
@ -231,6 +232,8 @@
|
|||
|
||||
/* For EXYNOS5 */
|
||||
|
||||
#define EXYNOS5_SYS_I2C_CFG S5P_SYSREG(0x0234)
|
||||
|
||||
#define EXYNOS5_AUTO_WDTRESET_DISABLE S5P_PMUREG(0x0408)
|
||||
#define EXYNOS5_MASK_WDTRESET_REQUEST S5P_PMUREG(0x040C)
|
||||
|
||||
|
|
|
@ -13,11 +13,12 @@
|
|||
#include <linux/of_fdt.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <mach/map.h>
|
||||
#include <mach/regs-pmu.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/regs-serial.h>
|
||||
|
@ -124,6 +125,28 @@ static void __init exynos5_dt_map_io(void)
|
|||
|
||||
static void __init exynos5_dt_machine_init(void)
|
||||
{
|
||||
struct device_node *i2c_np;
|
||||
const char *i2c_compat = "samsung,s3c2440-i2c";
|
||||
unsigned int tmp;
|
||||
|
||||
/*
|
||||
* Exynos5's legacy i2c controller and new high speed i2c
|
||||
* controller have muxed interrupt sources. By default the
|
||||
* interrupts for 4-channel HS-I2C controller are enabled.
|
||||
* If node for first four channels of legacy i2c controller
|
||||
* are available then re-configure the interrupts via the
|
||||
* system register.
|
||||
*/
|
||||
for_each_compatible_node(i2c_np, NULL, i2c_compat) {
|
||||
if (of_device_is_available(i2c_np)) {
|
||||
if (of_alias_get_id(i2c_np, "i2c") < 4) {
|
||||
tmp = readl(EXYNOS5_SYS_I2C_CFG);
|
||||
writel(tmp & ~(0x1 << of_alias_get_id(i2c_np, "i2c")),
|
||||
EXYNOS5_SYS_I2C_CFG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (of_machine_is_compatible("samsung,exynos5250"))
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
exynos5250_auxdata_lookup, NULL);
|
||||
|
|
|
@ -62,6 +62,10 @@ static struct sleep_save exynos4_vpll_save[] = {
|
|||
SAVE_ITEM(EXYNOS4_VPLL_CON1),
|
||||
};
|
||||
|
||||
static struct sleep_save exynos5_sys_save[] = {
|
||||
SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
|
||||
};
|
||||
|
||||
static struct sleep_save exynos_core_save[] = {
|
||||
/* SROM side */
|
||||
SAVE_ITEM(S5P_SROM_BW),
|
||||
|
@ -101,6 +105,7 @@ static void exynos_pm_prepare(void)
|
|||
s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
|
||||
s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
|
||||
} else {
|
||||
s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
|
||||
/* Disable USE_RETENTION of JPEG_MEM_OPTION */
|
||||
tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
|
||||
tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
|
||||
|
@ -304,6 +309,10 @@ static void exynos_pm_resume(void)
|
|||
__raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
|
||||
__raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
|
||||
|
||||
if (soc_is_exynos5250())
|
||||
s3c_pm_do_restore(exynos5_sys_save,
|
||||
ARRAY_SIZE(exynos5_sys_save));
|
||||
|
||||
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
|
||||
|
||||
if (!soc_is_exynos5250()) {
|
||||
|
|
|
@ -295,10 +295,10 @@ struct clk sh7372_pllc2_clk = {
|
|||
};
|
||||
|
||||
/* External input clock (pin name: FSIACK/FSIBCK ) */
|
||||
struct clk sh7372_fsiack_clk = {
|
||||
static struct clk fsiack_clk = {
|
||||
};
|
||||
|
||||
struct clk sh7372_fsibck_clk = {
|
||||
static struct clk fsibck_clk = {
|
||||
};
|
||||
|
||||
static struct clk *main_clks[] = {
|
||||
|
@ -314,8 +314,8 @@ static struct clk *main_clks[] = {
|
|||
&pllc1_clk,
|
||||
&pllc1_div2_clk,
|
||||
&sh7372_pllc2_clk,
|
||||
&sh7372_fsiack_clk,
|
||||
&sh7372_fsibck_clk,
|
||||
&fsiack_clk,
|
||||
&fsibck_clk,
|
||||
};
|
||||
|
||||
static void div4_kick(struct clk *clk)
|
||||
|
@ -399,14 +399,14 @@ static struct clk *hdmi_parent[] = {
|
|||
static struct clk *fsiackcr_parent[] = {
|
||||
[0] = &pllc1_div2_clk,
|
||||
[1] = &sh7372_pllc2_clk,
|
||||
[2] = &sh7372_fsiack_clk, /* external input for FSI A */
|
||||
[2] = &fsiack_clk, /* external input for FSI A */
|
||||
[3] = NULL, /* setting prohibited */
|
||||
};
|
||||
|
||||
static struct clk *fsibckcr_parent[] = {
|
||||
[0] = &pllc1_div2_clk,
|
||||
[1] = &sh7372_pllc2_clk,
|
||||
[2] = &sh7372_fsibck_clk, /* external input for FSI B */
|
||||
[2] = &fsibck_clk, /* external input for FSI B */
|
||||
[3] = NULL, /* setting prohibited */
|
||||
};
|
||||
|
||||
|
@ -507,8 +507,8 @@ static struct clk_lookup lookups[] = {
|
|||
CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
|
||||
CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
|
||||
CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk),
|
||||
CLKDEV_CON_ID("fsidiva", &fsidivs[FSIDIV_A]),
|
||||
CLKDEV_CON_ID("fsidivb", &fsidivs[FSIDIV_B]),
|
||||
CLKDEV_CON_ID("fsiack", &fsiack_clk),
|
||||
CLKDEV_CON_ID("fsibck", &fsibck_clk),
|
||||
|
||||
/* DIV4 clocks */
|
||||
CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
|
||||
|
@ -606,8 +606,8 @@ static struct clk_lookup lookups[] = {
|
|||
CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
|
||||
CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]),
|
||||
CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]),
|
||||
CLKDEV_ICK_ID("xcka", "sh_fsi2", &sh7372_fsiack_clk),
|
||||
CLKDEV_ICK_ID("xckb", "sh_fsi2", &sh7372_fsibck_clk),
|
||||
CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk),
|
||||
CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk),
|
||||
};
|
||||
|
||||
void __init sh7372_clock_init(void)
|
||||
|
|
|
@ -477,8 +477,6 @@ extern struct clk sh7372_extal2_clk;
|
|||
extern struct clk sh7372_dv_clki_clk;
|
||||
extern struct clk sh7372_dv_clki_div2_clk;
|
||||
extern struct clk sh7372_pllc2_clk;
|
||||
extern struct clk sh7372_fsiack_clk;
|
||||
extern struct clk sh7372_fsibck_clk;
|
||||
|
||||
extern void sh7372_intcs_suspend(void);
|
||||
extern void sh7372_intcs_resume(void);
|
||||
|
|
|
@ -32,8 +32,24 @@
|
|||
|
||||
#define EMEV2_SCU_BASE 0x1e000000
|
||||
|
||||
static DEFINE_SPINLOCK(scu_lock);
|
||||
static void __iomem *scu_base;
|
||||
|
||||
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
/* we assume this code is running on a different cpu
|
||||
* than the one that is changing coherency setting */
|
||||
spin_lock(&scu_lock);
|
||||
tmp = readl(scu_base + 8);
|
||||
tmp &= ~clr;
|
||||
tmp |= set;
|
||||
writel(tmp, scu_base + 8);
|
||||
spin_unlock(&scu_lock);
|
||||
|
||||
}
|
||||
|
||||
static unsigned int __init emev2_get_core_count(void)
|
||||
{
|
||||
if (!scu_base) {
|
||||
|
@ -79,7 +95,7 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
|
|||
cpu = cpu_logical_map(cpu);
|
||||
|
||||
/* enable cache coherency */
|
||||
scu_power_mode(scu_base, 0);
|
||||
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
||||
|
||||
/* Tell ROM loader about our vector (in headsmp.S) */
|
||||
emev2_set_boot_vector(__pa(shmobile_secondary_vector));
|
||||
|
@ -90,10 +106,12 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
|
|||
|
||||
static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int cpu = cpu_logical_map(0);
|
||||
|
||||
scu_enable(scu_base);
|
||||
|
||||
/* enable cache coherency on CPU0 */
|
||||
scu_power_mode(scu_base, 0);
|
||||
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
||||
}
|
||||
|
||||
static void __init emev2_smp_init_cpus(void)
|
||||
|
|
|
@ -61,6 +61,9 @@ static void __iomem *scu_base_addr(void)
|
|||
return (void __iomem *)0xf0000000;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(scu_lock);
|
||||
static unsigned long tmp;
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
|
||||
|
||||
|
@ -70,6 +73,20 @@ void __init r8a7779_register_twd(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
|
||||
spin_lock(&scu_lock);
|
||||
tmp = __raw_readl(scu_base + 8);
|
||||
tmp &= ~clr;
|
||||
tmp |= set;
|
||||
spin_unlock(&scu_lock);
|
||||
|
||||
/* disable cache coherency after releasing the lock */
|
||||
__raw_writel(tmp, scu_base + 8);
|
||||
}
|
||||
|
||||
static unsigned int __init r8a7779_get_core_count(void)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
|
@ -85,7 +102,7 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
|
|||
cpu = cpu_logical_map(cpu);
|
||||
|
||||
/* disable cache coherency */
|
||||
scu_power_mode(scu_base_addr(), 3);
|
||||
modify_scu_cpu_psr(3 << (cpu * 8), 0);
|
||||
|
||||
if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
|
||||
ch = r8a7779_ch_cpu[cpu];
|
||||
|
@ -128,7 +145,7 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
|
|||
cpu = cpu_logical_map(cpu);
|
||||
|
||||
/* enable cache coherency */
|
||||
scu_power_mode(scu_base_addr(), 0);
|
||||
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
||||
|
||||
if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
|
||||
ch = r8a7779_ch_cpu[cpu];
|
||||
|
@ -141,13 +158,15 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
|
|||
|
||||
static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int cpu = cpu_logical_map(0);
|
||||
|
||||
scu_enable(scu_base_addr());
|
||||
|
||||
/* Map the reset vector (in headsmp.S) */
|
||||
__raw_writel(__pa(shmobile_secondary_vector), AVECR);
|
||||
|
||||
/* enable cache coherency on CPU0 */
|
||||
scu_power_mode(scu_base_addr(), 0);
|
||||
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
||||
|
||||
r8a7779_pm_init();
|
||||
|
||||
|
|
|
@ -41,6 +41,9 @@ static void __iomem *scu_base_addr(void)
|
|||
return (void __iomem *)0xf0000000;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(scu_lock);
|
||||
static unsigned long tmp;
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
|
||||
void __init sh73a0_register_twd(void)
|
||||
|
@ -49,6 +52,20 @@ void __init sh73a0_register_twd(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
|
||||
spin_lock(&scu_lock);
|
||||
tmp = __raw_readl(scu_base + 8);
|
||||
tmp &= ~clr;
|
||||
tmp |= set;
|
||||
spin_unlock(&scu_lock);
|
||||
|
||||
/* disable cache coherency after releasing the lock */
|
||||
__raw_writel(tmp, scu_base + 8);
|
||||
}
|
||||
|
||||
static unsigned int __init sh73a0_get_core_count(void)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
|
@ -66,7 +83,7 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
|
|||
cpu = cpu_logical_map(cpu);
|
||||
|
||||
/* enable cache coherency */
|
||||
scu_power_mode(scu_base_addr(), 0);
|
||||
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
||||
|
||||
if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
|
||||
__raw_writel(1 << cpu, WUPCR); /* wake up */
|
||||
|
@ -78,6 +95,8 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
|
|||
|
||||
static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int cpu = cpu_logical_map(0);
|
||||
|
||||
scu_enable(scu_base_addr());
|
||||
|
||||
/* Map the reset vector (in headsmp.S) */
|
||||
|
@ -85,7 +104,7 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
|
|||
__raw_writel(__pa(shmobile_secondary_vector), SBAR);
|
||||
|
||||
/* enable cache coherency on CPU0 */
|
||||
scu_power_mode(scu_base_addr(), 0);
|
||||
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
||||
}
|
||||
|
||||
static void __init sh73a0_smp_init_cpus(void)
|
||||
|
|
|
@ -12,5 +12,6 @@ config ARCH_SOCFPGA
|
|||
select GENERIC_CLOCKEVENTS
|
||||
select GPIO_PL061 if GPIOLIB
|
||||
select HAVE_ARM_SCU
|
||||
select HAVE_SMP
|
||||
select SPARSE_IRQ
|
||||
select USE_OF
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
#
|
||||
|
||||
obj-y := socfpga.o
|
||||
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
|
||||
|
|
34
arch/arm/mach-socfpga/core.h
Normal file
34
arch/arm/mach-socfpga/core.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2012 Pavel Machek <pavel@denx.de>
|
||||
* Copyright (C) 2012 Altera Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __MACH_CORE_H
|
||||
#define __MACH_CORE_H
|
||||
|
||||
extern void secondary_startup(void);
|
||||
extern void __iomem *socfpga_scu_base_addr;
|
||||
|
||||
extern void socfpga_init_clocks(void);
|
||||
extern void socfpga_sysmgr_init(void);
|
||||
|
||||
extern struct smp_operations socfpga_smp_ops;
|
||||
extern char secondary_trampoline, secondary_trampoline_end;
|
||||
|
||||
#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
|
||||
|
||||
#endif
|
25
arch/arm/mach-socfpga/headsmp.S
Normal file
25
arch/arm/mach-socfpga/headsmp.S
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2003 ARM Limited
|
||||
* Copyright (c) u-boot contributors
|
||||
* Copyright (c) 2012 Pavel Machek <pavel@denx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
__CPUINIT
|
||||
.arch armv7-a
|
||||
|
||||
#define CPU1_START_ADDR 0xffd08010
|
||||
|
||||
ENTRY(secondary_trampoline)
|
||||
movw r0, #:lower16:CPU1_START_ADDR
|
||||
movt r0, #:upper16:CPU1_START_ADDR
|
||||
|
||||
ldr r1, [r0]
|
||||
bx r1
|
||||
|
||||
ENTRY(secondary_trampoline_end)
|
116
arch/arm/mach-socfpga/platsmp.c
Normal file
116
arch/arm/mach-socfpga/platsmp.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright 2010-2011 Calxeda, Inc.
|
||||
* Copyright 2012 Pavel Machek <pavel@denx.de>
|
||||
* Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
|
||||
* Copyright (C) 2012 Altera Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
extern void __iomem *sys_manager_base_addr;
|
||||
extern void __iomem *rst_manager_base_addr;
|
||||
|
||||
static void __cpuinit socfpga_secondary_init(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* if any interrupts are already enabled for the primary
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
* for us: do so
|
||||
*/
|
||||
gic_secondary_init(0);
|
||||
}
|
||||
|
||||
static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
|
||||
|
||||
memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
|
||||
|
||||
__raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
|
||||
|
||||
flush_cache_all();
|
||||
smp_wmb();
|
||||
outer_clean_range(0, trampoline_size);
|
||||
|
||||
/* This will release CPU #1 out of reset.*/
|
||||
__raw_writel(0, rst_manager_base_addr + 0x10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the CPU possible map early - this describes the CPUs
|
||||
* which may be present or become present in the system.
|
||||
*/
|
||||
static void __init socfpga_smp_init_cpus(void)
|
||||
{
|
||||
unsigned int i, ncores;
|
||||
|
||||
ncores = scu_get_core_count(socfpga_scu_base_addr);
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
|
||||
/* sanity check */
|
||||
if (ncores > num_possible_cpus()) {
|
||||
pr_warn("socfpga: no. of cores (%d) greater than configured"
|
||||
"maximum of %d - clipping\n", ncores, num_possible_cpus());
|
||||
ncores = num_possible_cpus();
|
||||
}
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
|
||||
set_smp_cross_call(gic_raise_softirq);
|
||||
}
|
||||
|
||||
static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
scu_enable(socfpga_scu_base_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* platform-specific code to shutdown a CPU
|
||||
*
|
||||
* Called with IRQs disabled
|
||||
*/
|
||||
static void socfpga_cpu_die(unsigned int cpu)
|
||||
{
|
||||
cpu_do_idle();
|
||||
|
||||
/* We should have never returned from idle */
|
||||
panic("cpu %d unexpectedly exit from shutdown\n", cpu);
|
||||
}
|
||||
|
||||
struct smp_operations socfpga_smp_ops __initdata = {
|
||||
.smp_init_cpus = socfpga_smp_init_cpus,
|
||||
.smp_prepare_cpus = socfpga_smp_prepare_cpus,
|
||||
.smp_secondary_init = socfpga_secondary_init,
|
||||
.smp_boot_secondary = socfpga_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_die = socfpga_cpu_die,
|
||||
#endif
|
||||
};
|
|
@ -15,23 +15,73 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/dw_apb_timer.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
extern void socfpga_init_clocks(void);
|
||||
#include "core.h"
|
||||
|
||||
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
|
||||
void __iomem *sys_manager_base_addr;
|
||||
void __iomem *rst_manager_base_addr;
|
||||
|
||||
static struct map_desc scu_io_desc __initdata = {
|
||||
.virtual = SOCFPGA_SCU_VIRT_BASE,
|
||||
.pfn = 0, /* run-time */
|
||||
.length = SZ_8K,
|
||||
.type = MT_DEVICE,
|
||||
};
|
||||
|
||||
static struct map_desc uart_io_desc __initdata = {
|
||||
.virtual = 0xfec02000,
|
||||
.pfn = __phys_to_pfn(0xffc02000),
|
||||
.length = SZ_8K,
|
||||
.type = MT_DEVICE,
|
||||
};
|
||||
|
||||
static void __init socfpga_scu_map_io(void)
|
||||
{
|
||||
unsigned long base;
|
||||
|
||||
/* Get SCU base */
|
||||
asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
|
||||
|
||||
scu_io_desc.pfn = __phys_to_pfn(base);
|
||||
iotable_init(&scu_io_desc, 1);
|
||||
}
|
||||
|
||||
static void __init socfpga_map_io(void)
|
||||
{
|
||||
socfpga_scu_map_io();
|
||||
iotable_init(&uart_io_desc, 1);
|
||||
early_printk("Early printk initialized\n");
|
||||
}
|
||||
|
||||
const static struct of_device_id irq_match[] = {
|
||||
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
|
||||
{}
|
||||
};
|
||||
|
||||
void __init socfpga_sysmgr_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
|
||||
sys_manager_base_addr = of_iomap(np, 0);
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
|
||||
rst_manager_base_addr = of_iomap(np, 0);
|
||||
}
|
||||
|
||||
static void __init gic_init_irq(void)
|
||||
{
|
||||
of_irq_init(irq_match);
|
||||
socfpga_sysmgr_init();
|
||||
}
|
||||
|
||||
static void socfpga_cyclone5_restart(char mode, const char *cmd)
|
||||
|
@ -53,6 +103,8 @@ static const char *altera_dt_match[] = {
|
|||
};
|
||||
|
||||
DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
|
||||
.smp = smp_ops(socfpga_smp_ops),
|
||||
.map_io = socfpga_map_io,
|
||||
.init_irq = gic_init_irq,
|
||||
.handle_irq = gic_handle_irq,
|
||||
.timer = &dw_apb_timer,
|
||||
|
|
|
@ -389,6 +389,72 @@ int __init s3c24xx_register_baseclocks(unsigned long xtal)
|
|||
|
||||
static struct dentry *clk_debugfs_root;
|
||||
|
||||
static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
|
||||
{
|
||||
struct clk *child;
|
||||
const char *state;
|
||||
char buf[255] = { 0 };
|
||||
int n = 0;
|
||||
|
||||
if (c->name)
|
||||
n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
|
||||
|
||||
if (c->devname)
|
||||
n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
|
||||
|
||||
state = (c->usage > 0) ? "on" : "off";
|
||||
|
||||
seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
|
||||
level * 3 + 1, "",
|
||||
50 - level * 3, buf,
|
||||
state, c->usage, clk_get_rate(c));
|
||||
|
||||
list_for_each_entry(child, &clocks, list) {
|
||||
if (child->parent != c)
|
||||
continue;
|
||||
|
||||
clock_tree_show_one(s, child, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int clock_tree_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct clk *c;
|
||||
unsigned long flags;
|
||||
|
||||
seq_printf(s, " clock state ref rate\n");
|
||||
seq_printf(s, "----------------------------------------------------\n");
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
|
||||
list_for_each_entry(c, &clocks, list)
|
||||
if (c->parent == NULL)
|
||||
clock_tree_show_one(s, c, 0);
|
||||
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clock_tree_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, clock_tree_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations clock_tree_fops = {
|
||||
.open = clock_tree_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int clock_rate_show(void *data, u64 *val)
|
||||
{
|
||||
struct clk *c = data;
|
||||
*val = clk_get_rate(c);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
|
||||
|
||||
static int clk_debugfs_register_one(struct clk *c)
|
||||
{
|
||||
int err;
|
||||
|
@ -411,7 +477,7 @@ static int clk_debugfs_register_one(struct clk *c)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
|
||||
d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
|
||||
if (!d) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
|
@ -446,13 +512,18 @@ static int __init clk_debugfs_init(void)
|
|||
{
|
||||
struct clk *c;
|
||||
struct dentry *d;
|
||||
int err;
|
||||
int err = -ENOMEM;
|
||||
|
||||
d = debugfs_create_dir("clock", NULL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
clk_debugfs_root = d;
|
||||
|
||||
d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
|
||||
&clock_tree_fops);
|
||||
if (!d)
|
||||
goto err_out;
|
||||
|
||||
list_for_each_entry(c, &clocks, list) {
|
||||
err = clk_debugfs_register(c);
|
||||
if (err)
|
||||
|
|
|
@ -401,7 +401,6 @@ static int fsidiv_enable(struct clk *clk)
|
|||
|
||||
static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
u32 val;
|
||||
int idx;
|
||||
|
||||
idx = (clk->parent->rate / rate) & 0xffff;
|
||||
|
|
Loading…
Reference in a new issue