Commit 18656782 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC driver updates from Olof Johansson:
 "These are changes for drivers that are intimately tied to some SoC and
  for some reason could not get merged through the respective subsystem
  maintainer tree.

  This time around, much of this is for at91, with the bulk of it being
  syscon and udc drivers.

  Also, there's:
   - coupled cpuidle support for Samsung Exynos4210
   - Renesas 73A0 common-clk work
   - of/platform changes to tear down DMA mappings on device destruction
   - a few updates to the TI Keystone knav code"

* tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (26 commits)
  cpuidle: exynos: add coupled cpuidle support for exynos4210
  ARM: EXYNOS: apply S5P_CENTRAL_SEQ_OPTION fix only when necessary
  soc: ti: knav_qmss_queue: change knav_range_setup_acc_irq to static
  soc: ti: knav_qmss_queue: makefile tweak to build as dynamic module
  pcmcia: at91_cf: depend on !ARCH_MULTIPLATFORM
  soc: ti: knav_qmss_queue: export API calls for use by user driver
  of/platform: teardown DMA mappings on device destruction
  usb: gadget: at91_udc: Allocate udc instance
  usb: gadget: at91_udc: Update DT binding documentation
  usb: gadget: at91_udc: Rework for multi-platform kernel support
  usb: gadget: at91_udc: Simplify probe and remove functions
  usb: gadget: at91_udc: Remove non-DT handling code
  usb: gadget: at91_udc: Document DT clocks and clock-names property
  usb: gadget: at91_udc: Drop uclk clock
  usb: gadget: at91_udc: Fix clock names
  mfd: syscon: Add Atmel SMC binding doc
  mfd: syscon: Add atmel-smc registers definition
  mfd: syscon: Add Atmel Matrix bus DT binding documentation
  mfd: syscon: Add atmel-matrix registers definition
  clk: shmobile: fix sparse NULL pointer warning
  ...
parents a233bb74 6f4554bd
These bindings should be considered EXPERIMENTAL for now.
* Renesas SH73A0 Clock Pulse Generator (CPG)
The CPG generates core clocks for the SH73A0 SoC. It includes four PLLs
and several fixed ratio dividers.
Required Properties:
- compatible: Must be "renesas,sh73a0-cpg-clocks"
- reg: Base address and length of the memory resource used by the CPG
- clocks: Reference to the parent clocks ("extal1" and "extal2")
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are "main",
"pll0", "pll1", "pll2", "pll3", "dsi0phy", "dsi1phy", "zg", "m3", "b",
"m1", "m2", "z", "zx", and "hp".
Example
-------
cpg_clocks: cpg_clocks@e6150000 {
compatible = "renesas,sh73a0-cpg-clocks";
reg = <0 0xe6150000 0 0x10000>;
clocks = <&extal1_clk>, <&extal2_clk>;
#clock-cells = <1>;
clock-output-names = "main", "pll0", "pll1", "pll2",
"pll3", "dsi0phy", "dsi1phy",
"zg", "m3", "b", "m1", "m2",
"z", "zx", "hp";
};
* Device tree bindings for Atmel Bus Matrix
The Bus Matrix registers are used to configure Atmel SoCs internal bus
behavior (master/slave priorities, undefined burst length type, ...)
Required properties:
- compatible: Should be one of the following
"atmel,at91sam9260-matrix", "syscon"
"atmel,at91sam9261-matrix", "syscon"
"atmel,at91sam9263-matrix", "syscon"
"atmel,at91sam9rl-matrix", "syscon"
"atmel,at91sam9g45-matrix", "syscon"
"atmel,at91sam9n12-matrix", "syscon"
"atmel,at91sam9x5-matrix", "syscon"
"atmel,sama5d3-matrix", "syscon"
- reg: Contains offset/length value of the Bus Matrix
memory region.
Example:
matrix: matrix@ffffec00 {
compatible = "atmel,sama5d3-matrix", "syscon";
reg = <0xffffec00 0x200>;
};
* Device tree bindings for Atmel SMC (Static Memory Controller)
The SMC registers are used to configure Atmel EBI (External Bus Interface)
to interface with standard memory devices (NAND, NOR, SRAM or specialized
devices like FPGAs).
Required properties:
- compatible: Should be one of the following
"atmel,at91sam9260-smc", "syscon"
"atmel,sama5d3-smc", "syscon"
- reg: Contains offset/length value of the SMC memory
region.
Example:
smc: smc@ffffc000 {
compatible = "atmel,sama5d3-smc", "syscon";
reg = <0xffffc000 0x1000>;
};
...@@ -33,9 +33,17 @@ usb1: ehci@00800000 { ...@@ -33,9 +33,17 @@ usb1: ehci@00800000 {
AT91 USB device controller AT91 USB device controller
Required properties: Required properties:
- compatible: Should be "atmel,at91rm9200-udc" - compatible: Should be one of the following
"atmel,at91rm9200-udc"
"atmel,at91sam9260-udc"
"atmel,at91sam9261-udc"
"atmel,at91sam9263-udc"
- reg: Address and length of the register set for the device - reg: Address and length of the register set for the device
- interrupts: Should contain macb interrupt - interrupts: Should contain macb interrupt
- clocks: Should reference the peripheral and the AHB clocks
- clock-names: Should contains two strings
"pclk" for the peripheral clock
"hclk" for the AHB clock
Optional properties: Optional properties:
- atmel,vbus-gpio: If present, specifies a gpio that needs to be - atmel,vbus-gpio: If present, specifies a gpio that needs to be
......
...@@ -182,6 +182,10 @@ &cmt1 { ...@@ -182,6 +182,10 @@ &cmt1 {
status = "okay"; status = "okay";
}; };
&extal2_clk {
clock-frequency = <48000000>;
};
&i2c0 { &i2c0 {
status = "okay"; status = "okay";
as3711@40 { as3711@40 {
......
This diff is collapsed.
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#define __ARCH_ARM_MACH_EXYNOS_COMMON_H #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_data/cpuidle-exynos.h>
#define EXYNOS3250_SOC_ID 0xE3472000 #define EXYNOS3250_SOC_ID 0xE3472000
#define EXYNOS3_SOC_MASK 0xFFFFF000 #define EXYNOS3_SOC_MASK 0xFFFFF000
...@@ -150,8 +151,11 @@ extern void exynos_pm_central_suspend(void); ...@@ -150,8 +151,11 @@ extern void exynos_pm_central_suspend(void);
extern int exynos_pm_central_resume(void); extern int exynos_pm_central_resume(void);
extern void exynos_enter_aftr(void); extern void exynos_enter_aftr(void);
extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data;
extern void s5p_init_cpu(void __iomem *cpuid_addr); extern void s5p_init_cpu(void __iomem *cpuid_addr);
extern unsigned int samsung_rev(void); extern unsigned int samsung_rev(void);
extern void __iomem *cpu_boot_reg_base(void);
static inline void pmu_raw_writel(u32 val, u32 offset) static inline void pmu_raw_writel(u32 val, u32 offset)
{ {
......
...@@ -211,6 +211,10 @@ static void __init exynos_dt_machine_init(void) ...@@ -211,6 +211,10 @@ static void __init exynos_dt_machine_init(void)
if (!IS_ENABLED(CONFIG_SMP)) if (!IS_ENABLED(CONFIG_SMP))
exynos_sysram_init(); exynos_sysram_init();
#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
if (of_machine_is_compatible("samsung,exynos4210"))
exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data;
#endif
if (of_machine_is_compatible("samsung,exynos4210") || if (of_machine_is_compatible("samsung,exynos4210") ||
of_machine_is_compatible("samsung,exynos4212") || of_machine_is_compatible("samsung,exynos4212") ||
(of_machine_is_compatible("samsung,exynos4412") && (of_machine_is_compatible("samsung,exynos4412") &&
......
...@@ -194,7 +194,7 @@ int exynos_cluster_power_state(int cluster) ...@@ -194,7 +194,7 @@ int exynos_cluster_power_state(int cluster)
S5P_CORE_LOCAL_PWR_EN); S5P_CORE_LOCAL_PWR_EN);
} }
static inline void __iomem *cpu_boot_reg_base(void) void __iomem *cpu_boot_reg_base(void)
{ {
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
return pmu_base_addr + S5P_INFORM5; return pmu_base_addr + S5P_INFORM5;
......
...@@ -98,10 +98,6 @@ void exynos_pm_central_suspend(void) ...@@ -98,10 +98,6 @@ void exynos_pm_central_suspend(void)
tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
tmp &= ~S5P_CENTRAL_LOWPWR_CFG; tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
/* Setting SEQ_OPTION register */
pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
S5P_CENTRAL_SEQ_OPTION);
} }
int exynos_pm_central_resume(void) int exynos_pm_central_resume(void)
...@@ -165,6 +161,13 @@ void exynos_enter_aftr(void) ...@@ -165,6 +161,13 @@ void exynos_enter_aftr(void)
exynos_pm_central_suspend(); exynos_pm_central_suspend();
if (of_machine_is_compatible("samsung,exynos4212") ||
of_machine_is_compatible("samsung,exynos4412")) {
/* Setting SEQ_OPTION register */
pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
S5P_CENTRAL_SEQ_OPTION);
}
cpu_suspend(0, exynos_aftr_finisher); cpu_suspend(0, exynos_aftr_finisher);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
...@@ -177,3 +180,125 @@ void exynos_enter_aftr(void) ...@@ -177,3 +180,125 @@ void exynos_enter_aftr(void)
cpu_pm_exit(); cpu_pm_exit();
} }
static atomic_t cpu1_wakeup = ATOMIC_INIT(0);
static int exynos_cpu0_enter_aftr(void)
{
int ret = -1;
/*
* If the other cpu is powered on, we have to power it off, because
* the AFTR state won't work otherwise
*/
if (cpu_online(1)) {
/*
* We reach a sync point with the coupled idle state, we know
* the other cpu will power down itself or will abort the
* sequence, let's wait for one of these to happen
*/
while (exynos_cpu_power_state(1)) {
/*
* The other cpu may skip idle and boot back
* up again
*/
if (atomic_read(&cpu1_wakeup))
goto abort;
/*
* The other cpu may bounce through idle and
* boot back up again, getting stuck in the
* boot rom code
*/
if (__raw_readl(cpu_boot_reg_base()) == 0)
goto abort;
cpu_relax();
}
}
exynos_enter_aftr();
ret = 0;
abort:
if (cpu_online(1)) {
/*
* Set the boot vector to something non-zero
*/
__raw_writel(virt_to_phys(exynos_cpu_resume),
cpu_boot_reg_base());
dsb();
/*
* Turn on cpu1 and wait for it to be on
*/
exynos_cpu_power_up(1);
while (exynos_cpu_power_state(1) != S5P_CORE_LOCAL_PWR_EN)
cpu_relax();
while (!atomic_read(&cpu1_wakeup)) {
/*
* Poke cpu1 out of the boot rom
*/
__raw_writel(virt_to_phys(exynos_cpu_resume),
cpu_boot_reg_base());
arch_send_wakeup_ipi_mask(cpumask_of(1));
}
}
return ret;
}
static int exynos_wfi_finisher(unsigned long flags)
{
cpu_do_idle();
return -1;
}
static int exynos_cpu1_powerdown(void)
{
int ret = -1;
/*
* Idle sequence for cpu1
*/
if (cpu_pm_enter())
goto cpu1_aborted;
/*
* Turn off cpu 1
*/
exynos_cpu_power_down(1);
ret = cpu_suspend(0, exynos_wfi_finisher);
cpu_pm_exit();
cpu1_aborted:
dsb();
/*
* Notify cpu 0 that cpu 1 is awake
*/
atomic_set(&cpu1_wakeup, 1);
return ret;
}
static void exynos_pre_enter_aftr(void)
{
__raw_writel(virt_to_phys(exynos_cpu_resume), cpu_boot_reg_base());
}
static void exynos_post_enter_aftr(void)
{
atomic_set(&cpu1_wakeup, 0);
}
struct cpuidle_exynos_data cpuidle_coupled_exynos_data = {
.cpu0_enter_aftr = exynos_cpu0_enter_aftr,
.cpu1_powerdown = exynos_cpu1_powerdown,
.pre_enter_aftr = exynos_pre_enter_aftr,
.post_enter_aftr = exynos_post_enter_aftr,
};
...@@ -319,6 +319,10 @@ static int exynos_pm_suspend(void) ...@@ -319,6 +319,10 @@ static int exynos_pm_suspend(void)
{ {
exynos_pm_central_suspend(); exynos_pm_central_suspend();
/* Setting SEQ_OPTION register */
pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
S5P_CENTRAL_SEQ_OPTION);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_save_register(); exynos_cpu_save_register();
......
...@@ -766,7 +766,9 @@ void __init __weak sh73a0_register_twd(void) { } ...@@ -766,7 +766,9 @@ void __init __weak sh73a0_register_twd(void) { }
void __init sh73a0_earlytimer_init(void) void __init sh73a0_earlytimer_init(void)
{ {
shmobile_init_delay(); shmobile_init_delay();
#ifndef CONFIG_COMMON_CLK
sh73a0_clock_init(); sh73a0_clock_init();
#endif
shmobile_earlytimer_init(); shmobile_earlytimer_init();
sh73a0_register_twd(); sh73a0_register_twd();
} }
...@@ -785,8 +787,9 @@ void __init sh73a0_add_early_devices(void) ...@@ -785,8 +787,9 @@ void __init sh73a0_add_early_devices(void)
void __init sh73a0_add_standard_devices_dt(void) void __init sh73a0_add_standard_devices_dt(void)
{ {
/* clocks are setup late during boot in the case of DT */ /* clocks are setup late during boot in the case of DT */
#ifndef CONFIG_COMMON_CLK
sh73a0_clock_init(); sh73a0_clock_init();
#endif
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
} }
......
...@@ -5,5 +5,6 @@ obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o ...@@ -5,5 +5,6 @@ obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o
obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o
obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o
/*
* sh73a0 Core CPG Clocks
*
* Copyright (C) 2014 Ulrich Hecht
*
* 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; version 2 of the License.
*/
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/clk/shmobile.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/spinlock.h>
struct sh73a0_cpg {
struct clk_onecell_data data;
spinlock_t lock;
void __iomem *reg;
};
#define CPG_FRQCRA 0x00
#define CPG_FRQCRB 0x04
#define CPG_SD0CKCR 0x74
#define CPG_SD1CKCR 0x78
#define CPG_SD2CKCR 0x7c
#define CPG_PLLECR 0xd0
#define CPG_PLL0CR 0xd8
#define CPG_PLL1CR 0x28
#define CPG_PLL2CR 0x2c
#define CPG_PLL3CR 0xdc
#define CPG_CKSCR 0xc0
#define CPG_DSI0PHYCR 0x6c
#define CPG_DSI1PHYCR 0x70
#define CLK_ENABLE_ON_INIT BIT(0)
struct div4_clk {
const char *name;
const char *parent;
unsigned int reg;
unsigned int shift;
};
static struct div4_clk div4_clks[] = {
{ "zg", "pll0", CPG_FRQCRA, 16 },
{ "m3", "pll1", CPG_FRQCRA, 12 },
{ "b", "pll1", CPG_FRQCRA, 8 },
{ "m1", "pll1", CPG_FRQCRA, 4 },
{ "m2", "pll1", CPG_FRQCRA, 0 },
{ "zx", "pll1", CPG_FRQCRB, 12 },
{ "hp", "pll1", CPG_FRQCRB, 4 },
{ NULL, NULL, 0, 0 },
};
static const struct clk_div_table div4_div_table[] = {
{ 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 },
{ 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 },
{ 12, 7 }, { 0, 0 }
};
static const struct clk_div_table z_div_table[] = {
/* ZSEL == 0 */
{ 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 },
{ 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 },
{ 12, 1 }, { 13, 1 }, { 14, 1 }, { 15, 1 },
/* ZSEL == 1 */
{ 16, 2 }, { 17, 3 }, { 18, 4 }, { 19, 6 }, { 20, 8 }, { 21, 12 },
{ 22, 16 }, { 24, 24 }, { 27, 48 }, { 0, 0 }
};
static struct clk * __init
sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
const char *name)
{
const struct clk_div_table *table = NULL;
unsigned int shift, reg, width;
const char *parent_name;
unsigned int mult = 1;
unsigned int div = 1;
if (!strcmp(name, "main")) {
/* extal1, extal1_div2, extal2, extal2_div2 */
u32 parent_idx = (clk_readl(cpg->reg + CPG_CKSCR) >> 28) & 3;
parent_name = of_clk_get_parent_name(np, parent_idx >> 1);
div = (parent_idx & 1) + 1;
} else if (!strncmp(name, "pll", 3)) {
void __iomem *enable_reg = cpg->reg;
u32 enable_bit = name[3] - '0';
parent_name = "main";
switch (enable_bit) {
case 0:
enable_reg += CPG_PLL0CR;
break;
case 1:
enable_reg += CPG_PLL1CR;
break;
case 2:
enable_reg += CPG_PLL2CR;
break;
case 3:
enable_reg += CPG_PLL3CR;
break;
default:
return ERR_PTR(-EINVAL);
}
if (clk_readl(cpg->reg + CPG_PLLECR) & BIT(enable_bit)) {
mult = ((clk_readl(enable_reg) >> 24) & 0x3f) + 1;
/* handle CFG bit for PLL1 and PLL2 */
if (enable_bit == 1 || enable_bit == 2)
if (clk_readl(enable_reg) & BIT(20))
mult *= 2;
}
} else if (!strcmp(name, "dsi0phy") || !strcmp(name, "dsi1phy")) {
u32 phy_no = name[3] - '0';
void __iomem *dsi_reg = cpg->reg +
(phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR);
parent_name = phy_no ? "dsi1pck" : "dsi0pck";
mult = __raw_readl(dsi_reg);
if (!(mult & 0x8000))
mult = 1;
else
mult = (mult & 0x3f) + 1;
} else if (!strcmp(name, "z")) {
parent_name = "pll0";
table = z_div_table;
reg = CPG_FRQCRB;
shift = 24;
width = 5;
} else {
struct div4_clk *c;
for (c = div4_clks; c->name; c++) {
if (!strcmp(name, c->name)) {
parent_name = c->parent;
table = div4_div_table;
reg = c->reg;
shift = c->shift;
width = 4;
break;
}
}
if (!c->name)
return ERR_PTR(-EINVAL);
}
if (!table) {
return clk_register_fixed_factor(NULL, name, parent_name, 0,
mult, div);
} else {
return clk_register_divider_table(NULL, name, parent_name, 0,
cpg->reg + reg, shift, width, 0,
table, &cpg->lock);
}
}
static void __init sh73a0_cpg_clocks_init(struct device_node *np)
{
struct sh73a0_cpg *cpg;
struct clk **clks;
unsigned int i;
int num_clks;
num_clks = of_property_count_strings(np, "clock-output-names");
if (num_clks < 0) {
pr_err("%s: failed to count clocks\n", __func__);
return;
}
cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
if (cpg == NULL || clks == NULL) {
/* We're leaking memory on purpose, there's no point in cleaning
* up as the system won't boot anyway.
*/
return;
}
spin_lock_init(&cpg->lock);
cpg->data.clks = clks;
cpg->data.clk_num = num_clks;
cpg->reg = of_iomap(np, 0);
if (WARN_ON(cpg->reg == NULL))
return;
/* Set SDHI clocks to a known state */
clk_writel(0x108, cpg->reg + CPG_SD0CKCR);
clk_writel(0x108, cpg->reg + CPG_SD1CKCR);
clk_writel(0x108, cpg->reg + CPG_SD2CKCR);
for (i = 0; i < num_clks; ++i) {
const char *name;
struct clk *clk;
of_property_read_string_index(np, "clock-output-names", i,
&name);
clk = sh73a0_cpg_register_clock(np, cpg, name);
if (IS_ERR(clk))
pr_err("%s: failed to register %s %s clock (%ld)\n",
__func__, np->name, name, PTR_ERR(clk));
else
cpg->data.clks[i] = clk;
}
of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
}
CLK_OF_DECLARE(sh73a0_cpg_clks, "renesas,sh73a0-cpg-clocks",
sh73a0_cpg_clocks_init);
...@@ -55,6 +55,7 @@ config ARM_AT91_CPUIDLE ...@@ -55,6 +55,7 @@ config ARM_AT91_CPUIDLE
config ARM_EXYNOS_CPUIDLE config ARM_EXYNOS_CPUIDLE
bool "Cpu Idle Driver for the Exynos processors" bool "Cpu Idle Driver for the Exynos processors"
depends on ARCH_EXYNOS depends on ARCH_EXYNOS
select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
help help
Select this to enable cpuidle for Exynos processors Select this to enable cpuidle for Exynos processors
......
/* linux/arch/arm/mach-exynos/cpuidle.c /*
* * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Coupled cpuidle support based on the work of:
* Colin Cross <ccross@android.com>
* Daniel Lezcano <daniel.lezcano@linaro.org>
*
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
...@@ -13,13 +16,49 @@ ...@@ -13,13 +16,49 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/platform_data/cpuidle-exynos.h>
#include <asm/proc-fns.h> #include <asm/proc-fns.h>
#include <asm/suspend.h> #include <asm/suspend.h>
#include <asm/cpuidle.h> #include <asm/cpuidle.h>
static atomic_t exynos_idle_barrier;
static struct cpuidle_exynos_data *exynos_cpuidle_pdata;
static void (*exynos_enter_aftr)(void); static void (*exynos_enter_aftr)(void);
static int exynos_enter_coupled_lowpower(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
int ret;
exynos_cpuidle_pdata->pre_enter_aftr();
/*
* Waiting all cpus to reach this point at the same moment
*/
cpuidle_coupled_parallel_barrier(dev, &exynos_idle_barrier);
/*
* Both cpus will reach this point at the same time
*/
ret = dev->cpu ? exynos_cpuidle_pdata->cpu1_powerdown()
: exynos_cpuidle_pdata->cpu0_enter_aftr();
if (ret)
index = ret;
/*
* Waiting all cpus to finish the power sequence before going further
*/
cpuidle_coupled_parallel_barrier(dev, &exynos_idle_barrier);
exynos_cpuidle_pdata->post_enter_aftr();
return index;
}
static int exynos_enter_lowpower(struct cpuidle_device *dev, static int exynos_enter_lowpower(struct cpuidle_device *dev,
struct cpuidle_driver *drv, struct cpuidle_driver *drv,
int index) int index)
...@@ -55,13 +94,40 @@ static struct cpuidle_driver exynos_idle_driver = { ...@@ -55,13 +94,40 @@ static struct cpuidle_driver exynos_idle_driver = {
.safe_state_index = 0, .safe_state_index = 0,
}; };
static struct cpuidle_driver exynos_coupled_idle_driver = {
.name = "exynos_coupled_idle",
.owner = THIS_MODULE,
.states = {
[0] = ARM_CPUIDLE_WFI_STATE,
[1] = {
.enter = exynos_enter_coupled_lowpower,
.exit_latency = 5000,
.target_residency = 10000,
.flags = CPUIDLE_FLAG_COUPLED |
CPUIDLE_FLAG_TIMER_STOP,
.name = "C1",
.desc = "ARM power down",
},
},
.state_count = 2,
.safe_state_index = 0,
};
static int exynos_cpuidle_probe(struct platform_device *pdev) static int exynos_cpuidle_probe(struct platform_device *pdev)
{ {
int ret; int ret;
if (of_machine_is_compatible("samsung,exynos4210")) {
exynos_cpuidle_pdata = pdev->dev.platform_data;
ret = cpuidle_register(&exynos_coupled_idle_driver,
cpu_possible_mask);
} else {
exynos_enter_aftr = (void *)(pdev->dev.platform_data); exynos_enter_aftr = (void *)(pdev->dev.platform_data);
ret = cpuidle_register(&exynos_idle_driver, NULL); ret = cpuidle_register(&exynos_idle_driver, NULL);
}
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register cpuidle driver\n"); dev_err(&pdev->dev, "failed to register cpuidle driver\n");
return ret; return ret;
......
...@@ -526,6 +526,7 @@ static int of_platform_device_destroy(struct device *dev, void *data) ...@@ -526,6 +526,7 @@ static int of_platform_device_destroy(struct device *dev, void *data)
amba_device_unregister(to_amba_device(dev)); amba_device_unregister(to_amba_device(dev));
#endif #endif
of_dma_deconfigure(dev);
of_node_clear_flag(dev->of_node, OF_POPULATED); of_node_clear_flag(dev->of_node, OF_POPULATED);
of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
return 0; return 0;
......
...@@ -279,6 +279,7 @@ config BFIN_CFPCMCIA ...@@ -279,6 +279,7 @@ config BFIN_CFPCMCIA
config AT91_CF config AT91_CF
tristate "AT91 CompactFlash Controller" tristate "AT91 CompactFlash Controller"
depends on PCMCIA && ARCH_AT91 depends on PCMCIA && ARCH_AT91
depends on !ARCH_MULTIPLATFORM
help help
Say Y here to support the CompactFlash controller on AT91 chips. Say Y here to support the CompactFlash controller on AT91 chips.
Or choose M to compile the driver as a module named "at91_cf". Or choose M to compile the driver as a module named "at91_cf".
......
# #
# TI Keystone SOC drivers # TI Keystone SOC drivers
# #
obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss_queue.o knav_qmss_acc.o obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss.o
knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o
...@@ -209,7 +209,7 @@ static irqreturn_t knav_acc_int_handler(int irq, void *_instdata) ...@@ -209,7 +209,7 @@ static irqreturn_t knav_acc_int_handler(int irq, void *_instdata)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
int knav_range_setup_acc_irq(struct knav_range_info *range, static int knav_range_setup_acc_irq(struct knav_range_info *range,
int queue, bool enabled) int queue, bool enabled)
{ {
struct knav_device *kdev = range->kdev; struct knav_device *kdev = range->kdev;
......
...@@ -626,6 +626,7 @@ int knav_queue_push(void *qhandle, dma_addr_t dma, ...@@ -626,6 +626,7 @@ int knav_queue_push(void *qhandle, dma_addr_t dma,
atomic_inc(&qh->stats.pushes); atomic_inc(&qh->stats.pushes);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(knav_queue_push);
/** /**
* knav_queue_pop() - pop data (or descriptor) from the head of a queue * knav_queue_pop() - pop data (or descriptor) from the head of a queue
...@@ -663,6 +664,7 @@ dma_addr_t knav_queue_pop(void *qhandle, unsigned *size) ...@@ -663,6 +664,7 @@ dma_addr_t knav_queue_pop(void *qhandle, unsigned *size)
atomic_inc(&qh->stats.pops); atomic_inc(&qh->stats.pops);
return dma; return dma;
} }
EXPORT_SYMBOL_GPL(knav_queue_pop);
/* carve out descriptors and push into queue */ /* carve out descriptors and push into queue */
static void kdesc_fill_pool(struct knav_pool *pool) static void kdesc_fill_pool(struct knav_pool *pool)
...@@ -717,12 +719,14 @@ dma_addr_t knav_pool_desc_virt_to_dma(void *ph, void *virt) ...@@ -717,12 +719,14 @@ dma_addr_t knav_pool_desc_virt_to_dma(void *ph, void *virt)
struct knav_pool *pool = ph; struct knav_pool *pool = ph;
return pool->region->dma_start + (virt - pool->region->virt_start); return pool->region->dma_start + (virt - pool->region->virt_start);
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_virt_to_dma);
void *knav_pool_desc_dma_to_virt(void *ph, dma_addr_t dma) void *knav_pool_desc_dma_to_virt(void *ph, dma_addr_t dma)
{ {
struct knav_pool *pool = ph; struct knav_pool *pool = ph;
return pool->region->virt_start + (dma - pool->region->dma_start); return pool->region->virt_start + (dma - pool->region->dma_start);
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_dma_to_virt);
/** /**
* knav_pool_create() - Create a pool of descriptors * knav_pool_create() - Create a pool of descriptors
...@@ -878,6 +882,7 @@ void *knav_pool_desc_get(void *ph) ...@@ -878,6 +882,7 @@ void *knav_pool_desc_get(void *ph)
data = knav_pool_desc_dma_to_virt(pool, dma); data = knav_pool_desc_dma_to_virt(pool, dma);
return data; return data;
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_get);
/** /**
* knav_pool_desc_put() - return a descriptor to the pool * knav_pool_desc_put() - return a descriptor to the pool
...@@ -890,6 +895,7 @@ void knav_pool_desc_put(void *ph, void *desc) ...@@ -890,6 +895,7 @@ void knav_pool_desc_put(void *ph, void *desc)
dma = knav_pool_desc_virt_to_dma(pool, desc); dma = knav_pool_desc_virt_to_dma(pool, desc);
knav_queue_push(pool->queue, dma, pool->region->desc_size, 0); knav_queue_push(pool->queue, dma, pool->region->desc_size, 0);
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_put);
/** /**
* knav_pool_desc_map() - Map descriptor for DMA transfer * knav_pool_desc_map() - Map descriptor for DMA transfer
...@@ -916,6 +922,7 @@ int knav_pool_desc_map(void *ph, void *desc, unsigned size, ...@@ -916,6 +922,7 @@ int knav_pool_desc_map(void *ph, void *desc, unsigned size,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_map);
/** /**
* knav_pool_desc_unmap() - Unmap descriptor after DMA transfer * knav_pool_desc_unmap() - Unmap descriptor after DMA transfer
...@@ -938,6 +945,7 @@ void *knav_pool_desc_unmap(void *ph, dma_addr_t dma, unsigned dma_sz) ...@@ -938,6 +945,7 @@ void *knav_pool_desc_unmap(void *ph, dma_addr_t dma, unsigned dma_sz)
prefetch(desc); prefetch(desc);
return desc; return desc;
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_unmap);
/** /**
* knav_pool_count() - Get the number of descriptors in pool. * knav_pool_count() - Get the number of descriptors in pool.
...@@ -949,6 +957,7 @@ int knav_pool_count(void *ph) ...@@ -949,6 +957,7 @@ int knav_pool_count(void *ph)
struct knav_pool *pool = ph; struct knav_pool *pool = ph;
return knav_queue_get_count(pool->queue); return knav_queue_get_count(pool->queue);
} }
EXPORT_SYMBOL_GPL(knav_pool_count);
static void knav_queue_setup_region(struct knav_device *kdev, static void knav_queue_setup_region(struct knav_device *kdev,
struct knav_region *region) struct knav_region *region)
......
...@@ -32,6 +32,7 @@ menu "USB Peripheral Controller" ...@@ -32,6 +32,7 @@ menu "USB Peripheral Controller"
config USB_AT91 config USB_AT91
tristate "Atmel AT91 USB Device Port" tristate "Atmel AT91 USB Device Port"
depends on ARCH_AT91 depends on ARCH_AT91
depends on OF || COMPILE_TEST
help help
Many Atmel AT91 processors (such as the AT91RM2000) have a Many Atmel AT91 processors (such as the AT91RM2000) have a
full speed USB Device Port with support for five configurable full speed USB Device Port with support for five configurable
......
This diff is collapsed.
...@@ -107,6 +107,11 @@ struct at91_ep { ...@@ -107,6 +107,11 @@ struct at91_ep {
unsigned fifo_bank:1; unsigned fifo_bank:1;
}; };
struct at91_udc_caps {
int (*init)(struct at91_udc *udc);
void (*pullup)(struct at91_udc *udc, int is_on);
};
/* /*
* driver is non-SMP, and just blocks IRQs whenever it needs * driver is non-SMP, and just blocks IRQs whenever it needs
* access protection for chip registers or driver state * access protection for chip registers or driver state
...@@ -115,6 +120,7 @@ struct at91_udc { ...@@ -115,6 +120,7 @@ struct at91_udc {
struct usb_gadget gadget; struct usb_gadget gadget;
struct at91_ep ep[NUM_ENDPOINTS]; struct at91_ep ep[NUM_ENDPOINTS];
struct usb_gadget_driver *driver; struct usb_gadget_driver *driver;
const struct at91_udc_caps *caps;
unsigned vbus:1; unsigned vbus:1;
unsigned enabled:1; unsigned enabled:1;
unsigned clocked:1; unsigned clocked:1;
...@@ -125,7 +131,7 @@ struct at91_udc { ...@@ -125,7 +131,7 @@ struct at91_udc {
unsigned active_suspend:1; unsigned active_suspend:1;
u8 addr; u8 addr;
struct at91_udc_data board; struct at91_udc_data board;
struct clk *iclk, *fclk, *uclk; struct clk *iclk, *fclk;
struct platform_device *pdev; struct platform_device *pdev;
struct proc_dir_entry *pde; struct proc_dir_entry *pde;
void __iomem *udp_baseaddr; void __iomem *udp_baseaddr;
...@@ -133,6 +139,7 @@ struct at91_udc { ...@@ -133,6 +139,7 @@ struct at91_udc {
spinlock_t lock; spinlock_t lock;
struct timer_list vbus_timer; struct timer_list vbus_timer;
struct work_struct vbus_timer_work; struct work_struct vbus_timer_work;
struct regmap *matrix;
}; };
static inline struct at91_udc *to_udc(struct usb_gadget *g) static inline struct at91_udc *to_udc(struct usb_gadget *g)
......
/*
* Copyright 2014 Ulrich Hecht
*
* 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.
*/
#ifndef __DT_BINDINGS_CLOCK_SH73A0_H__
#define __DT_BINDINGS_CLOCK_SH73A0_H__
/* CPG */
#define SH73A0_CLK_MAIN 0
#define SH73A0_CLK_PLL0 1
#define SH73A0_CLK_PLL1 2
#define SH73A0_CLK_PLL2 3
#define SH73A0_CLK_PLL3 4
#define SH73A0_CLK_DSI0PHY 5
#define SH73A0_CLK_DSI1PHY 6
#define SH73A0_CLK_ZG 7
#define SH73A0_CLK_M3 8
#define SH73A0_CLK_B 9
#define SH73A0_CLK_M1 10
#define SH73A0_CLK_M2 11
#define SH73A0_CLK_Z 12
#define SH73A0_CLK_ZX 13
#define SH73A0_CLK_HP 14
/* MSTP0 */
#define SH73A0_CLK_IIC2 1
/* MSTP1 */
#define SH73A0_CLK_CEU1 29
#define SH73A0_CLK_CSI2_RX1 28
#define SH73A0_CLK_CEU0 27
#define SH73A0_CLK_CSI2_RX0 26
#define SH73A0_CLK_TMU0 25
#define SH73A0_CLK_DSITX0 18
#define SH73A0_CLK_IIC0 16
#define SH73A0_CLK_SGX 12
#define SH73A0_CLK_LCDC0 0
/* MSTP2 */
#define SH73A0_CLK_SCIFA7 19
#define SH73A0_CLK_SY_DMAC 18
#define SH73A0_CLK_MP_DMAC 17
#define SH73A0_CLK_SCIFA5 7
#define SH73A0_CLK_SCIFB 6
#define SH73A0_CLK_SCIFA0 4
#define SH73A0_CLK_SCIFA1 3
#define SH73A0_CLK_SCIFA2 2
#define SH73A0_CLK_SCIFA3 1
#define SH73A0_CLK_SCIFA4 0
/* MSTP3 */
#define SH73A0_CLK_SCIFA6 31
#define SH73A0_CLK_CMT1 29
#define SH73A0_CLK_FSI 28
#define SH73A0_CLK_IRDA 25
#define SH73A0_CLK_IIC1 23
#define SH73A0_CLK_USB 22
#define SH73A0_CLK_FLCTL 15
#define SH73A0_CLK_SDHI0 14
#define SH73A0_CLK_SDHI1 13
#define SH73A0_CLK_MMCIF0 12
#define SH73A0_CLK_SDHI2 11
#define SH73A0_CLK_TPU0 4
#define SH73A0_CLK_TPU1 3
#define SH73A0_CLK_TPU2 2
#define SH73A0_CLK_TPU3 1
#define SH73A0_CLK_TPU4 0
/* MSTP4 */
#define SH73A0_CLK_IIC3 11
#define SH73A0_CLK_IIC4 10
#define SH73A0_CLK_KEYSC 3
#endif
/*
* Copyright (C) 2014 Atmel Corporation.
*
* Memory Controllers (MATRIX, EBI) - System peripherals registers.
*
* 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.
*/
#ifndef _LINUX_MFD_SYSCON_ATMEL_MATRIX_H
#define _LINUX_MFD_SYSCON_ATMEL_MATRIX_H
#define AT91SAM9260_MATRIX_MCFG 0x00
#define AT91SAM9260_MATRIX_SCFG 0x40
#define AT91SAM9260_MATRIX_PRS 0x80
#define AT91SAM9260_MATRIX_MRCR 0x100
#define AT91SAM9260_MATRIX_EBICSA 0x11c
#define AT91SAM9261_MATRIX_MRCR 0x0
#define AT91SAM9261_MATRIX_SCFG 0x4
#define AT91SAM9261_MATRIX_TCR 0x24
#define AT91SAM9261_MATRIX_EBICSA 0x30
#define AT91SAM9261_MATRIX_USBPUCR 0x34
#define AT91SAM9263_MATRIX_MCFG 0x00
#define AT91SAM9263_MATRIX_SCFG 0x40
#define AT91SAM9263_MATRIX_PRS 0x80
#define AT91SAM9263_MATRIX_MRCR 0x100
#define AT91SAM9263_MATRIX_TCR 0x114
#define AT91SAM9263_MATRIX_EBI0CSA 0x120
#define AT91SAM9263_MATRIX_EBI1CSA 0x124
#define AT91SAM9RL_MATRIX_MCFG 0x00
#define AT91SAM9RL_MATRIX_SCFG 0x40
#define AT91SAM9RL_MATRIX_PRS 0x80
#define AT91SAM9RL_MATRIX_MRCR 0x100
#define AT91SAM9RL_MATRIX_TCR 0x114
#define AT91SAM9RL_MATRIX_EBICSA 0x120
#define AT91SAM9G45_MATRIX_MCFG 0x00
#define AT91SAM9G45_MATRIX_SCFG 0x40
#define AT91SAM9G45_MATRIX_PRS 0x80
#define AT91SAM9G45_MATRIX_MRCR 0x100
#define AT91SAM9G45_MATRIX_TCR 0x110
#define AT91SAM9G45_MATRIX_DDRMPR 0x118
#define AT91SAM9G45_MATRIX_EBICSA 0x128
#define AT91SAM9N12_MATRIX_MCFG 0x00
#define AT91SAM9N12_MATRIX_SCFG 0x40
#define AT91SAM9N12_MATRIX_PRS 0x80
#define AT91SAM9N12_MATRIX_MRCR 0x100
#define AT91SAM9N12_MATRIX_EBICSA 0x118
#define AT91SAM9X5_MATRIX_MCFG 0x00
#define AT91SAM9X5_MATRIX_SCFG 0x40
#define AT91SAM9X5_MATRIX_PRS 0x80
#define AT91SAM9X5_MATRIX_MRCR 0x100
#define AT91SAM9X5_MATRIX_EBICSA 0x120
#define SAMA5D3_MATRIX_MCFG 0x00
#define SAMA5D3_MATRIX_SCFG 0x40
#define SAMA5D3_MATRIX_PRS 0x80
#define SAMA5D3_MATRIX_MRCR 0x100
#define AT91_MATRIX_MCFG(o, x) ((o) + ((x) * 0x4))
#define AT91_MATRIX_ULBT GENMASK(2, 0)
#define AT91_MATRIX_ULBT_INFINITE (0 << 0)
#define AT91_MATRIX_ULBT_SINGLE (1 << 0)
#define AT91_MATRIX_ULBT_FOUR (2 << 0)
#define AT91_MATRIX_ULBT_EIGHT (3 << 0)
#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0)
#define AT91_MATRIX_SCFG(o, x) ((o) + ((x) * 0x4))
#define AT91_MATRIX_SLOT_CYCLE GENMASK(7, 0)
#define AT91_MATRIX_DEFMSTR_TYPE GENMASK(17, 16)
#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16)
#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16)
#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16)
#define AT91_MATRIX_FIXED_DEFMSTR GENMASK(20, 18)
#define AT91_MATRIX_ARBT GENMASK(25, 24)
#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24)
#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
#define AT91_MATRIX_ITCM_SIZE GENMASK(3, 0)
#define AT91_MATRIX_ITCM_0 (0 << 0)
#define AT91_MATRIX_ITCM_16 (5 << 0)
#define AT91_MATRIX_ITCM_32 (6 << 0)
#define AT91_MATRIX_ITCM_64 (7 << 0)
#define AT91_MATRIX_DTCM_SIZE GENMASK(7, 4)
#define AT91_MATRIX_DTCM_0 (0 << 4)
#define AT91_MATRIX_DTCM_16 (5 << 4)
#define AT91_MATRIX_DTCM_32 (6 << 4)
#define AT91_MATRIX_DTCM_64 (7 << 4)
#define AT91_MATRIX_PRAS(o, x) ((o) + ((x) * 0x8))
#define AT91_MATRIX_PRBS(o, x) ((o) + ((x) * 0x8) + 0x4)
#define AT91_MATRIX_MPR(x) GENMASK(((x) * 0x4) + 1, ((x) * 0x4))
#define AT91_MATRIX_RCB(x) BIT(x)
#define AT91_MATRIX_CSA(cs, val) (val << (cs))
#define AT91_MATRIX_DBPUC BIT(8)
#define AT91_MATRIX_DBPDC BIT(9)
#define AT91_MATRIX_VDDIOMSEL BIT(16)
#define AT91_MATRIX_VDDIOMSEL_1_8V (0 << 16)
#define AT91_MATRIX_VDDIOMSEL_3_3V (1 << 16)
#define AT91_MATRIX_EBI_IOSR BIT(17)
#define AT91_MATRIX_DDR_IOSR BIT(18)
#define AT91_MATRIX_NFD0_SELECT BIT(24)
#define AT91_MATRIX_DDR_MP_EN BIT(25)
#define AT91_MATRIX_EBI_NUM_CS 8
#define AT91_MATRIX_USBPUCR_PUON BIT(30)
#endif /* _LINUX_MFD_SYSCON_ATMEL_MATRIX_H */
/*
* Atmel SMC (Static Memory Controller) register offsets and bit definitions.
*
* Copyright (C) 2014 Atmel
* Copyright (C) 2014 Free Electrons
*
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
*
* 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.
*/
#ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_
#define _LINUX_MFD_SYSCON_ATMEL_SMC_H_
#include <linux/kernel.h>
#include <linux/regmap.h>
#define AT91SAM9_SMC_GENERIC 0x00
#define AT91SAM9_SMC_GENERIC_BLK_SZ 0x10
#define SAMA5_SMC_GENERIC 0x600
#define SAMA5_SMC_GENERIC_BLK_SZ 0x14
#define AT91SAM9_SMC_SETUP(o) ((o) + 0x00)
#define AT91SAM9_SMC_NWESETUP(x) (x)
#define AT91SAM9_SMC_NCS_WRSETUP(x) ((x) << 8)
#define AT91SAM9_SMC_NRDSETUP(x) ((x) << 16)
#define AT91SAM9_SMC_NCS_NRDSETUP(x) ((x) << 24)
#define AT91SAM9_SMC_PULSE(o) ((o) + 0x04)
#define AT91SAM9_SMC_NWEPULSE(x) (x)
#define AT91SAM9_SMC_NCS_WRPULSE(x) ((x) << 8)
#define AT91SAM9_SMC_NRDPULSE(x) ((x) << 16)
#define AT91SAM9_SMC_NCS_NRDPULSE(x) ((x) << 24)
#define AT91SAM9_SMC_CYCLE(o) ((o) + 0x08)
#define AT91SAM9_SMC_NWECYCLE(x) (x)
#define AT91SAM9_SMC_NRDCYCLE(x) ((x) << 16)
#define AT91SAM9_SMC_MODE(o) ((o) + 0x0c)
#define SAMA5_SMC_MODE(o) ((o) + 0x10)
#define AT91_SMC_READMODE BIT(0)
#define AT91_SMC_READMODE_NCS (0 << 0)
#define AT91_SMC_READMODE_NRD (1 << 0)
#define AT91_SMC_WRITEMODE BIT(1)
#define AT91_SMC_WRITEMODE_NCS (0 << 1)
#define AT91_SMC_WRITEMODE_NWE (1 << 1)
#define AT91_SMC_EXNWMODE GENMASK(5, 4)
#define AT91_SMC_EXNWMODE_DISABLE (0 << 4)
#define AT91_SMC_EXNWMODE_FROZEN (2 << 4)
#define AT91_SMC_EXNWMODE_READY (3 << 4)
#define AT91_SMC_BAT BIT(8)
#define AT91_SMC_BAT_SELECT (0 << 8)
#define AT91_SMC_BAT_WRITE (1 << 8)
#define AT91_SMC_DBW GENMASK(13, 12)
#define AT91_SMC_DBW_8 (0 << 12)
#define AT91_SMC_DBW_16 (1 << 12)
#define AT91_SMC_DBW_32 (2 << 12)
#define AT91_SMC_TDF GENMASK(19, 16)
#define AT91_SMC_TDF_(x) ((((x) - 1) << 16) & AT91_SMC_TDF)
#define AT91_SMC_TDF_MAX 16
#define AT91_SMC_TDFMODE_OPTIMIZED BIT(20)
#define AT91_SMC_PMEN BIT(24)
#define AT91_SMC_PS GENMASK(29, 28)
#define AT91_SMC_PS_4 (0 << 28)
#define AT91_SMC_PS_8 (1 << 28)
#define AT91_SMC_PS_16 (2 << 28)
#define AT91_SMC_PS_32 (3 << 28)
/*
* This function converts a setup timing expressed in nanoseconds into an
* encoded value that can be written in the SMC_SETUP register.
*
* The following formula is described in atmel datasheets (section
* "SMC Setup Register"):
*
* setup length = (128* SETUP[5] + SETUP[4:0])
*
* where setup length is the timing expressed in cycles.
*/
static inline u32 at91sam9_smc_setup_ns_to_cycles(unsigned int clk_rate,
u32 timing_ns)
{
u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
u32 coded_cycles = 0;
u32 cycles;
cycles = DIV_ROUND_UP(timing_ns, clk_period);
if (cycles / 32) {
coded_cycles |= 1 << 5;
if (cycles < 128)
cycles = 0;
}
coded_cycles |= cycles % 32;
return coded_cycles;
}
/*
* This function converts a pulse timing expressed in nanoseconds into an
* encoded value that can be written in the SMC_PULSE register.
*
* The following formula is described in atmel datasheets (section
* "SMC Pulse Register"):
*
* pulse length = (256* PULSE[6] + PULSE[5:0])
*
* where pulse length is the timing expressed in cycles.
*/
static inline u32 at91sam9_smc_pulse_ns_to_cycles(unsigned int clk_rate,
u32 timing_ns)
{
u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
u32 coded_cycles = 0;
u32 cycles;
cycles = DIV_ROUND_UP(timing_ns, clk_period);
if (cycles / 64) {
coded_cycles |= 1 << 6;
if (cycles < 256)
cycles = 0;
}
coded_cycles |= cycles % 64;
return coded_cycles;
}
/*
* This function converts a cycle timing expressed in nanoseconds into an
* encoded value that can be written in the SMC_CYCLE register.
*
* The following formula is described in atmel datasheets (section
* "SMC Cycle Register"):
*
* cycle length = (CYCLE[8:7]*256 + CYCLE[6:0])
*
* where cycle length is the timing expressed in cycles.
*/
static inline u32 at91sam9_smc_cycle_ns_to_cycles(unsigned int clk_rate,
u32 timing_ns)
{
u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
u32 coded_cycles = 0;
u32 cycles;
cycles = DIV_ROUND_UP(timing_ns, clk_period);
if (cycles / 128) {
coded_cycles = cycles / 256;
cycles %= 256;
if (cycles >= 128) {
coded_cycles++;
cycles = 0;
}
if (coded_cycles > 0x3) {
coded_cycles = 0x3;
cycles = 0x7f;
}
coded_cycles <<= 7;
}
coded_cycles |= cycles % 128;
return coded_cycles;
}
#endif /* _LINUX_MFD_SYSCON_ATMEL_SMC_H_ */
/*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* 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.
*/
#ifndef __CPUIDLE_EXYNOS_H
#define __CPUIDLE_EXYNOS_H
struct cpuidle_exynos_data {
int (*cpu0_enter_aftr)(void);
int (*cpu1_powerdown)(void);
void (*pre_enter_aftr)(void);
void (*post_enter_aftr)(void);
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment