From efe491be15ead3bbcf7e715337fdee7dfa41f699 Mon Sep 17 00:00:00 2001 From: Alison Wang Date: Tue, 11 Dec 2012 15:32:19 +0800 Subject: ENGR00216076-1: PM: Add Power Management driver for Vybrid System could run into STOP and LPRun modes. When system was working in STOP mode, pressing SW1 button or inserting or removing SD card could wake up it. Signed-off-by: Alison Wang --- arch/arm/mach-mvf/Makefile | 4 +- arch/arm/mach-mvf/board-twr-vf700.c | 15 +- arch/arm/mach-mvf/cpu.c | 3 +- arch/arm/mach-mvf/crm_regs.h | 1 + arch/arm/mach-mvf/irq.c | 10 +- arch/arm/mach-mvf/mvf_suspend.S | 484 ++++++++++++++++++++++++++++ arch/arm/mach-mvf/pm.c | 312 ++++++++++++++++++ arch/arm/mach-mvf/regs-pm.h | 77 +++++ arch/arm/mach-mvf/regs-src.h | 45 +++ arch/arm/mach-mvf/system.c | 139 +++++++- arch/arm/plat-mxc/devices/platform-imx-pm.c | 7 +- arch/arm/plat-mxc/include/mach/mvf.h | 17 +- arch/arm/plat-mxc/include/mach/mxc.h | 14 + 13 files changed, 1107 insertions(+), 21 deletions(-) create mode 100644 arch/arm/mach-mvf/mvf_suspend.S create mode 100644 arch/arm/mach-mvf/pm.c create mode 100644 arch/arm/mach-mvf/regs-pm.h create mode 100644 arch/arm/mach-mvf/regs-src.h diff --git a/arch/arm/mach-mvf/Makefile b/arch/arm/mach-mvf/Makefile index c103e4dc3078..e25fb28b7216 100644 --- a/arch/arm/mach-mvf/Makefile +++ b/arch/arm/mach-mvf/Makefile @@ -3,8 +3,8 @@ # # Object file lists. -obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o mvf_fec.o usb_dr.o usb_dr2.o +obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o mvf_fec.o usb_dr.o usb_dr2.o pm.o obj-y += l2switch.o -obj-$(CONFIG_ARCH_MVFA5) += clock.o +obj-$(CONFIG_ARCH_MVFA5) += clock.o mvf_suspend.o obj-$(CONFIG_MACH_MVFA5_TWR_VF700) += board-twr-vf700.o diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index 03cc6ad51788..5903f7ae0244 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -364,22 +365,20 @@ static void spi_device_init(void) ARRAY_SIZE(mvf_spi_board_info)); } -#if 1 -static void vf700_suspend_enter(void) +static void vf600_suspend_enter(void) { /* suspend preparation */ } -static void vf700_suspend_exit(void) +static void vf600_suspend_exit(void) { /* resmue resore */ } -static const struct pm_platform_data mvf_vf700_pm_data __initconst = { +static const struct pm_platform_data mvf_vf600_pm_data __initconst = { .name = "mvf_pm", - .suspend_enter = vf700_suspend_enter, - .suspend_exit = vf700_suspend_exit, + .suspend_enter = vf600_suspend_enter, + .suspend_exit = vf600_suspend_exit, }; -#endif static struct mvf_dcu_platform_data mvf_dcu_pdata = { .mode_str = "480x272", @@ -458,6 +457,8 @@ static void __init mvf_board_init(void) mvf_add_snvs_rtc(); + mvf_add_pm_imx(0, &mvf_vf600_pm_data); + mvf_add_sdhci_esdhc_imx(1, &mvfa5_sd1_data); mvf_add_imx_i2c(0, &mvf600_i2c_data); diff --git a/arch/arm/mach-mvf/cpu.c b/arch/arm/mach-mvf/cpu.c index 2254ac5974c5..4c6d018cd076 100644 --- a/arch/arm/mach-mvf/cpu.c +++ b/arch/arm/mach-mvf/cpu.c @@ -81,8 +81,7 @@ EXPORT_SYMBOL(mvf_revision); static int __init post_cpu_init(void) { - - /*iram_init(MVF_IRAM_BASE_ADDR, MVF_IRAM_SIZE);*/ + iram_init(MVF_IRAM_BASE_ADDR, MVF_IRAM_SIZE); /* Move wait routine into iRAM */ ccm_base = MVF_IO_ADDRESS(MVF_CCM_BASE_ADDR); diff --git a/arch/arm/mach-mvf/crm_regs.h b/arch/arm/mach-mvf/crm_regs.h index 78604eb96447..57fac5bbe973 100644 --- a/arch/arm/mach-mvf/crm_regs.h +++ b/arch/arm/mach-mvf/crm_regs.h @@ -50,6 +50,7 @@ #define PFD_480_BASE_ADDR (MXC_PLL_BASE + 0xF0) #define PFD_528_BASE_ADDR (MXC_PLL_BASE + 0x100) #define PFD_528SYS_BASE_ADDR (MXC_PLL_BASE + 0x2B0) +#define ANADIG_2P5_ADDR (MXC_PLL_BASE + 0x130) #define ANADIG_MISC0_REG (MXC_PLL_BASE + 0x150) #define ANADIG_MISC1_REG (MXC_PLL_BASE + 0x160) #define PLL_PFD_480_USB1 (MXC_PLL_BASE + 0xF0) diff --git a/arch/arm/mach-mvf/irq.c b/arch/arm/mach-mvf/irq.c index c3e7b9291faa..89c7d382173f 100644 --- a/arch/arm/mach-mvf/irq.c +++ b/arch/arm/mach-mvf/irq.c @@ -36,9 +36,9 @@ static int mvf_gic_irq_set_wake(struct irq_data *d, unsigned int enable) if (enable) { gpc_wake_irq[d->irq / 32 - 1] |= 1 << (d->irq % 32); - printk(KERN_INFO "add wake up source irq %d\n", d->irq); + printk(KERN_DEBUG "add wake up source irq %d\n", d->irq); } else { - printk(KERN_INFO "remove wake up source irq %d\n", d->irq); + printk(KERN_DEBUG "remove wake up source irq %d\n", d->irq); gpc_wake_irq[d->irq / 32 - 1] &= ~(1 << (d->irq % 32)); } return 0; @@ -48,6 +48,7 @@ void mvf_init_irq(void) unsigned int i; void __iomem *int_router_base = MVF_IO_ADDRESS(MVF_MSCM_INT_ROUTER_BASE); + struct irq_desc *desc; /* start offset if private timer irq id, which is 29. * ID table: @@ -60,6 +61,11 @@ void mvf_init_irq(void) gic_init(0, 27, MVF_IO_ADDRESS(MVF_INTD_BASE_ADDR), MVF_IO_ADDRESS(MVF_SCUGIC_BASE_ADDR + 0x100)); + for (i = MXC_INT_START; i <= MXC_INT_END; i++) { + desc = irq_to_desc(i); + desc->irq_data.chip->irq_set_wake = mvf_gic_irq_set_wake; + } + mvf_register_gpios(); for (i = 0; i < 112; i++) diff --git a/arch/arm/mach-mvf/mvf_suspend.S b/arch/arm/mach-mvf/mvf_suspend.S new file mode 100644 index 000000000000..ce9205162538 --- /dev/null +++ b/arch/arm/mach-mvf/mvf_suspend.S @@ -0,0 +1,484 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include "regs-src.h" +#include "crm_regs.h" + +#define PERIPBASE_VIRT_OFFSET 0xb2000000 +#define TTRBIT_MASK 0xffffc000 +#define TABLE_INDEX_MASK 0xfff00000 +#define TABLE_ENTRY 0x00000c02 +#define CACHE_DISABLE_MASK 0xfffffffb +#define IRAM_SUSPEND_SIZE (1 << 15) + +/************************************************************* +mvf_suspend: + +Suspend the processor (eg, wait for interrupt). + +r1: iram_paddr +r2: suspend_iram_base +*************************************************************/ + + .macro mvf_stop_mode_enter + + ldr r3, =MVF_ANATOP_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + /* pll7 disable */ + ldr r4, [r3, #0x20] + bic r4, r4, #0x2000 + str r4, [r3, #0x20] + + /* pll3 disable */ + ldr r4, [r3, #0x10] + bic r4, r4, #0x2000 + str r4, [r3, #0x10] + + /* pll4 disable */ + ldr r4, [r3, #0x70] + bic r4, r4, #0x2000 + str r4, [r3, #0x70] + + /* pll6 disable */ + ldr r4, [r3, #0xa0] + bic r4, r4, #0x2000 + str r4, [r3, #0xa0] + + /* pll5 disable */ + ldr r4, [r3, #0xe0] + bic r4, r4, #0x2000 + str r4, [r3, #0xe0] + + /* pll1 disable */ + ldr r4, [r3, #0x270] + bic r4, r4, #0x2000 + str r4, [r3, #0x270] + + /* stop mode is masked to Anatop */ + ldr r3, =MVF_CCM_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + ldr r4, [r3, #0x2c] + bic r4, r4, #0x100 + str r4, [r3, #0x2c] + + ldr r3, =MVF_GPC_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + /* ensure power domain 0 */ + ldr r4, [r3, #0x0] + bic r4, r4, #0x01 + str r4, [r3, #0x0] + + /* enable deep sleep for memories */ + ldr r4, [r3, #0x0] + orr r4, r4, #0x80 + str r4, [r3, #0x0] + + /* disable well bias */ + ldr r4, [r3, #0x0] + bic r4, r4, #0x10 + str r4, [r3, #0x0] + + /* turn off HPREG in stop mode */ + ldr r4, [r3, #0x0] + orr r4, r4, #0x08 + str r4, [r3, #0x0] + + /* gpc_lpmr set stop mode */ + ldr r4, =0x02 + str r4, [r3, #0x40] + + .endm + + .macro mvf_lpstop_mode_enter + + ldr r3, =MVF_ANATOP_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + /* pll7 disable */ + ldr r4, [r3, #0x20] + bic r4, r4, #0x2000 + str r4, [r3, #0x20] + + /* pll3 disable */ + ldr r4, [r3, #0x10] + bic r4, r4, #0x2000 + str r4, [r3, #0x10] + + /* pll4 disable */ + ldr r4, [r3, #0x70] + bic r4, r4, #0x2000 + str r4, [r3, #0x70] + + /* pll6 disable */ + ldr r4, [r3, #0xa0] + bic r4, r4, #0x2000 + str r4, [r3, #0xa0] + + /* pll5 disable */ + ldr r4, [r3, #0xe0] + bic r4, r4, #0x2000 + str r4, [r3, #0xe0] + + /* pll1 disable */ + ldr r4, [r3, #0x270] + bic r4, r4, #0x2000 + str r4, [r3, #0x270] + + ldr r3, =MVF_CCM_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + ldr r4, [r3, #0x2c] + bic r4, r4, #0x100 + str r4, [r3, #0x2c] + + ldr r3, =MVF_GPC_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + /* enable deep sleep for memories */ + ldr r4, [r3, #0x0] + orr r4, r4, #0x40 + str r4, [r3, #0x0] + + /* enable LPSTOP3 */ + ldr r4, [r3, #0x0] + bic r4, r4, #0x04 + bic r4, r4, #0x02 + str r4, [r3, #0x0] + + /* ensure power domain 1 */ + ldr r4, [r3, #0x0] + orr r4, r4, #0x01 + str r4, [r3, #0x0] + + /* gpc_lpmr set low-power stop mode */ + ldr r4, =0x02 + str r4, [r3, #0x40] + + .endm + +/****************************************************************** +Invalidate l1 dcache, r0-r4, r6, r7 used +******************************************************************/ + .macro invalidate_l1_dcache + + mov r0, #0 + mcr p15, 2, r0, c0, c0, 0 + mrc p15, 1, r0, c0, c0, 0 + + ldr r1, =0x7fff + and r2, r1, r0, lsr #13 + + ldr r1, =0x3ff + + and r3, r1, r0, lsr #3 @ NumWays - 1 + add r2, r2, #1 @ NumSets + + and r0, r0, #0x7 + add r0, r0, #4 @ SetShift + + clz r1, r3 @ WayShift + add r4, r3, #1 @ NumWays +1: + sub r2, r2, #1 @ NumSets-- + mov r3, r4 @ Temp = NumWays +2: + subs r3, r3, #1 @ Temp-- + mov r7, r3, lsl r1 + mov r6, r2, lsl r0 + orr r7, r7, r6 + mcr p15, 0, r7, c7, c6, 2 + bgt 2b + cmp r2, #0 + bgt 1b + dsb + isb + + .endm + +/****************************************************************** +Flush and disable L1 dcache +******************************************************************/ + .macro flush_disable_l1_dcache + + /* + * Flush all data from the L1 data cache before disabling + * SCTLR.C bit. + */ + push {r0-r12, lr} + ldr r0, =v7_flush_dcache_all + mov lr, pc + mov pc, r0 + pop {r0-r12, lr} + + /* + * Clear the SCTLR.C bit to prevent further data cache + * allocation. Clearing SCTLR.C would make all the data accesses + * strongly ordered and would not hit the cache. + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + isb + + /* + * Invalidate L1 data cache. Even though only invalidate is + * necessary exported flush API is used here. Doing clean + * on already clean cache would be almost NOP. + */ + push {r0-r12, lr} + ldr r0, =v7_flush_dcache_all + mov lr, pc + mov pc, r0 + pop {r0-r12, lr} + + /* + * Execute an ISB instruction to ensure that all of the + * CP15 register changes have been committed. + */ + isb + + /* + * Execute a barrier instruction to ensure that all cache, + * TLB and branch predictor maintenance operations issued + * by any CPU in the cluster have completed. + */ + dsb + dmb + + .endm + +ENTRY(mvf_suspend) + stmfd sp!, {r0-r12} @ Save registers +/************************************************************* +suspend mode entry +*************************************************************/ + mov r11, r0 + + cmp r0, #0x1 + bne dormant + + /* Need to flush and disable L1 dcache*/ + flush_disable_l1_dcache + + wfi + + nop + nop + nop + nop + + /* Invalidate L1 I-cache first */ + mov r1, #0x0 + mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache + + /* Need to invalidate L1 dcache, as the power is dropped */ + invalidate_l1_dcache + + /* Enable L1 dcache first */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + +/*********************************************************** +never run to here +************************************************************/ + b out /* exit standby */ + /* Place the literal pool here so that literals are + within 16KB range */ + .ltorg + +/************************************************************ +dormant entry, data save in stack +************************************************************/ +dormant: + +/************************************************************ +saved register and context as below: + sp + spsr + lr + CPACR + TTBR0 + TTBR1 + TTBCR + DACR + PRRR + NMRR + ACTLR + Context ID + User r/w thread ID + Secure or NS VBAR + CPSR + SCTLR +************************************************************/ + /* stack is from the tail of iram_suspend base */ + mov r0, r2 /* get suspend_iram_base */ + add r0, r0, #IRAM_SUSPEND_SIZE + + mov r4, r11 @ Store state entered + stmfd r0!, {r4} + + mov r4, sp @ Store sp + mrs r5, spsr @ Store spsr + mov r6, lr @ Store lr + stmfd r0!, {r4-r6} + + /* c1 and c2 registers */ + mrc p15, 0, r4, c1, c0, 2 @ CPACR + mrc p15, 0, r5, c2, c0, 0 @ TTBR0 + mrc p15, 0, r6, c2, c0, 1 @ TTBR1 + mrc p15, 0, r7, c2, c0, 2 @ TTBCR + stmfd r0!, {r4-r7} + + /* c3 and c10 registers */ + mrc p15, 0, r4, c3, c0, 0 @ DACR + mrc p15, 0, r5, c10, c2, 0 @ PRRR + mrc p15, 0, r6, c10, c2, 1 @ NMRR + mrc p15, 0, r7, c1, c0, 1 @ ACTLR + stmfd r0!,{r4-r7} + + /* c12, c13 and CPSR registers */ + mrc p15, 0, r4, c13, c0, 1 @ Context ID + mrc p15, 0, r5, c13, c0, 2 @ User r/w thread ID + mrc p15, 0, r6, c12, c0, 0 @ Secure or NS VBAR + mrs r7, cpsr @ Store CPSR + stmfd r0!, {r4-r7} + + /* c1 control register */ + mrc p15, 0, r4, c1, c0, 0 @ SCTLR + stmfd r0!, {r4} + + /* Need to flush and disable L1 dcache*/ + flush_disable_l1_dcache + + /* Make sure TLBs are primed */ + ldr r1, =MVF_IOMUXC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + ldr r1, =MVF_SRC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + ldr r1, =MVF_CCM_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + ldr r1, =MVF_GPC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + ldr r1, =MVF_CCM_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT_OFFSET + add r1, r1, #0x20000 + ldr r0, [r1] + + /* Do a DSB to drain the buffers */ + dsb + + mvf_stop_mode_enter + +/**************************************************************** +execute a wfi instruction to let SOC go into stop mode. +****************************************************************/ + wfi + + nop + nop + nop + nop + +/**************************************************************** +if go here, means there is a wakeup irq pending, we should resume +system immediately. +****************************************************************/ + mov r0, r2 /* get suspend_iram_base */ + add r0, r0, #IRAM_SUSPEND_SIZE + + ldmea r0!, {r11} @ standby or mem + + /* mask all the GPC interrupts */ + ldr r3, =MVF_GPC_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + ldr r4, =0xffffffff + str r4, [r3, #0x44] + str r4, [r3, #0x48] + str r4, [r3, #0x4c] + str r4, [r3, #0x50] + + /* pll2 enable */ + ldr r3, =MVF_ANATOP_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT_OFFSET + add r3, r3, #0x20000 + + ldr r4, [r3, #0x30] + orr r4, r4, #0x2000 + str r4, [r3, #0x30] + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + mrc p15, 0, r1, c1, c0, 0 + orr r1, r1, #(1 << 2) @ Enable the C bit + mcr p15, 0, r1, c1, c0, 0 + + b out + +/************************************************ +return back to mvf_suspend_enter for suspend +*************************************************/ +out: + ldmfd sp!, {r0-r12} + mov pc, lr + + .type mvf_do_suspend, #object +ENTRY(mvf_do_suspend) + .word mvf_suspend + .size mvf_suspend, . - mvf_suspend diff --git a/arch/arm/mach-mvf/pm.c b/arch/arm/mach-mvf/pm.c new file mode 100644 index 000000000000..0e62caf372da --- /dev/null +++ b/arch/arm/mach-mvf/pm.c @@ -0,0 +1,312 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crm_regs.h" +#include "regs-anadig.h" +#include "regs-pm.h" +#include "regs-src.h" + +static struct clk *cpu_clk; +static struct clk *ipg_clk; +static struct clk *periph_clk; + +extern void mvf_suspend(suspend_state_t state); + +static struct device *pm_dev; +static void __iomem *scu_base; +static void __iomem *gpc_base; +static void __iomem *src_base; +static void __iomem *anadig_base; + +static void *suspend_iram_base; +static void (*suspend_in_iram)(suspend_state_t state, + unsigned long iram_paddr, unsigned long suspend_iram_base) = NULL; +static unsigned long iram_paddr, cpaddr; + +static u32 ccm_ccr, ccm_clpcr, ccm_ccsr, scu_ctrl; +static u32 gpc_imr[4], gpc_pgcr, gpc_lpmr; +static u32 ccm_anadig_pfd528, ccm_anadig_pfd480_usb0, ccm_anadig_2p5; +static int g_state; + +static void mvf_suspend_store(void) +{ + /* save some settings before suspend */ + ccm_ccr = __raw_readl(MXC_CCM_CCR); + ccm_clpcr = __raw_readl(MXC_CCM_CLPCR); + ccm_ccsr = __raw_readl(MXC_CCM_CCSR); + ccm_anadig_pfd528 = __raw_readl(PFD_528_BASE_ADDR); + ccm_anadig_pfd480_usb0 = __raw_readl(PFD_480_BASE_ADDR); + ccm_anadig_2p5 = __raw_readl(ANADIG_2P5_ADDR); + + scu_ctrl = __raw_readl(scu_base + SCU_CTRL_OFFSET); + gpc_imr[0] = __raw_readl(gpc_base + GPC_IMR1_OFFSET); + gpc_imr[1] = __raw_readl(gpc_base + GPC_IMR2_OFFSET); + gpc_imr[2] = __raw_readl(gpc_base + GPC_IMR3_OFFSET); + gpc_imr[3] = __raw_readl(gpc_base + GPC_IMR4_OFFSET); + gpc_pgcr = __raw_readl(gpc_base + GPC_PGCR_OFFSET); + gpc_lpmr = __raw_readl(gpc_base + GPC_LPMR_OFFSET); +} + +static void mvf_suspend_restore(void) +{ + /* restore settings after suspend */ + __raw_writel(ccm_anadig_2p5, ANADIG_2P5_ADDR); + + udelay(50); + + __raw_writel(ccm_ccr, MXC_CCM_CCR); + __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); + __raw_writel(ccm_anadig_pfd528, PFD_528_BASE_ADDR); + __raw_writel(ccm_anadig_pfd480_usb0, PFD_480_BASE_ADDR); + + __raw_writel(scu_ctrl, scu_base + SCU_CTRL_OFFSET); + __raw_writel(gpc_imr[0], gpc_base + GPC_IMR1_OFFSET); + __raw_writel(gpc_imr[1], gpc_base + GPC_IMR2_OFFSET); + __raw_writel(gpc_imr[2], gpc_base + GPC_IMR3_OFFSET); + __raw_writel(gpc_imr[3], gpc_base + GPC_IMR4_OFFSET); + __raw_writel(gpc_pgcr, gpc_base + GPC_PGCR_OFFSET); + __raw_writel(gpc_lpmr, gpc_base + GPC_LPMR_OFFSET); + + /* enable PLLs */ + __raw_writel(__raw_readl(PLL3_480_USB1_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL3_480_USB1_BASE_ADDR); + __raw_writel(__raw_readl(PLL3_480_USB2_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL3_480_USB2_BASE_ADDR); + __raw_writel(__raw_readl(PLL4_AUDIO_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL4_AUDIO_BASE_ADDR); + __raw_writel(__raw_readl(PLL6_VIDEO_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL6_VIDEO_BASE_ADDR); + __raw_writel(__raw_readl(PLL5_ENET_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL5_ENET_BASE_ADDR); + __raw_writel(__raw_readl(PLL1_SYS_BASE_ADDR) | ANADIG_PLL_ENABLE, + PLL1_SYS_BASE_ADDR); + + /* restore system clock */ + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); +} + +static void uart_reinit(unsigned long int clkspeed, unsigned long int baud) +{ + void __iomem *membase; + u8 tmp; + u16 sbr, brfa; + + membase = MVF_IO_ADDRESS(MVF_UART1_BASE_ADDR); + + __raw_writeb(0, membase + MXC_UARTMODEM); + + /* make sure the transmitter and receiver are + * disabled while changing settings */ + tmp = __raw_readb(membase + MXC_UARTCR2); + tmp &= ~MXC_UARTCR2_RE; + tmp &= ~MXC_UARTCR2_TE; + __raw_writeb(tmp, membase + MXC_UARTCR2); + + __raw_writeb(0, membase + MXC_UARTCR1); + + sbr = (u16) ((clkspeed * 1000) / (baud * 16)); + brfa = ((clkspeed * 1000) / baud) - (sbr * 16); + + tmp = __raw_readb(membase + MXC_UARTBDH); + tmp &= ~MXC_UARTBDH_SBR_MASK; + tmp |= ((sbr & 0x1f00) >> 8); + __raw_writeb(tmp, membase + MXC_UARTBDH); + tmp = sbr & 0x00ff; + __raw_writeb(tmp, membase + MXC_UARTBDL); + + tmp = __raw_readb(membase + MXC_UARTCR4); + tmp &= ~MXC_UARTCR4_BRFA_MASK; + tmp |= (brfa & MXC_UARTCR4_BRFA_MASK); + __raw_writeb(tmp , membase + MXC_UARTCR4); + + tmp = __raw_readb(membase + MXC_UARTCR2); + tmp |= MXC_UARTCR2_RE; + tmp |= MXC_UARTCR2_TE; + __raw_writeb(tmp, membase + MXC_UARTCR2); +} + +static int mvf_suspend_enter(suspend_state_t state) +{ + struct gic_dist_state gds; + struct gic_cpu_state gcs; + bool arm_pg = false; + + mvf_suspend_store(); + + switch (state) { + case PM_SUSPEND_MEM: + mvf_cpu_lp_set(LOW_POWER_STOP); + g_state = PM_SUSPEND_MEM; + arm_pg = true; + break; + case PM_SUSPEND_STANDBY: + mvf_cpu_lp_set(LOW_POWER_RUN); + g_state = PM_SUSPEND_STANDBY; + arm_pg = true; + break; + default: + return -EINVAL; + } + + if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) { + local_flush_tlb_all(); + flush_cache_all(); + + if (arm_pg) { + /* preserve GIC state */ + save_gic_dist_state(0, &gds); + save_gic_cpu_state(0, &gcs); + } + + suspend_in_iram(state, (unsigned long)iram_paddr, + (unsigned long)suspend_iram_base); + + /* reconfigure UART1 when using 24MHz system clock */ + uart_reinit(4000, 115200); + + printk(KERN_DEBUG "Read GPC_PGSR register: %x\n", + __raw_readl(gpc_base + GPC_PGSR_OFFSET)); + + /* mask all interrupts */ + __raw_writel(0xffffffff, gpc_base + GPC_IMR1_OFFSET); + __raw_writel(0xffffffff, gpc_base + GPC_IMR2_OFFSET); + __raw_writel(0xffffffff, gpc_base + GPC_IMR3_OFFSET); + __raw_writel(0xffffffff, gpc_base + GPC_IMR4_OFFSET); + + udelay(80); + + if (arm_pg) { + /* restore GIC registers */ + restore_gic_dist_state(0, &gds); + restore_gic_cpu_state(0, &gcs); + } + + mvf_suspend_restore(); + + /* reconfigure UART1 when using 396MHz system clock */ + uart_reinit(66000, 115200); + + __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, + ANADIG_MISC0_REG); + } else + cpu_do_idle(); + + return 0; +} + +static void mvf_suspend_finish(void) +{ + if (g_state == PM_SUSPEND_MEM) + free_irq(MVF_INT_WKPU0, NULL); +} + +static int mvf_pm_valid(suspend_state_t state) +{ + return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX); +} + +const struct platform_suspend_ops mvf_suspend_ops = { + .valid = mvf_pm_valid, + .enter = mvf_suspend_enter, + .finish = mvf_suspend_finish, +}; + +static int __devinit mvf_pm_probe(struct platform_device *pdev) +{ + pm_dev = &pdev->dev; + + return 0; +} + +static struct platform_driver mvf_pm_driver = { + .driver = { + .name = "imx_pm", + }, + .probe = mvf_pm_probe, +}; + +static int __init pm_init(void) +{ + scu_base = MVF_IO_ADDRESS(MVF_SCUGIC_BASE_ADDR); + gpc_base = MVF_GPC_BASE; + anadig_base = MXC_PLL_BASE; + src_base = MVF_IO_ADDRESS(MVF_SRC_BASE_ADDR); + + pr_info("Static Power Management for Freescale Vybrid\n"); + + if (platform_driver_register(&mvf_pm_driver) != 0) { + printk(KERN_ERR "mvf_pm_driver register failed\n"); + return -ENODEV; + } + + suspend_set_ops(&mvf_suspend_ops); + + /* move suspend routine into sram */ + cpaddr = (unsigned long)iram_alloc(SZ_32K, &iram_paddr); + + /* need to remap the area here since we want the memory region + * to be executable */ + suspend_iram_base = __arm_ioremap(iram_paddr, SZ_32K, + MT_MEMORY_NONCACHED); + printk(KERN_DEBUG "cpaddr = %x suspend_iram_base=%x iram_paddr %x\n", + (unsigned int)cpaddr, (unsigned int)suspend_iram_base, + (unsigned int)iram_paddr); + + /* need to run the suspend code from sram */ + memcpy((void *)cpaddr, mvf_suspend, SZ_32K); + + suspend_in_iram = (void *)suspend_iram_base; + + cpu_clk = clk_get(NULL, "cpu_clk"); + if (IS_ERR(cpu_clk)) { + printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__); + return PTR_ERR(cpu_clk); + } + ipg_clk = clk_get(NULL, "ipg_clk"); + if (IS_ERR(ipg_clk)) { + printk(KERN_DEBUG "%s: failed to get ipg_clk\n", __func__); + return PTR_ERR(ipg_clk); + } + periph_clk = clk_get(NULL, "periph_clk"); + if (IS_ERR(periph_clk)) { + printk(KERN_DEBUG "%s: failed to get periph_clk\n", __func__); + return PTR_ERR(periph_clk); + } + + printk(KERN_INFO "PM driver module loaded\n"); + return 0; +} + +static void __exit pm_cleanup(void) +{ + platform_driver_unregister(&mvf_pm_driver); +} + +module_init(pm_init); +module_exit(pm_cleanup); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("PM driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-mvf/regs-pm.h b/arch/arm/mach-mvf/regs-pm.h new file mode 100644 index 000000000000..c54bdd346709 --- /dev/null +++ b/arch/arm/mach-mvf/regs-pm.h @@ -0,0 +1,77 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This 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 __ARCH_ARM_MACH_MVF_REGS_PM_H__ +#define __ARCH_ARM_MACH_MVF_REGS_PM_H__ + +/* GPC registers */ +#define GPC_PGCR_OFFSET (0x00) +#define GPC_PGCR_DS_STOP (0x000000080) +#define GPC_PGCR_DS_LPSTOP (0x000000040) +#define GPC_PGCR_WB_STOP (0x000000010) +#define GPC_PGCR_HP_OFF (0x000000008) +#define GPC_PGCR_PG_48K (0x000000004) +#define GPC_PGCR_PG_16K (0x000000002) +#define GPC_PGCR_PG_PD1 (0x000000001) + +#define GPC_PGSR_OFFSET (0x0c) + +#define GPC_LPMR_OFFSET (0x40) +#define GPC_LPMR_CLPCR_RUN (0x00000000) +#define GPC_LPMR_CLPCR_WAIT (0x00000001) +#define GPC_LPMR_CLPCR_STOP (0x00000002) + +#define GPC_IMR1_OFFSET (0x44) +#define GPC_IMR2_OFFSET (0x48) +#define GPC_IMR3_OFFSET (0x4c) +#define GPC_IMR4_OFFSET (0x50) +#define GPC_ISR1_OFFSET (0x54) +#define GPC_ISR2_OFFSET (0x58) +#define GPC_ISR3_OFFSET (0x5c) +#define GPC_ISR4_OFFSET (0x60) + +/* VREG registers */ +#define VREG_CTRL_OFFSET (0x00) +#define VREG_CTRL_PORPU (0x00010000) +#define VREG_CTRL_HVDMASK (0x00000001) +#define VREG_STAT_OFFSET (0x04) + +/* WKPU registers */ +#define WKPU_NSR_OFFSET (0x00) + +#define WKPU_NCR_OFFSET (0x08) +#define WKPU_NCR_NLOCK0 (0x80000000) +#define WKPU_NCR_NWRE0 (0x10000000) +#define WKPU_NCR_NREE0 (0x04000000) +#define WKPU_NCR_NFEE0 (0x02000000) +#define WKPU_NCR_NFE0 (0x01000000) + +#define WKPU_WISR_OFFSET (0x14) + +#define WKPU_IRER_OFFSET (0x18) + +#define WKPU_WRER_OFFSET (0x1c) + +#define WKPU_WIREER_OFFSET (0x28) + +#define WKPU_WIFEER_OFFSET (0x2c) + +#define WKPU_WIFER_OFFSET (0x30) + +#define WKPU_WIPUER_OFFSET (0x34) + +#define RISING_EDGE_ENABLED (0x9e) +#define FALLING_EDGE_ENABLED (0xfe) + +/* SCU registers */ +#define SCU_CTRL_OFFSET (0x00) + + +#endif /* __ARCH_ARM_MACH_MVF_REGS_PM_H__ */ diff --git a/arch/arm/mach-mvf/regs-src.h b/arch/arm/mach-mvf/regs-src.h new file mode 100644 index 000000000000..b93e99d92da1 --- /dev/null +++ b/arch/arm/mach-mvf/regs-src.h @@ -0,0 +1,45 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc, + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _SRC_REGISTER_HEADER_ +#define _SRC_REGISTER_HEADER_ + +#define SRC_SCR_OFFSET 0x000 +#define SRC_SBMR_OFFSET 0x004 +#define SRC_SRSR_OFFSET 0x008 +#define SRC_SECR_OFFSET 0x00c +#define SRC_SISR_OFFSET 0x014 +#define SRC_SIMR_OFFSET 0x018 +#define SRC_SBMR2_OFFSET 0x01c +#define SRC_GPR0_OFFSET 0x020 +#define SRC_GPR1_OFFSET 0x024 +#define SRC_GPR2_OFFSET 0x028 +#define SRC_GPR3_OFFSET 0x02c +#define SRC_GPR4_OFFSET 0x030 +#define SRC_HAB0_OFFSET 0x034 +#define SRC_HAB1_OFFSET 0x038 +#define SRC_HAB2_OFFSET 0x03c +#define SRC_HAB3_OFFSET 0x040 +#define SRC_HAB4_OFFSET 0x044 +#define SRC_HAB5_OFFSET 0x048 +#define SRC_MISC0_OFFSET 0x04c +#define SRC_MISC1_OFFSET 0x050 +#define SRC_MISC2_OFFSET 0x054 +#define SRC_MISC3_OFFSET 0x058 + +#endif diff --git a/arch/arm/mach-mvf/system.c b/arch/arm/mach-mvf/system.c index 764c608cbf42..989c75a02ed1 100644 --- a/arch/arm/mach-mvf/system.c +++ b/arch/arm/mach-mvf/system.c @@ -21,7 +21,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -29,6 +30,142 @@ #include #include "crm_regs.h" #include "regs-anadig.h" +#include "regs-pm.h" + +#define SW1_WAKEUP_PIN 38 +#define SW1_PORT1_PCR6_ADDR 0x4004a018 + +static void __iomem *gpc_base = MVF_GPC_BASE; + +void gpc_set_wakeup(void) +{ + __raw_writel(0xffffffff, gpc_base + GPC_IMR1_OFFSET); + __raw_writel(0xffffffff, gpc_base + GPC_IMR2_OFFSET); + /* unmask WKPU0 interrupt */ + __raw_writel(0xefffffff, gpc_base + GPC_IMR3_OFFSET); + /* unmask GPIO4 interrupt */ + __raw_writel(0xffff7fff, gpc_base + GPC_IMR4_OFFSET); + + return; +} + +void enable_wkpu(u32 source, u32 rise_fall) +{ + __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_IRER_OFFSET); + __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WRER_OFFSET); + + if (rise_fall == RISING_EDGE_ENABLED) + __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WIREER_OFFSET); + else + __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WIFEER_OFFSET); +} + +static irqreturn_t wkpu_irq(int irq, void *dev_id) +{ + u32 wisr; + + wisr = __raw_readl(MVF_WKPU_BASE + WKPU_WISR_OFFSET); + if (wisr) + __raw_writel(wisr, MVF_WKPU_BASE + WKPU_WISR_OFFSET); + + return IRQ_NONE; +} + +/* set cpu multiple modes before WFI instruction */ +void mvf_cpu_lp_set(enum mvf_cpu_pwr_mode mode) +{ + u32 ccm_ccsr, ccm_clpcr, ccm_ccr; + u32 tmp; + int ret; + + if ((mode == LOW_POWER_STOP) || (mode == STOP_MODE)) { + /* config SW1 for waking up system */ + gpio_request_one(SW1_WAKEUP_PIN, GPIOF_IN, "SW1 wakeup"); + gpio_set_value(SW1_WAKEUP_PIN, 0); + /* PORT1_PCR6 IRQC interrupt/dma request disabled */ + tmp = __raw_readl(MVF_IO_ADDRESS(SW1_PORT1_PCR6_ADDR)); + tmp &= ~0x000f0000; + __raw_writel(tmp, MVF_IO_ADDRESS(SW1_PORT1_PCR6_ADDR)); + + ret = request_irq(MVF_INT_WKPU0, wkpu_irq, + IRQF_DISABLED, "wkpu irq", NULL); + if (ret) + printk(KERN_ERR "Request wkpu IRQ failed\n"); + + /* enable WKPU interrupt */ + enable_wkpu(11, FALLING_EDGE_ENABLED); + } + + ccm_ccr = __raw_readl(MXC_CCM_CCR); + ccm_ccsr = __raw_readl(MXC_CCM_CCSR); + + switch (mode) { + case WAIT_MODE: + break; + case LOW_POWER_RUN: + ccm_ccr |= MXC_CCM_CCR_FIRC_EN; + __raw_writel(ccm_ccr, MXC_CCM_CCR); + ccm_ccsr &= ~MXC_CCM_CCSR_FAST_CLK_SEL_MASK; + ccm_ccsr &= ~MXC_CCM_CCSR_SLOW_CLK_SEL_MASK; + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); + + /* switch system clock to FIRC 24MHz */ + ccm_ccsr &= ~MXC_CCM_CCSR_SYS_CLK_SEL_MASK; + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); + + __raw_writel(__raw_readl(PLL3_480_USB1_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL3_480_USB1_BASE_ADDR); + __raw_writel(__raw_readl(PLL3_480_USB2_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL3_480_USB2_BASE_ADDR); + __raw_writel(__raw_readl(PLL4_AUDIO_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL4_AUDIO_BASE_ADDR); + __raw_writel(__raw_readl(PLL6_VIDEO_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL6_VIDEO_BASE_ADDR); + __raw_writel(__raw_readl(PLL5_ENET_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL5_ENET_BASE_ADDR); + __raw_writel(__raw_readl(PLL1_SYS_BASE_ADDR) & + ~ANADIG_PLL_ENABLE, PLL1_SYS_BASE_ADDR); + break; + case STOP_MODE: + case LOW_POWER_STOP: + gpc_set_wakeup(); + + /* unmask UART1 in low-power mode */ + __raw_writel(0xfffeffff, MXC_CCM_CCGR0); + /* unmask WKUP and GPC in low-power mode */ + __raw_writel(0xfeefffff, MXC_CCM_CCGR4); + /* unmask DDRC in low-power mode */ + __raw_writel(0xefffffff, MXC_CCM_CCGR6); + + ccm_ccr |= MXC_CCM_CCR_FIRC_EN; + __raw_writel(ccm_ccr, MXC_CCM_CCR); + ccm_ccsr &= ~MXC_CCM_CCSR_FAST_CLK_SEL_MASK; + ccm_ccsr &= ~MXC_CCM_CCSR_SLOW_CLK_SEL_MASK; + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); + + /* switch system clock to FIRC 24MHz */ + ccm_ccsr &= ~MXC_CCM_CCSR_SYS_CLK_SEL_MASK; + __raw_writel(ccm_ccsr, MXC_CCM_CCSR); + + /* on-chip oscillator will not be + * powered down in stop mode */ + ccm_clpcr = __raw_readl(MXC_CCM_CLPCR); + ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS; + ccm_clpcr &= ~MXC_CCM_CLPCR_M_CORE1_WFI; + ccm_clpcr &= ~MXC_CCM_CLPCR_M_CORE0_WFI; + ccm_clpcr &= ~MXC_CCM_CLPCR_ARM_CLK_LPM; + __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); + + /* mask stop mode to Anatop */ + __raw_writel(ccm_clpcr & ~MXC_CCM_CLPCR_ANATOP_STOP_MODE, + MXC_CCM_CLPCR); + + break; + default: + printk(KERN_WARNING "UNKNOW cpu power mode: %d\n", mode); + return; + } +} void arch_idle(void) { diff --git a/arch/arm/plat-mxc/devices/platform-imx-pm.c b/arch/arm/plat-mxc/devices/platform-imx-pm.c index f901e18368c2..2b55d0344830 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-pm.c +++ b/arch/arm/plat-mxc/devices/platform-imx-pm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -30,6 +30,11 @@ const struct imx_pm_imx_data imx6q_pm_imx_data[] __initconst = imx_pm_imx_data_entry_single(MX6Q); #endif +#ifdef CONFIG_SOC_MVFA5 +const struct imx_pm_imx_data mvf_pm_imx_data[] __initconst = + imx_pm_imx_data_entry_single(MVF); +#endif + struct platform_device *__init imx_add_pm_imx( const struct imx_pm_imx_data *data, const struct pm_platform_data *pdata) diff --git a/arch/arm/plat-mxc/include/mach/mvf.h b/arch/arm/plat-mxc/include/mach/mvf.h index 9ef4de35d4c0..1e3f74f98857 100644 --- a/arch/arm/plat-mxc/include/mach/mvf.h +++ b/arch/arm/plat-mxc/include/mach/mvf.h @@ -53,8 +53,7 @@ * IRAM */ #define MVF_IRAM_BASE_ADDR 0x3F000000 /* internal ram */ -#define MVF_IRAM_PARTITIONS 2 -#define MVF_IRAM_SIZE (MVF_IRAM_PARTITIONS * SZ_256K) /* 512KB */ +#define MVF_IRAM_SIZE (SZ_256K) /* 256KB */ #ifdef CONFIG_MXC_VPU_IRAM @@ -169,12 +168,12 @@ #define MVF_EWM_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00065000) #define MVF_I2C0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00066000) #define MVF_I2C1_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00067000) -#define MVF_WKUP_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006A000) +#define MVF_WKPU_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006A000) #define MVF_CCM_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006B000) -#define MVF_GPC_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006C000) -#define MVF_VREG_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006D000) -#define MVF_SRC_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006E000) +#define MVF_GPC_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006C000) +#define MVF_VREG_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006D000) +#define MVF_SRC_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006E000) #define MVF_CMU_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006F000) #define L2_BASE_ADDR MVF_L2C_BASE_ADDR @@ -283,6 +282,12 @@ #define MVF_PGC_GPU_PGCR (MVF_PGC_GPU_BASE + 0x0) #define MVF_PGC_GPU_PGSR (MVF_PGC_GPU_BASE + 0xC) +/* Voltage Regulators */ +#define MVF_VREG_BASE (MVF_IO_ADDRESS(MVF_VREG_BASE_ADDR)) + +/* WKPU */ +#define MVF_WKPU_BASE (MVF_IO_ADDRESS(MVF_WKPU_BASE_ADDR)) + /* * defines for SPBA modules */ diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index afcf1255150b..b291d9015025 100755 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -257,6 +257,15 @@ struct cpu_op { u32 cpu_podf; }; +#ifdef CONFIG_SOC_MVFA5 +enum mvf_cpu_pwr_mode { + RUN_MODE, + LOW_POWER_RUN, + WAIT_MODE, + STOP_MODE, + LOW_POWER_STOP, +}; +#else enum mxc_cpu_pwr_mode { WAIT_CLOCKED, /* wfi only */ WAIT_UNCLOCKED, /* WAIT */ @@ -265,10 +274,15 @@ enum mxc_cpu_pwr_mode { STOP_POWER_OFF, /* STOP + SRPG */ ARM_POWER_OFF, /* STOP + SRPG + ARM power off */ }; +#endif int tzic_enable_wake(int is_idle); +#ifdef CONFIG_SOC_MVFA5 +extern void mvf_cpu_lp_set(enum mvf_cpu_pwr_mode mode); +#else extern void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode); +#endif extern int tzic_enable_wake(int is_idle); #endif -- cgit v1.2.3 From 97bb163197f3dc3405af90b5159e0f6b8a302586 Mon Sep 17 00:00:00 2001 From: Alison Wang Date: Tue, 11 Dec 2012 15:36:08 +0800 Subject: ENGR00216076-2: DCU: Update DCU driver for PM and blending issue Fix layers blending and reinitialization issue for DCU driver. Update power management part for DCU driver. Signed-off-by: Alison Wang --- arch/arm/plat-mxc/devices/platform-mvf-dcu.c | 4 +- arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h | 52 +------------------ drivers/video/mvf_dcu.c | 47 +++++++++++++----- include/linux/Kbuild | 1 + include/linux/mvf-fb.h | 74 ++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 66 deletions(-) create mode 100644 include/linux/mvf-fb.h diff --git a/arch/arm/plat-mxc/devices/platform-mvf-dcu.c b/arch/arm/plat-mxc/devices/platform-mvf-dcu.c index 13258aba9bb0..0fe5099eca34 100644 --- a/arch/arm/plat-mxc/devices/platform-mvf-dcu.c +++ b/arch/arm/plat-mxc/devices/platform-mvf-dcu.c @@ -38,8 +38,8 @@ int __init mvf_dcu_init(int id) } const struct mvf_dcu_data mvfa5_dcu_data[] __initconst = { - mvf_dcu_data_entry_single(MVF, 0, SZ_4K, mvf_dcu_init), - mvf_dcu_data_entry_single(MVF, 1, SZ_4K, mvf_dcu_init), + mvf_dcu_data_entry_single(MVF, 0, SZ_8K, mvf_dcu_init), + mvf_dcu_data_entry_single(MVF, 1, SZ_8K, mvf_dcu_init), }; struct platform_device *__init mvf_add_dcu( diff --git a/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h b/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h index b9d8dd3b93bb..9a5ba8e396a9 100644 --- a/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h +++ b/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h @@ -14,6 +14,7 @@ #define __MVF_DCU_FB_H__ #include +#include struct mvf_dcu_platform_data { char *mode_str; @@ -21,11 +22,6 @@ struct mvf_dcu_platform_data { int (*init) (int); }; -struct mfb_alpha { - int enable; - int alpha; -}; - struct dfb_chroma_key { int enable; __u8 red_max; @@ -36,60 +32,14 @@ struct dfb_chroma_key { __u8 blue_min; }; -struct layer_display_offset { - int x_layer_d; - int y_layer_d; -}; - #define DCU_LCD_ENABLE_PIN 30 #define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key) #define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8) -#define MFB_SET_ALPHA 0x80014d00 -#define MFB_GET_ALPHA 0x40014d00 -#define MFB_SET_LAYER 0x80084d04 -#define MFB_GET_LAYER 0x40084d04 - -#define FBIOGET_GWINFO 0x46E0 -#define FBIOPUT_GWINFO 0x46E1 - #ifdef __KERNEL__ #include -/* - * These are the fields of control descriptor for every layer - */ -struct dcu_layer_desc { - u32 layer_num; - u32 width; - u32 height; - u32 posx; - u32 posy; - u32 addr; - u32 blend; - u32 chroma_key_en; - u32 lut_offset; - u32 rle_en; - u32 bpp; - u32 trans; - u32 safety_en; - u32 data_sel_clut; - u32 tile_en; - u32 en; - u32 ck_r_min; - u32 ck_r_max; - u32 ck_g_min; - u32 ck_g_max; - u32 ck_b_min; - u32 ck_b_max; - u32 tile_width; - u32 tile_height; - u32 trans_fgcolor; - u32 trans_bgcolor; -} __packed; - - /* DCU registers */ #define DCU_CTRLDESCCURSOR1 0x0000 #define DCU_CTRLDESCCURSOR1_HEIGHT(x) (x << 16) diff --git a/drivers/video/mvf_dcu.c b/drivers/video/mvf_dcu.c index 719e465b77e6..d9fc6fa664c7 100644 --- a/drivers/video/mvf_dcu.c +++ b/drivers/video/mvf_dcu.c @@ -138,6 +138,8 @@ static struct mfb_info mfb_template[] = { }, }; +static int total_open_layers = 0; + static int mvf_dcu_enable_panel(struct fb_info *info) { @@ -422,11 +424,6 @@ static void update_lcdc(struct fb_info *info) writel(DCU_THRESHOLD_LS_BF_VS(0x3) | DCU_THRESHOLD_OUT_BUF_HIGH(0x78) | DCU_THRESHOLD_OUT_BUF_LOW(0), dcu->base + DCU_THRESHOLD); - writel(0, dcu->base + DCU_INT_STATUS); - writel(0, dcu->base + DCU_PARR_ERR_STA_1); - writel(0, dcu->base + DCU_PARR_ERR_STA_2); - writel(0, dcu->base + DCU_PARR_ERR_STA_3); - /* Enable the DCU */ enable_lcdc(info); } @@ -718,10 +715,34 @@ static int mvf_dcu_ioctl(struct fb_info *info, unsigned int cmd, static int mvf_dcu_open(struct fb_info *info, int user) { struct mfb_info *mfbi = info->par; + struct mvf_dcu_fb_data *dcu = mfbi->parent; + int i; int ret = 0; mfbi->index = info->node; spin_lock(&dcu_lock); + + /* if first time any layer open (e.g., at boot time) reset all */ + if (total_open_layers == 0) { + + writel(0, dcu->base + DCU_INT_STATUS); + writel(0, dcu->base + DCU_PARR_ERR_STA_1); + writel(0, dcu->base + DCU_PARR_ERR_STA_2); + writel(0, dcu->base + DCU_PARR_ERR_STA_3); + + for (i = 0; i < 64; i++) { + writel(0, dcu->base + DCU_CTRLDESCLN_0(i)); + writel(0, dcu->base + DCU_CTRLDESCLN_1(i)); + writel(0, dcu->base + DCU_CTRLDESCLN_2(i)); + writel(0, dcu->base + DCU_CTRLDESCLN_3(i)); + writel(0, dcu->base + DCU_CTRLDESCLN_4(i)); + writel(0, dcu->base + DCU_CTRLDESCLN_5(i)); + writel(0, dcu->base + DCU_CTRLDESCLN_6(i)); + writel(0, dcu->base + DCU_CTRLDESCLN_7(i)); + writel(0, dcu->base + DCU_CTRLDESCLN_8(i)); + } + } + mfbi->count++; if (mfbi->count == 1) { pr_debug("open layer index %d\n", mfbi->index); @@ -729,6 +750,8 @@ static int mvf_dcu_open(struct fb_info *info, int user) ret = mvf_dcu_set_par(info); if (ret < 0) mfbi->count--; + else + total_open_layers++; } spin_unlock(&dcu_lock); @@ -747,6 +770,8 @@ static int mvf_dcu_release(struct fb_info *info, int user) ret = mvf_dcu_disable_panel(info); if (ret < 0) mfbi->count++; + else + total_open_layers--; } spin_unlock(&dcu_lock); @@ -895,21 +920,17 @@ static void free_irq_local(int irq, struct mvf_dcu_fb_data *dcu) static int mvf_dcu_suspend(struct platform_device *pdev, pm_message_t state) { - struct mvf_dcu_fb_data *dcu; - - dcu = dev_get_drvdata(&pdev->dev); - disable_lcdc(dcu->mvf_dcu_info[0]); + struct mvf_dcu_fb_data *dcu = dev_get_drvdata(&pdev->dev); + clk_disable(dcu->clk); return 0; } static int mvf_dcu_resume(struct platform_device *pdev) { - struct mvf_dcu_fb_data *dcu; - - dcu = dev_get_drvdata(&pdev->dev); - enable_lcdc(dcu->mvf_dcu_info[0]); + struct mvf_dcu_fb_data *dcu = dev_get_drvdata(&pdev->dev); + clk_enable(dcu->clk); return 0; } #else diff --git a/include/linux/Kbuild b/include/linux/Kbuild index c65d1b9eb546..947d36f054e5 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -35,6 +35,7 @@ header-y += mxc_si4702.h header-y += mxc_sim_interface.h header-y += mxc_v4l2.h header-y += mxcfb.h +header-y += mvf-fb.h header-y += pmic_adc.h header-y += pmic_battery.h header-y += pmic_external.h diff --git a/include/linux/mvf-fb.h b/include/linux/mvf-fb.h new file mode 100644 index 000000000000..836767697d76 --- /dev/null +++ b/include/linux/mvf-fb.h @@ -0,0 +1,74 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * Freescale DCU Frame Buffer device driver ioctls + * + * 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 __MVF_FB_H__ +#define __MVF_FB_H__ + +#include + +/* ioctls */ + +#define MFB_SET_ALPHA 0x80014d00 +#define MFB_GET_ALPHA 0x40014d00 +#define MFB_SET_LAYER 0x80084d04 +#define MFB_GET_LAYER 0x40084d04 + +#define FBIOGET_GWINFO 0x46E0 +#define FBIOPUT_GWINFO 0x46E1 + +#ifndef u32 +#define u32 unsigned int +#endif + +struct mfb_alpha { + int enable; + int alpha; +}; + +struct layer_display_offset { + int x_layer_d; + int y_layer_d; +}; + +/* + * These are the fields of control descriptor for every layer + */ +struct dcu_layer_desc { + u32 layer_num; + u32 width; + u32 height; + u32 posx; + u32 posy; + u32 addr; + u32 blend; + u32 chroma_key_en; + u32 lut_offset; + u32 rle_en; + u32 bpp; + u32 trans; + u32 safety_en; + u32 data_sel_clut; + u32 tile_en; + u32 en; + u32 ck_r_min; + u32 ck_r_max; + u32 ck_g_min; + u32 ck_g_max; + u32 ck_b_min; + u32 ck_b_max; + u32 tile_width; + u32 tile_height; + u32 trans_fgcolor; + u32 trans_bgcolor; +} __packed; + +#endif -- cgit v1.2.3 From 3e67deec905904e2786129bfbffea1e20b18a8fe Mon Sep 17 00:00:00 2001 From: Alison Wang Date: Tue, 11 Dec 2012 15:38:00 +0800 Subject: ENGR00216076-3: DSPI: Update DSPI driver for PM Update power management part for DSPI driver. Signed-off-by: Alison Wang --- drivers/spi/spi_mvf_dspi.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/drivers/spi/spi_mvf_dspi.c b/drivers/spi/spi_mvf_dspi.c index 21dc672975be..a394659a3b02 100644 --- a/drivers/spi/spi_mvf_dspi.c +++ b/drivers/spi/spi_mvf_dspi.c @@ -1033,34 +1033,12 @@ static void spi_mvf_shutdown(struct platform_device *pdev) #ifdef CONFIG_PM -static int suspend_devices(struct device *dev, void *pm_message) -{ - pm_message_t *state = pm_message; - - if (dev->power.power_state.event != state->event) { - dev_warn(dev, "pm state does not match request\n"); - return -1; - } - - return 0; -} - static int spi_mvf_suspend(struct platform_device *pdev, pm_message_t state) { struct spi_mvf_data *spi_mvf = platform_get_drvdata(pdev); - int ret = 0; - - /* Check all childern for current power state */ - if (device_for_each_child(&pdev->dev, - &state, suspend_devices) != 0) { - dev_warn(&pdev->dev, "suspend aborted\n"); - return -1; - } - ret = stop_queue(spi_mvf); - if (ret != 0) - return ret; + clk_disable(spi_mvf->clk); return 0; } @@ -1068,14 +1046,8 @@ static int spi_mvf_suspend(struct platform_device *pdev, static int spi_mvf_resume(struct platform_device *pdev) { struct spi_mvf_data *spi_mvf = platform_get_drvdata(pdev); - int ret = 0; - /* Start the queue running */ - ret = start_queue(spi_mvf); - if (ret != 0) { - dev_err(&pdev->dev, "problem starting queue (%d)\n", ret); - return ret; - } + clk_enable(spi_mvf->clk); return 0; } -- cgit v1.2.3 From 6dedc932b4d43948145f8d3a0e56f7b3e7b65354 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Wed, 5 Dec 2012 13:19:53 +0800 Subject: ENGR00216087-1: ASRC support for Vybrid The ASRC driver supports stereo audio streams resample, the ASRCK1 serial clock using audio external clock source can not support 44.1K sample rate due to divider and prescaler restriction. Signed-off-by: Jingchang Lu --- drivers/mxc/asrc/Kconfig | 2 +- drivers/mxc/asrc/Makefile | 4 + drivers/mxc/asrc/mvf_asrc.c | 1941 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mxc_asrc.h | 22 + 4 files changed, 1968 insertions(+), 1 deletion(-) create mode 100644 drivers/mxc/asrc/mvf_asrc.c diff --git a/drivers/mxc/asrc/Kconfig b/drivers/mxc/asrc/Kconfig index 017042126f8d..743b6cdbbc63 100644 --- a/drivers/mxc/asrc/Kconfig +++ b/drivers/mxc/asrc/Kconfig @@ -6,7 +6,7 @@ menu "MXC Asynchronous Sample Rate Converter support" config MXC_ASRC tristate "ASRC support" - depends on ARCH_MX35 || ARCH_MX53 || ARCH_MX6 + depends on ARCH_MX35 || ARCH_MX53 || ARCH_MX6 || ARCH_MVF ---help--- Say Y to get the ASRC service. diff --git a/drivers/mxc/asrc/Makefile b/drivers/mxc/asrc/Makefile index 7e9aba3abb56..afc7be8e0a7d 100644 --- a/drivers/mxc/asrc/Makefile +++ b/drivers/mxc/asrc/Makefile @@ -1,4 +1,8 @@ # # Makefile for the kernel Asynchronous Sample Rate Converter driver # +ifdef CONFIG_ARCH_MVF +obj-$(CONFIG_MXC_ASRC) += mvf_asrc.o +else obj-$(CONFIG_MXC_ASRC) += mxc_asrc.o +endif diff --git a/drivers/mxc/asrc/mvf_asrc.c b/drivers/mxc/asrc/mvf_asrc.c new file mode 100644 index 000000000000..fc3f5dfa4f9a --- /dev/null +++ b/drivers/mxc/asrc/mvf_asrc.c @@ -0,0 +1,1941 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Vybrid ASRC driver based on mxc_asrc.c + * + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int asrc_major; +static struct class *asrc_class; +#define ASRC_PROC_PATH "driver/asrc" + +#define ASRC_RATIO_DECIMAL_DEPTH 26 + +DEFINE_SPINLOCK(data_lock); +DEFINE_SPINLOCK(input_int_lock); +DEFINE_SPINLOCK(output_int_lock); + +#if 1 +#define DBG(x...) +#else +#define DBG(x...) printk(x) +#endif + +/* ASRC control register bits */ +/* pair C/B/A automatic selection for processing options */ +#define ASRCTR_ATSC (0x01 << 22) +#define ASRCTR_ATSB (0x01 << 21) +#define ASRCTR_ATSA (0x01 << 20) +#define ASRCTR_USRC (0x01 << 18) /* use ratio for pair C */ +#define ASRCTR_IDRC (0x01 << 17) /* use ideal ratio for pair C */ +#define ASRCTR_USRB (0x01 << 16) /* use ratio for pair B */ +#define ASRCTR_IDRB (0x01 << 15) /* use ideal ratio for pair B */ +#define ASRCTR_USRA (0x01 << 14) /* use ratio for pair A */ +#define ASRCTR_IDRA (0x01 << 13) /* use ideal ratio for pair A */ +#define ASRCTR_SRST (0x01 << 4) /* software reset */ +#define ASRCTR_ASREC (0x01 << 3) /* ASRC enable C */ +#define ASRCTR_ASREB (0x01 << 2) /* ASRC enable B */ +#define ASRCTR_ASREA (0x01 << 1) /* ASRC enable A */ +#define ASRCTR_ASRCEN (0x01 << 0) /* ASRC enable */ + +/* clock divider register bits */ +#define AICPA 0 /* Input Clock Divider A Offset */ +#define AICDA 3 /* Input Clock Prescaler A Offset */ +#define AICPB 6 /* Input Clock Divider B Offset */ +#define AICDB 9 /* Input Clock Prescaler B Offset */ +#define AOCPA 12 /* Output Clock Divider A Offset */ +#define AOCDA 15 /* Output Clock Prescaler A Offset */ +#define AOCPB 18 /* Output Clock Divider B Offset */ +#define AOCDB 21 /* Output Clock Prescaler B Offset */ +#define AICPC 0 /* Input Clock Divider C Offset */ +#define AICDC 3 /* Input Clock Prescaler C Offset */ +#define AOCDC 6 /* Output Clock Prescaler C Offset */ +#define AOCPC 9 /* Output Clock Divider C Offset */ + +char *asrc_pair_id[] = { + [0] = "ASRC RX PAIR A", + [1] = "ASRC TX PAIR A", + [2] = "ASRC RX PAIR B", + [3] = "ASRC TX PAIR B", + [4] = "ASRC RX PAIR C", + [5] = "ASRC TX PAIR C", +}; + +enum asrc_status { + ASRC_ASRSTR_AIDEA = 0x01, + ASRC_ASRSTR_AIDEB = 0x02, + ASRC_ASRSTR_AIDEC = 0x04, + ASRC_ASRSTR_AODFA = 0x08, + ASRC_ASRSTR_AODFB = 0x10, + ASRC_ASRSTR_AODFC = 0x20, + ASRC_ASRSTR_AOLE = 0x40, + ASRC_ASRSTR_FPWT = 0x80, + ASRC_ASRSTR_AIDUA = 0x100, + ASRC_ASRSTR_AIDUB = 0x200, + ASRC_ASRSTR_AIDUC = 0x400, + ASRC_ASRSTR_AODOA = 0x800, + ASRC_ASRSTR_AODOB = 0x1000, + ASRC_ASRSTR_AODOC = 0x2000, + ASRC_ASRSTR_AIOLA = 0x4000, + ASRC_ASRSTR_AIOLB = 0x8000, + ASRC_ASRSTR_AIOLC = 0x10000, + ASRC_ASRSTR_AOOLA = 0x20000, + ASRC_ASRSTR_AOOLB = 0x40000, + ASRC_ASRSTR_AOOLC = 0x80000, + ASRC_ASRSTR_ATQOL = 0x100000, + ASRC_ASRSTR_DSLCNT = 0x200000, +}; + +/* Sample rates are aligned with that defined in pcm.h file */ +static const unsigned char asrc_process_table[][8][2] = { + /* 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 128kHz 192kHz */ +/*8kHz*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, +/*11025Hz*/ + {{0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, +/*16kHz*/ + {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, +/*22050Hz*/ + {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, +/*32kHz*/ + {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, +/*44.1kHz*/ + {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, +/*48kHz*/ + {{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, +/*64kHz*/ + {{0, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, +/*88.2kHz*/ + {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, +/*96kHz*/ + {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, +/*128kHz*/ + {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, +/*192kHz*/ + {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, +}; + +static struct asrc_data *g_asrc_data; +static struct proc_dir_entry *proc_asrc; +static unsigned long asrc_vrt_base_addr; +static unsigned long asrc_phy_base_addr; +static struct imx_asrc_platform_data *mxc_asrc_data; +struct dma_async_tx_descriptor *desc_in; +struct dma_async_tx_descriptor *desc_out; +static int asrc_dmarx[3]; +static int asrc_dmatx[3]; +#ifdef CONFIG_ARCH_MVF +static struct dma_async_tx_descriptor dummy_desc; +#endif + +/* The following tables map the relationship between asrc_inclk/asrc_outclk in + * mxc_asrc.h and the registers of ASRCSR + */ +static unsigned char input_clk_map_v1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, +}; + +static unsigned char output_clk_map_v1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, +}; + +static unsigned char input_clk_map_v2[] = { + 0, 1, 2, 3, 4, 5, 0xf, 0xf, 0xf, 8, 9, 0xa, 0xb, 0xc, 0xf, 0xd, +}; + +static unsigned char output_clk_map_v2[] = { + 8, 9, 0xa, 0, 0xc, 0x5, 0xf, 0xf, 0, 1, 2, 0xf, 0xf, 4, 0xf, 0xd, +}; + +static unsigned char input_clk_map_v3[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0, 2, 3, 0xf, 5, 6, 1, 4, 7, 0xd, 0x0f, 9, 0xa, 8, 0xf, 0xc, +}; + +static unsigned char output_clk_map_v3[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 7, 0xd, 0xf, 0xf, 0xa, 6, 8, 1, 0, 2, 3, 4, 5, 9, 0xf, 0xc, +}; + +static unsigned char *input_clk_map, *output_clk_map; + +#ifdef CONFIG_ARCH_MVF +static struct dma_async_tx_descriptor *imx_asrc_dma_config(u32 ch, u32 dma_addr, + void *buf_addr, u32 buf_len, int in); +#endif +/* Ideal Ratio calc */ +static int asrc_set_clock_ratio(enum asrc_pair_index index, + int input_sample_rate, int output_sample_rate) +{ + int i; + int integ = 0; + unsigned long reg_val = 0; + + DBG("%s:in/out sample rate = %d/%d\n", __func__, + input_sample_rate, output_sample_rate); + + if (output_sample_rate == 0) + return -1; + while (input_sample_rate >= output_sample_rate) { + input_sample_rate -= output_sample_rate; + integ++; + } + reg_val |= (integ << 26); + + for (i = 1; i <= ASRC_RATIO_DECIMAL_DEPTH; i++) { + if ((input_sample_rate * 2) >= output_sample_rate) { + reg_val |= (1 << (ASRC_RATIO_DECIMAL_DEPTH - i)); + input_sample_rate = + input_sample_rate * 2 - output_sample_rate; + } else + input_sample_rate = input_sample_rate << 1; + + if (input_sample_rate == 0) + break; + } + + __raw_writel(reg_val, + (asrc_vrt_base_addr + ASRC_ASRIDRLA_REG + (index << 3))); + __raw_writel((reg_val >> 24), + (asrc_vrt_base_addr + ASRC_ASRIDRHA_REG + (index << 3))); + return 0; +} + +static int asrc_set_process_configuration(enum asrc_pair_index index, + int input_sample_rate, + int output_sample_rate) +{ + int i = 0, j = 0; + unsigned long reg; + + DBG("%s:in/out sample rate = %d/%d\n", __func__, + input_sample_rate, output_sample_rate); + + switch (input_sample_rate) { + case 8000: + i = 0; + break; + case 11025: + i = 1; + break; + case 16000: + i = 2; + break; + case 22050: + i = 3; + break; + case 32000: + i = 4; + break; + case 44100: + i = 5; + break; + case 48000: + i = 6; + break; + case 64000: + i = 7; + break; + case 88200: + i = 8; + break; + case 96000: + i = 9; + break; + case 128000: + i = 10; + break; + case 192000: + i = 11; + break; + default: + return -1; + } + + switch (output_sample_rate) { + case 32000: + j = 0; + break; + case 44100: + j = 1; + break; + case 48000: + j = 2; + break; + case 64000: + j = 3; + break; + case 88200: + j = 4; + break; + case 96000: + j = 5; + break; + case 128000: + j = 6; + break; + case 192000: + j = 7; + break; + default: + return -1; + } + + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCFG_REG); + reg &= ~(0x0f << (6 + (index << 2))); + reg |= + ((asrc_process_table[i][j][0] << (6 + (index << 2))) | + (asrc_process_table[i][j][1] << (8 + (index << 2)))); + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCFG_REG); + + return 0; +} + +static int asrc_get_asrck_clock_divider(int samplerate) +{ + unsigned int prescaler, divider; + unsigned int i; + unsigned int ratio, ra; + unsigned long bitclk = clk_get_rate(mxc_asrc_data->asrc_audio_clk); + + DBG("%s:bitclk/sample rate = %lu/%d\n", __func__, + bitclk, samplerate); + + ra = bitclk/samplerate; + ratio = ra; + /*calculate the prescaler*/ + i = 0; + while (ratio > 8) { + i++; + ratio = ratio >> 1; + } + prescaler = i; + /*calculate the divider*/ + if (i >= 1) + divider = ((ra + (1 << (i - 1)) - 1) >> i) - 1; + else + divider = ra - 1; + + /*the totally divider is (2^prescaler)*divider*/ + return (divider << 3) + prescaler; +} + +int asrc_req_pair(int chn_num, enum asrc_pair_index *index) +{ + int err = 0; + unsigned long lock_flags; + spin_lock_irqsave(&data_lock, lock_flags); + + if (chn_num > 2) { + if (g_asrc_data->asrc_pair[ASRC_PAIR_C].active + || (chn_num > g_asrc_data->asrc_pair[ASRC_PAIR_C].chn_max)) + err = -EBUSY; + else { + *index = ASRC_PAIR_C; + g_asrc_data->asrc_pair[ASRC_PAIR_C].chn_num = chn_num; + g_asrc_data->asrc_pair[ASRC_PAIR_C].active = 1; + } + } else { + if (g_asrc_data->asrc_pair[ASRC_PAIR_A].active || + (g_asrc_data->asrc_pair[ASRC_PAIR_A].chn_max == 0)) { + if (g_asrc_data->asrc_pair[ASRC_PAIR_B]. + active + || (g_asrc_data->asrc_pair[ASRC_PAIR_B]. + chn_max == 0)) + err = -EBUSY; + else { + *index = ASRC_PAIR_B; + g_asrc_data->asrc_pair[ASRC_PAIR_B].chn_num = 2; + g_asrc_data->asrc_pair[ASRC_PAIR_B].active = 1; + } + } else { + *index = ASRC_PAIR_A; + g_asrc_data->asrc_pair[ASRC_PAIR_A].chn_num = 2; + g_asrc_data->asrc_pair[ASRC_PAIR_A].active = 1; + } + } + + spin_unlock_irqrestore(&data_lock, lock_flags); + return err; +} +EXPORT_SYMBOL(asrc_req_pair); + +void asrc_release_pair(enum asrc_pair_index index) +{ + unsigned long reg; + unsigned long lock_flags; + + spin_lock_irqsave(&data_lock, lock_flags); + g_asrc_data->asrc_pair[index].active = 0; + g_asrc_data->asrc_pair[index].overload_error = 0; + /********Disable PAIR*************/ + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG); + reg &= ~(1 << (index + 1)); + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG); + spin_unlock_irqrestore(&data_lock, lock_flags); +} +EXPORT_SYMBOL(asrc_release_pair); + +int asrc_config_pair(struct asrc_config *config) +{ + int err = 0; + int reg, tmp, channel_num; + unsigned long lock_flags; + + DBG("%s\n", __func__); + + /* Set the channel number */ + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCNCR_REG); + spin_lock_irqsave(&data_lock, lock_flags); + g_asrc_data->asrc_pair[config->pair].chn_num = config->channel_num; + spin_unlock_irqrestore(&data_lock, lock_flags); + reg &= + ~((0xFFFFFFFF >> (32 - mxc_asrc_data->channel_bits)) << + (mxc_asrc_data->channel_bits * config->pair)); + if (mxc_asrc_data->channel_bits > 3) + channel_num = config->channel_num; + else + channel_num = (config->channel_num + 1) / 2; + tmp = channel_num << (mxc_asrc_data->channel_bits * config->pair); + reg |= tmp; + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCNCR_REG); +#if 0 + /* Set processing options */ + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG); + /* disable automatic selection for processing options */ + reg &= ~(1 << (20 + config->pair)); + /* enable idea ratio for pair */ + reg |= (0x3 << (13 + (config->pair << 1))); + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG); +#endif + /* Set the clock source */ + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCSR_REG); + tmp = ~(0x0f << (config->pair << 2)); + reg &= tmp; + tmp = ~(0x0f << (12 + (config->pair << 2))); + reg &= tmp; + reg |= + ((input_clk_map[config->inclk] << (config->pair << 2)) | + (output_clk_map[config->outclk] << (12 + (config->pair << 2)))); + + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCSR_REG); + + /* config Misc Control Register 1 for Pair X + * all FIFO data align LSB without sign extension + */ + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRMCR1A_REG + + config->pair * 4); + reg &= ~((0x0F << 8) | 0x06); + if (config->word_width == 16) { + /* 16-bits output */ + reg |= 0x01; + /* 16-bits input */ + reg |= (0x01 << 9); + } else { + /* 24-bits output */ + reg &= ~0x01; + /* 24-bits input */ + } + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRMCR1A_REG + + config->pair * 4); + + /* Default Clock Divider Setting */ + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCDR1_REG); + if (config->pair == ASRC_PAIR_A) { + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCDR1_REG); + reg &= 0xfc0fc0; + /* Input Part */ + if ((config->inclk & 0x0f) == INCLK_SPDIF_RX) + reg |= 7 << AICPA; + else if ((config->inclk & 0x0f) == INCLK_SPDIF_TX) + reg |= 6 << AICPA; + else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) { + tmp = + asrc_get_asrck_clock_divider(config-> + input_sample_rate); + reg |= tmp << AICPA; + } else if ((config->inclk & 0x0F) == INCLK_NONE) { + /* do nothing, will use ideal ratio for convert */ + } else { + if (config->word_width == 16 || config->word_width == 8) + reg |= 5 << AICPA; + else if (config->word_width == 32 + || config->word_width == 24) + reg |= 6 << AICPA; + else + err = -EFAULT; + } + /* Output Part */ + if ((config->outclk & 0x0f) == OUTCLK_SPDIF_RX) + reg |= 7 << AOCPA; + else if ((config->outclk & 0x0f) == OUTCLK_SPDIF_TX) + reg |= 6 << AOCPA; + else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) { + tmp = + asrc_get_asrck_clock_divider(config-> + output_sample_rate); + reg |= tmp << AOCPA; + } else { + if (config->word_width == 16 || config->word_width == 8) + reg |= 5 << AOCPA; + else if (config->word_width == 32 + || config->word_width == 24) + reg |= 6 << AOCPA; + else + err = -EFAULT; + } + + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCDR1_REG); + + } else if (config->pair == ASRC_PAIR_B) { + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCDR1_REG); + reg &= 0x03f03f; + /* Input Part */ + if ((config->inclk & 0x0f) == INCLK_SPDIF_RX) + reg |= 7 << AICPB; + else if ((config->inclk & 0x0f) == INCLK_SPDIF_TX) + reg |= 6 << AICPB; + else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) { + tmp = + asrc_get_asrck_clock_divider(config-> + input_sample_rate); + reg |= tmp << AICPB; + } else if ((config->inclk & 0x0F) == INCLK_NONE) { + /* pass through */ + } else { + if (config->word_width == 16 || config->word_width == 8) + reg |= 5 << AICPB; + else if (config->word_width == 32 + || config->word_width == 24) + reg |= 6 << AICPB; + else + err = -EFAULT; + } + /* Output Part */ + if ((config->outclk & 0x0f) == OUTCLK_SPDIF_RX) + reg |= 7 << AOCPB; + else if ((config->outclk & 0x0f) == OUTCLK_SPDIF_TX) + reg |= 6 << AOCPB; + else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) { + tmp = + asrc_get_asrck_clock_divider(config-> + output_sample_rate); + reg |= tmp << AOCPB; + } else { + if (config->word_width == 16 || config->word_width == 8) + reg |= 5 << AOCPB; + else if (config->word_width == 32 + || config->word_width == 24) + reg |= 6 << AOCPB; + else + err = -EFAULT; + } + + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCDR1_REG); + + } else { + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCDR2_REG); + reg &= 0; + /* Input Part */ + if ((config->inclk & 0x0f) == INCLK_SPDIF_RX) + reg |= 7 << AICPC; + else if ((config->inclk & 0x0f) == INCLK_SPDIF_TX) + reg |= 6 << AICPC; + else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) { + tmp = + asrc_get_asrck_clock_divider(config-> + input_sample_rate); + reg |= tmp << AICPC; + } else if ((config->inclk & 0x0F) == INCLK_NONE) { + /* pass through */ + } else { + if (config->word_width == 16 || config->word_width == 8) + reg |= 5 << AICPC; + else if (config->word_width == 32 + || config->word_width == 24) + reg |= 6 << AICPC; + else + err = -EFAULT; + } + /* Output Part */ + if ((config->outclk & 0x0f) == OUTCLK_SPDIF_RX) + reg |= 7 << AOCPC; + else if ((config->outclk & 0x0f) == OUTCLK_SPDIF_TX) + reg |= 6 << AOCPC; + else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) { + tmp = + asrc_get_asrck_clock_divider(config-> + output_sample_rate); + reg |= tmp << AOCPC; + } else { + if (config->word_width == 16 || config->word_width == 8) + reg |= 5 << AOCPC; + else if (config->word_width == 32 + || config->word_width == 24) + reg |= 6 << AOCPC; + else + err = -EFAULT; + } + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCDR2_REG); + + } + + /* check whether ideal ratio is a must */ + if ((config->inclk & 0x0f) == INCLK_NONE) { + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG); + /* clear ATSC */ + reg &= ~(1 << (20 + config->pair)); + reg |= (0x03 << (13 + (config->pair << 1))); + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG); + err = asrc_set_clock_ratio(config->pair, + config->input_sample_rate, + config->output_sample_rate); + if (err < 0) + return err; + + err = asrc_set_process_configuration(config->pair, + config->input_sample_rate, + config-> + output_sample_rate); + if (err < 0) + return err; + + } else if ((config->inclk & 0x0f) == INCLK_ASRCK1_CLK) { + if (config->input_sample_rate < 24000) { + pr_info + ("ASRC core clock cann't support sample rate %d\n", + config->input_sample_rate); + err = -EFAULT; + } + if (config->input_sample_rate == 44100 + || config->input_sample_rate == 88200) { + pr_info + ("ASRC core clock cann't support sample rate %d\n", + config->input_sample_rate); + err = -EFAULT; + } + } else if ((config->outclk & 0x0f) == OUTCLK_ASRCK1_CLK) { + if (config->output_sample_rate < 24000) { + pr_info + ("ASRC core clock cann't support sample rate %d\n", + config->input_sample_rate); + err = -EFAULT; + } + if (config->output_sample_rate == 44100 + || config->output_sample_rate == 88200) { + pr_info + ("ASRC core clock cann't support sample rate %d\n", + config->input_sample_rate); + err = -EFAULT; + } + } + + return err; +} +EXPORT_SYMBOL(asrc_config_pair); + +void asrc_start_conv(enum asrc_pair_index index) +{ + int reg; + unsigned long lock_flags; + + spin_lock_irqsave(&data_lock, lock_flags); + + __raw_writel(0x40, asrc_vrt_base_addr + ASRC_ASRIER_REG); + + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG); + + reg |= ASRCTR_ASRCEN; /* enable the ASRC */ + reg |= ASRCTR_ASREA << index; /* enable pair A or B or C convert */ + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG); + + spin_unlock_irqrestore(&data_lock, lock_flags); + + return; +} +EXPORT_SYMBOL(asrc_start_conv); + +void asrc_stop_conv(enum asrc_pair_index index) +{ + unsigned long reg; + unsigned long lock_flags; + + spin_lock_irqsave(&data_lock, lock_flags); + + __raw_writel(0, asrc_vrt_base_addr + ASRC_ASRIER_REG); + + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG); + reg &= ~(0x1 << (1 + index)); + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG); + + spin_unlock_irqrestore(&data_lock, lock_flags); + return; +} +EXPORT_SYMBOL(asrc_stop_conv); + +/*! + * @brief asrc interrupt handler + */ +static irqreturn_t asrc_isr(int irq, void *dev_id) +{ + unsigned long status; + + status = __raw_readl(asrc_vrt_base_addr + ASRC_ASRSTR_REG); + + if (g_asrc_data->asrc_pair[ASRC_PAIR_A].active == 1) { + if (status & ASRC_ASRSTR_ATQOL) + g_asrc_data->asrc_pair[ASRC_PAIR_A].overload_error |= + ASRC_TASK_Q_OVERLOAD; + if (status & ASRC_ASRSTR_AOOLA) + g_asrc_data->asrc_pair[ASRC_PAIR_A].overload_error |= + ASRC_OUTPUT_TASK_OVERLOAD; + if (status & ASRC_ASRSTR_AIOLA) + g_asrc_data->asrc_pair[ASRC_PAIR_A].overload_error |= + ASRC_INPUT_TASK_OVERLOAD; + if (status & ASRC_ASRSTR_AODOA) + g_asrc_data->asrc_pair[ASRC_PAIR_A].overload_error |= + ASRC_OUTPUT_BUFFER_OVERFLOW; + if (status & ASRC_ASRSTR_AIDUA) + g_asrc_data->asrc_pair[ASRC_PAIR_A].overload_error |= + ASRC_INPUT_BUFFER_UNDERRUN; + } else if (g_asrc_data->asrc_pair[ASRC_PAIR_B].active == 1) { + if (status & ASRC_ASRSTR_ATQOL) + g_asrc_data->asrc_pair[ASRC_PAIR_B].overload_error |= + ASRC_TASK_Q_OVERLOAD; + if (status & ASRC_ASRSTR_AOOLB) + g_asrc_data->asrc_pair[ASRC_PAIR_B].overload_error |= + ASRC_OUTPUT_TASK_OVERLOAD; + if (status & ASRC_ASRSTR_AIOLB) + g_asrc_data->asrc_pair[ASRC_PAIR_B].overload_error |= + ASRC_INPUT_TASK_OVERLOAD; + if (status & ASRC_ASRSTR_AODOB) + g_asrc_data->asrc_pair[ASRC_PAIR_B].overload_error |= + ASRC_OUTPUT_BUFFER_OVERFLOW; + if (status & ASRC_ASRSTR_AIDUB) + g_asrc_data->asrc_pair[ASRC_PAIR_B].overload_error |= + ASRC_INPUT_BUFFER_UNDERRUN; + } else if (g_asrc_data->asrc_pair[ASRC_PAIR_C].active == 1) { + if (status & ASRC_ASRSTR_ATQOL) + g_asrc_data->asrc_pair[ASRC_PAIR_C].overload_error |= + ASRC_TASK_Q_OVERLOAD; + if (status & ASRC_ASRSTR_AOOLC) + g_asrc_data->asrc_pair[ASRC_PAIR_C].overload_error |= + ASRC_OUTPUT_TASK_OVERLOAD; + if (status & ASRC_ASRSTR_AIOLC) + g_asrc_data->asrc_pair[ASRC_PAIR_C].overload_error |= + ASRC_INPUT_TASK_OVERLOAD; + if (status & ASRC_ASRSTR_AODOC) + g_asrc_data->asrc_pair[ASRC_PAIR_C].overload_error |= + ASRC_OUTPUT_BUFFER_OVERFLOW; + if (status & ASRC_ASRSTR_AIDUC) + g_asrc_data->asrc_pair[ASRC_PAIR_C].overload_error |= + ASRC_INPUT_BUFFER_UNDERRUN; + } + + /* try to clean the overload error */ + __raw_writel(status, asrc_vrt_base_addr + ASRC_ASRSTR_REG); + + return IRQ_HANDLED; +} + +void asrc_get_status(struct asrc_status_flags *flags) +{ + unsigned long lock_flags; + enum asrc_pair_index index; + + spin_lock_irqsave(&data_lock, lock_flags); + index = flags->index; + flags->overload_error = g_asrc_data->asrc_pair[index].overload_error; + + spin_unlock_irqrestore(&data_lock, lock_flags); + return; +} +EXPORT_SYMBOL(asrc_get_status); + +static int mxc_init_asrc(void) +{ + DBG("%s\n", __func__); + + __raw_writel(ASRCTR_ASRCEN, asrc_vrt_base_addr + ASRC_ASRCTR_REG); + /* do a soft reset for ASRC on Faraday */ + __raw_writel(ASRCTR_SRST | ASRCTR_ASRCEN, + asrc_vrt_base_addr + ASRC_ASRCTR_REG); + /* wait for reset finished */ + while (__raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG) & ASRCTR_SRST) + ; + + /* Disable all interrupt */ + __raw_writel(0x00, asrc_vrt_base_addr + ASRC_ASRIER_REG); + + /* Default 6: 2: 2 channel assignment for pair C, B, A */ + __raw_writel((0x06 << mxc_asrc_data->channel_bits * + 2) | (0x02 << mxc_asrc_data->channel_bits) | 0x02, + asrc_vrt_base_addr + ASRC_ASRCNCR_REG); + + /* Parameter Registers recommended settings */ + __raw_writel(0x7fffff, asrc_vrt_base_addr + ASRC_ASRPM1_REG); + __raw_writel(0x255555, asrc_vrt_base_addr + ASRC_ASRPM2_REG); + __raw_writel(0xff7280, asrc_vrt_base_addr + ASRC_ASRPM3_REG); + __raw_writel(0xff7280, asrc_vrt_base_addr + ASRC_ASRPM4_REG); + __raw_writel(0xff7280, asrc_vrt_base_addr + ASRC_ASRPM5_REG); + + __raw_writel(0x001f00, asrc_vrt_base_addr + ASRC_ASRTFR1); + + /* 132M ipg bus clock */ + __raw_writel(0x6C8, asrc_vrt_base_addr + ASRC_ASR76K_REG); + __raw_writel(0x935, asrc_vrt_base_addr + ASRC_ASR56K_REG); + + return 0; +} + +static int asrc_get_output_buffer_size(int input_buffer_size, + int input_sample_rate, + int output_sample_rate) +{ + int i = 0; + int outbuffer_size = 0; + int outsample = output_sample_rate; + + while (outsample >= input_sample_rate) { + ++i; + outsample -= input_sample_rate; + } + outbuffer_size = i * input_buffer_size; + i = 1; + while (((input_buffer_size >> i) > 2) && (outsample != 0)) { + if (((outsample << 1) - input_sample_rate) >= 0) { + outsample = (outsample << 1) - input_sample_rate; + outbuffer_size += (input_buffer_size >> i); + } else { + outsample = outsample << 1; + } + i++; + } + outbuffer_size = (outbuffer_size >> 5) << 5; + + return outbuffer_size; +} + +static irqreturn_t asrc_input_dma_callback(int ch, void *data) +{ + struct asrc_pair_params *params; + struct dma_block *block; + u32 dma_addr; + void *buf_addr; + + params = (struct asrc_pair_params *)data; + + params->input_queue_empty--; + if (!list_empty(¶ms->input_queue)) { + block = + list_entry(params->input_queue.next, + struct dma_block, queue); + dma_addr = + (asrc_phy_base_addr + ASRC_ASRDIA_REG + + (params->index << 3)); + buf_addr = block->dma_vaddr; + desc_in = imx_asrc_dma_config( + params->input_dma_channel, + dma_addr, buf_addr, + block->length, 1); + if (!desc_in) + printk(KERN_DEBUG "%s:%d failed to config dma\n", + __func__, __LINE__); + list_del(params->input_queue.next); + list_add_tail(&block->queue, ¶ms->input_done_queue); + params->input_queue_empty++; + + mcf_edma_enable_transfer(params->input_dma_channel); + + } + params->input_counter++; + wake_up_interruptible(¶ms->input_wait_queue); + + return IRQ_HANDLED; +} + +static irqreturn_t asrc_output_dma_callback(int ch, void *data) +{ + struct asrc_pair_params *params; + struct dma_block *block; + u32 dma_addr; + void *buf_addr; + + params = (struct asrc_pair_params *)data; + + params->output_queue_empty--; + + if (!list_empty(¶ms->output_queue)) { + block = + list_entry(params->output_queue.next, + struct dma_block, queue); + + dma_addr = + (asrc_phy_base_addr + ASRC_ASRDOA_REG + + (params->index << 3)); + buf_addr = block->dma_vaddr; + desc_out = imx_asrc_dma_config( + params->output_dma_channel, + dma_addr, buf_addr, + block->length, 0); + if (!desc_out) + printk(KERN_DEBUG "%s:%d failed to config dma\n", + __func__, __LINE__); + + list_del(params->output_queue.next); + list_add_tail(&block->queue, ¶ms->output_done_queue); + params->output_queue_empty++; + + mcf_edma_enable_transfer(params->output_dma_channel); + + } + params->output_counter++; + + wake_up_interruptible(¶ms->output_wait_queue); + return IRQ_HANDLED; +} + +static void mxc_free_dma_buf(struct asrc_pair_params *params) +{ + int i; + + if (params->input_dma[0].dma_vaddr != NULL) { + kfree(params->input_dma[0].dma_vaddr); + for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { + params->input_dma[i].dma_vaddr = NULL; + params->input_dma[i].dma_paddr = 0; + } + } + if (params->output_dma[0].dma_vaddr != NULL) { + kfree(params->output_dma[0].dma_vaddr); + for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { + params->output_dma[i].dma_vaddr = NULL; + params->output_dma[i].dma_paddr = 0; + } + } + + return; +} + +static int mxc_allocate_dma_buf(struct asrc_pair_params *params) +{ + int i; + + params->input_dma[0].dma_vaddr = NULL; + params->input_dma[0].dma_vaddr = + kzalloc(PAGE_ALIGN(params->input_buffer_size) * + ASRC_DMA_BUFFER_NUM, + GFP_DMA/*GFP_KERNEL*/); + + if (!params->input_dma[0].dma_vaddr) { + mxc_free_dma_buf(params); + pr_info("can't allocate buff\n"); + return -ENOBUFS; + } + + for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { + params->input_dma[i].dma_vaddr = + (unsigned char *) + ((unsigned long)params->input_dma[0].dma_vaddr + + i * PAGE_ALIGN(params->input_buffer_size)); + params->input_dma[i].dma_paddr = + virt_to_dma(NULL, params->input_dma[i].dma_vaddr); + if (params->input_dma[i].dma_vaddr == NULL) { + mxc_free_dma_buf(params); + pr_info("can't allocate input buff\n"); + return -ENOBUFS; + } + } + + params->output_dma[0].dma_vaddr = NULL; + params->output_dma[0].dma_vaddr = + kzalloc(PAGE_ALIGN(params->output_buffer_size) * + ASRC_DMA_BUFFER_NUM, + GFP_DMA/*GFP_KERNEL*/); + if (!params->output_dma[0].dma_vaddr) { + mxc_free_dma_buf(params); + pr_info("can't allocate buff\n"); + return -ENOBUFS; + } + + for (i = 0; i < ASRC_DMA_BUFFER_NUM; i++) { + params->output_dma[i].dma_vaddr = + (unsigned char *) + ((unsigned long)params->output_dma[0].dma_vaddr + + i * PAGE_ALIGN(params->output_buffer_size)); + params->output_dma[i].dma_paddr = + virt_to_dma(NULL, params->output_dma[i].dma_vaddr); + if (params->output_dma[i].dma_vaddr == NULL) { + mxc_free_dma_buf(params); + pr_info("can't allocate output buff\n"); + return -ENOBUFS; + } + } + return 0; +} + +static bool filter(struct dma_chan *chan, void *param) +{ + + if (!imx_dma_is_general_purpose(chan)) + return false; + + chan->private = param; + return true; +} + + +#ifdef CONFIG_ARCH_MVF +static struct dma_async_tx_descriptor *imx_asrc_dma_config(u32 ch, + u32 dma_addr, void *buf_addr, + u32 buf_len, int in) +{ + struct scatterlist sg; + u32 src, dst; + int ret; + + if (buf_len <= 0) { + printk(KERN_INFO " asrc config dma size error %d\n", buf_len); + return NULL; + } + /* make sure the eDMA channel is stopped */ + mcf_edma_stop_transfer(ch); + + sg_init_one(&sg, buf_addr, buf_len); + ret = dma_map_sg(NULL, &sg, 1, in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + if (ret != 1) + return NULL; + if (in) { /* input: buffer to engine */ + dst = dma_addr; /* reg IN */ + src = (u32)sg_phys(&sg); + mcf_edma_set_tcd_params(ch, + src, dst, + MCF_EDMA_TCD_ATTR_SSIZE_32BIT | + MCF_EDMA_TCD_ATTR_DSIZE_32BIT, + 4, /* soff */ + 4 * 32, /* nbyte */ + 0, /* slast */ + buf_len/(4 * 32), /* citer */ + buf_len/(4 * 32), /* biter */ + 0, 0, /* doff, dlast */ + 1, 1, 0); /* major int, disable request, sg */ + /*DBG("config dma(%d) IN, cnt=%d, buf=%#x\n", ch, buf_len/4, src);*/ + + } else { /* output: engine to buffer */ + dst = (u32)sg_phys(&sg); + src = dma_addr; + mcf_edma_set_tcd_params(ch, + src, dst, + MCF_EDMA_TCD_ATTR_SSIZE_32BIT | + MCF_EDMA_TCD_ATTR_DSIZE_32BIT, + 0, + 4 * 32, + 0, + buf_len/(4 * 32), + buf_len/(4 * 32), + 4, 0, + 1, 1, 0); + /*DBG("config dma(%d) OUT, cnt=%d, buf=%#x\n", ch, buf_len/4, dst);*/ + } + + return &dummy_desc; +} +#endif + +/*! + * asrc interface - ioctl function + * + * @param inode struct inode * + * + * @param file struct file * + * + * @param cmd unsigned int + * + * @param arg unsigned long + * + * @return 0 success, ENODEV for invalid device instance, + * -1 for other errors. + */ +static long asrc_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int err = 0; + struct asrc_pair_params *params; + params = file->private_data; + if (down_interruptible(¶ms->busy_lock)) + return -EBUSY; + switch (cmd) { + case ASRC_REQ_PAIR: + { + struct asrc_req req; + if (copy_from_user(&req, (void __user *)arg, + sizeof(struct asrc_req))) { + err = -EFAULT; + break; + } + err = asrc_req_pair(req.chn_num, &req.index); + if (err < 0) + break; + params->pair_hold = 1; + params->index = req.index; + if (copy_to_user + ((void __user *)arg, &req, sizeof(struct asrc_req))) + err = -EFAULT; + + break; + } + case ASRC_CONFIG_PAIR: + { + struct asrc_config config; + u32 rx_id, tx_id; + char *rx_name, *tx_name; + if (copy_from_user + (&config, (void __user *)arg, + sizeof(struct asrc_config))) { + err = -EFAULT; + break; + } + err = asrc_config_pair(&config); + if (err < 0) + break; + params->output_buffer_size = + asrc_get_output_buffer_size(config. + dma_buffer_size, + config. + input_sample_rate, + config. + output_sample_rate); + params->input_buffer_size = config.dma_buffer_size; + if (config.buffer_num > ASRC_DMA_BUFFER_NUM) + params->buffer_num = ASRC_DMA_BUFFER_NUM; + else + params->buffer_num = config.buffer_num; + err = mxc_allocate_dma_buf(params); + if (err < 0) + break; + + /* TBD - need to update when new SDMA interface ready */ + if (config.pair == ASRC_PAIR_A) { + rx_id = asrc_dmarx[ASRC_PAIR_A]; + tx_id = asrc_dmatx[ASRC_PAIR_A]; + rx_name = asrc_pair_id[0]; + tx_name = asrc_pair_id[1]; + } else if (config.pair == ASRC_PAIR_B) { + rx_id = asrc_dmarx[ASRC_PAIR_B]; + tx_id = asrc_dmatx[ASRC_PAIR_B]; + rx_name = asrc_pair_id[2]; + tx_name = asrc_pair_id[3]; + } else { + rx_id = asrc_dmarx[ASRC_PAIR_C]; + tx_id = asrc_dmatx[ASRC_PAIR_C]; + rx_name = asrc_pair_id[4]; + tx_name = asrc_pair_id[5]; + } + + params->input_dma_channel = mcf_edma_request_channel( + tx_id, + asrc_input_dma_callback, NULL, + 6, params, NULL, tx_name); + + params->output_dma_channel = mcf_edma_request_channel( + rx_id, + asrc_output_dma_callback, NULL, + 6, params, NULL, rx_name); + + params->input_queue_empty = 0; + params->output_queue_empty = 0; + INIT_LIST_HEAD(¶ms->input_queue); + INIT_LIST_HEAD(¶ms->input_done_queue); + INIT_LIST_HEAD(¶ms->output_queue); + INIT_LIST_HEAD(¶ms->output_done_queue); + init_waitqueue_head(¶ms->input_wait_queue); + init_waitqueue_head(¶ms->output_wait_queue); + + if (copy_to_user + ((void __user *)arg, &config, + sizeof(struct asrc_config))) + err = -EFAULT; + break; + } + case ASRC_QUERYBUF: + { + struct asrc_querybuf buffer; + if (copy_from_user + (&buffer, (void __user *)arg, + sizeof(struct asrc_querybuf))) { + err = -EFAULT; + break; + } + buffer.input_offset = + (unsigned long)params->input_dma[buffer. + buffer_index]. + dma_paddr; + buffer.input_length = params->input_buffer_size; + buffer.output_offset = + (unsigned long)params->output_dma[buffer. + buffer_index]. + dma_paddr; + buffer.output_length = params->output_buffer_size; + if (copy_to_user + ((void __user *)arg, &buffer, + sizeof(struct asrc_querybuf))) + err = -EFAULT; + break; + } + case ASRC_RELEASE_PAIR: + { + enum asrc_pair_index index; + if (copy_from_user + (&index, (void __user *)arg, + sizeof(enum asrc_pair_index))) { + err = -EFAULT; + break; + } + + if (params->input_dma_channel) + mcf_edma_free_channel( + params->input_dma_channel, params); + if (params->output_dma_channel) + mcf_edma_free_channel( + params->output_dma_channel, params); + + mxc_free_dma_buf(params); + asrc_release_pair(index); + params->pair_hold = 0; + break; + } + case ASRC_Q_INBUF: /* queue input buffer */ + { + struct asrc_buffer buf; + struct dma_block *block; + u32 dma_addr; + void *buf_addr; + unsigned long lock_flags; + if (copy_from_user + (&buf, (void __user *)arg, + sizeof(struct asrc_buffer))) { + err = -EFAULT; + break; + } + + spin_lock_irqsave(&input_int_lock, lock_flags); + params->input_dma[buf.index].index = buf.index; + params->input_dma[buf.index].length = buf.length; + list_add_tail(¶ms->input_dma[buf.index]. + queue, ¶ms->input_queue); + if (params->input_queue_empty == 0) { + block = + list_entry(params->input_queue.next, + struct dma_block, queue); + dma_addr = + (asrc_phy_base_addr + ASRC_ASRDIA_REG + + (params->index << 3)); + buf_addr = block->dma_vaddr; + spin_unlock_irqrestore(&input_int_lock, + lock_flags); + desc_in = imx_asrc_dma_config( + params->input_dma_channel, + dma_addr, buf_addr, + block->length, 1); + + spin_lock_irqsave(&input_int_lock, lock_flags); + params->input_queue_empty++; + list_del(params->input_queue.next); + list_add_tail(&block->queue, + ¶ms->input_done_queue); + if (params->asrc_active) + mcf_edma_enable_transfer( + params->input_dma_channel); + } + + spin_unlock_irqrestore(&input_int_lock, lock_flags); + break; + } + case ASRC_DQ_INBUF:{ /* dequeue input buffer */ + struct asrc_buffer buf; + struct dma_block *block; + unsigned long lock_flags; + if (copy_from_user + (&buf, (void __user *)arg, + sizeof(struct asrc_buffer))) { + err = -EFAULT; + break; + } + + /* if ASRC is inactive, nonsense to DQ buffer */ + if (params->asrc_active == 0) { + err = -EFAULT; + buf.buf_valid = ASRC_BUF_NA; + if (copy_to_user + ((void __user *)arg, &buf, + sizeof(struct asrc_buffer))) + err = -EFAULT; + break; + } + + if (!wait_event_interruptible_timeout + (params->input_wait_queue, + params->input_counter != 0, 10 * HZ)) { + pr_info + ("ASRC_DQ_INBUF timeout counter %x\n", + params->input_counter); + err = -ETIME; + break; + } else if (signal_pending(current)) { + pr_info("ASRC_DQ_INBUF interrupt received\n"); + err = -ERESTARTSYS; + break; + } + spin_lock_irqsave(&input_int_lock, lock_flags); + params->input_counter--; + block = + list_entry(params->input_done_queue.next, + struct dma_block, queue); + list_del(params->input_done_queue.next); + spin_unlock_irqrestore(&input_int_lock, lock_flags); + buf.index = block->index; + buf.length = block->length; + buf.buf_valid = ASRC_BUF_AV; + if (copy_to_user + ((void __user *)arg, &buf, + sizeof(struct asrc_buffer))) + err = -EFAULT; + + break; + } + case ASRC_Q_OUTBUF:{ /* queue output buffer */ + struct asrc_buffer buf; + struct dma_block *block; + u32 dma_addr; + void *buf_addr; + unsigned long lock_flags; + if (copy_from_user + (&buf, (void __user *)arg, + sizeof(struct asrc_buffer))) { + err = -EFAULT; + break; + } + + spin_lock_irqsave(&output_int_lock, lock_flags); + params->output_dma[buf.index].index = buf.index; + params->output_dma[buf.index].length = buf.length; + list_add_tail(¶ms->output_dma[buf.index]. + queue, ¶ms->output_queue); + if (params->output_queue_empty == 0) { + block = + list_entry(params->output_queue. + next, struct dma_block, queue); + dma_addr = + (asrc_phy_base_addr + ASRC_ASRDOA_REG + + (params->index << 3)); + buf_addr = block->dma_vaddr; + spin_unlock_irqrestore(&output_int_lock, + lock_flags); + + desc_out = imx_asrc_dma_config( + params->output_dma_channel, + dma_addr, buf_addr, block->length, 0); + spin_lock_irqsave(&output_int_lock, lock_flags); + + list_del(params->output_queue.next); + list_add_tail(&block->queue, + ¶ms->output_done_queue); + params->output_queue_empty++; + + if (params->asrc_active) + mcf_edma_enable_transfer( + params->output_dma_channel); + } + + spin_unlock_irqrestore(&output_int_lock, lock_flags); + break; + } + case ASRC_DQ_OUTBUF:{ + struct asrc_buffer buf; + struct dma_block *block; + unsigned long lock_flags; + if (copy_from_user + (&buf, (void __user *)arg, + sizeof(struct asrc_buffer))) { + err = -EFAULT; + break; + } + + /* if ASRC is inactive, nonsense to DQ buffer */ + if (params->asrc_active == 0) { + buf.buf_valid = ASRC_BUF_NA; + err = -EFAULT; + if (copy_to_user + ((void __user *)arg, &buf, + sizeof(struct asrc_buffer))) + err = -EFAULT; + break; + } + + if (!wait_event_interruptible_timeout + (params->output_wait_queue, + params->output_counter != 0, 10 * HZ)) { + pr_info + ("ASRC_DQ_OUTBUF timeout counter %x\n", + params->output_counter); + err = -ETIME; + break; + } else if (signal_pending(current)) { + pr_info("ASRC_DQ_INBUF interrupt received\n"); + err = -ERESTARTSYS; + break; + } + spin_lock_irqsave(&output_int_lock, lock_flags); + params->output_counter--; + block = + list_entry(params->output_done_queue.next, + struct dma_block, queue); + list_del(params->output_done_queue.next); + spin_unlock_irqrestore(&output_int_lock, lock_flags); + buf.index = block->index; + buf.length = block->length; + buf.buf_valid = ASRC_BUF_AV; + if (copy_to_user + ((void __user *)arg, &buf, + sizeof(struct asrc_buffer))) + err = -EFAULT; + + break; + } + case ASRC_START_CONV:{ + enum asrc_pair_index index; + unsigned long lock_flags; + + if (copy_from_user + (&index, (void __user *)arg, + sizeof(enum asrc_pair_index))) { + err = -EFAULT; + break; + } + spin_lock_irqsave(&input_int_lock, lock_flags); + if (params->input_queue_empty == 0) { + err = -EFAULT; + pr_info + ("ASRC_START_CONV - no block available\n"); + break; + } + spin_unlock_irqrestore(&input_int_lock, lock_flags); + params->asrc_active = 1; + + mcf_edma_enable_transfer(params->output_dma_channel); + mcf_edma_enable_transfer(params->input_dma_channel); + + asrc_start_conv(index); + break; + } + case ASRC_STOP_CONV:{ + enum asrc_pair_index index; + + if (copy_from_user + (&index, (void __user *)arg, + sizeof(enum asrc_pair_index))) { + err = -EFAULT; + break; + } + mcf_edma_stop_transfer(params->input_dma_channel); + mcf_edma_stop_transfer(params->output_dma_channel); + asrc_stop_conv(index); + params->asrc_active = 0; + break; + } + case ASRC_STATUS:{ + struct asrc_status_flags flags; + if (copy_from_user + (&flags, (void __user *)arg, + sizeof(struct asrc_status_flags))) { + err = -EFAULT; + break; + } + asrc_get_status(&flags); + if (copy_to_user + ((void __user *)arg, &flags, + sizeof(struct asrc_status_flags))) + err = -EFAULT; + break; + } + case ASRC_FLUSH:{ + /* flush input dma buffer */ + unsigned long lock_flags; + u32 rx_id, tx_id; + char *rx_name, *tx_name; + + spin_lock_irqsave(&input_int_lock, lock_flags); + while (!list_empty(¶ms->input_queue)) + list_del(params->input_queue.next); + while (!list_empty(¶ms->input_done_queue)) + list_del(params->input_done_queue.next); + params->input_counter = 0; + params->input_queue_empty = 0; + spin_unlock_irqrestore(&input_int_lock, lock_flags); + + /* flush output dma buffer */ + spin_lock_irqsave(&output_int_lock, lock_flags); + while (!list_empty(¶ms->output_queue)) + list_del(params->output_queue.next); + while (!list_empty(¶ms->output_done_queue)) + list_del(params->output_done_queue.next); + params->output_counter = 0; + params->output_queue_empty = 0; + spin_unlock_irqrestore(&output_int_lock, lock_flags); + + /* release DMA and request again */ + mcf_edma_free_channel(params->input_dma_channel, + params); + mcf_edma_free_channel(params->output_dma_channel, + params); + + if (params->index == ASRC_PAIR_A) { + rx_id = asrc_dmarx[ASRC_PAIR_A]; + tx_id = asrc_dmatx[ASRC_PAIR_A]; + rx_name = asrc_pair_id[0]; + tx_name = asrc_pair_id[1]; + } else if (params->index == ASRC_PAIR_B) { + rx_id = asrc_dmarx[ASRC_PAIR_B]; + tx_id = asrc_dmatx[ASRC_PAIR_B]; + rx_name = asrc_pair_id[2]; + tx_name = asrc_pair_id[3]; + } else { + rx_id = asrc_dmarx[ASRC_PAIR_C]; + tx_id = asrc_dmatx[ASRC_PAIR_C]; + rx_name = asrc_pair_id[4]; + tx_name = asrc_pair_id[5]; + } + params->input_dma_channel = mcf_edma_request_channel( + tx_id, asrc_input_dma_callback, NULL, + 6, params, NULL, NULL); + + if (params->input_dma_channel == 0) { + pr_err("unable to get input channel %d\n", + tx_id); + err = -EBUSY; + } + + params->output_dma_channel = mcf_edma_request_channel( + rx_id, asrc_output_dma_callback, NULL, + 6, params, NULL, NULL); + + if (params->output_dma_channel == 0) { + pr_err("unable to get output channel %d\n", + rx_id); + err = -EBUSY; + } + + break; + } + default: + break; + } + + up(¶ms->busy_lock); + return err; +} + +/*! + * asrc interface - open function + * + * @param inode structure inode * + * + * @param file structure file * + * + * @return status 0 success, ENODEV invalid device instance, + * ENOBUFS failed to allocate buffer, ERESTARTSYS interrupted by user + */ +static int mxc_asrc_open(struct inode *inode, struct file *file) +{ + int err = 0; + struct asrc_pair_params *pair_params; + + clk_enable(mxc_asrc_data->asrc_core_clk); + if (signal_pending(current)) + return -EINTR; + pair_params = kzalloc(sizeof(struct asrc_pair_params), GFP_KERNEL); + if (pair_params == NULL) { + pr_debug("Failed to allocate pair_params\n"); + err = -ENOBUFS; + } + + sema_init(&pair_params->busy_lock, 1); + file->private_data = pair_params; + + return err; +} + +/*! + * asrc interface - close function + * + * @param inode struct inode * + * @param file structure file * + * + * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error + */ +static int mxc_asrc_close(struct inode *inode, struct file *file) +{ + struct asrc_pair_params *pair_params; + pair_params = file->private_data; + + if (pair_params->asrc_active == 1) { + asrc_stop_conv(pair_params->index); + wake_up_interruptible(&pair_params->input_wait_queue); + wake_up_interruptible(&pair_params->output_wait_queue); + } + if (pair_params->pair_hold == 1) { + mcf_edma_free_channel(pair_params->input_dma_channel, + pair_params); + mcf_edma_free_channel(pair_params->output_dma_channel, + pair_params); + mxc_free_dma_buf(pair_params); + asrc_release_pair(pair_params->index); + } + + kfree(pair_params); + file->private_data = NULL; + clk_disable(mxc_asrc_data->asrc_core_clk); + + return 0; +} + +/*! + * asrc interface - mmap function + * + * @param file structure file * + * + * @param vma structure vm_area_struct * + * + * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error + */ +static int mxc_asrc_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long size; + int res = 0; + size = vma->vm_end - vma->vm_start; + + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + if (remap_pfn_range(vma, vma->vm_start, + vma->vm_pgoff, size, vma->vm_page_prot)) + return -ENOBUFS; + + vma->vm_flags &= ~VM_IO; + return res; +} + +static const struct file_operations asrc_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = asrc_ioctl, + .mmap = mxc_asrc_mmap, + .open = mxc_asrc_open, + .release = mxc_asrc_close, +}; + +static int asrc_read_proc_attr(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + unsigned long reg; + int len = 0; + clk_enable(mxc_asrc_data->asrc_core_clk); + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCNCR_REG); + clk_disable(mxc_asrc_data->asrc_core_clk); + + len += sprintf(page, "ANCA: %d\n", + (int)(reg & + (0xFFFFFFFF >> + (32 - mxc_asrc_data->channel_bits)))); + len += + sprintf(page + len, "ANCB: %d\n", + (int)((reg >> mxc_asrc_data-> + channel_bits) & (0xFFFFFFFF >> (32 - + mxc_asrc_data-> + channel_bits)))); + len += + sprintf(page + len, "ANCC: %d\n", + (int)((reg >> (mxc_asrc_data->channel_bits * 2)) & + (0xFFFFFFFF >> (32 - mxc_asrc_data->channel_bits)))); + + if (off > len) + return 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + return min(count, len - (int)off); +} + +static int asrc_write_proc_attr(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char buf[50]; + unsigned long reg; + int na, nb, nc; + int total; + if (count > 48) + return -EINVAL; + if (copy_from_user(buf, buffer, count)) { + pr_debug("Attr proc write, Failed to copy buffer from user\n"); + return -EFAULT; + } + + clk_enable(mxc_asrc_data->asrc_core_clk); + reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCNCR_REG); + clk_disable(mxc_asrc_data->asrc_core_clk); + sscanf(buf, "ANCA: %d\nANCB: %d\nANCC: %d", &na, &nb, &nc); + if (mxc_asrc_data->channel_bits > 3) + total = 10; + else + total = 5; + if ((na + nb + nc) != total) { + pr_info("Wrong ASRCNR settings\n"); + return -EFAULT; + } + reg = na | (nb << mxc_asrc_data-> + channel_bits) | (nc << (mxc_asrc_data->channel_bits * 2)); + + clk_enable(mxc_asrc_data->asrc_core_clk); + __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCNCR_REG); + clk_disable(mxc_asrc_data->asrc_core_clk); + + return count; +} + +static void asrc_proc_create(void) +{ + struct proc_dir_entry *proc_attr; + proc_asrc = proc_mkdir(ASRC_PROC_PATH, NULL); + if (proc_asrc) { + proc_attr = create_proc_entry("ChSettings", + S_IFREG | S_IRUGO | + S_IWUSR, proc_asrc); + if (proc_attr) { + proc_attr->read_proc = asrc_read_proc_attr; + proc_attr->write_proc = asrc_write_proc_attr; + proc_attr->size = 48; + proc_attr->uid = proc_attr->gid = 0; + } else { + remove_proc_entry(ASRC_PROC_PATH, NULL); + pr_info("Failed to create proc attribute entry\n"); + } + } else { + pr_info("ASRC: Failed to create proc entry %s\n", + ASRC_PROC_PATH); + } +} + +/*! + * Entry point for the asrc device + * + * @param pdev Pionter to the registered platform device + * @return Error code indicating success or failure + */ +static int mxc_asrc_probe(struct platform_device *pdev) +{ + int err = 0; + struct resource *res; + struct device *temp_class; + int irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENOENT; + + g_asrc_data = kzalloc(sizeof(struct asrc_data), GFP_KERNEL); + + if (g_asrc_data == NULL) { + pr_info("Failed to allocate g_asrc_data\n"); + return -ENOMEM; + } + + g_asrc_data->asrc_pair[0].chn_max = 2; + g_asrc_data->asrc_pair[1].chn_max = 2; + g_asrc_data->asrc_pair[2].chn_max = 6; + g_asrc_data->asrc_pair[0].overload_error = 0; + g_asrc_data->asrc_pair[1].overload_error = 0; + g_asrc_data->asrc_pair[2].overload_error = 0; + + asrc_major = register_chrdev(asrc_major, "mxc_asrc", &asrc_fops); + if (asrc_major < 0) { + pr_info("Unable to register asrc device\n"); + err = -EBUSY; + goto error; + } + + asrc_class = class_create(THIS_MODULE, "mxc_asrc"); + if (IS_ERR(asrc_class)) { + err = PTR_ERR(asrc_class); + goto err_out_chrdev; + } + + temp_class = device_create(asrc_class, NULL, MKDEV(asrc_major, 0), + NULL, "mxc_asrc"); + if (IS_ERR(temp_class)) { + err = PTR_ERR(temp_class); + goto err_out_class; + } + + asrc_phy_base_addr = res->start; + asrc_vrt_base_addr = + (unsigned long)ioremap(res->start, res->end - res->start + 1); + + mxc_asrc_data = + (struct imx_asrc_platform_data *)pdev->dev.platform_data; + + clk_enable(mxc_asrc_data->asrc_core_clk); + + switch (mxc_asrc_data->clk_map_ver) { + case 1: + input_clk_map = &input_clk_map_v1[0]; + output_clk_map = &output_clk_map_v1[0]; + break; + case 3: + input_clk_map = &input_clk_map_v3[0]; + output_clk_map = &output_clk_map_v3[0]; + break; + case 2: + default: + input_clk_map = &input_clk_map_v2[0]; + output_clk_map = &output_clk_map_v2[0]; + break; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx1"); + if (res) + asrc_dmatx[0] = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx1"); + if (res) + asrc_dmarx[0] = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx2"); + if (res) + asrc_dmatx[1] = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx2"); + if (res) + asrc_dmarx[1] = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx3"); + if (res) + asrc_dmatx[2] = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx3"); + if (res) + asrc_dmarx[2] = res->start; + + irq = platform_get_irq(pdev, 0); + if (request_irq(irq, asrc_isr, 0, "asrc", NULL)) + return -1; + + asrc_proc_create(); + err = mxc_init_asrc(); + if (err < 0) + goto err_out_class; + clk_disable(mxc_asrc_data->asrc_core_clk); + goto out; + +err_out_class: + clk_disable(mxc_asrc_data->asrc_core_clk); + device_destroy(asrc_class, MKDEV(asrc_major, 0)); + class_destroy(asrc_class); +err_out_chrdev: + unregister_chrdev(asrc_major, "mxc_asrc"); +error: + kfree(g_asrc_data); +out: + pr_info("MVF ASRC registered\n"); + + return err; +} + +/*! + * Exit asrc device + * + * @param pdev Pionter to the registered platform device + * @return Error code indicating success or failure + */ +static int mxc_asrc_remove(struct platform_device *pdev) +{ + int irq = platform_get_irq(pdev, 0); + free_irq(irq, NULL); + kfree(g_asrc_data); + mxc_asrc_data = NULL; + iounmap((unsigned long __iomem *)asrc_vrt_base_addr); + remove_proc_entry("ChSettings", proc_asrc); + remove_proc_entry(ASRC_PROC_PATH, NULL); + device_destroy(asrc_class, MKDEV(asrc_major, 0)); + class_destroy(asrc_class); + unregister_chrdev(asrc_major, "mxc_asrc"); + return 0; +} + +/*! mxc asrc driver definition + * + */ +static struct platform_driver mxc_asrc_driver = { + .driver = { + .name = "mxc_asrc", + }, + .probe = mxc_asrc_probe, + .remove = mxc_asrc_remove, +}; + +/*! + * Register asrc driver + * + */ +static __init int asrc_init(void) +{ + int ret; + ret = platform_driver_register(&mxc_asrc_driver); + return ret; +} + +/*! + * Exit and free the asrc data + * + */ +static void __exit asrc_exit(void) +{ + platform_driver_unregister(&mxc_asrc_driver); + return; +} + +module_init(asrc_init); +module_exit(asrc_exit); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("Asynchronous Sample Rate Converter"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mxc_asrc.h b/include/linux/mxc_asrc.h index f0136f0502f0..d860dccb5374 100644 --- a/include/linux/mxc_asrc.h +++ b/include/linux/mxc_asrc.h @@ -47,13 +47,17 @@ enum asrc_pair_index { enum asrc_inclk { INCLK_NONE = 0x03, INCLK_ESAI_RX = 0x00, + INCLK_SSI0_RX = 0x06, INCLK_SSI1_RX = 0x01, INCLK_SSI2_RX = 0x02, + INCLK_SSI3_RX = 0x07, INCLK_SPDIF_RX = 0x04, INCLK_MLB_CLK = 0x05, INCLK_ESAI_TX = 0x08, + INCLK_SSI0_TX = 0xd, INCLK_SSI1_TX = 0x09, INCLK_SSI2_TX = 0x0a, + INCLK_SSI3_TX = 0x0b, INCLK_SPDIF_TX = 0x0c, INCLK_ASRCK1_CLK = 0x0f, }; @@ -61,13 +65,17 @@ enum asrc_inclk { enum asrc_outclk { OUTCLK_NONE = 0x03, OUTCLK_ESAI_TX = 0x00, + OUTCLK_SSI0_TX = 0x06, OUTCLK_SSI1_TX = 0x01, OUTCLK_SSI2_TX = 0x02, + OUTCLK_SSI3_TX = 0x0d, OUTCLK_SPDIF_TX = 0x04, OUTCLK_MLB_CLK = 0x05, OUTCLK_ESAI_RX = 0x08, + OUTCLK_SSI0_RX = 0x07, OUTCLK_SSI1_RX = 0x09, OUTCLK_SSI2_RX = 0x0a, + OUTCLK_SSI3_RX = 0x0b, OUTCLK_SPDIF_RX = 0x0c, OUTCLK_ASRCK1_CLK = 0x0f, }; @@ -162,6 +170,15 @@ enum asrc_error_status { #define ASRC_ASRIDRLC_REG 0x94 #define ASRC_ASR76K_REG 0x98 #define ASRC_ASR56K_REG 0x9C +#define ASRC_ASRMCRA_REG 0xA0 +#define ASRC_ASRFSTA_REG 0xA4 +#define ASRC_ASRMCRB_REG 0xA8 +#define ASRC_ASRFSTB_REG 0xAC +#define ASRC_ASRMCRC_REG 0xB0 +#define ASRC_ASRFSTC_REG 0xB4 +#define ASRC_ASRMCR1A_REG 0xC0 +#define ASRC_ASRMCR1B_REG 0xC4 +#define ASRC_ASRMCR1C_REG 0xC8 struct dma_block { unsigned int index; @@ -183,8 +200,13 @@ struct asrc_pair_params { unsigned int output_counter; unsigned int input_queue_empty; unsigned int output_queue_empty; +#ifdef CONFIG_ARCH_MVF + unsigned long input_dma_channel; + unsigned long output_dma_channel; +#else struct dma_chan *input_dma_channel; struct dma_chan *output_dma_channel; +#endif unsigned int input_buffer_size; unsigned int output_buffer_size; unsigned int buffer_num; -- cgit v1.2.3 From 3bb1551c08e3a5b0303bd0a4f52d048ee75cee65 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Mon, 10 Dec 2012 13:09:42 +0800 Subject: ENGR00216087-2:Add Vybrid ASRC platform device Signed-off-by: Jingchang Lu --- arch/arm/mach-mvf/board-twr-vf700.c | 9 +++++++++ arch/arm/mach-mvf/clock.c | 25 +++++++++++++++++++++++++ arch/arm/plat-mxc/devices/platform-imx-asrc.c | 18 +++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index 5903f7ae0244..d9d0ff6161dd 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -426,6 +426,11 @@ static struct led_pwm_platform_data mvf_led_data __initdata = { .leds = &mvf_led, }; +static struct imx_asrc_platform_data imx_asrc_data = { + .channel_bits = 4, + .clk_map_ver = 3, +}; + static void __init mvf_twr_init_usb(void) { imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR); @@ -483,6 +488,10 @@ static void __init mvf_board_init(void) mvf_add_mxc_pwm(0); mvf_add_pwm_leds(&mvf_led_data); + imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk"); + imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk"); + mvf_add_asrc(&imx_asrc_data); + } static void __init mvf_timer_init(void) diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index cfcea6eccff2..140f0edee565 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1818,6 +1818,29 @@ static struct clk qspi1_clk = { .get_rate = _clk_qspi1_get_rate, }; +static int _clk_asrc_serial_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} + +static struct clk asrc_clk[] = { + { + __INIT_CLK_DEBUG(asrc_clk) + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + __INIT_CLK_DEBUG(asrc_serial_clk) + .id = 1, + .parent = &audio_external_clk, + .set_rate = _clk_asrc_serial_set_rate, + }, +}; + static struct clk dummy_clk = { .id = 0, }; @@ -1874,6 +1897,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "mvf-usb.1", usb_phy1_clk), _REGISTER_CLOCK(NULL, "pwm", ftm_pwm_clk), _REGISTER_CLOCK("mvf-qspi.0", NULL, qspi0_clk), + _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk[0]), + _REGISTER_CLOCK(NULL, "asrc_serial_clk", asrc_clk[1]), }; static void clk_tree_init(void) diff --git a/arch/arm/plat-mxc/devices/platform-imx-asrc.c b/arch/arm/plat-mxc/devices/platform-imx-asrc.c index c112a9ba8671..a35617d71a0e 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-asrc.c +++ b/arch/arm/plat-mxc/devices/platform-imx-asrc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. * * 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 @@ -38,6 +38,22 @@ const struct imx_imx_asrc_data imx6q_imx_asrc_data[] __initconst = { }; #endif /* ifdef CONFIG_SOC_IMX6Q */ +#ifdef CONFIG_SOC_MVFA5 +const struct imx_imx_asrc_data mvf_imx_asrc_data[] __initconst = { + [0] = { + .id = 0, + .iobase = MVF_ASRC_BASE_ADDR, + .iosize = SZ_4K, + .irq = MVF_INT_ASRC, + .dmatx1 = DMA_MUX12_ASRC0_TX + 64, + .dmarx1 = DMA_MUX12_ASRC0_RX + 64, + .dmatx2 = DMA_MUX12_ASRC1_TX + 64, + .dmarx2 = DMA_MUX12_ASRC1_RX + 64, + .dmatx3 = DMA_MUX12_ASRC2_TX + 64, + .dmarx3 = DMA_MUX12_ASRC2_RX + 64, + }, +}; +#endif struct platform_device *__init imx_add_imx_asrc( const struct imx_imx_asrc_data *data, const struct imx_asrc_platform_data *pdata) -- cgit v1.2.3 From 051e157a7bcacf3d4f84289c2e8cc561ecb4a3c3 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Fri, 7 Dec 2012 17:28:16 +0800 Subject: ENGR00216081-1:Add USB host and gadget PM support Handle usb suspend/resume, currently the BSP doesn't support usb plug/unplug wakeup. Signed-off-by: Jingchang Lu --- arch/arm/mach-mvf/board-twr-vf700.c | 6 +- arch/arm/mach-mvf/devices-mvf.h | 8 +- arch/arm/mach-mvf/usb_dr.c | 198 ++++++++++++++++++++- arch/arm/mach-mvf/usb_dr2.c | 181 ++++++++++++++++++- .../plat-mxc/devices/platform-fsl-usb2-wakeup.c | 17 +- arch/arm/plat-mxc/usb_common.c | 3 + arch/arm/plat-mxc/usb_wakeup.c | 25 ++- drivers/usb/gadget/arcotg_udc.c | 12 +- drivers/usb/host/ehci-arc.c | 51 +----- 9 files changed, 437 insertions(+), 64 deletions(-) diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index d9d0ff6161dd..a267df7a303f 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -435,12 +435,12 @@ static void __init mvf_twr_init_usb(void) { imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR); /*mvf_set_otghost_vbus_func(mvf_twr_usbotg_vbus);*/ -#ifdef CONFIG_USB_GADGET_ARC - mvf_usb_dr_init(); -#endif #ifdef CONFIG_USB_EHCI_ARC mvf_usb_dr2_init(); #endif +#ifdef CONFIG_USB_GADGET_ARC + mvf_usb_dr_init(); +#endif } /*! diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index 61792fb34530..b8bea993bdee 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -69,9 +69,11 @@ extern const struct imx_fsl_usb2_otg_data mvf_fsl_usb2_otg_data __initconst; imx_add_fsl_usb2_otg(&mvf_fsl_usb2_otg_data, pdata) extern -const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data __initconst; -#define mvf_add_fsl_usb2_otg_wakeup(pdata) \ - imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data, pdata) +const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst; +#define mvf_add_fsl_usb2_ehci_otg_wakeup(pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[1], pdata) +#define mvf_add_fsl_usb2_udc_wakeup(pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[0], pdata) extern const struct imx_fsl_usb2_wakeup_data mvf_fsl_hs_wakeup_data[] __initconst; diff --git a/arch/arm/mach-mvf/usb_dr.c b/arch/arm/mach-mvf/usb_dr.c index 2467acc1bf28..bbd29f3b45a9 100644 --- a/arch/arm/mach-mvf/usb_dr.c +++ b/arch/arm/mach-mvf/usb_dr.c @@ -35,6 +35,7 @@ static int usbotg_init_ext(struct platform_device *pdev); static void usbotg_uninit_ext(struct platform_device *pdev); static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); +static void usbotg_wakeup_event_clear(void); /* The usb_phy0_clk do not have enable/disable function at clock.c * and PLL output for usb0's phy should be always enabled. @@ -62,6 +63,13 @@ static struct fsl_usb2_platform_data dr_utmi_config = { .dr_discharge_line = _dr_discharge_line, }; +/* Platform data for wakeup operation */ +static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = { + .name = "Gadget wakeup", + .usb_clock_for_pm = usbotg_clock_gate, + .usb_wakeup_exhandle = usbotg_wakeup_event_clear, +}; + static void usbotg_internal_phy_clock_gate(bool on) { u32 reg; @@ -183,25 +191,213 @@ static void _dr_discharge_line(bool enable) /* Below two macros are used at otg mode to indicate usb mode*/ #define ENABLED_BY_HOST (0x1 << 0) #define ENABLED_BY_DEVICE (0x1 << 1) +static u32 low_power_enable_src; /* only useful at otg mode */ +static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + u32 tmp; + pr_debug("DR: %s begins, enable is %d\n", __func__, enable); + + if (enable) { + UOG_PORTSC1 |= PORTSC_PHCD; + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET); + usbotg_internal_phy_clock_gate(false); + + } else { + if (UOG_PORTSC1 & PORTSC_PHCD) { + UOG_PORTSC1 &= ~PORTSC_PHCD; + mdelay(1); + } + usbotg_internal_phy_clock_gate(true); + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); + + } + pr_debug("DR: %s ends, enable is %d\n", __func__, enable); +} + +static void __phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable, int source) +{ + if (enable) { + low_power_enable_src |= source; + enter_phy_lowpower_suspend(pdata, enable); + } else { + enter_phy_lowpower_suspend(pdata, enable); + low_power_enable_src &= ~source; + } +} + +static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + + pr_debug("%s, enable is %d\n", __func__, enable); + if (enable) { + __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP + | BM_USBPHY_CTRL_ENVBUSCHG_WKUP + | BM_USBPHY_CTRL_ENDPDMCHG_WKUP + | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS + | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD + | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE + | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE + | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL, + phy_reg + HW_USBPHY_CTRL_SET); + USBC0_CTRL |= UCTRL_OWIE; + } else { + USBC0_CTRL &= ~UCTRL_OWIE; + /* The interrupt must be disabled for at least 3 clock + * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ + udelay(100); + } +} + +static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata, + bool on, int source) +{ + /* otg host and device share the OWIE bit, only when host and device + * all enable the wakeup irq, we can enable the OWIE bit + */ + if (on) { + otg_wake_up_enable(pdata, on); + } else { + otg_wake_up_enable(pdata, on); + /* The interrupt must be disabled for at least 3 clock + * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ + udelay(100); + } +} + +/* The wakeup operation for DR port, it will clear the wakeup irq status + * and re-enable the wakeup + */ +static void usbotg_wakeup_event_clear(void) +{ + int wakeup_req = USBC0_CTRL & UCTRL_OWIR; + + if (wakeup_req != 0) { + pr_debug("Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC); + /* Disable OWIE to clear OWIR, wait 3 clock + * cycles of standly clock(32KHz) + */ + USBC0_CTRL &= ~UCTRL_OWIE; + udelay(100); + USBC0_CTRL |= UCTRL_OWIE; + } +} +/* End of Common operation for DR port */ #ifdef CONFIG_USB_EHCI_ARC_OTG #endif /* CONFIG_USB_EHCI_ARC_OTG */ #ifdef CONFIG_USB_GADGET_ARC +/* Beginning of device related operation for DR port */ +static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __phy_lowpower_suspend(pdata, enable, ENABLED_BY_DEVICE); +} + +static void _device_wakeup_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __wakeup_irq_enable(pdata, enable, ENABLED_BY_DEVICE); + if (enable) { + pr_debug("device wakeup enable\n"); + device_wakeup_enable(&pdata->pdev->dev); + } else { + pr_debug("device wakeup disable\n"); + device_wakeup_disable(&pdata->pdev->dev); + } +} + +static enum usb_wakeup_event +_is_device_wakeup(struct fsl_usb2_platform_data *pdata) +{ + int wakeup_req = USBC0_CTRL & UCTRL_OWIR; + + /* if ID=1, it is a device wakeup event */ + if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && + (UOG_USBSTS & USBSTS_URI)) { + printk(KERN_INFO "otg udc wakeup, host sends reset signal\n"); + return WAKEUP_EVENT_DPDM; + } + if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && \ + ((UOG_USBSTS & USBSTS_PCI) || + (UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME))) { + /* + * When the line state from J to K, the Port Change Detect bit + * in the USBSTS register is also set to '1'. + */ + printk(KERN_INFO "otg udc wakeup, host sends resume signal\n"); + return WAKEUP_EVENT_DPDM; + } + if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && + (UOG_OTGSC & OTGSC_STS_A_VBUS_VALID) && + (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)) { + printk(KERN_INFO "otg udc vbus rising wakeup\n"); + return WAKEUP_EVENT_VBUS; + } + if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && + !(UOG_OTGSC & OTGSC_STS_A_VBUS_VALID)) { + printk(KERN_INFO "otg udc vbus falling wakeup\n"); + return WAKEUP_EVENT_VBUS; + } + + return WAKEUP_EVENT_DPDM; +} + +static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata) +{ + _device_phy_lowpower_suspend(pdata, false); + _device_wakeup_enable(pdata, false); +} +/* end of device related operation for DR port */ #endif /* CONFIG_USB_GADGET_ARC */ void __init mvf_usb_dr_init(void) { - struct platform_device *pdev; + struct platform_device *pdev, *pdev_wakeup; u32 reg; #ifdef CONFIG_USB_GADGET_ARC dr_utmi_config.operating_mode = DR_UDC_MODE; + dr_utmi_config.wake_up_enable = _device_wakeup_enable; dr_utmi_config.platform_suspend = NULL; dr_utmi_config.platform_resume = NULL; + dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend; + dr_utmi_config.is_wakeup_event = _is_device_wakeup; + dr_utmi_config.wakeup_pdata = &dr_wakeup_config; + dr_utmi_config.wakeup_handler = device_wakeup_handler; pdev = mvf_add_fsl_usb2_udc(&dr_utmi_config); + dr_wakeup_config.usb_pdata[2] = pdev->dev.platform_data; + + /* register wakeup device */ + pdev_wakeup = mvf_add_fsl_usb2_udc_wakeup(&dr_wakeup_config); + if (pdev != NULL) + ((struct fsl_usb2_platform_data *) + (pdev->dev.platform_data))->wakeup_pdata = + (struct fsl_usb2_wakeup_platform_data *) + (pdev_wakeup->dev.platform_data); + + device_set_wakeup_capable(&pdev->dev, true); __raw_writel(((0x01 << 30) | 0x2), ANADIG_USB1_MISC); __raw_writel(0x00000894, USBPHY1_CTRL); diff --git a/arch/arm/mach-mvf/usb_dr2.c b/arch/arm/mach-mvf/usb_dr2.c index d26cfde125e0..67e3fcdbc921 100644 --- a/arch/arm/mach-mvf/usb_dr2.c +++ b/arch/arm/mach-mvf/usb_dr2.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ static int usbotg2_init_ext(struct platform_device *pdev); static void usbotg2_uninit_ext(struct platform_device *pdev); static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); +static void usbotg_wakeup_event_clear(void); static struct clk *usb_phy1_clk; static u8 otg2_used; @@ -58,6 +60,13 @@ static struct fsl_usb2_platform_data dr_utmi_config = { .dr_discharge_line = _dr_discharge_line, }; +/* Platform data for wakeup operation */ +static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = { + .name = "Host wakeup", + .usb_clock_for_pm = usbotg_clock_gate, + .usb_wakeup_exhandle = usbotg_wakeup_event_clear, +}; + static void usbotg_internal_phy_clock_gate(bool on) { void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY1_BASE_ADDR); @@ -181,6 +190,113 @@ static void _dr_discharge_line(bool enable) /* Below two macros are used at otg mode to indicate usb mode*/ #define ENABLED_BY_HOST (0x1 << 0) #define ENABLED_BY_DEVICE (0x1 << 1) +static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY1_BASE_ADDR); + u32 tmp; + pr_debug("DR: %s begins, enable is %d\n", __func__, enable); + + if (enable) { + UOG2_PORTSC1 |= PORTSC_PHCD; + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET); + usbotg_internal_phy_clock_gate(false); + + } else { + if (UOG2_PORTSC1 & PORTSC_PHCD) { + UOG2_PORTSC1 &= ~PORTSC_PHCD; + mdelay(1); + } + usbotg_internal_phy_clock_gate(true); + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); + + } + pr_debug("DR: %s ends, enable is %d\n", __func__, enable); +} + +static void __phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable, int source) +{ + if (enable) + enter_phy_lowpower_suspend(pdata, enable); + else { + pr_debug("phy lowpower disable\n"); + enter_phy_lowpower_suspend(pdata, enable); + } +} + +static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY1_BASE_ADDR); + + pr_debug("%s, enable is %d\n", __func__, enable); + if (enable) { + __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP + | BM_USBPHY_CTRL_ENVBUSCHG_WKUP + | BM_USBPHY_CTRL_ENDPDMCHG_WKUP + | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS + | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD + | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE + | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE + | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL, + phy_reg + HW_USBPHY_CTRL_SET); + USBC1_CTRL |= UCTRL_OWIE; + } else { + USBC1_CTRL &= ~UCTRL_OWIE; + /* The interrupt must be disabled for at least 3 clock + * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ + udelay(100); + } +} + +static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata, + bool on, int source) +{ + pr_debug("USB Host %s,on=%d\n", __func__, on); + mdelay(3); + if (on) { + otg_wake_up_enable(pdata, on); + } else { + otg_wake_up_enable(pdata, on); + /* The interrupt must be disabled for at least 3 clock + * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ + udelay(100); + } +} + +/* The wakeup operation for DR port, it will clear the wakeup irq status + * and re-enable the wakeup + */ +static void usbotg_wakeup_event_clear(void) +{ + int wakeup_req = USBC1_CTRL & UCTRL_OWIR; + + if (wakeup_req != 0) { + pr_debug("Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC); + /* Disable OWIE to clear OWIR, wait 3 clock + * cycles of standly clock(32KHz) + */ + USBC1_CTRL &= ~UCTRL_OWIE; + udelay(100); + USBC1_CTRL |= UCTRL_OWIE; + } +} + /* End of Common operation for DR port */ #ifdef CONFIG_USB_EHCI_ARC_OTG @@ -215,22 +331,85 @@ static void _host_platform_resume(struct fsl_usb2_platform_data *pdata) __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); } +static void _host_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __phy_lowpower_suspend(pdata, enable, ENABLED_BY_HOST); +} + +static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + __wakeup_irq_enable(pdata, enable, ENABLED_BY_HOST); + + if (enable) + device_wakeup_enable(&pdata->pdev->dev); + else + device_wakeup_disable(&pdata->pdev->dev); +} + +static enum usb_wakeup_event +_is_host_wakeup(struct fsl_usb2_platform_data *pdata) +{ + u32 wakeup_req = USBC1_CTRL & UCTRL_OWIR; + u32 otgsc = UOG2_OTGSC; + + if (wakeup_req) { + pr_debug("the otgsc is 0x%x, usbsts is 0x%x," + " portsc is 0x%x, wakeup_irq is 0x%x\n", + UOG2_OTGSC, UOG2_USBSTS, UOG2_PORTSC1, wakeup_req); + } + /* if ID change sts, it is a host wakeup event */ + if (wakeup_req && (otgsc & OTGSC_IS_USB_ID)) { + pr_debug("otg host ID wakeup\n"); + /* if host ID wakeup, we must clear the b session change sts */ + otgsc &= (~OTGSC_IS_USB_ID); + return WAKEUP_EVENT_ID; + } + if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) { + pr_debug("otg host Remote wakeup\n"); + return WAKEUP_EVENT_DPDM; + } + return WAKEUP_EVENT_INVALID; +} + +static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata) +{ + _host_phy_lowpower_suspend(pdata, false); + _host_wakeup_enable(pdata, false); +} + /* End of host related operation for DR port */ #endif /* CONFIG_USB_EHCI_ARC_OTG */ void __init mvf_usb_dr2_init(void) { - struct platform_device *pdev; + struct platform_device *pdev, *pdev_wakeup; u32 reg; #ifdef CONFIG_USB_EHCI_ARC_OTG dr_utmi_config.operating_mode = DR_HOST_MODE; + dr_utmi_config.wake_up_enable = _host_wakeup_enable; dr_utmi_config.platform_suspend = _host_platform_suspend; dr_utmi_config.platform_resume = _host_platform_resume; + dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend; + dr_utmi_config.is_wakeup_event = _is_host_wakeup; + dr_utmi_config.wakeup_pdata = &dr_wakeup_config; + dr_utmi_config.wakeup_handler = host_wakeup_handler; pdev = mvf_add_fsl_ehci_otg(&dr_utmi_config); + dr_wakeup_config.usb_pdata[1] = pdev->dev.platform_data; + + /* register wakeup device */ + pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(&dr_wakeup_config); + if (pdev != NULL) + ((struct fsl_usb2_platform_data *) + (pdev->dev.platform_data))->wakeup_pdata = + (struct fsl_usb2_wakeup_platform_data *) + (pdev_wakeup->dev.platform_data); + __raw_writel(0x0220C802, USBPHY2_CTRL); udelay(20); diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c index 523c5d4599e1..957c96a7996e 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. * * Copyright (C) 2010 Pengutronix * Uwe Kleine-Koenig @@ -26,6 +26,21 @@ const struct imx_fsl_usb2_wakeup_data imx6q_fsl_hs_wakeup_data[] __initconst = { imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 3, HS3), }; #endif /* ifdef CONFIG_SOC_IMX6Q */ +#ifdef CONFIG_SOC_MVFA5 +const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst = { + { + .id = 0, + .irq_phy = MVF_INT_USBOTG0, + .irq_core = MVF_INT_USBOTG0, + }, + { + .id = 1, + .irq_phy = MVF_INT_USB2, + .irq_core = MVF_INT_USB2, + } +}; + +#endif struct platform_device *__init imx_add_fsl_usb2_wakeup( const struct imx_fsl_usb2_wakeup_data *data, diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c index 0aa3d590d1d2..96cede81d319 100755 --- a/arch/arm/plat-mxc/usb_common.c +++ b/arch/arm/plat-mxc/usb_common.c @@ -1049,6 +1049,9 @@ EXPORT_SYMBOL(usb_debounce_id_vbus); int usb_event_is_otg_wakeup(struct fsl_usb2_platform_data *pdata) { +#ifdef CONFIG_ARCH_MVF + return false; +#endif return (USBCTRL & UCTRL_OWIR) ? true : false; } EXPORT_SYMBOL(usb_event_is_otg_wakeup); diff --git a/arch/arm/plat-mxc/usb_wakeup.c b/arch/arm/plat-mxc/usb_wakeup.c index 4704eae91a51..7187eff67426 100755 --- a/arch/arm/plat-mxc/usb_wakeup.c +++ b/arch/arm/plat-mxc/usb_wakeup.c @@ -36,7 +36,8 @@ struct wakeup_ctrl { struct task_struct *thread; struct completion event; }; -static struct wakeup_ctrl *g_ctrl; +static struct wakeup_ctrl *g_ctrl[2]; +static unsigned int g_ctrls; extern int usb_event_is_otg_wakeup(struct fsl_usb2_platform_data *pdata); extern void usb_debounce_id_vbus(void); @@ -166,7 +167,7 @@ static int wakeup_dev_probe(struct platform_device *pdev) int status; unsigned long interrupt_flag; - printk(KERN_INFO "IMX usb wakeup probe\n"); + printk(KERN_INFO "IMX usb wakeup probe. id=%d\n", pdev->id); if (!pdev || !pdev->dev.platform_data) return -ENODEV; @@ -192,11 +193,12 @@ static int wakeup_dev_probe(struct platform_device *pdev) if (status) goto error1; - ctrl->thread = kthread_run(wakeup_event_thread, (void *)ctrl, "usb_wakeup thread"); + ctrl->thread = kthread_run(wakeup_event_thread, (void *)ctrl, + "usb_wakeup:%d", pdev->id); status = IS_ERR(ctrl->thread) ? -1 : 0; if (status) goto error2; - g_ctrl = ctrl; + g_ctrl[g_ctrls++] = ctrl; printk(KERN_DEBUG "the wakeup pdata is 0x%p\n", pdata); return 0; @@ -209,12 +211,17 @@ error1: static int wakeup_dev_exit(struct platform_device *pdev) { - if (g_ctrl->thread) { - complete(&g_ctrl->event); - kthread_stop(g_ctrl->thread); + int i; + for (i = 0; i < g_ctrls; i++) { + if (g_ctrl[i]->thread) { + complete(&g_ctrl[i]->event); + kthread_stop(g_ctrl[i]->thread); + } + free_irq(g_ctrl[i]->wakeup_irq, (void *)g_ctrl[i]); + kfree(g_ctrl[i]); + g_ctrl[i] = NULL; + g_ctrls = 0; } - free_irq(g_ctrl->wakeup_irq, (void *)g_ctrl); - kfree(g_ctrl); return 0; } static struct platform_driver wakeup_d = { diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index 5a1aab94b405..c7c99cd9f3cb 100755 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -3356,9 +3356,15 @@ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state) (udc_controller->usb_state > USB_STATE_POWERED) && (udc_controller->usb_state < USB_STATE_SUSPENDED)) { return -EBUSY;/* keep the clk on */ - } else + } else { + if (udc_controller->pdata->wake_up_enable) + udc_controller->pdata->wake_up_enable( + udc_controller->pdata, true); ret = udc_suspend(udc_controller); - dr_clk_gate(false); + } + + if (udc_controller->stopped) + dr_clk_gate(false); printk(KERN_DEBUG "USB Gadget suspend ends\n"); return ret; @@ -3408,6 +3414,8 @@ static int fsl_udc_resume(struct platform_device *pdev) /* prevent the quirk interrupts from resuming */ disable_irq_nosync(udc_controller->irq); + if (pdata->wake_up_enable) + pdata->wake_up_enable(pdata, false); /* * If the controller was stopped at suspend time, then * don't resume it now. diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c index 81ab1cffe374..0f5335d6381e 100755 --- a/drivers/usb/host/ehci-arc.c +++ b/drivers/usb/host/ehci-arc.c @@ -670,28 +670,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; printk(KERN_DEBUG "USB Host suspend begins\n"); -#ifdef CONFIG_ARCH_MVF - if (pdata->suspended) { - pr_debug("%s: already suspended, leaving early\n", __func__); - pdata->already_suspended = 1; - return 0; - } - - pr_debug("%s: suspending...\n", __func__); - - hcd->state = HC_STATE_SUSPENDED; - pdev->dev.power.power_state = PMSG_SUSPEND; - - /* ignore non-host interrupts */ - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* stop the controller */ - tmp = ehci_readl(ehci, &ehci->regs->command); - tmp &= ~CMD_RUN; - ehci_writel(ehci, tmp, &ehci->regs->command); - pdata->suspended = 1; -#else /* Only handles OTG mode switch event, system suspend event will be done in bus suspend */ if (pdata->pmflags == 0) { printk(KERN_DEBUG "%s, pm event\n", __func__); @@ -706,7 +685,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, printk(KERN_DEBUG "host suspend ends\n"); return 0; } - +#ifndef CONFIG_ARCH_MVF /* only the otg host can go here */ /* wait for all usb device on the hcd dettached */ usb_lock_device(roothub); @@ -740,7 +719,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, fsl_usb_clk_gate(hcd->self.controller->platform_data, true); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); } -#endif + port_status = ehci_readl(ehci, &ehci->regs->port_status[0]); /* save EHCI registers */ pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); @@ -772,6 +751,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, } pdata->pmflags = 0; printk(KERN_DEBUG "host suspend ends\n"); +#endif return 0; } @@ -786,27 +766,13 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) struct fsl_usb2_wakeup_platform_data *wake_up_pdata = pdata->wakeup_pdata; /* Only handles OTG mode switch event */ printk(KERN_DEBUG "ehci fsl drv resume begins: %s\n", pdata->name); -#ifdef CONFIG_ARCH_MVF - if (pdata->already_suspended) { - pr_debug("already suspended, leaving early\n"); - pdata->already_suspended = 0; - return 0; - } - if (!pdata->suspended) { - pr_debug("not suspended, leaving early\n"); - return 0; - } - - pdata->suspended = 0; - - pr_debug("%s resuming...\n", __func__); -#else if (pdata->pmflags == 0) { printk(KERN_DEBUG "%s,pm event, wait for wakeup irq if needed\n", __func__); wait_event_interruptible(wake_up_pdata->wq, !wake_up_pdata->usb_wakeup_is_pending); return 0; } +#ifndef CONFIG_ARCH_MVF if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); fsl_usb_clk_gate(hcd->self.controller->platform_data, true); @@ -815,7 +781,7 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) fsl_usb_lowpower_mode(pdata, false); spin_unlock_irqrestore(&ehci->lock, flags); } -#endif + spin_lock_irqsave(&ehci->lock, flags); /* set host mode */ fsl_platform_set_host_mode(hcd); @@ -837,19 +803,16 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) ehci_writel(ehci, tmp, &ehci->regs->command); spin_unlock_irqrestore(&ehci->lock, flags); -#ifdef CONFIG_ARCH_MVF - usb_hcd_resume_root_hub(hcd); -#else if ((hcd->state & HC_STATE_SUSPENDED)) { printk(KERN_DEBUG "will resume roothub and its children\n"); usb_lock_device(roothub); usb_resume(&roothub->dev, PMSG_USER_RESUME); usb_unlock_device(roothub); } -#endif + pdata->pmflags = 0; printk(KERN_DEBUG "ehci fsl drv resume ends: %s\n", pdata->name); - +#endif return 0; } #endif -- cgit v1.2.3 From 74e4dd3713a06947ac42aed73c822d7641735239 Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Mon, 10 Dec 2012 13:55:03 +0800 Subject: ENGR00216081-2:Errata workaround for usb suspend and resume Toggle PHYPWD.PWD after set PORTSC.SUSP with 8ms to trigger the LS_SE0/LS_EOP append flag after resume within UTM block. Signed-off-by: Jingchang Lu --- drivers/usb/host/ehci-hub.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index d6a80d9731a2..544ed44ef28c 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -29,8 +29,9 @@ /*-------------------------------------------------------------------------*/ #include -#ifdef CONFIG_ARCH_MX6 +#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MVF) #define MX6_USB_HOST_HACK +#define MVF_USB_HOST_HACK #include #endif #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) @@ -1081,6 +1082,14 @@ static int ehci_hub_control ( pdata = hcd->self.controller->platform_data; if (pdata->platform_suspend) pdata->platform_suspend(pdata); +#ifdef MVF_USB_HOST_HACK + /* workaround: + * Toggle HW_USBPHY_PWD to flag controller + * generating LS-SE0/LS-EOP after resume + */ + if (pdata->platform_resume) + pdata->platform_resume(pdata); +#endif } #endif if (hostpc_reg) { -- cgit v1.2.3 From 3664f4e8ca3d18e87bc695f4b6838be61382dc17 Mon Sep 17 00:00:00 2001 From: Wang Xiaojun Date: Mon, 10 Dec 2012 18:35:41 +0800 Subject: ENGR00181365-1: ADC: Add platform support for ADC driver Add platform support for ADC driver. Signed-off-by: Wang Xiaojun --- arch/arm/mach-mvf/board-twr-vf700.c | 7 ++++ arch/arm/mach-mvf/clock.c | 13 +++++++ arch/arm/mach-mvf/devices-mvf.h | 4 ++ arch/arm/plat-mxc/devices/Kconfig | 4 ++ arch/arm/plat-mxc/devices/Makefile | 1 + arch/arm/plat-mxc/devices/platform-mvf-adc.c | 50 +++++++++++++++++++++++++ arch/arm/plat-mxc/include/mach/devices-common.h | 9 +++++ arch/arm/plat-mxc/include/mach/mvf.h | 2 +- 8 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 arch/arm/plat-mxc/devices/platform-mvf-adc.c diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index a267df7a303f..d64622b2db19 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -443,6 +443,11 @@ static void __init mvf_twr_init_usb(void) #endif } +static void __init mvf_init_adc(void) +{ + mvf_add_adc(0); +} + /*! * Board specific initialization. */ @@ -462,6 +467,8 @@ static void __init mvf_board_init(void) mvf_add_snvs_rtc(); + mvf_init_adc(); + mvf_add_pm_imx(0, &mvf_vf600_pm_data); mvf_add_sdhci_esdhc_imx(1, &mvfa5_sd1_data); diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index 140f0edee565..16d86fb73368 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1626,6 +1626,18 @@ static struct clk pit_clk = { .get_rate = _clk_uart_get_rate, }; +static struct clk adc_clk[] = { + { + __INIT_CLK_DEBUG(adc_clk) + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + static struct clk i2c_clk[] = { { __INIT_CLK_DEBUG(i2c_clk_0) @@ -1886,6 +1898,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("pit", NULL, pit_clk), _REGISTER_CLOCK("fec.0", NULL, enet_clk[0]), _REGISTER_CLOCK("fec.1", NULL, enet_clk[1]), + _REGISTER_CLOCK("mvf-adc.0", NULL, adc_clk[0]), _REGISTER_CLOCK("switch.0", NULL, enet_clk[0]), _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk), _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc1_clk), diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index b8bea993bdee..6bc61871fd5e 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -144,6 +144,10 @@ extern const struct imx_imx2_wdt_data mvf_imx2_wdt_data[] __initconst; #define mvf_add_imx2_wdt(id, pdata) \ imx_add_imx2_wdt(&mvf_imx2_wdt_data[id]) +extern const struct mvf_adc_data mvfa5_adc_data[] __initconst; +#define mvf_add_adc(id) \ + mvf_add_adcdev(&mvfa5_adc_data[id]) + extern const struct imx_imx2_wdt_data fsl_imx2_wdt_data[] __initconst; #define mvf_add_wdt(id) \ imx_add_imx2_wdt(&fsl_imx2_wdt_data[id]) diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig index de80caba49c3..22e160789d06 100755 --- a/arch/arm/plat-mxc/devices/Kconfig +++ b/arch/arm/plat-mxc/devices/Kconfig @@ -28,6 +28,10 @@ config IMX_HAVE_PLATFORM_IMX21_HCD config IMX_HAVE_PLATFORM_IMX2_WDT bool +config IMX_HAVE_PLATFORM_MVF_ADC + bool + default y if ARCH_MVF + config IMX_HAVE_PLATFORM_IMXDI_RTC bool diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile index 63be99251f08..45d9869bd730 100755 --- a/arch/arm/plat-mxc/devices/Makefile +++ b/arch/arm/plat-mxc/devices/Makefile @@ -62,5 +62,6 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_ASRC) += platform-imx-asrc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_DSI) += platform-imx-mipi_dsi.o obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_CSI2) += platform-imx-mipi_csi2.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_SPI) += platform-mvf-spi.o +obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_ADC) += platform-mvf-adc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_DCU) += platform-mvf-dcu.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_SAI) += platform-mvf-sai.o diff --git a/arch/arm/plat-mxc/devices/platform-mvf-adc.c b/arch/arm/plat-mxc/devices/platform-mvf-adc.c new file mode 100644 index 000000000000..38add8b5fd4f --- /dev/null +++ b/arch/arm/plat-mxc/devices/platform-mvf-adc.c @@ -0,0 +1,50 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include + +#define mvf_adc_data_entry_single(soc, _id, _size) \ + { \ + .id = _id, \ + .iobase = soc ## _ADC ## _id ## _BASE_ADDR, \ + .iosize = _size, \ + .irq = soc ## _INT_ADC ## _id, \ + } +#define mvf_adc_data_entry(soc, _id, _size) \ + [_id] = mvf_adc_data_entry_single(soc, _id, _size) + +#ifdef CONFIG_SOC_MVFA5 +const struct mvf_adc_data mvfa5_adc_data[] __initconst = { + mvf_adc_data_entry(MVF, 0, SZ_4K), +}; +#endif + +struct platform_device *__init mvf_add_adcdev( + const struct mvf_adc_data *data) +{ + struct resource res[] = { + { + .start = data->iobase, + .end = data->iobase + data->iosize - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = data->irq, + .end = data->irq, + .flags = IORESOURCE_IRQ, + }, + }; + + return imx_add_platform_device("mvf-adc", data->id, res, + ARRAY_SIZE(res), NULL, 0); +} diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index a8a8034c1010..3cdcceaea09f 100755 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -89,6 +89,15 @@ struct imx_imx2_wdt_data { struct platform_device *__init imx_add_imx2_wdt( const struct imx_imx2_wdt_data *data); +struct mvf_adc_data { + int id; + resource_size_t iobase; + resource_size_t iosize; + resource_size_t irq; +}; +struct platform_device *__init mvf_add_adcdev( + const struct mvf_adc_data *data); + struct imx_imxdi_rtc_data { resource_size_t iobase; resource_size_t irq; diff --git a/arch/arm/plat-mxc/include/mach/mvf.h b/arch/arm/plat-mxc/include/mach/mvf.h index 1e3f74f98857..6512c4e2bac6 100644 --- a/arch/arm/plat-mxc/include/mach/mvf.h +++ b/arch/arm/plat-mxc/include/mach/mvf.h @@ -145,7 +145,7 @@ #define MVF_PIT_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00037000) #define MVF_FTM0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00038000) #define MVF_FTM1_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00039000) -#define MVF_ADC_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0003B000) +#define MVF_ADC0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0003B000) #define MVF_TCON0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0003D000) #define MVF_WDOG1_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0003E000) #define MVF_LPTMR_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00040000) -- cgit v1.2.3 From b358081d3db11e4f4582bea7658b93a7eef539d3 Mon Sep 17 00:00:00 2001 From: Wang Xiaojun Date: Mon, 10 Dec 2012 18:05:18 +0800 Subject: ENGR00181365-2: ADC: Add driver support for ADC Vybrid Add driver support for ADC Vybrid. Signed-off-by: Wang Xiaojun --- drivers/misc/Kconfig | 10 + drivers/misc/Makefile | 1 + drivers/misc/mvf_adc.c | 771 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mvf_adc.h | 204 +++++++++++++ 4 files changed, 986 insertions(+) create mode 100644 drivers/misc/mvf_adc.c create mode 100644 include/linux/mvf_adc.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b8bc353fa6aa..8ffd002f0649 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -490,6 +490,16 @@ config PCH_PHUB To compile this driver as a module, choose M here: the module will be called pch_phub. +config MVF_ADC + tristate "Vybrid board adc Driver" + depends on ARCH_MVF + help + If you say yes here you get support for the Vybrid board + analog-to-digital converter. + This driver is for Vybrid board. + To compile this driver as a module, choose M here: the module will + be called mvf_adc. + config MXS_PERFMON tristate "i.MX Performance Monitor" depends on ARCH_MX50 || ARCH_MX6 diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 88a160b2eb1d..1531d0f5b594 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -47,3 +47,4 @@ obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o obj-y += lis3lv02d/ obj-y += carma/ obj-$(CONFIG_MXS_PERFMON) += mxs-perfmon.o +obj-$(CONFIG_MVF_ADC) += mvf_adc.o diff --git a/drivers/misc/mvf_adc.c b/drivers/misc/mvf_adc.c new file mode 100644 index 000000000000..63e0f95804f9 --- /dev/null +++ b/drivers/misc/mvf_adc.c @@ -0,0 +1,771 @@ +/* Copyright 2012 Freescale Semiconductor, Inc. + * + * Freescale Faraday Quad ADC driver + * + * 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. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "mvf-adc" +#define DRV_VERSION "1.0" + +/* + * wait_event_interruptible(wait_queue_head_t suspendq, int suspend_flag) + */ + +struct adc_client { + struct platform_device *pdev; + struct list_head list; + wait_queue_head_t *wait; + + unsigned int result; + unsigned int channel; +}; + +static LIST_HEAD(client_list);/* Initialization client list head */ +static DECLARE_COMPLETION(adc_tsi); + +struct adc_device { + struct platform_device *pdev; + struct platform_device *owner; + struct clk *clk; + struct adc_client *cur; + void __iomem *regs; + spinlock_t lock; + + int irq; +}; + +struct data { + unsigned int res_value; + bool flag; +}; + +struct data data_array[7]; + +static struct adc_device *adc_dev; + +#define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg) + +static int res_proc(void); +struct adc_client *adc_register(struct platform_device *pdev, + unsigned char channel); + +/* select channel and enable conversion */ +static inline void adc_convert(struct adc_device *adc, + struct adc_client *client) +{ + + unsigned con = readl(adc->regs + ADC_HC0); + con = ADCHC0(client->channel); + con |= IRQ_EN; + writel(con, adc->regs + ADC_HC0); +} + +/* find next conversion client */ +static void adc_try(struct adc_device *adc) +{ + struct adc_client *next = adc->cur; + if (!list_empty(&client_list)) { + next = list_entry(client_list.next, + struct adc_client, list); + list_del(client_list.next); + + adc->cur = next; + adc_convert(adc, adc->cur); + } +} + +/* channel and sample */ +int adc_start(struct adc_client *client, + unsigned int channel, unsigned int nr_samples) +{ + struct adc_device *adc = adc_dev; + unsigned long flags; + + if (!adc) { + printk(KERN_ERR "%s: failed to find adc\n", __func__); + return -EINVAL; + } + + + spin_lock_irqsave(&adc->lock, flags); + + client->channel = channel; + + if (!adc->cur) + adc_try(adc_dev); + + spin_unlock_irqrestore(&adc->lock, flags); + + return 0; +} + +int adc_initiate(struct adc_device *adc_dev) +{ + unsigned long reg, tmp, pin; + struct adc_device *adc = adc_dev; + + + /* PCTL: pin control 5 for Sliding rheostat */ + pin = readl(adc->regs+ADC_PCTL); + pin &= ~CLEPCTL23; + pin &= SETPCTL5; + writel(pin, adc->regs+ADC_PCTL); + + /* CFG: Feature set */ + reg = readl(adc->regs+ADC_CFG); + reg &= ~CLECFG16; + reg |= SETCFG; + writel(reg, adc->regs+ADC_CFG); + + /* GC: software trigger */ + tmp = readl(adc->regs+ADC_GC); + tmp = 0; + writel(tmp, adc->regs+ADC_GC); + + return 0; +} + +static int adc_set(struct adc_device *adc_dev, struct adc_feature *adc_fea) +{ + struct adc_device *adc = adc_dev; + int con, res; + con = readl(adc->regs+ADC_CFG); + res = readl(adc->regs+ADC_GC); + + /* clock select and clock devide */ + switch (adc_fea->clk_sel) { + case ADCIOC_BUSCLK_SET: + /* clear 1-0,6-5 */ + con &= ~CLEAR_CLK_BIT; + switch (adc_fea->clk_div_num) { + case 1: + break; + case 2: + con |= CLK_DIV2; + break; + case 4: + con |= CLK_DIV4; + break; + case 8: + con |= CLK_DIV8; + break; + case 16: + con |= BUSCLK2_SEL | CLK_DIV8; + break; + default: + return -EINVAL; + } + writel(con, adc->regs+ADC_CFG); + + break; + + case ADCIOC_ALTCLK_SET: + /* clear 1-0,6-5 */ + con &= ~CLEAR_CLK_BIT; + + con |= ALTCLK_SEL; + switch (adc_fea->clk_div_num) { + case 1: + break; + case 2: + con |= CLK_DIV2; + break; + case 4: + con |= CLK_DIV4; + break; + case 8: + con |= CLK_DIV8; + break; + default: + return -EINVAL; + } + writel(con, adc->regs+ADC_CFG); + + break; + + case ADCIOC_ADACK_SET: + /* clear 1-0,6-5 */ + con &= ~CLEAR_CLK_BIT; + + con |= ADACK_SEL; + switch (adc_fea->clk_div_num) { + case 1: + break; + case 2: + con |= CLK_DIV2; + break; + case 4: + con |= CLK_DIV4; + break; + case 8: + con |= CLK_DIV8; + break; + default: + return -EINVAL; + } + writel(con, adc->regs+ADC_CFG); + break; + + default: + pr_debug("adc_ioctl: unsupported ioctl command 0x%x\n", + adc_fea->clk_sel); + return -EINVAL; + } + + /* resolution mode,clear 3-2 */ + con &= ~CLEAR_MODE_BIT; + switch (adc_fea->res_mode) { + case 8: + break; + case 10: + con |= BIT10; + break; + case 12: + con |= BIT12; + break; + default: + pr_debug("adc_ioctl: unsupported ioctl resolution mode 0x%x\n", + adc_fea->res_mode); + return -EINVAL; + } + writel(con, adc->regs+ADC_CFG); + + /* Defines the sample time duration */ + /* clear 4, 9-8 */ + con &= ~CLEAR_LSTC_BIT; + switch (adc_fea->sam_time) { + case 2: + break; + case 4: + con |= ADSTS_SHORT; + break; + case 6: + con |= ADSTS_NORMAL; + break; + case 8: + con |= ADSTS_LONG; + break; + case 12: + con |= ADLSMP_LONG; + break; + case 16: + con |= ADLSMP_LONG | ADSTS_SHORT; + break; + case 20: + con |= ADLSMP_LONG | ADSTS_NORMAL; + break; + case 24: + con |= ADLSMP_LONG | ADSTS_LONG; + break; + default: + pr_debug("adc_ioctl: unsupported ioctl sample" + "time duration 0x%x\n", + adc_fea->sam_time); + return -EINVAL; + } + writel(con, adc->regs+ADC_CFG); + + /* low power configuration */ + /* */ + switch (adc_fea->lp_con) { + case ADCIOC_LPOFF_SET: + con &= ~CLEAR_ADLPC_BIT; + writel(con, adc->regs+ADC_CFG); + break; + + case ADCIOC_LPON_SET: + con &= ~CLEAR_ADLPC_BIT; + con |= ADLPC_EN; + writel(con, adc->regs+ADC_CFG); + break; + default: + return -EINVAL; + + } + /* high speed operation */ + switch (adc_fea->hs_oper) { + case ADCIOC_HSON_SET: + con &= ~CLEAR_ADHSC_BIT; + con |= ADHSC_EN; + writel(con, adc->regs+ADC_CFG); + break; + + case ADCIOC_HSOFF_SET: + con &= ~CLEAR_ADHSC_BIT; + writel(con, adc->regs+ADC_CFG); + break; + default: + return -EINVAL; + } + + /* voltage reference*/ + switch (adc_fea->vol_ref) { + case ADCIOC_VR_VREF_SET: + con &= ~CLEAR_REFSEL_BIT; + writel(con, adc->regs+ADC_CFG); + break; + + case ADCIOC_VR_VALT_SET: + con &= ~CLEAR_REFSEL_BIT; + con |= REFSEL_VALT; + writel(con, adc->regs+ADC_CFG); + break; + + case ADCIOC_VR_VBG_SET: + con &= ~CLEAR_REFSEL_BIT; + con |= REFSEL_VBG; + writel(con, adc->regs+ADC_CFG); + break; + default: + return -EINVAL; + } + + /* trigger select */ + switch (adc_fea->tri_sel) { + case ADCIOC_SOFTTS_SET: + con &= ~CLEAR_ADTRG_BIT; + writel(con, adc->regs+ADC_CFG); + break; + + case ADCIOC_HARDTS_SET: + con &= ~CLEAR_ADTRG_BIT; + con |= ADTRG_HARD; + writel(con, adc->regs+ADC_CFG); + break; + default: + return -EINVAL; + } + + /* hardware average select */ + switch (adc_fea->ha_sel) { + case ADCIOC_HA_DIS: + res &= ~CLEAR_AVGE_BIT; + writel(con, adc->regs+ADC_GC); + break; + + case ADCIOC_HA_SET: + con &= ~CLEAR_AVGS_BIT; + switch (adc_fea->ha_sam) { + case 4: + break; + case 8: + con |= AVGS_8; + break; + case 16: + con |= AVGS_16; + break; + case 32: + con |= AVGS_32; + break; + default: + return -EINVAL; + } + res &= ~CLEAR_AVGE_BIT; + res |= AVGEN; + writel(con, adc->regs+ADC_CFG); + writel(res, adc->regs+ADC_GC); + + break; + default: + return -EINVAL; + } + + /* data overwrite enable */ + switch (adc_fea->do_ena) { + case ADCIOC_DOEON_SET: + con &= ~CLEAR_OVWREN_BIT; + writel(con, adc->regs+ADC_CFG); + break; + + case ADCIOC_DOEOFF_SET: + con |= OVWREN; + writel(con, adc->regs+ADC_CFG); + break; + default: + return -EINVAL; + } + + /* Asynchronous clock output enable */ + switch (adc_fea->ac_ena) { + case ADCIOC_ADACKENON_SET: + res &= ~CLEAR_ADACKEN_BIT; + writel(res, adc->regs+ADC_GC); + break; + + case ADCIOC_ADACKENOFF_SET: + res &= ~CLEAR_ADACKEN_BIT; + res |= ADACKEN; + writel(res, adc->regs+ADC_GC); + break; + default: + return -EINVAL; + } + + /* dma enable */ + switch (adc_fea->dma_ena) { + case ADCIDC_DMAON_SET: + res &= ~CLEAR_DMAEN_BIT; + writel(res, adc->regs+ADC_GC); + break; + + case ADCIDC_DMAOFF_SET: + res &= ~CLEAR_DMAEN_BIT; + res |= DMAEN; + writel(res, adc->regs+ADC_GC); + break; + default: + return -EINVAL; + } + + /* continue function enable */ + switch (adc_fea->cc_ena) { + case ADCIOC_CCEOFF_SET: + res &= ~CLEAR_ADCO_BIT; + writel(res, adc->regs+ADC_GC); + break; + + case ADCIOC_CCEON_SET: + res &= ~CLEAR_ADCO_BIT; + res |= ADCON; + writel(res, adc->regs+ADC_GC); + break; + default: + return -EINVAL; + } + + /* compare function enable */ + switch (adc_fea->compare_func_ena) { + case ADCIOC_ACFEON_SET: + res &= ~CLEAR_ACFE_BIT; + res |= ACFE; + writel(res, adc->regs+ADC_GC); + break; + + case ADCIOC_ACFEOFF_SET: + res &= ~CLEAR_ACFE_BIT; + writel(res, adc->regs+ADC_GC); + break; + default: + return -EINVAL; + } + + /* greater than enable */ + switch (adc_fea->greater_ena) { + case ADCIOC_ACFGTON_SET: + res &= ~CLEAR_ACFGT_BIT; + res |= ACFGT; + writel(res, adc->regs+ADC_GC); + break; + + case ADCIOC_ACFGTOFF_SET: + res &= ~CLEAR_ACFGT_BIT; + writel(res, adc->regs+ADC_GC); + break; + default: + return -EINVAL; + } + + /* range enable */ + switch (adc_fea->range_ena) { + case ADCIOC_ACRENON_SET: + res &= ~CLEAR_ACREN_BIT; + res |= ACREN; + writel(res, adc->regs+ADC_GC); + break; + + case ADCIOC_ACRENOFF_SET: + res &= ~CLEAR_ACREN_BIT; + writel(res, adc->regs+ADC_GC); + break; + + default: return -ENOTTY; + } + return 0; +} + +static long adc_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + struct adc_feature feature; + int channel; + + if (_IOC_TYPE(cmd) != 'p') + return -ENOTTY; + + if (copy_from_user(&feature, (struct adc_feature *)argp, + sizeof(feature))) { + return -EFAULT; + } + + switch (cmd) { + case ADC_INIT: + adc_initiate(adc_dev); + break; + + case ADC_CONFIGURATION: + + adc_set(adc_dev, &feature); + break; + + case ADC_REG_CLIENT: + channel = feature.channel; + adc_register(adc_dev->pdev, channel); + break; + + case ADC_CONVERT: + INIT_COMPLETION(adc_tsi); + adc_try(adc_dev); + wait_for_completion_interruptible(&adc_tsi); + if (data_array[feature.channel].flag) { + feature.result0 = data_array[feature.channel].res_value; + data_array[feature.channel].flag = 0; + } + if (copy_to_user((struct adc_feature *)argp, &feature, + sizeof(feature))) + return -EFAULT; + + kfree(adc_dev->cur); + break; + + default: + pr_debug("adc_ioctl: unsupported ioctl command 0x%x\n", cmd); + return -EINVAL; + } + return 0; +} + +/* client register */ +struct adc_client *adc_register(struct platform_device *pdev, + unsigned char channel) +{ + struct adc_client *client = kzalloc(sizeof(struct adc_client), + GFP_KERNEL); + + WARN_ON(!pdev); + + if (!pdev) + return ERR_PTR(-EINVAL); + + + if (!client) { + dev_err(&pdev->dev, "no memory for adc client\n"); + return ERR_PTR(-ENOMEM); + } + + client->pdev = pdev; + client->channel = channel; + list_add(&client->list, &client_list); + + return client; +} + + +/*result process */ +static int res_proc(void) +{ + int con, res; + struct adc_device *adc = adc_dev; + con = readl(adc->regs + ADC_CFG); + + if ((con & (1 << 2)) == 0) { + if ((con & (1 << 3)) == 1) + res = (0xFFF & readl(adc->regs + ADC_R0)); + else + res = (0xFF & readl(adc->regs + ADC_R0)); + } else + res = (0x3FF & readl(adc->regs + ADC_R0)); + + return readl(adc->regs + ADC_R0); + return res; +} + +static irqreturn_t adc_irq(int irq, void *pw) +{ + int coco; + struct adc_device *adc = pw; + struct adc_client *client = adc->cur; + + if (!client) { + dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__); + goto exit; + } + + coco = readl(adc->regs + ADC_HS); + if (coco & 1) { + data_array[client->channel].res_value = res_proc(); + data_array[client->channel].flag = 1; + complete(&adc_tsi); + } + +exit: + return IRQ_NONE; +} + +static const struct file_operations adc_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = adc_ioctl, + .open = NULL, + .read = NULL, +}; + +/* probe */ +static int __devinit adc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct adc_device *adc; + struct resource *regs; + struct cdev *adc_cdev; + static struct class *adc_class; + int ret; + dev_t id; + + + adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL); + if (adc == NULL) { + dev_err(dev, "failed to allocate adc_device\n"); + return -ENOMEM; + } + adc->pdev = pdev; + + /* Initialize spin_lock */ + spin_lock_init(&adc->lock); + + adc->irq = platform_get_irq(pdev, 0); + if (adc->irq <= 0) { + dev_err(dev, "failed to get adc irq\n"); + ret = -EINVAL; + goto err_alloc; + } + + ret = request_irq(adc->irq, adc_irq, 0, dev_name(dev), adc); + if (ret < 0) { + dev_err(dev, "failed to attach adc irq\n"); + goto err_alloc; + } + + adc->clk = clk_get(dev, NULL); + if (IS_ERR(adc->clk)) { + dev_err(dev, "failed to get adc clock\n"); + ret = PTR_ERR(adc->clk); + goto err_irq; + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(dev, "failed to find registers\n"); + ret = -ENXIO; + goto err_clk; + } + + adc->regs = ioremap(regs->start, resource_size(regs)); + if (!adc->regs) { + dev_err(dev, "failed to map registers\n"); + ret = -ENXIO; + goto err_clk; + } + + /* Obtain device numbers and register char device */ + ret = alloc_chrdev_region(&id, 0, 1, "mvf-adc"); + if (ret < 0) + return ret; + + adc_cdev = cdev_alloc(); + adc_cdev->ops = &adc_fops; + adc_cdev->owner = THIS_MODULE; + ret = cdev_add(adc_cdev, id, 1); + if (ret < 0) + return ret; + + adc_class = class_create(THIS_MODULE, "mvf-adc.0"); + if (IS_ERR(adc_class)) + return -1; + + device_create(adc_class, NULL, id, NULL, "mvf-adc.0"); + /* clk enable */ + clk_enable(adc->clk); + /* Associated structures */ + platform_set_drvdata(pdev, adc); + + adc_dev = adc; + + dev_info(dev, "attached adc driver\n"); + + return 0; + +err_clk: + clk_put(adc->clk); + +err_irq: + free_irq(adc->irq, adc); + +err_alloc: + kfree(adc); + + return ret; +} + +static int __devexit adc_remove(struct platform_device *pdev) +{ + struct adc_device *adc = platform_get_drvdata(pdev); + + iounmap(adc->regs); + free_irq(adc->irq, adc); + clk_disable(adc->clk); + clk_put(adc->clk); + kfree(adc); + + return 0; +} + +static struct platform_driver adc_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = adc_probe, + .remove = __devexit_p(adc_remove), +}; + +static int __init adc_init(void) +{ + int ret; + ret = platform_driver_register(&adc_driver); + if (ret) + printk(KERN_ERR "%s: failed to add adc driver\n", __func__); + + return ret; +} + +static void __exit adc_exit(void) +{ + platform_driver_unregister(&adc_driver); +} +module_init(adc_init); +module_exit(adc_exit); + +MODULE_AUTHOR("Xiaojun Wang"); +MODULE_DESCRIPTION("Vybrid ADC driver"); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION(DRV_VERSION); diff --git a/include/linux/mvf_adc.h b/include/linux/mvf_adc.h new file mode 100644 index 000000000000..26562531afe0 --- /dev/null +++ b/include/linux/mvf_adc.h @@ -0,0 +1,204 @@ +/* Copyright 2012 Freescale Semiconductor, Inc. + * + * Freescale Faraday Quad ADC driver + * + * 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. +*/ + +#ifndef MVF_ADC_H +#define MVF_ADC_H + +#define ADC_CFG 0x14 /* Configuration Register */ + +/* Input Clock Select 1-0, Divide ratio 6-5 */ +#define CLEAR_CLK_BIT 0x63 +#define BUSCLK_SEL 0x00 +#define BUSCLK2_SEL 0x01 +#define ALTCLK_SEL 0x02 +#define ADACK_SEL 0x03 +#define CLK_DIV2 0x20 +#define CLK_DIV4 0x40 +#define CLK_DIV8 0x60 +/* Conversion RES Mode Selection 3-2 */ +#define CLEAR_MODE_BIT 0xC +#define BIT8 0x00 +#define BIT10 0x01 +#define BIT12 0x10 +/* Low-Power Configuration 7 */ +#define CLEAR_ADLPC_BIT 0x80 +#define ADLPC_EN 0x80 +/* Long/Short Sample Time Configuration 4,9-8 */ +#define CLEAR_LSTC_BIT 0x310 +#define ADLSMP_LONG 0x10 +#define ADSTS_SHORT 0x100 +#define ADSTS_NORMAL 0x200 +#define ADSTS_LONG 0x300 +/* High speed operation 10 */ +#define CLEAR_ADHSC_BIT 0x400 +#define ADHSC_EN 0x400 +/* Voltage Reference Selection 12-11 */ +#define CLEAR_REFSEL_BIT 0x1800 +#define REFSEL_VALT 0x100 +#define REFSEL_VBG 0x1000 +/* Conversion Trigger Select 13 */ +#define CLEAR_ADTRG_BIT 0x2000 +#define ADTRG_HARD 0x2000 +/* Hardware Average select 15-14 */ +#define CLEAR_AVGS_BIT 0xC000 +#define AVGS_8 0x4000 +#define AVGS_16 0x8000 +#define AVGS_32 0xC000 +/* Data Overwrite Enable 16 */ +#define CLEAR_OVWREN_BIT 0x10000 +#define OVWREN 0x10000 + +#define ADC_GC 0x18 /* General control register */ + +/* Asynchronous clock output 0 */ +#define CLEAR_ADACKEN_BIT 0x1 +#define ADACKEN 0x1 +/* DMA Enable 1 */ +#define CLEAR_DMAEN_BIT 0x2 +#define DMAEN 0x2 +/* Compare Function Rang Enable 2*/ +#define CLEAR_ACREN_BIT 0x4 +#define ACREN 0x4 +/* Compare Function Greater Than Enable 3 */ +#define CLEAR_ACFGT_BIT 0x8 +#define ACFGT 0x8 +/* Enable compare function 4 */ +#define CLEAR_ACFE_BIT 0x10 +#define ACFE 0x10 +/* Hardware Average Enable 5 */ +#define CLEAR_AVGE_BIT 0x20 +#define AVGEN 0x20 +/* Continue Conversion Enable 6 */ +#define CLEAR_ADCO_BIT 0x40 +#define ADCON 0x40 + + +#define ADC_HC0 0x00/* Control register for hardware triggers 0 */ +#define ADC_HC1 0x04/* Control register for hardware triggers 1 */ + +#define IRQ_EN 0x80 +#define ADCHC0(x) ((x)&0xF) +#define AIEN1 0x00000080 +#define COCOA 0x00000000 + +#define ADC_HS 0x08/* Status register for HW triggers */ + +#define ADC_R0 0x0c/* Data result register for HW triggers */ +#define ADC_R1 0x10/* Data result register for HW triggers */ + +#define ADC_GS 0x1c/* General status register (ADC0_GS) */ +#define ADC_CV 0x20/* Compare value register (ADC0_CV) */ +/* Offset correction value register (ADC0_OFS) */ +#define ADC_OFS 0x24 +#define ADC_CAL 0x28/* Calibration value register (ADC0_CAL) */ +#define ADC_PCTL 0x30/* Pin control register (ADC0_PCTL) */ + +/* init */ +#define CLECFG16 0x1ffff +#define SETCFG 0x10098 + +#define CLEHC0 0xff +#define SETHC0 0x85 + +#define CLEPCTL23 0xffffff +#define SETPCTL5 0x20 + +#define ADC_INIT _IO('p', 0xb1) +#define ADC_CONVERT _IO('p', 0xb2) +#define ADC_CONFIGURATION _IOWR('p', 0xb3, struct adc_feature) +#define ADC_REG_CLIENT _IOWR('p', 0xb4, struct adc_feature) + +enum clk_sel { + ADCIOC_BUSCLK_SET, + ADCIOC_ALTCLK_SET, + ADCIOC_ADACK_SET, +}; + + +#define ADCIOC_LPOFF_SET 0 +#define ADCIOC_LPON_SET 1 + +#define ADCIOC_HSON_SET 1 +#define ADCIOC_HSOFF_SET 0 + +enum vol_ref { + ADCIOC_VR_VREF_SET, + ADCIOC_VR_VALT_SET, + ADCIOC_VR_VBG_SET, +}; + +#define ADCIOC_SOFTTS_SET 0 +#define ADCIOC_HARDTS_SET 1 + +#define ADCIOC_HA_DIS 0 +#define ADCIOC_HA_SET 1 + +#define ADCIOC_DOEON_SET 1 +#define ADCIOC_DOEOFF_SET 0 + +#define ADCIOC_ADACKENON_SET 1 +#define ADCIOC_ADACKENOFF_SET 0 + +#define ADCIDC_DMAON_SET 1 +#define ADCIDC_DMAOFF_SET 0 + +#define ADCIOC_CCEOFF_SET 0 +#define ADCIOC_CCEON_SET 1 + +#define ADCIOC_ACFEON_SET 1 +#define ADCIOC_ACFEOFF_SET 0 + +#define ADCIOC_ACFGTON_SET 1 +#define ADCIOC_ACFGTOFF_SET 0 + +#define ADCIOC_ACRENON_SET 1 +#define ADCIOC_ACRENOFF_SET 0 + +enum adc_channel { + ADC0, + ADC1, + ADC2, + ADC3, + ADC4, + ADC5, + ADC6, + ADC7, + ADC8, + ADC9, + ADC10, + ADC11, + ADC12, + ADC13, + ADC14, + ADC15, +}; + +struct adc_feature { + enum adc_channel channel; + enum clk_sel clk_sel;/* clock select */ + int clk_div_num;/* clock divide number*/ + int res_mode;/* resolution sample */ + int sam_time;/* sample time */ + int lp_con;/* low power configuration */ + int hs_oper;/* high speed operation */ + enum vol_ref vol_ref;/* voltage reference */ + int tri_sel;/* trigger select */ + int ha_sel;/* hardware average select */ + int ha_sam;/* hardware average sample */ + int do_ena;/* data overwrite enable */ + int ac_ena;/* Asynchronous clock output enable */ + int dma_ena;/* DMA enable */ + int cc_ena;/* continue converdion enable */ + int compare_func_ena;/* enable compare function */ + int range_ena;/* range enable */ + int greater_ena;/* greater than enable */ + unsigned int result0, result1; +}; + +#endif -- cgit v1.2.3 From a64b342273229257877df4b89879cd207289675b Mon Sep 17 00:00:00 2001 From: Alison Wang Date: Tue, 11 Dec 2012 16:34:25 +0800 Subject: mvf: update default kernel config for Faraday Signed-off-by: Alison Wang --- arch/arm/configs/mvf600_defconfig | 66 ++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/arch/arm/configs/mvf600_defconfig b/arch/arm/configs/mvf600_defconfig index 23646435c6af..510f87d8a409 100644 --- a/arch/arm/configs/mvf600_defconfig +++ b/arch/arm/configs/mvf600_defconfig @@ -178,7 +178,7 @@ CONFIG_INLINE_WRITE_UNLOCK=y CONFIG_INLINE_WRITE_UNLOCK_IRQ=y # CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set # CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set +CONFIG_FREEZER=y # # System Type @@ -246,6 +246,7 @@ CONFIG_IMX_HAVE_PLATFORM_FLEXCAN=y CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC=y CONFIG_IMX_HAVE_PLATFORM_GPMI_NFC=y CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT=y +CONFIG_IMX_HAVE_PLATFORM_MVF_ADC=y CONFIG_IMX_HAVE_PLATFORM_IMX_SNVS_RTC=y CONFIG_IMX_HAVE_PLATFORM_IMX_I2C=y CONFIG_IMX_HAVE_PLATFORM_IMX_SSI=y @@ -325,14 +326,20 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set -# CONFIG_CACHE_L2X0 is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y CONFIG_ARM_L1_CACHE_SHIFT=5 CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_CPU_HAS_PMU=y # CONFIG_ARM_ERRATA_430973 is not set # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set CONFIG_ARM_ERRATA_743622=y +# CONFIG_ARM_ERRATA_753970 is not set CONFIG_ARM_ERRATA_754322=y CONFIG_ARM_GIC=y @@ -342,6 +349,7 @@ CONFIG_ARM_GIC=y # CONFIG_PCI_SYSCALL is not set # CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set +# CONFIG_PL310_ERRATA_769419 is not set # # Kernel Features @@ -419,7 +427,9 @@ CONFIG_CMDLINE_FROM_BOOTLOADER=y # # At least one emulation must be selected # -# CONFIG_VFP is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_NEON is not set # # Userspace binary formats @@ -433,7 +443,9 @@ CONFIG_HAVE_AOUT=y # # Power management options # -# CONFIG_SUSPEND is not set +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y CONFIG_PM_RUNTIME=y CONFIG_PM=y # CONFIG_PM_DEBUG is not set @@ -652,7 +664,41 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_MG_DISK is not set # CONFIG_BLK_DEV_RBD is not set # CONFIG_SENSORS_LIS3LV02D is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +CONFIG_MVF_ADC=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -748,6 +794,7 @@ CONFIG_NET_ETHERNET=y # CONFIG_KS8851 is not set # CONFIG_KS8851_MLL is not set CONFIG_FEC=y +# CONFIG_FEC1 is not set # CONFIG_FEC_1588 is not set # CONFIG_FTMAC100 is not set # CONFIG_NETDEV_1000 is not set @@ -795,6 +842,7 @@ CONFIG_INPUT_POLLDEV=y # CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_PSAUX=y +# CONFIG_TSDEV_COMPATIBLE is not set CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set @@ -858,6 +906,7 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_ST1232 is not set # CONFIG_TOUCHSCREEN_P1003 is not set # CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_CRTOUCH is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_ATI_REMOTE is not set @@ -975,10 +1024,11 @@ CONFIG_SPI_MASTER=y # # CONFIG_SPI_ALTERA is not set # CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_MVF_QSPI is not set # CONFIG_SPI_GPIO is not set # CONFIG_SPI_IMX is not set CONFIG_SPI_MVF=y -# CONFIG_SPI_MVF_DSPI_EDMA is not set +CONFIG_SPI_MVF_DSPI_EDMA=y # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PXA2XX_PCI is not set # CONFIG_SPI_XILINX is not set @@ -1434,7 +1484,8 @@ CONFIG_DMADEVICES=y # DMA Devices # # CONFIG_DW_DMAC is not set -CONFIG_MCF_EDMA=y +CONFIG_MVF_EDMA=y +CONFIG_MVF_EDMA_TEST=m # CONFIG_MXC_PXP is not set # CONFIG_MXC_PXP_V2 is not set # CONFIG_TIMB_DMA is not set @@ -1499,6 +1550,7 @@ CONFIG_CLKSRC_MMIO=y # # MXC Asynchronous Sample Rate Converter support # +CONFIG_MXC_ASRC=y # # MXC Bluetooth support -- cgit v1.2.3 From da9fd56e1e47c7773c8dfc4db445e3d1852d5aa5 Mon Sep 17 00:00:00 2001 From: Jason Jin Date: Tue, 11 Dec 2012 18:25:40 +0800 Subject: Vybrid CAAM driver From Singh Pradip-B09147. Integrate by Jason Jin Signed-off-by: Jason Jin --- arch/arm/mach-mvf/Kconfig | 1 + arch/arm/mach-mvf/board-twr-vf700.c | 2 + arch/arm/mach-mvf/clock.c | 10 +- arch/arm/mach-mvf/devices-mvf.h | 4 + arch/arm/plat-mxc/devices/Kconfig | 4 + arch/arm/plat-mxc/devices/Makefile | 1 + arch/arm/plat-mxc/devices/platform-mvf-caam.c | 107 ++ arch/arm/plat-mxc/include/mach/devices-common.h | 17 + arch/arm/plat-mxc/include/mach/mvf.h | 16 +- drivers/crypto/Kconfig | 11 +- drivers/crypto/caam/Kconfig | 82 +- drivers/crypto/caam/Makefile | 8 +- drivers/crypto/caam/caamalg.c | 2295 ++++++++++++++++------ drivers/crypto/caam/caamhash.c | 1969 +++++++++++++++++++ drivers/crypto/caam/caamrng.c | 381 ++++ drivers/crypto/caam/compat.h | 18 +- drivers/crypto/caam/ctrl.c | 430 ++++- drivers/crypto/caam/desc.h | 2310 ++++++++++++----------- drivers/crypto/caam/desc_constr.h | 117 +- drivers/crypto/caam/error.c | 5 +- drivers/crypto/caam/error.h | 2 +- drivers/crypto/caam/intern.h | 80 +- drivers/crypto/caam/jr.c | 89 +- drivers/crypto/caam/key_gen.c | 124 ++ drivers/crypto/caam/key_gen.h | 17 + drivers/crypto/caam/regs.h | 282 ++- drivers/crypto/caam/secvio.c | 310 +++ drivers/crypto/caam/secvio.h | 64 + drivers/crypto/caam/sg_sw_sec4.h | 165 ++ drivers/crypto/caam/sm.h | 86 + drivers/crypto/caam/sm_store.c | 890 +++++++++ drivers/crypto/caam/sm_test.c | 796 ++++++++ drivers/crypto/caam/snvsregs.h | 237 +++ 33 files changed, 9104 insertions(+), 1826 deletions(-) create mode 100644 arch/arm/plat-mxc/devices/platform-mvf-caam.c create mode 100644 drivers/crypto/caam/caamhash.c create mode 100644 drivers/crypto/caam/caamrng.c create mode 100644 drivers/crypto/caam/key_gen.c create mode 100644 drivers/crypto/caam/key_gen.h create mode 100644 drivers/crypto/caam/secvio.c create mode 100644 drivers/crypto/caam/secvio.h create mode 100644 drivers/crypto/caam/sg_sw_sec4.h create mode 100644 drivers/crypto/caam/sm.h create mode 100644 drivers/crypto/caam/sm_store.c create mode 100644 drivers/crypto/caam/sm_test.c create mode 100644 drivers/crypto/caam/snvsregs.h diff --git a/arch/arm/mach-mvf/Kconfig b/arch/arm/mach-mvf/Kconfig index 10ec5b6307df..931ef6af6dd4 100644 --- a/arch/arm/mach-mvf/Kconfig +++ b/arch/arm/mach-mvf/Kconfig @@ -54,6 +54,7 @@ config MACH_MVFA5_TWR_VF700 select IMX_HAVE_PLATFORM_MVF_DCU select IMX_HAVE_PLATFORM_MVF_SAI select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_MVF_CAAM help Include support for MVF TWR-VF700 platform. This includes specific configurations for the board and its peripherals. diff --git a/arch/arm/mach-mvf/board-twr-vf700.c b/arch/arm/mach-mvf/board-twr-vf700.c index d64622b2db19..01fd4dc364cc 100644 --- a/arch/arm/mach-mvf/board-twr-vf700.c +++ b/arch/arm/mach-mvf/board-twr-vf700.c @@ -471,6 +471,8 @@ static void __init mvf_board_init(void) mvf_add_pm_imx(0, &mvf_vf600_pm_data); + mvf700_add_caam(); + mvf_add_sdhci_esdhc_imx(1, &mvfa5_sd1_data); mvf_add_imx_i2c(0, &mvf600_i2c_data); diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index 16d86fb73368..5ac0ff1766fb 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1613,6 +1613,14 @@ static struct clk clko2_clk = { .get_rate = _clk_clko2_get_rate, .round_rate = _clk_clko_round_rate, }; +static struct clk caam_clk = { + __INIT_CLK_DEBUG(caam_clk) + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR11, + .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +}; static struct clk pit_clk = { __INIT_CLK_DEBUG(pit_clk) @@ -1912,10 +1920,10 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("mvf-qspi.0", NULL, qspi0_clk), _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk[0]), _REGISTER_CLOCK(NULL, "asrc_serial_clk", asrc_clk[1]), + _REGISTER_CLOCK(NULL, "caam_clk", caam_clk), }; static void clk_tree_init(void) - { unsigned int reg = 0xffffffff; diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index 6bc61871fd5e..c434834ba0b2 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -224,3 +224,7 @@ extern const struct imx_epdc_data mvf_epdc_data __initconst; #define mvf_add_pwm_leds(pdata) \ imx_add_platform_device("leds_pwm", 0, NULL, 0, pdata, sizeof(*pdata)) + +extern const struct mvf_caam_data mvf_caam_data __initconst; +#define mvf700_add_caam() \ + mvf_add_caam(&mvf_caam_data) diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig index 22e160789d06..42a52220383e 100755 --- a/arch/arm/plat-mxc/devices/Kconfig +++ b/arch/arm/plat-mxc/devices/Kconfig @@ -41,6 +41,10 @@ config IMX_HAVE_PLATFORM_IMX_SRTC config IMX_HAVE_PLATFORM_IMX_SNVS_RTC bool +config IMX_HAVE_PLATFORM_MVF_CAAM + bool + default y if SOC_MVFA5 + config IMX_HAVE_PLATFORM_IMX_FB bool select HAVE_FB_IMX diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile index 45d9869bd730..807de8385db0 100755 --- a/arch/arm/plat-mxc/devices/Makefile +++ b/arch/arm/plat-mxc/devices/Makefile @@ -65,3 +65,4 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_SPI) += platform-mvf-spi.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_ADC) += platform-mvf-adc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_DCU) += platform-mvf-dcu.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_SAI) += platform-mvf-sai.o +obj-$(CONFIG_IMX_HAVE_PLATFORM_MVF_CAAM) += platform-mvf-caam.o diff --git a/arch/arm/plat-mxc/devices/platform-mvf-caam.c b/arch/arm/plat-mxc/devices/platform-mvf-caam.c new file mode 100644 index 000000000000..0f716911698f --- /dev/null +++ b/arch/arm/plat-mxc/devices/platform-mvf-caam.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include + +/* + * security violation interrupt is used as CAAM base _INT_SNVS_SEC + * SNVS consolidated = _INT_SNVS + * JR0 = MXC_INT_CAAM_INT0_NUM + * JR1 = MXC_INT_CAAM_INT1_NUM + */ + +const struct mvf_caam_data mvf_caam_data __initconst = { + .iobase_caam = MVF_CAAM_BASE_ADDR, + .iobase_caam_sm = MVF_CAAM_SECMEM_BASE_ADDR, + .iobase_snvs = MVF_SNVS_BASE_ADDR, + .irq_sec_vio = MVF_INT_SNVS_SEC, + .irq_snvs = MVF_INT_SNVS, + .jr[0].offset_jr = 0x1000, + .jr[0].irq_jr = MVF_INT_CAAM, + .jr[1].offset_jr = 0x2000, + .jr[1].irq_jr = MVF_INT_CAAM, +}; + +struct platform_device *__init mvf_add_caam( + const struct mvf_caam_data *data) +{ + u32 res_count = 0; + struct resource res[] = { + { + /* Define base range for entire CAAM register map */ + .name = "iobase_caam", + .start = data->iobase_caam, + .end = data->iobase_caam + ((SZ_32K + SZ_4K) - 1), + .flags = IORESOURCE_MEM, + }, { + /* Define range for secure memory */ + .name = "iobase_caam_sm", + .start = data->iobase_caam_sm, + .end = data->iobase_caam_sm + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, { + /* Define range for SNVS */ + .name = "iobase_snvs", + .start = data->iobase_snvs, + .end = data->iobase_snvs + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + /* Define interrupt for security violations */ + .name = "irq_sec_vio", + .start = data->irq_sec_vio, + .end = data->irq_sec_vio, + .flags = IORESOURCE_IRQ, + }, { + /* Define general SNVS interrupt */ + .name = "irq_snvs", + .start = data->irq_snvs, + .end = data->irq_snvs, + .flags = IORESOURCE_IRQ, + }, { + .name = "offset_jr0", + .start = data->jr[0].offset_jr, + .end = data->jr[0].offset_jr, + .flags = IORESOURCE_MEM, + }, { + .name = "irq_jr0", + .start = data->jr[0].irq_jr, + .end = data->jr[0].irq_jr, + .flags = IORESOURCE_IRQ, + }, { + .name = "offset_jr1", + .start = data->jr[1].offset_jr, + .end = data->jr[1].offset_jr, + .flags = IORESOURCE_MEM, + }, { + .name = "irq_jr1", + .start = data->jr[1].irq_jr, + .end = data->jr[1].irq_jr, + .flags = IORESOURCE_IRQ, + }, + }; + + res_count = ARRAY_SIZE(res); + BUG_ON(!res_count); + + return imx_add_platform_device("caam", 0, + res, ARRAY_SIZE(res), NULL, 0); +} diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index 3cdcceaea09f..0e2a2a1d13e9 100755 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -681,3 +681,20 @@ struct imx_rngb_data { struct platform_device *__init imx_add_rngb( const struct imx_rngb_data *data); + +struct mvf_caam_jr_data { + resource_size_t offset_jr; + resource_size_t irq_jr; +}; + +struct mvf_caam_data { + resource_size_t iobase_caam; /* entirety of CAAM register map */ + resource_size_t iobase_caam_sm; /* base of secure memory */ + resource_size_t iobase_snvs; /* base of SNVS */ + resource_size_t irq_sec_vio; /* SNVS security violation */ + resource_size_t irq_snvs; /* SNVS consolidated (incl. RTC) */ + struct mvf_caam_jr_data jr[4]; /* offset+IRQ for each possible ring */ +}; + +struct platform_device *__init mvf_add_caam( + const struct mvf_caam_data *data); diff --git a/arch/arm/plat-mxc/include/mach/mvf.h b/arch/arm/plat-mxc/include/mach/mvf.h index 6512c4e2bac6..838eef400e95 100644 --- a/arch/arm/plat-mxc/include/mach/mvf.h +++ b/arch/arm/plat-mxc/include/mach/mvf.h @@ -176,6 +176,11 @@ #define MVF_SRC_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0006E000) #define MVF_CMU_BASE_ADDR (MVF_AIPS1_BASE_ADDR + 0x0006F000) +#define MVF_CAAM_SECMEM_BASE_ADDR \ + (MVF_AIPS0_BASE_ADDR + 0x0007C000) +#define MVF_CAAM_SECMEM_END_ADDR \ + (MVF_AIPS0_BASE_ADDR + 0x0007FFFF) + #define L2_BASE_ADDR MVF_L2C_BASE_ADDR #define MVF_USBC0_CTRL_BASE_ADDR 0x40034800 @@ -563,15 +568,16 @@ #define MVF_INT_ESAI_BIFIFO 120 #define MVF_INT_SPDIF 121 #define MVF_INT_ASRC 122 -#define MVF_INT_CMU 123 +#define MVF_INT_CMU 123 #define MVF_INT_WKPU0 124 #define MVF_INT_WKPU1 125 -#define MVF_INT_CCM 126 +#define MVF_INT_CCM 126 -#define MVF_INT_SRC 128 -#define MVF_INT_PDB 129 -#define MVF_INT_EWM 130 +#define MVF_INT_SRC 128 +#define MVF_INT_PDB 129 +#define MVF_INT_EWM 130 #define MVF_INT_SNVS 132 +#define MVF_INT_SNVS_SEC 133 #define MVF_INT_CAAM 134 diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 13fdb2c3c465..ed37f0a758d8 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -173,6 +173,7 @@ config CRYPTO_DEV_MV_CESA select CRYPTO_ALGAPI select CRYPTO_AES select CRYPTO_BLKCIPHER2 + select CRYPTO_HASH help This driver allows you to utilize the Cryptographic Engines and Security Accelerator (CESA) which can be found on the Marvell Orion @@ -293,13 +294,13 @@ config CRYPTO_DEV_S5P algorithms execution. config CRYPTO_DEV_DCP tristate "Support for the DCP engine" - depends on SOC_IMX28 || SOC_IMX23 || SOC_IMX50 + depends on SOC_IMX28 || SOC_IMX23 || SOC_IMX50 || SOC_IMX6SL select CRYPTO_ALGAPI select CRYPTO_BLKCIPHER help - Say 'Y' here to use the DCP AES and SHA - engine for the CryptoAPI algorithms. - To compile this driver as a module, choose M here: the module - will be called geode-aes. + Say 'Y' here to use the DCP AES and SHA + engine for the CryptoAPI algorithms. + To compile this driver as a module, choose M here: the module + will be called geode-aes. endif # CRYPTO_HW diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index 2d876bb98ff4..bc7fbd450e9e 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -1,6 +1,6 @@ config CRYPTO_DEV_FSL_CAAM tristate "Freescale CAAM-Multicore driver backend" - depends on FSL_SOC + depends on FSL_SOC || ARCH_MXC help Enables the driver module for Freescale's Cryptographic Accelerator and Assurance Module (CAAM), also known as the SEC version 4 (SEC4). @@ -58,7 +58,9 @@ config CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD threshold. Range is 1-65535. config CRYPTO_DEV_FSL_CAAM_CRYPTO_API - tristate "Register algorithm implementations with the Crypto API" +# Forced to non-module for current ARM branch, until CONFIG_OF possible +# tristate "Register algorithm implementations with the Crypto API" + boolean "Register algorithm implementations with the Crypto API" depends on CRYPTO_DEV_FSL_CAAM default y select CRYPTO_ALGAPI @@ -70,3 +72,79 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API To compile this as a module, choose M here: the module will be called caamalg. + +config CRYPTO_DEV_FSL_CAAM_AHASH_API +# Forced to non-module for current ARM branch, until CONFIG_OF possible +# tristate "Register hash algorithm implementations with Crypto API" + boolean "Register hash algorithm implementations with Crypto API" + depends on CRYPTO_DEV_FSL_CAAM + default y + select CRYPTO_AHASH + help + Selecting this will offload ahash for users of the + scatterlist crypto API to the SEC4 via job ring. + + To compile this as a module, choose M here: the module + will be called caamhash. + +config CRYPTO_DEV_FSL_CAAM_RNG_API +# Forced to non-module for current ARM branch, until CONFIG_OF possible +# tristate "Register caam device for hwrng API" + boolean "Register caam device for hwrng API" + depends on CRYPTO_DEV_FSL_CAAM + default y + select CRYPTO_RNG + help + Selecting this will register the SEC4 hardware rng to + the hw_random API for suppying the kernel entropy pool. + + To compile this as a module, choose M here: the module + will be called caamrng. + +config CRYPTO_DEV_FSL_CAAM_RNG_TEST + boolean "Test caam rng" + depends on CRYPTO_DEV_FSL_CAAM_RNG_API + default n + help + Selecting this will enable self-test for caam rng. + +config CRYPTO_DEV_FSL_CAAM_SM + boolean "CAAM Secure Memory / Keystore API (EXPERIMENTAL)" + default n + help + Enables use of a prototype kernel-level Keystore API with CAAM + Secure Memory for insertion/extraction of bus-protected secrets. + +config CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE + int "Size of each keystore slot in Secure Memory" + depends on CRYPTO_DEV_FSL_CAAM_SM + range 5 9 + default 7 + help + Select size of allocation units to divide Secure Memory pages into + (the size of a "slot" as referenced inside the API code). + Established as powers of two. + Examples: + 5 => 32 bytes + 6 => 64 bytes + 7 => 128 bytes + 8 => 256 bytes + 9 => 512 bytes + +config CRYPTO_DEV_FSL_CAAM_SM_TEST + boolean "CAAM Secure Memory - Keystore Test/Example (EXPERIMENTAL)" + depends on CRYPTO_DEV_FSL_CAAM_SM + default n + help + Example thread to exercise the Keystore API and to verify that + stored and recovered secrets can be used for general purpose + encryption/decryption. + +config CRYPTO_DEV_FSL_CAAM_SECVIO + boolean "CAAM/SNVS Security Violation Handler (EXPERIMENTAL)" + depends on CRYPTO_DEV_FSL_CAAM + default n + help + Enables installation of an interrupt handler with registrable + handler functions which can be specified to act on the consequences + of a security violation. \ No newline at end of file diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index ef39011b4505..36bc651a368d 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile @@ -4,5 +4,11 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SM) += sm_store.o +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST) += sm_test.o +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO) += secvio.o + +caam-objs := ctrl.o jr.o error.o key_gen.o -caam-objs := ctrl.o jr.o error.o diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 676d957c22b0..0f0a9731c941 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -1,7 +1,7 @@ /* * caam - Freescale FSL CAAM support for crypto API * - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. * * Based on talitos crypto API driver. * @@ -37,9 +37,10 @@ * | ShareDesc Pointer | * | SEQ_OUT_PTR | * | (output buffer) | + * | (output length) | * | SEQ_IN_PTR | * | (input buffer) | - * | LOAD (to DECO) | + * | (input length) | * --------------------- */ @@ -50,7 +51,10 @@ #include "desc_constr.h" #include "jr.h" #include "error.h" +#include "sg_sw_sec4.h" +#include "key_gen.h" +/*#define DEBUG*/ /* * crypto alg */ @@ -62,10 +66,22 @@ #define CAAM_MAX_IV_LENGTH 16 /* length of descriptors text */ -#define DESC_AEAD_SHARED_TEXT_LEN 4 -#define DESC_AEAD_ENCRYPT_TEXT_LEN 21 -#define DESC_AEAD_DECRYPT_TEXT_LEN 24 -#define DESC_AEAD_GIVENCRYPT_TEXT_LEN 27 +#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3) + +#define DESC_AEAD_BASE (4 * CAAM_CMD_SZ) +#define DESC_AEAD_ENC_LEN (DESC_AEAD_BASE + 16 * CAAM_CMD_SZ) +#define DESC_AEAD_DEC_LEN (DESC_AEAD_BASE + 21 * CAAM_CMD_SZ) +#define DESC_AEAD_GIVENC_LEN (DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ) + +#define DESC_ABLKCIPHER_BASE (3 * CAAM_CMD_SZ) +#define DESC_ABLKCIPHER_ENC_LEN (DESC_ABLKCIPHER_BASE + \ + 20 * CAAM_CMD_SZ) +#define DESC_ABLKCIPHER_DEC_LEN (DESC_ABLKCIPHER_BASE + \ + 15 * CAAM_CMD_SZ) + +#define DESC_MAX_USED_BYTES (DESC_AEAD_GIVENC_LEN + \ + CAAM_MAX_KEY_SIZE) +#define DESC_MAX_USED_LEN (DESC_MAX_USED_BYTES / CAAM_CMD_SZ) #ifdef DEBUG /* for print_hex_dumps with line references */ @@ -76,217 +92,385 @@ #define debug(format, arg...) #endif +/* Set DK bit in class 1 operation if shared */ +static inline void append_dec_op1(u32 *desc, u32 type) +{ + u32 *jump_cmd, *uncond_jump_cmd; + + jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD); + append_operation(desc, type | OP_ALG_AS_INITFINAL | + OP_ALG_DECRYPT); + uncond_jump_cmd = append_jump(desc, JUMP_TEST_ALL); + set_jump_tgt_here(desc, jump_cmd); + append_operation(desc, type | OP_ALG_AS_INITFINAL | + OP_ALG_DECRYPT | OP_ALG_AAI_DK); + set_jump_tgt_here(desc, uncond_jump_cmd); +} + +/* + * Wait for completion of class 1 key loading before allowing + * error propagation + */ +static inline void append_dec_shr_done(u32 *desc) +{ + u32 *jump_cmd; + + jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TEST_ALL); + set_jump_tgt_here(desc, jump_cmd); + append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD); +} + +/* + * For aead functions, read payload and write payload, + * both of which are specified in req->src and req->dst + */ +static inline void aead_append_src_dst(u32 *desc, u32 msg_type) +{ + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | + KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH); + append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF); +} + +/* + * For aead encrypt and decrypt, read iv for both classes + */ +static inline void aead_append_ld_iv(u32 *desc, int ivsize) +{ + append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT | + LDST_CLASS_1_CCB | ivsize); + append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO | ivsize); +} + +/* + * For ablkcipher encrypt and decrypt, read from req->src and + * write to req->dst + */ +static inline void ablkcipher_append_src_dst(u32 *desc) +{ + append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ); + append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | + KEY_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1); + append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF); +} + +/* + * If all data, including src (with assoc and iv) or dst (with iv only) are + * contiguous + */ +#define GIV_SRC_CONTIG 1 +#define GIV_DST_CONTIG (1 << 1) + /* * per-session context */ struct caam_ctx { struct device *jrdev; - u32 *sh_desc; - dma_addr_t shared_desc_phys; + u32 sh_desc_enc[DESC_MAX_USED_LEN]; + u32 sh_desc_dec[DESC_MAX_USED_LEN]; + u32 sh_desc_givenc[DESC_MAX_USED_LEN]; + dma_addr_t sh_desc_enc_dma; + dma_addr_t sh_desc_dec_dma; + dma_addr_t sh_desc_givenc_dma; u32 class1_alg_type; u32 class2_alg_type; u32 alg_op; - u8 *key; - dma_addr_t key_phys; + u8 key[CAAM_MAX_KEY_SIZE]; + dma_addr_t key_dma; unsigned int enckeylen; unsigned int split_key_len; unsigned int split_key_pad_len; unsigned int authsize; }; -static int aead_authenc_setauthsize(struct crypto_aead *authenc, - unsigned int authsize) +static void append_key_aead(u32 *desc, struct caam_ctx *ctx, + int keys_fit_inline) { - struct caam_ctx *ctx = crypto_aead_ctx(authenc); - - ctx->authsize = authsize; - - return 0; + if (keys_fit_inline) { + append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len, + ctx->split_key_len, CLASS_2 | + KEY_DEST_MDHA_SPLIT | KEY_ENC); + append_key_as_imm(desc, (void *)ctx->key + + ctx->split_key_pad_len, ctx->enckeylen, + ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG); + } else { + append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 | + KEY_DEST_MDHA_SPLIT | KEY_ENC); + append_key(desc, ctx->key_dma + ctx->split_key_pad_len, + ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG); + } } -struct split_key_result { - struct completion completion; - int err; -}; - -static void split_key_done(struct device *dev, u32 *desc, u32 err, - void *context) +static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx, + int keys_fit_inline) { - struct split_key_result *res = context; + u32 *key_jump_cmd; -#ifdef DEBUG - dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); -#endif - if (err) { - char tmp[CAAM_ERROR_STR_MAX]; + init_sh_desc(desc, HDR_SHARE_SERIAL); - dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); - } + /* Skip if already shared */ + key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | + JUMP_COND_SHRD); - res->err = err; + append_key_aead(desc, ctx, keys_fit_inline); - complete(&res->completion); + set_jump_tgt_here(desc, key_jump_cmd); + + /* Propagate errors from shared to job descriptor */ + append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD); } -/* -get a split ipad/opad key - -Split key generation----------------------------------------------- - -[00] 0xb0810008 jobdesc: stidx=1 share=never len=8 -[01] 0x04000014 key: class2->keyreg len=20 - @0xffe01000 -[03] 0x84410014 operation: cls2-op sha1 hmac init dec -[04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm -[05] 0xa4000001 jump: class2 local all ->1 [06] -[06] 0x64260028 fifostr: class2 mdsplit-jdk len=40 - @0xffe04000 -*/ -static u32 gen_split_key(struct caam_ctx *ctx, const u8 *key_in, u32 authkeylen) +static int aead_set_sh_desc(struct crypto_aead *aead) { + struct aead_tfm *tfm = &aead->base.crt_aead; + struct caam_ctx *ctx = crypto_aead_ctx(aead); struct device *jrdev = ctx->jrdev; + bool keys_fit_inline = 0; + u32 *key_jump_cmd, *jump_cmd; + u32 geniv, moveiv; u32 *desc; - struct split_key_result result; - dma_addr_t dma_addr_in, dma_addr_out; - int ret = 0; - desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); + if (!ctx->enckeylen || !ctx->authsize) + return 0; - init_job_desc(desc, 0); + /* + * Job Descriptor and Shared Descriptors + * must all fit into the 64-word Descriptor h/w Buffer + */ + if (DESC_AEAD_ENC_LEN + DESC_JOB_IO_LEN + + ctx->split_key_pad_len + ctx->enckeylen <= + CAAM_DESC_BYTES_MAX) + keys_fit_inline = 1; - dma_addr_in = dma_map_single(jrdev, (void *)key_in, authkeylen, - DMA_TO_DEVICE); - if (dma_mapping_error(jrdev, dma_addr_in)) { - dev_err(jrdev, "unable to map key input memory\n"); - kfree(desc); - return -ENOMEM; - } - append_key(desc, dma_addr_in, authkeylen, CLASS_2 | - KEY_DEST_CLASS_REG); + /* aead_encrypt shared descriptor */ + desc = ctx->sh_desc_enc; - /* Sets MDHA up into an HMAC-INIT */ - append_operation(desc, ctx->alg_op | OP_ALG_DECRYPT | - OP_ALG_AS_INIT); + init_sh_desc_key_aead(desc, ctx, keys_fit_inline); - /* - * do a FIFO_LOAD of zero, this will trigger the internal key expansion - into both pads inside MDHA - */ - append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB | - FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2); + /* Class 2 operation */ + append_operation(desc, ctx->class2_alg_type | + OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT); - /* - * FIFO_STORE with the explicit split-key content store - * (0x26 output type) - */ - dma_addr_out = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len, - DMA_FROM_DEVICE); - if (dma_mapping_error(jrdev, dma_addr_out)) { - dev_err(jrdev, "unable to map key output memory\n"); - kfree(desc); + /* cryptlen = seqoutlen - authsize */ + append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize); + + /* assoclen + cryptlen = seqinlen - ivsize */ + append_math_sub_imm_u32(desc, REG2, SEQINLEN, IMM, tfm->ivsize); + + /* assoclen + cryptlen = (assoclen + cryptlen) - cryptlen */ + append_math_sub(desc, VARSEQINLEN, REG2, REG3, CAAM_CMD_SZ); + + /* read assoc before reading payload */ + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG | + KEY_VLF); + aead_append_ld_iv(desc, tfm->ivsize); + + /* Class 1 operation */ + append_operation(desc, ctx->class1_alg_type | + OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT); + + /* Read and write cryptlen bytes */ + append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); + append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); + aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2); + + /* Write ICV */ + append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB | + LDST_SRCDST_BYTE_CONTEXT); + + ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc, + desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); return -ENOMEM; } - append_fifo_store(desc, dma_addr_out, ctx->split_key_len, - LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK); - #ifdef DEBUG - print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, key_in, authkeylen, 1); - print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); + print_hex_dump(KERN_ERR, "aead enc shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); #endif - result.err = 0; - init_completion(&result.completion); + dma_sync_single_for_cpu(jrdev, ctx->sh_desc_enc_dma, desc_bytes(desc), + DMA_TO_DEVICE); + /* + * Job Descriptor and Shared Descriptors + * must all fit into the 64-word Descriptor h/w Buffer + */ + if (DESC_AEAD_DEC_LEN + DESC_JOB_IO_LEN + + ctx->split_key_pad_len + ctx->enckeylen <= + CAAM_DESC_BYTES_MAX) + keys_fit_inline = 1; - ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); - if (!ret) { - /* in progress */ - wait_for_completion_interruptible(&result.completion); - ret = result.err; -#ifdef DEBUG - print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, - ctx->split_key_pad_len, 1); -#endif - } + desc = ctx->sh_desc_dec; - dma_unmap_single(jrdev, dma_addr_out, ctx->split_key_pad_len, - DMA_FROM_DEVICE); - dma_unmap_single(jrdev, dma_addr_in, authkeylen, DMA_TO_DEVICE); + /* aead_decrypt shared descriptor */ + init_sh_desc(desc, HDR_SHARE_SERIAL); - kfree(desc); + /* Skip if already shared */ + key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | + JUMP_COND_SHRD); - return ret; -} + append_key_aead(desc, ctx, keys_fit_inline); -static int build_sh_desc_ipsec(struct caam_ctx *ctx) -{ - struct device *jrdev = ctx->jrdev; - u32 *sh_desc; - u32 *jump_cmd; - bool keys_fit_inline = 0; + /* Only propagate error immediately if shared */ + jump_cmd = append_jump(desc, JUMP_TEST_ALL); + set_jump_tgt_here(desc, key_jump_cmd); + append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD); + set_jump_tgt_here(desc, jump_cmd); + + /* Class 2 operation */ + append_operation(desc, ctx->class2_alg_type | + OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON); + + /* assoclen + cryptlen = seqinlen - ivsize */ + append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM, + ctx->authsize + tfm->ivsize) + /* assoclen = (assoclen + cryptlen) - cryptlen */ + append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ); + append_math_sub(desc, VARSEQINLEN, REG3, REG2, CAAM_CMD_SZ); + + /* read assoc before reading payload */ + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG | + KEY_VLF); + + aead_append_ld_iv(desc, tfm->ivsize); + + append_dec_op1(desc, ctx->class1_alg_type); + + /* Read and write cryptlen bytes */ + append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ); + append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ); + aead_append_src_dst(desc, FIFOLD_TYPE_MSG); + + /* Load ICV */ + append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS2 | + FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV); + append_dec_shr_done(desc); + + ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc, + desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); + return -ENOMEM; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "aead dec shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + dma_sync_single_for_cpu(jrdev, ctx->sh_desc_dec_dma, desc_bytes(desc), + DMA_TO_DEVICE); /* - * largest Job Descriptor and its Shared Descriptor - * must both fit into the 64-word Descriptor h/w Buffer + * Job Descriptor and Shared Descriptors + * must all fit into the 64-word Descriptor h/w Buffer */ - if ((DESC_AEAD_GIVENCRYPT_TEXT_LEN + - DESC_AEAD_SHARED_TEXT_LEN) * CAAM_CMD_SZ + - ctx->split_key_pad_len + ctx->enckeylen <= CAAM_DESC_BYTES_MAX) + if (DESC_AEAD_GIVENC_LEN + DESC_JOB_IO_LEN + + ctx->split_key_pad_len + ctx->enckeylen <= + CAAM_DESC_BYTES_MAX) keys_fit_inline = 1; - /* build shared descriptor for this session */ - sh_desc = kmalloc(CAAM_CMD_SZ * DESC_AEAD_SHARED_TEXT_LEN + - (keys_fit_inline ? - ctx->split_key_pad_len + ctx->enckeylen : - CAAM_PTR_SZ * 2), GFP_DMA | GFP_KERNEL); - if (!sh_desc) { - dev_err(jrdev, "could not allocate shared descriptor\n"); - return -ENOMEM; - } + /* aead_givencrypt shared descriptor */ + desc = ctx->sh_desc_givenc; - init_sh_desc(sh_desc, HDR_SAVECTX | HDR_SHARE_SERIAL); + init_sh_desc_key_aead(desc, ctx, keys_fit_inline); - jump_cmd = append_jump(sh_desc, CLASS_BOTH | JUMP_TEST_ALL | - JUMP_COND_SHRD | JUMP_COND_SELF); + /* Generate IV */ + geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO | + NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 | + NFIFOENTRY_PTYPE_RND | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT); + append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB | + LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM); + append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO); + append_move(desc, MOVE_SRC_INFIFO | + MOVE_DEST_CLASS1CTX | (tfm->ivsize << MOVE_LEN_SHIFT)); + append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO); - /* - * process keys, starting with class 2/authentication. - */ - if (keys_fit_inline) { - append_key_as_imm(sh_desc, ctx->key, ctx->split_key_pad_len, - ctx->split_key_len, - CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC); + /* Copy IV to class 1 context */ + append_move(desc, MOVE_SRC_CLASS1CTX | + MOVE_DEST_OUTFIFO | (tfm->ivsize << MOVE_LEN_SHIFT)); - append_key_as_imm(sh_desc, (void *)ctx->key + - ctx->split_key_pad_len, ctx->enckeylen, - ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG); - } else { - append_key(sh_desc, ctx->key_phys, ctx->split_key_len, CLASS_2 | - KEY_DEST_MDHA_SPLIT | KEY_ENC); - append_key(sh_desc, ctx->key_phys + ctx->split_key_pad_len, - ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG); - } + /* Return to encryption */ + append_operation(desc, ctx->class2_alg_type | + OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT); + + /* ivsize + cryptlen = seqoutlen - authsize */ + append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize); + + /* assoclen = seqinlen - (ivsize + cryptlen) */ + append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ); + + /* read assoc before reading payload */ + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG | + KEY_VLF); + + /* Copy iv from class 1 ctx to class 2 fifo*/ + moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 | + NFIFOENTRY_DTYPE_MSG | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT); + append_load_imm_u32(desc, moveiv, LDST_CLASS_IND_CCB | + LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM); + append_load_imm_u32(desc, tfm->ivsize, LDST_CLASS_2_CCB | + LDST_SRCDST_WORD_DATASZ_REG | LDST_IMM); + + /* Class 1 operation */ + append_operation(desc, ctx->class1_alg_type | + OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT); - /* update jump cmd now that we are at the jump target */ - set_jump_tgt_here(sh_desc, jump_cmd); + /* Will write ivsize + cryptlen */ + append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ); - ctx->shared_desc_phys = dma_map_single(jrdev, sh_desc, - desc_bytes(sh_desc), - DMA_TO_DEVICE); - if (dma_mapping_error(jrdev, ctx->shared_desc_phys)) { + /* Not need to reload iv */ + append_seq_fifo_load(desc, tfm->ivsize, + FIFOLD_CLASS_SKIP); + + /* Will read cryptlen */ + append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); + aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2); + + /* Write ICV */ + append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB | + LDST_SRCDST_BYTE_CONTEXT); + + ctx->sh_desc_givenc_dma = dma_map_single(jrdev, desc, + desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_givenc_dma)) { dev_err(jrdev, "unable to map shared descriptor\n"); - kfree(sh_desc); return -ENOMEM; } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "aead givenc shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + dma_sync_single_for_cpu(jrdev, ctx->sh_desc_givenc_dma, + desc_bytes(desc), DMA_TO_DEVICE); + + return 0; +} - ctx->sh_desc = sh_desc; +static int aead_setauthsize(struct crypto_aead *authenc, + unsigned int authsize) +{ + struct caam_ctx *ctx = crypto_aead_ctx(authenc); + + ctx->authsize = authsize; + aead_set_sh_desc(authenc); return 0; } -static int aead_authenc_setkey(struct crypto_aead *aead, +static u32 gen_split_aead_key(struct caam_ctx *ctx, const u8 *key_in, + u32 authkeylen) +{ + return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len, + ctx->split_key_pad_len, key_in, authkeylen, + ctx->alg_op); +} + +static int aead_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */ @@ -326,27 +510,19 @@ static int aead_authenc_setkey(struct crypto_aead *aead, print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); #endif - ctx->key = kmalloc(ctx->split_key_pad_len + enckeylen, - GFP_KERNEL | GFP_DMA); - if (!ctx->key) { - dev_err(jrdev, "could not allocate key output memory\n"); - return -ENOMEM; - } - ret = gen_split_key(ctx, key, authkeylen); + ret = gen_split_aead_key(ctx, key, authkeylen); if (ret) { - kfree(ctx->key); goto badkey; } /* postpend encryption key to auth split key */ memcpy(ctx->key + ctx->split_key_pad_len, key + authkeylen, enckeylen); - ctx->key_phys = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len + + ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len + enckeylen, DMA_TO_DEVICE); - if (dma_mapping_error(jrdev, ctx->key_phys)) { + if (dma_mapping_error(jrdev, ctx->key_dma)) { dev_err(jrdev, "unable to map key i/o memory\n"); - kfree(ctx->key); return -ENOMEM; } #ifdef DEBUG @@ -354,14 +530,16 @@ static int aead_authenc_setkey(struct crypto_aead *aead, DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, ctx->split_key_pad_len + enckeylen, 1); #endif + dma_sync_single_for_device(jrdev, ctx->key_dma, + ctx->split_key_pad_len + enckeylen, + DMA_TO_DEVICE); ctx->enckeylen = enckeylen; - ret = build_sh_desc_ipsec(ctx); + ret = aead_set_sh_desc(aead); if (ret) { - dma_unmap_single(jrdev, ctx->key_phys, ctx->split_key_pad_len + + dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len + enckeylen, DMA_TO_DEVICE); - kfree(ctx->key); } return ret; @@ -370,73 +548,244 @@ badkey: return -EINVAL; } -struct link_tbl_entry { - u64 ptr; - u32 len; - u8 reserved; - u8 buf_pool_id; - u16 offset; -}; +static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, + const u8 *key, unsigned int keylen) +{ + struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); + struct ablkcipher_tfm *tfm = &ablkcipher->base.crt_ablkcipher; + struct device *jrdev = ctx->jrdev; + int ret = 0; + u32 *key_jump_cmd, *jump_cmd; + u32 *desc; + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); +#endif + memcpy(ctx->key, key, keylen); + ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen, + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->key_dma)) { + dev_err(jrdev, "unable to map key i/o memory\n"); + return -ENOMEM; + } + ctx->enckeylen = keylen; + dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, DMA_TO_DEVICE); + + /* ablkcipher_encrypt shared descriptor */ + desc = ctx->sh_desc_enc; + init_sh_desc(desc, HDR_SHARE_SERIAL); + /* Skip if already shared */ + key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | + JUMP_COND_SHRD); + + /* Load class1 key only */ + append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen, + ctx->enckeylen, CLASS_1 | + KEY_DEST_CLASS_REG); + + set_jump_tgt_here(desc, key_jump_cmd); + + /* Propagate errors from shared to job descriptor */ + append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD); + + /* Load iv */ + append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT | + LDST_CLASS_1_CCB | tfm->ivsize); + + /* Load operation */ + append_operation(desc, ctx->class1_alg_type | + OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT); + + /* Perform operation */ + ablkcipher_append_src_dst(desc); + + ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc, + desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); + return -ENOMEM; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ablkcipher enc shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, + desc_bytes(desc), DMA_TO_DEVICE); + + /* ablkcipher_decrypt shared descriptor */ + desc = ctx->sh_desc_dec; + + init_sh_desc(desc, HDR_SHARE_SERIAL); + /* Skip if already shared */ + key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | + JUMP_COND_SHRD); + + /* Load class1 key only */ + append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen, + ctx->enckeylen, CLASS_1 | + KEY_DEST_CLASS_REG); + + /* For aead, only propagate error immediately if shared */ + jump_cmd = append_jump(desc, JUMP_TEST_ALL); + set_jump_tgt_here(desc, key_jump_cmd); + append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD); + set_jump_tgt_here(desc, jump_cmd); + + /* load IV */ + append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT | + LDST_CLASS_1_CCB | tfm->ivsize); + + /* Choose operation */ + append_dec_op1(desc, ctx->class1_alg_type); + + /* Perform operation */ + ablkcipher_append_src_dst(desc); + + /* Wait for key to load before allowing propagating error */ + append_dec_shr_done(desc); + + ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc, + desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); + return -ENOMEM; + } + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ablkcipher dec shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, + desc_bytes(desc), DMA_TO_DEVICE); + + return ret; +} /* - * ipsec_esp_edesc - s/w-extended ipsec_esp descriptor + * aead_edesc - s/w-extended aead descriptor + * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist + * @assoc_chained: if source is chained * @src_nents: number of segments in input scatterlist + * @src_chained: if source is chained * @dst_nents: number of segments in output scatterlist - * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist + * @dst_chained: if destination is chained + * @iv_dma: dma address of iv for checking continuity and link table * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE) - * @link_tbl_bytes: length of dma mapped link_tbl space - * @link_tbl_dma: bus physical mapped address of h/w link table + * @sec4_sg_bytes: length of dma mapped sec4_sg space + * @sec4_sg_dma: bus physical mapped address of h/w link table * @hw_desc: the h/w job descriptor followed by any referenced link tables */ -struct ipsec_esp_edesc { +struct aead_edesc { int assoc_nents; + bool assoc_chained; int src_nents; + bool src_chained; int dst_nents; - int link_tbl_bytes; - dma_addr_t link_tbl_dma; - struct link_tbl_entry *link_tbl; + bool dst_chained; + dma_addr_t iv_dma; + int sec4_sg_bytes; + dma_addr_t sec4_sg_dma; + struct sec4_sg_entry *sec4_sg; u32 hw_desc[0]; }; -static void ipsec_esp_unmap(struct device *dev, - struct ipsec_esp_edesc *edesc, - struct aead_request *areq) -{ - dma_unmap_sg(dev, areq->assoc, edesc->assoc_nents, DMA_TO_DEVICE); +/* + * ablkcipher_edesc - s/w-extended ablkcipher descriptor + * @src_nents: number of segments in input scatterlist + * @src_chained: if source is chained + * @dst_nents: number of segments in output scatterlist + * @dst_chained: if destination is chained + * @iv_dma: dma address of iv for checking continuity and link table + * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE) + * @sec4_sg_bytes: length of dma mapped sec4_sg space + * @sec4_sg_dma: bus physical mapped address of h/w link table + * @hw_desc: the h/w job descriptor followed by any referenced link tables + */ +struct ablkcipher_edesc { + int src_nents; + bool src_chained; + int dst_nents; + bool dst_chained; + dma_addr_t iv_dma; + int sec4_sg_bytes; + dma_addr_t sec4_sg_dma; + struct sec4_sg_entry *sec4_sg; + u32 hw_desc[0]; +}; - if (unlikely(areq->dst != areq->src)) { - dma_unmap_sg(dev, areq->src, edesc->src_nents, - DMA_TO_DEVICE); - dma_unmap_sg(dev, areq->dst, edesc->dst_nents, - DMA_FROM_DEVICE); +static void caam_unmap(struct device *dev, struct scatterlist *src, + struct scatterlist *dst, int src_nents, + bool src_chained, int dst_nents, bool dst_chained, + dma_addr_t iv_dma, int ivsize, dma_addr_t sec4_sg_dma, + int sec4_sg_bytes) +{ + if (dst != src) { + dma_unmap_sg_chained(dev, src, src_nents ? : 1, DMA_TO_DEVICE, + src_chained); + dma_unmap_sg_chained(dev, dst, dst_nents ? : 1, DMA_FROM_DEVICE, + dst_chained); } else { - dma_unmap_sg(dev, areq->src, edesc->src_nents, - DMA_BIDIRECTIONAL); + dma_unmap_sg_chained(dev, src, src_nents ? : 1, + DMA_BIDIRECTIONAL, src_chained); } - if (edesc->link_tbl_bytes) - dma_unmap_single(dev, edesc->link_tbl_dma, - edesc->link_tbl_bytes, + if (iv_dma) + dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE); + + if (sec4_sg_bytes) + dma_unmap_single(dev, sec4_sg_dma, sec4_sg_bytes, DMA_TO_DEVICE); } -/* - * ipsec_esp descriptor callbacks - */ -static void ipsec_esp_encrypt_done(struct device *jrdev, u32 *desc, u32 err, +static void aead_unmap(struct device *dev, + struct aead_edesc *edesc, + struct aead_request *req) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + int ivsize = crypto_aead_ivsize(aead); + + dma_unmap_sg_chained(dev, req->assoc, edesc->assoc_nents, + DMA_TO_DEVICE, edesc->assoc_chained); + + caam_unmap(dev, req->src, req->dst, + edesc->src_nents, edesc->src_chained, edesc->dst_nents, + edesc->dst_chained, edesc->iv_dma, ivsize, + edesc->sec4_sg_dma, edesc->sec4_sg_bytes); +} + +static void ablkcipher_unmap(struct device *dev, + struct ablkcipher_edesc *edesc, + struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + + caam_unmap(dev, req->src, req->dst, + edesc->src_nents, edesc->src_chained, edesc->dst_nents, + edesc->dst_chained, edesc->iv_dma, ivsize, + edesc->sec4_sg_dma, edesc->sec4_sg_bytes); +} + +static void aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err, void *context) { - struct aead_request *areq = context; - struct ipsec_esp_edesc *edesc; + struct aead_request *req = context; + struct aead_edesc *edesc; #ifdef DEBUG - struct crypto_aead *aead = crypto_aead_reqtfm(areq); - int ivsize = crypto_aead_ivsize(aead); + struct crypto_aead *aead = crypto_aead_reqtfm(req); struct caam_ctx *ctx = crypto_aead_ctx(aead); + int ivsize = crypto_aead_ivsize(aead); dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); #endif - edesc = (struct ipsec_esp_edesc *)((char *)desc - - offsetof(struct ipsec_esp_edesc, hw_desc)); + + edesc = (struct aead_edesc *)((char *)desc - + offsetof(struct aead_edesc, hw_desc)); if (err) { char tmp[CAAM_ERROR_STR_MAX]; @@ -444,39 +793,50 @@ static void ipsec_esp_encrypt_done(struct device *jrdev, u32 *desc, u32 err, dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); } - ipsec_esp_unmap(jrdev, edesc, areq); + aead_unmap(jrdev, edesc, req); #ifdef DEBUG print_hex_dump(KERN_ERR, "assoc @"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->assoc), - areq->assoclen , 1); + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc), + req->assoclen , 1); print_hex_dump(KERN_ERR, "dstiv @"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src) - ivsize, + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src) - ivsize, edesc->src_nents ? 100 : ivsize, 1); print_hex_dump(KERN_ERR, "dst @"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src), - edesc->src_nents ? 100 : areq->cryptlen + + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src), + edesc->src_nents ? 100 : req->cryptlen + ctx->authsize + 4, 1); #endif kfree(edesc); - aead_request_complete(areq, err); + aead_request_complete(req, err); } -static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err, +static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err, void *context) { - struct aead_request *areq = context; - struct ipsec_esp_edesc *edesc; + struct aead_request *req = context; + struct aead_edesc *edesc; #ifdef DEBUG - struct crypto_aead *aead = crypto_aead_reqtfm(areq); + struct crypto_aead *aead = crypto_aead_reqtfm(req); struct caam_ctx *ctx = crypto_aead_ctx(aead); + int ivsize = crypto_aead_ivsize(aead); dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); #endif - edesc = (struct ipsec_esp_edesc *)((char *)desc - - offsetof(struct ipsec_esp_edesc, hw_desc)); + + edesc = (struct aead_edesc *)((char *)desc - + offsetof(struct aead_edesc, hw_desc)); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "dstiv @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->iv, + ivsize, 1); + print_hex_dump(KERN_ERR, "dst @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst), + req->cryptlen, 1); +#endif if (err) { char tmp[CAAM_ERROR_STR_MAX]; @@ -484,7 +844,7 @@ static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err, dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); } - ipsec_esp_unmap(jrdev, edesc, areq); + aead_unmap(jrdev, edesc, req); /* * verify hw auth check passed else return -EBADMSG @@ -495,190 +855,631 @@ static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err, #ifdef DEBUG print_hex_dump(KERN_ERR, "iphdrout@"xstr(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, - ((char *)sg_virt(areq->assoc) - sizeof(struct iphdr)), - sizeof(struct iphdr) + areq->assoclen + - ((areq->cryptlen > 1500) ? 1500 : areq->cryptlen) + + ((char *)sg_virt(req->assoc) - sizeof(struct iphdr)), + sizeof(struct iphdr) + req->assoclen + + ((req->cryptlen > 1500) ? 1500 : req->cryptlen) + ctx->authsize + 36, 1); - if (!err && edesc->link_tbl_bytes) { - struct scatterlist *sg = sg_last(areq->src, edesc->src_nents); + if (!err && edesc->sec4_sg_bytes) { + struct scatterlist *sg = sg_last(req->src, edesc->src_nents); print_hex_dump(KERN_ERR, "sglastout@"xstr(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(sg), sg->length + ctx->authsize + 16, 1); } #endif + kfree(edesc); - aead_request_complete(areq, err); + aead_request_complete(req, err); } -/* - * convert scatterlist to h/w link table format - * scatterlist must have been previously dma mapped - */ -static void sg_to_link_tbl(struct scatterlist *sg, int sg_count, - struct link_tbl_entry *link_tbl_ptr, u32 offset) +static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err, + void *context) { - while (sg_count) { - link_tbl_ptr->ptr = sg_dma_address(sg); - link_tbl_ptr->len = sg_dma_len(sg); - link_tbl_ptr->reserved = 0; - link_tbl_ptr->buf_pool_id = 0; - link_tbl_ptr->offset = offset; - link_tbl_ptr++; - sg = sg_next(sg); - sg_count--; + struct ablkcipher_request *req = context; + struct ablkcipher_edesc *edesc; +#ifdef DEBUG + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + + dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); +#endif + + edesc = (struct ablkcipher_edesc *)((char *)desc - + offsetof(struct ablkcipher_edesc, hw_desc)); + + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); } - /* set Final bit (marks end of link table) */ - link_tbl_ptr--; - link_tbl_ptr->len |= 0x40000000; +#ifdef DEBUG + print_hex_dump(KERN_ERR, "dstiv @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->info, + edesc->src_nents > 1 ? 100 : ivsize, 1); + print_hex_dump(KERN_ERR, "dst @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src), + edesc->dst_nents > 1 ? 100 : req->nbytes, 1); +#endif + + ablkcipher_unmap(jrdev, edesc, req); + kfree(edesc); + + ablkcipher_request_complete(req, err); +} + +static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err, + void *context) +{ + struct ablkcipher_request *req = context; + struct ablkcipher_edesc *edesc; +#ifdef DEBUG + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + + dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); +#endif + + edesc = (struct ablkcipher_edesc *)((char *)desc - + offsetof(struct ablkcipher_edesc, hw_desc)); + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "dstiv @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->info, + ivsize, 1); + print_hex_dump(KERN_ERR, "dst @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src), + edesc->dst_nents > 1 ? 100 : req->nbytes, 1); +#endif + + ablkcipher_unmap(jrdev, edesc, req); + kfree(edesc); + + ablkcipher_request_complete(req, err); } /* - * fill in and submit ipsec_esp job descriptor + * Fill in aead job descriptor */ -static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, - u32 encrypt, - void (*callback) (struct device *dev, u32 *desc, - u32 err, void *context)) +static void init_aead_job(u32 *sh_desc, dma_addr_t ptr, + struct aead_edesc *edesc, + struct aead_request *req, + bool all_contig, bool encrypt) { - struct crypto_aead *aead = crypto_aead_reqtfm(areq); + struct crypto_aead *aead = crypto_aead_reqtfm(req); struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; - u32 *desc = edesc->hw_desc, options; - int ret, sg_count, assoc_sg_count; int ivsize = crypto_aead_ivsize(aead); int authsize = ctx->authsize; - dma_addr_t ptr, dst_dma, src_dma; -#ifdef DEBUG - u32 *sh_desc = ctx->sh_desc; + u32 *desc = edesc->hw_desc; + u32 out_options = 0, in_options; + dma_addr_t dst_dma, src_dma; + int len, sec4_sg_index = 0; +#ifdef DEBUG debug("assoclen %d cryptlen %d authsize %d\n", - areq->assoclen, areq->cryptlen, authsize); + req->assoclen, req->cryptlen, authsize); print_hex_dump(KERN_ERR, "assoc @"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->assoc), - areq->assoclen , 1); + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc), + req->assoclen , 1); print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src) - ivsize, + DUMP_PREFIX_ADDRESS, 16, 4, req->iv, edesc->src_nents ? 100 : ivsize, 1); print_hex_dump(KERN_ERR, "src @"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src), - edesc->src_nents ? 100 : areq->cryptlen + authsize, 1); + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src), + edesc->src_nents ? 100 : req->cryptlen, 1); print_hex_dump(KERN_ERR, "shrdesc@"xstr(__LINE__)": ", DUMP_PREFIX_ADDRESS, 16, 4, sh_desc, desc_bytes(sh_desc), 1); #endif - assoc_sg_count = dma_map_sg(jrdev, areq->assoc, edesc->assoc_nents ?: 1, - DMA_TO_DEVICE); - if (areq->src == areq->dst) - sg_count = dma_map_sg(jrdev, areq->src, edesc->src_nents ? : 1, - DMA_BIDIRECTIONAL); + + len = desc_len(sh_desc); + init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE); + + if (all_contig) { + src_dma = sg_dma_address(req->assoc); + in_options = 0; + } else { + src_dma = edesc->sec4_sg_dma; + sec4_sg_index += (edesc->assoc_nents ? : 1) + 1 + + (edesc->src_nents ? : 1); + in_options = LDST_SGF; + } + if (encrypt) + append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + + req->cryptlen - authsize, in_options); else - sg_count = dma_map_sg(jrdev, areq->src, edesc->src_nents ? : 1, - DMA_TO_DEVICE); + append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + + req->cryptlen, in_options); - /* start auth operation */ - append_operation(desc, ctx->class2_alg_type | OP_ALG_AS_INITFINAL | - (encrypt ? : OP_ALG_ICV_ON)); + if (likely(req->src == req->dst)) { + if (all_contig) { + dst_dma = sg_dma_address(req->src); + } else { + dst_dma = src_dma + sizeof(struct sec4_sg_entry) * + ((edesc->assoc_nents ? : 1) + 1); + out_options = LDST_SGF; + } + } else { + if (!edesc->dst_nents) { + dst_dma = sg_dma_address(req->dst); + } else { + dst_dma = edesc->sec4_sg_dma + + sec4_sg_index * + sizeof(struct sec4_sg_entry); + out_options = LDST_SGF; + } + } + if (encrypt) + append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options); + else + append_seq_out_ptr(desc, dst_dma, req->cryptlen - authsize, + out_options); +} + +/* + * Fill in aead givencrypt job descriptor + */ +static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr, + struct aead_edesc *edesc, + struct aead_request *req, + int contig) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct caam_ctx *ctx = crypto_aead_ctx(aead); + int ivsize = crypto_aead_ivsize(aead); + int authsize = ctx->authsize; + u32 *desc = edesc->hw_desc; + u32 out_options = 0, in_options; + dma_addr_t dst_dma, src_dma; + int len, sec4_sg_index = 0; + +#ifdef DEBUG + debug("assoclen %d cryptlen %d authsize %d\n", + req->assoclen, req->cryptlen, authsize); + print_hex_dump(KERN_ERR, "assoc @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc), + req->assoclen , 1); + print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->iv, ivsize, 1); + print_hex_dump(KERN_ERR, "src @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src), + edesc->src_nents > 1 ? 100 : req->cryptlen, 1); + print_hex_dump(KERN_ERR, "shrdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sh_desc, + desc_bytes(sh_desc), 1); +#endif - /* Load FIFO with data for Class 2 CHA */ - options = FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG; - if (!edesc->assoc_nents) { - ptr = sg_dma_address(areq->assoc); + len = desc_len(sh_desc); + init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE); + + if (contig & GIV_SRC_CONTIG) { + src_dma = sg_dma_address(req->assoc); + in_options = 0; } else { - sg_to_link_tbl(areq->assoc, edesc->assoc_nents, - edesc->link_tbl, 0); - ptr = edesc->link_tbl_dma; - options |= LDST_SGF; + src_dma = edesc->sec4_sg_dma; + sec4_sg_index += edesc->assoc_nents + 1 + edesc->src_nents; + in_options = LDST_SGF; } - append_fifo_load(desc, ptr, areq->assoclen, options); + append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + + req->cryptlen - authsize, in_options); - /* copy iv from cipher/class1 input context to class2 infifo */ - append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO | ivsize); + if (contig & GIV_DST_CONTIG) { + dst_dma = edesc->iv_dma; + } else { + if (likely(req->src == req->dst)) { + dst_dma = src_dma + sizeof(struct sec4_sg_entry) * + edesc->assoc_nents; + out_options = LDST_SGF; + } else { + dst_dma = edesc->sec4_sg_dma + + sec4_sg_index * + sizeof(struct sec4_sg_entry); + out_options = LDST_SGF; + } + } + + append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen, out_options); +} + +/* + * Fill in ablkcipher job descriptor + */ +static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr, + struct ablkcipher_edesc *edesc, + struct ablkcipher_request *req, + bool iv_contig) +{ + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + u32 *desc = edesc->hw_desc; + u32 out_options = 0, in_options; + dma_addr_t dst_dma, src_dma; + int len, sec4_sg_index = 0; - if (!encrypt) { - u32 *jump_cmd, *uncond_jump_cmd; +#ifdef DEBUG + print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->info, + ivsize, 1); + print_hex_dump(KERN_ERR, "src @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src), + edesc->src_nents ? 100 : req->nbytes, 1); +#endif - /* JUMP if shared */ - jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD); + len = desc_len(sh_desc); + init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE); + + if (iv_contig) { + src_dma = edesc->iv_dma; + in_options = 0; + } else { + src_dma = edesc->sec4_sg_dma; + sec4_sg_index += (iv_contig ? 0 : 1) + edesc->src_nents; + in_options = LDST_SGF; + } + append_seq_in_ptr(desc, src_dma, req->nbytes + ivsize, in_options); - /* start class 1 (cipher) operation, non-shared version */ - append_operation(desc, ctx->class1_alg_type | - OP_ALG_AS_INITFINAL); + if (likely(req->src == req->dst)) { + if (!edesc->src_nents && iv_contig) { + dst_dma = sg_dma_address(req->src); + } else { + dst_dma = edesc->sec4_sg_dma + + sizeof(struct sec4_sg_entry); + out_options = LDST_SGF; + } + } else { + if (!edesc->dst_nents) { + dst_dma = sg_dma_address(req->dst); + } else { + dst_dma = edesc->sec4_sg_dma + + sec4_sg_index * sizeof(struct sec4_sg_entry); + out_options = LDST_SGF; + } + } + append_seq_out_ptr(desc, dst_dma, req->nbytes, out_options); +} - uncond_jump_cmd = append_jump(desc, 0); +/* + * allocate and map the aead extended descriptor + */ +static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, + int desc_bytes, bool *all_contig_ptr) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct caam_ctx *ctx = crypto_aead_ctx(aead); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + int assoc_nents, src_nents, dst_nents = 0; + struct aead_edesc *edesc; + dma_addr_t iv_dma = 0; + int sgc; + bool all_contig = true; + bool assoc_chained = false, src_chained = false, dst_chained = false; + int ivsize = crypto_aead_ivsize(aead); + int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes; + + assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained); + src_nents = sg_count(req->src, req->cryptlen, &src_chained); + + if (unlikely(req->dst != req->src)) + dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained); + + sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1, + DMA_BIDIRECTIONAL, assoc_chained); + if (likely(req->src == req->dst)) { + sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, + DMA_BIDIRECTIONAL, src_chained); + } else { + sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, + DMA_TO_DEVICE, src_chained); + sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1, + DMA_FROM_DEVICE, dst_chained); + } + + /* Check if data are contiguous */ + iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE); + if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen != + iv_dma || src_nents || iv_dma + ivsize != + sg_dma_address(req->src)) { + all_contig = false; + assoc_nents = assoc_nents ? : 1; + src_nents = src_nents ? : 1; + sec4_sg_len = assoc_nents + 1 + src_nents; + } + sec4_sg_len += dst_nents; + + sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry); + dma_sync_single_for_device(jrdev, iv_dma, ivsize, DMA_TO_DEVICE); + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes + + sec4_sg_bytes, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, "could not allocate extended descriptor\n"); + return ERR_PTR(-ENOMEM); + } + + edesc->assoc_nents = assoc_nents; + edesc->assoc_chained = assoc_chained; + edesc->src_nents = src_nents; + edesc->src_chained = src_chained; + edesc->dst_nents = dst_nents; + edesc->dst_chained = dst_chained; + edesc->iv_dma = iv_dma; + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) + + desc_bytes; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, DMA_TO_DEVICE); + *all_contig_ptr = all_contig; + + sec4_sg_index = 0; + if (!all_contig) { + sg_to_sec4_sg(req->assoc, + (assoc_nents ? : 1), + edesc->sec4_sg + + sec4_sg_index, 0); + sec4_sg_index += assoc_nents ? : 1; + dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index, + iv_dma, ivsize, 0); + sec4_sg_index += 1; + sg_to_sec4_sg_last(req->src, + (src_nents ? : 1), + edesc->sec4_sg + + sec4_sg_index, 0); + sec4_sg_index += src_nents ? : 1; + } + if (dst_nents) { + sg_to_sec4_sg_last(req->dst, dst_nents, + edesc->sec4_sg + sec4_sg_index, 0); + } + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes, + DMA_TO_DEVICE); + + return edesc; +} + +static int aead_encrypt(struct aead_request *req) +{ + struct aead_edesc *edesc; + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct caam_ctx *ctx = crypto_aead_ctx(aead); + struct device *jrdev = ctx->jrdev; + bool all_contig; + u32 *desc; + int ret = 0; + + req->cryptlen += ctx->authsize; + + /* allocate extended descriptor */ + edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN * + CAAM_CMD_SZ, &all_contig); + if (IS_ERR(edesc)) + return PTR_ERR(edesc); + + /* Create and submit job descriptor */ + init_aead_job(ctx->sh_desc_enc, ctx->sh_desc_enc_dma, edesc, req, + all_contig, true); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc, + desc_bytes(edesc->hw_desc), 1); +#endif + + desc = edesc->hw_desc; + ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + aead_unmap(jrdev, edesc, req); + kfree(edesc); + } + + return ret; +} + +static int aead_decrypt(struct aead_request *req) +{ + struct aead_edesc *edesc; + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct caam_ctx *ctx = crypto_aead_ctx(aead); + struct device *jrdev = ctx->jrdev; + bool all_contig; + u32 *desc; + int ret = 0; + + /* allocate extended descriptor */ + edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN * + CAAM_CMD_SZ, &all_contig); + if (IS_ERR(edesc)) + return PTR_ERR(edesc); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "dec src@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src), + req->cryptlen, 1); +#endif + + /* Create and submit job descriptor*/ + init_aead_job(ctx->sh_desc_dec, + ctx->sh_desc_dec_dma, edesc, req, all_contig, false); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc, + desc_bytes(edesc->hw_desc), 1); +#endif + + desc = edesc->hw_desc; + ret = caam_jr_enqueue(jrdev, desc, aead_decrypt_done, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + aead_unmap(jrdev, edesc, req); + kfree(edesc); + } + + return ret; +} + +/* + * allocate and map the aead extended descriptor for aead givencrypt + */ +static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request + *greq, int desc_bytes, + u32 *contig_ptr) +{ + struct aead_request *req = &greq->areq; + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct caam_ctx *ctx = crypto_aead_ctx(aead); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + int assoc_nents, src_nents, dst_nents = 0; + struct aead_edesc *edesc; + dma_addr_t iv_dma = 0; + int sgc; + u32 contig = GIV_SRC_CONTIG | GIV_DST_CONTIG; + int ivsize = crypto_aead_ivsize(aead); + bool assoc_chained = false, src_chained = false, dst_chained = false; + int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes; + + assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained); + src_nents = sg_count(req->src, req->cryptlen, &src_chained); + + if (unlikely(req->dst != req->src)) + dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained); + + sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1, + DMA_BIDIRECTIONAL, assoc_chained); + if (likely(req->src == req->dst)) { + sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, + DMA_BIDIRECTIONAL, src_chained); + } else { + sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, + DMA_TO_DEVICE, src_chained); + sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1, + DMA_FROM_DEVICE, dst_chained); + } + + /* Check if data are contiguous */ + iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE); + if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen != + iv_dma || src_nents || iv_dma + ivsize != sg_dma_address(req->src)) + contig &= ~GIV_SRC_CONTIG; + if (dst_nents || iv_dma + ivsize != sg_dma_address(req->dst)) + contig &= ~GIV_DST_CONTIG; + if (unlikely(req->src != req->dst)) { + dst_nents = dst_nents ? : 1; + sec4_sg_len += 1; + } + if (!(contig & GIV_SRC_CONTIG)) { + assoc_nents = assoc_nents ? : 1; + src_nents = src_nents ? : 1; + sec4_sg_len += assoc_nents + 1 + src_nents; + if (likely(req->src == req->dst)) + contig &= ~GIV_DST_CONTIG; + } + sec4_sg_len += dst_nents; + + sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry); + + dma_sync_single_for_device(jrdev, iv_dma, ivsize, DMA_TO_DEVICE); + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kzalloc(sizeof(struct aead_edesc) + desc_bytes + + sec4_sg_bytes, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, "could not allocate extended descriptor\n"); + return ERR_PTR(-ENOMEM); + } + + edesc->assoc_nents = assoc_nents; + edesc->assoc_chained = assoc_chained; + edesc->src_nents = src_nents; + edesc->src_chained = src_chained; + edesc->dst_nents = dst_nents; + edesc->dst_chained = dst_chained; + edesc->iv_dma = iv_dma; + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) + + desc_bytes; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, DMA_TO_DEVICE); + *contig_ptr = contig; + + sec4_sg_index = 0; + if (!(contig & GIV_SRC_CONTIG)) { + sg_to_sec4_sg(req->assoc, assoc_nents, + edesc->sec4_sg + + sec4_sg_index, 0); + sec4_sg_index += assoc_nents; + dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index, + iv_dma, ivsize, 0); + sec4_sg_index += 1; + sg_to_sec4_sg_last(req->src, src_nents, + edesc->sec4_sg + + sec4_sg_index, 0); + sec4_sg_index += src_nents; + } + if (unlikely(req->src != req->dst && !(contig & GIV_DST_CONTIG))) { + dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index, + iv_dma, ivsize, 0); + sec4_sg_index += 1; + sg_to_sec4_sg_last(req->dst, dst_nents, + edesc->sec4_sg + sec4_sg_index, 0); + } + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes, + DMA_TO_DEVICE); + + return edesc; +} + +static int aead_givencrypt(struct aead_givcrypt_request *areq) +{ + struct aead_request *req = &areq->areq; + struct aead_edesc *edesc; + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct caam_ctx *ctx = crypto_aead_ctx(aead); + struct device *jrdev = ctx->jrdev; + u32 contig; + u32 *desc; + int ret = 0; - set_jump_tgt_here(desc, jump_cmd); + req->cryptlen += ctx->authsize; - /* start class 1 (cipher) operation, shared version */ - append_operation(desc, ctx->class1_alg_type | - OP_ALG_AS_INITFINAL | OP_ALG_AAI_DK); - set_jump_tgt_here(desc, uncond_jump_cmd); - } else - append_operation(desc, ctx->class1_alg_type | - OP_ALG_AS_INITFINAL | encrypt); + /* allocate extended descriptor */ + edesc = aead_giv_edesc_alloc(areq, DESC_JOB_IO_LEN * + CAAM_CMD_SZ, &contig); - /* load payload & instruct to class2 to snoop class 1 if encrypting */ - options = 0; - if (!edesc->src_nents) { - src_dma = sg_dma_address(areq->src); - } else { - sg_to_link_tbl(areq->src, edesc->src_nents, edesc->link_tbl + - edesc->assoc_nents, 0); - src_dma = edesc->link_tbl_dma + edesc->assoc_nents * - sizeof(struct link_tbl_entry); - options |= LDST_SGF; - } - append_seq_in_ptr(desc, src_dma, areq->cryptlen + authsize, options); - append_seq_fifo_load(desc, areq->cryptlen, FIFOLD_CLASS_BOTH | - FIFOLD_TYPE_LASTBOTH | - (encrypt ? FIFOLD_TYPE_MSG1OUT2 - : FIFOLD_TYPE_MSG)); - - /* specify destination */ - if (areq->src == areq->dst) { - dst_dma = src_dma; - } else { - sg_count = dma_map_sg(jrdev, areq->dst, edesc->dst_nents ? : 1, - DMA_FROM_DEVICE); - if (!edesc->dst_nents) { - dst_dma = sg_dma_address(areq->dst); - options = 0; - } else { - sg_to_link_tbl(areq->dst, edesc->dst_nents, - edesc->link_tbl + edesc->assoc_nents + - edesc->src_nents, 0); - dst_dma = edesc->link_tbl_dma + (edesc->assoc_nents + - edesc->src_nents) * - sizeof(struct link_tbl_entry); - options = LDST_SGF; - } - } - append_seq_out_ptr(desc, dst_dma, areq->cryptlen + authsize, options); - append_seq_fifo_store(desc, areq->cryptlen, FIFOST_TYPE_MESSAGE_DATA); + if (IS_ERR(edesc)) + return PTR_ERR(edesc); - /* ICV */ - if (encrypt) - append_seq_store(desc, authsize, LDST_CLASS_2_CCB | - LDST_SRCDST_BYTE_CONTEXT); - else - append_seq_fifo_load(desc, authsize, FIFOLD_CLASS_CLASS2 | - FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "giv src@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src), + req->cryptlen, 1); +#endif + /* Create and submit job descriptor*/ + init_aead_giv_job(ctx->sh_desc_givenc, + ctx->sh_desc_givenc_dma, edesc, req, contig); #ifdef DEBUG - debug("job_desc_len %d\n", desc_len(desc)); - print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc) , 1); - print_hex_dump(KERN_ERR, "jdlinkt@"xstr(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, edesc->link_tbl, - edesc->link_tbl_bytes, 1); + print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc, + desc_bytes(edesc->hw_desc), 1); #endif - ret = caam_jr_enqueue(jrdev, desc, callback, areq); - if (!ret) + desc = edesc->hw_desc; + ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req); + if (!ret) { ret = -EINPROGRESS; - else { - ipsec_esp_unmap(jrdev, edesc, areq); + } else { + aead_unmap(jrdev, edesc, req); kfree(edesc); } @@ -686,209 +1487,191 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, } /* - * derive number of elements in scatterlist - */ -static int sg_count(struct scatterlist *sg_list, int nbytes, int *chained) -{ - struct scatterlist *sg = sg_list; - int sg_nents = 0; - - *chained = 0; - while (nbytes > 0) { - sg_nents++; - nbytes -= sg->length; - if (!sg_is_last(sg) && (sg + 1)->length == 0) - *chained = 1; - sg = scatterwalk_sg_next(sg); - } - - return sg_nents; -} - -/* - * allocate and map the ipsec_esp extended descriptor + * allocate and map the ablkcipher extended descriptor for ablkcipher */ -static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq, - int desc_bytes) +static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request + *req, int desc_bytes, + bool *iv_contig_out) { - struct crypto_aead *aead = crypto_aead_reqtfm(areq); - struct caam_ctx *ctx = crypto_aead_ctx(aead); + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct device *jrdev = ctx->jrdev; - gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : - GFP_ATOMIC; - int assoc_nents, src_nents, dst_nents = 0, chained, link_tbl_bytes; - struct ipsec_esp_edesc *edesc; - - assoc_nents = sg_count(areq->assoc, areq->assoclen, &chained); - BUG_ON(chained); - if (likely(assoc_nents == 1)) - assoc_nents = 0; - - src_nents = sg_count(areq->src, areq->cryptlen + ctx->authsize, - &chained); - BUG_ON(chained); - if (src_nents == 1) - src_nents = 0; - - if (unlikely(areq->dst != areq->src)) { - dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize, - &chained); - BUG_ON(chained); - if (dst_nents == 1) - dst_nents = 0; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? + GFP_KERNEL : GFP_ATOMIC; + int src_nents, dst_nents = 0, sec4_sg_bytes; + struct ablkcipher_edesc *edesc; + dma_addr_t iv_dma = 0; + bool iv_contig = false; + int sgc; + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + bool src_chained = false, dst_chained = false; + int sec4_sg_index; + + src_nents = sg_count(req->src, req->nbytes, &src_chained); + + if (req->dst != req->src) + dst_nents = sg_count(req->dst, req->nbytes, &dst_chained); + + if (likely(req->src == req->dst)) { + sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, + DMA_BIDIRECTIONAL, src_chained); + } else { + sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, + DMA_TO_DEVICE, src_chained); + sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1, + DMA_FROM_DEVICE, dst_chained); } - link_tbl_bytes = (assoc_nents + src_nents + dst_nents) * - sizeof(struct link_tbl_entry); - debug("link_tbl_bytes %d\n", link_tbl_bytes); + /* FIXME: no test for sgc values returned above... */ + /* + * Check if iv can be contiguous with source and destination. + * If so, include it. If not, create scatterlist. + */ + iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE); + dma_sync_single_for_device(jrdev, iv_dma, ivsize, DMA_TO_DEVICE); + if (!src_nents && iv_dma + ivsize == sg_dma_address(req->src)) + iv_contig = true; + else + src_nents = src_nents ? : 1; + sec4_sg_bytes = ((iv_contig ? 0 : 1) + src_nents + dst_nents) * + sizeof(struct sec4_sg_entry); /* allocate space for base edesc and hw desc commands, link tables */ - edesc = kmalloc(sizeof(struct ipsec_esp_edesc) + desc_bytes + - link_tbl_bytes, GFP_DMA | flags); + edesc = kzalloc(sizeof(struct ablkcipher_edesc) + desc_bytes + + sec4_sg_bytes, GFP_DMA | flags); if (!edesc) { dev_err(jrdev, "could not allocate extended descriptor\n"); return ERR_PTR(-ENOMEM); } - edesc->assoc_nents = assoc_nents; edesc->src_nents = src_nents; + edesc->src_chained = src_chained; edesc->dst_nents = dst_nents; - edesc->link_tbl = (void *)edesc + sizeof(struct ipsec_esp_edesc) + - desc_bytes; - edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl, - link_tbl_bytes, DMA_TO_DEVICE); - edesc->link_tbl_bytes = link_tbl_bytes; - - return edesc; -} - -static int aead_authenc_encrypt(struct aead_request *areq) -{ - struct ipsec_esp_edesc *edesc; - struct crypto_aead *aead = crypto_aead_reqtfm(areq); - struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; - int ivsize = crypto_aead_ivsize(aead); - u32 *desc; - dma_addr_t iv_dma; - - /* allocate extended descriptor */ - edesc = ipsec_esp_edesc_alloc(areq, DESC_AEAD_ENCRYPT_TEXT_LEN * - CAAM_CMD_SZ); - if (IS_ERR(edesc)) - return PTR_ERR(edesc); + edesc->dst_chained = dst_chained; + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) + + desc_bytes; + + sec4_sg_index = 0; + if (!iv_contig) { + dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0); + sg_to_sec4_sg_last(req->src, src_nents, + edesc->sec4_sg + 1, 0); + sec4_sg_index += 1 + src_nents; + } - desc = edesc->hw_desc; + if (dst_nents) { + sg_to_sec4_sg_last(req->dst, dst_nents, + edesc->sec4_sg + sec4_sg_index, 0); + } - /* insert shared descriptor pointer */ - init_job_desc_shared(desc, ctx->shared_desc_phys, - desc_len(ctx->sh_desc), HDR_SHARE_DEFER); + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, DMA_TO_DEVICE); + edesc->iv_dma = iv_dma; - iv_dma = dma_map_single(jrdev, areq->iv, ivsize, DMA_TO_DEVICE); - /* check dma error */ + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes, + DMA_TO_DEVICE); - append_load(desc, iv_dma, ivsize, - LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ablkcipher sec4_sg@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, edesc->sec4_sg, + sec4_sg_bytes, 1); +#endif - return ipsec_esp(edesc, areq, OP_ALG_ENCRYPT, ipsec_esp_encrypt_done); + *iv_contig_out = iv_contig; + return edesc; } -static int aead_authenc_decrypt(struct aead_request *req) +static int ablkcipher_encrypt(struct ablkcipher_request *req) { - struct crypto_aead *aead = crypto_aead_reqtfm(req); - int ivsize = crypto_aead_ivsize(aead); - struct caam_ctx *ctx = crypto_aead_ctx(aead); + struct ablkcipher_edesc *edesc; + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct device *jrdev = ctx->jrdev; - struct ipsec_esp_edesc *edesc; + bool iv_contig; u32 *desc; - dma_addr_t iv_dma; - - req->cryptlen -= ctx->authsize; + int ret = 0; /* allocate extended descriptor */ - edesc = ipsec_esp_edesc_alloc(req, DESC_AEAD_DECRYPT_TEXT_LEN * - CAAM_CMD_SZ); + edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN * + CAAM_CMD_SZ, &iv_contig); if (IS_ERR(edesc)) return PTR_ERR(edesc); + /* Create and submit job descriptor*/ + init_ablkcipher_job(ctx->sh_desc_enc, + ctx->sh_desc_enc_dma, edesc, req, iv_contig); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc, + desc_bytes(edesc->hw_desc), 1); +#endif desc = edesc->hw_desc; + ret = caam_jr_enqueue(jrdev, desc, ablkcipher_encrypt_done, req); - /* insert shared descriptor pointer */ - init_job_desc_shared(desc, ctx->shared_desc_phys, - desc_len(ctx->sh_desc), HDR_SHARE_DEFER); - - iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE); - /* check dma error */ - - append_load(desc, iv_dma, ivsize, - LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT); + if (!ret) { + ret = -EINPROGRESS; + } else { + ablkcipher_unmap(jrdev, edesc, req); + kfree(edesc); + } - return ipsec_esp(edesc, req, !OP_ALG_ENCRYPT, ipsec_esp_decrypt_done); + return ret; } -static int aead_authenc_givencrypt(struct aead_givcrypt_request *req) +static int ablkcipher_decrypt(struct ablkcipher_request *req) { - struct aead_request *areq = &req->areq; - struct ipsec_esp_edesc *edesc; - struct crypto_aead *aead = crypto_aead_reqtfm(areq); - struct caam_ctx *ctx = crypto_aead_ctx(aead); + struct ablkcipher_edesc *edesc; + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct device *jrdev = ctx->jrdev; - int ivsize = crypto_aead_ivsize(aead); - dma_addr_t iv_dma; + bool iv_contig; u32 *desc; - - iv_dma = dma_map_single(jrdev, req->giv, ivsize, DMA_FROM_DEVICE); - - debug("%s: giv %p\n", __func__, req->giv); + int ret = 0; /* allocate extended descriptor */ - edesc = ipsec_esp_edesc_alloc(areq, DESC_AEAD_GIVENCRYPT_TEXT_LEN * - CAAM_CMD_SZ); + edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN * + CAAM_CMD_SZ, &iv_contig); if (IS_ERR(edesc)) return PTR_ERR(edesc); + /* Create and submit job descriptor*/ + init_ablkcipher_job(ctx->sh_desc_dec, + ctx->sh_desc_dec_dma, edesc, req, iv_contig); desc = edesc->hw_desc; +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc, + desc_bytes(edesc->hw_desc), 1); +#endif - /* insert shared descriptor pointer */ - init_job_desc_shared(desc, ctx->shared_desc_phys, - desc_len(ctx->sh_desc), HDR_SHARE_DEFER); - - /* - * LOAD IMM Info FIFO - * to DECO, Last, Padding, Random, Message, 16 bytes - */ - append_load_imm_u32(desc, NFIFOENTRY_DEST_DECO | NFIFOENTRY_LC1 | - NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DTYPE_MSG | - NFIFOENTRY_PTYPE_RND | ivsize, - LDST_SRCDST_WORD_INFO_FIFO); - - /* - * disable info fifo entries since the above serves as the entry - * this way, the MOVE command won't generate an entry. - * Note that this isn't required in more recent versions of - * SEC as a MOVE that doesn't do info FIFO entries is available. - */ - append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO); - - /* MOVE DECO Alignment -> C1 Context 16 bytes */ - append_move(desc, MOVE_SRC_INFIFO | MOVE_DEST_CLASS1CTX | ivsize); - - /* re-enable info fifo entries */ - append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO); - - /* MOVE C1 Context -> OFIFO 16 bytes */ - append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_OUTFIFO | ivsize); - - append_fifo_store(desc, iv_dma, ivsize, FIFOST_TYPE_MESSAGE_DATA); + ret = caam_jr_enqueue(jrdev, desc, ablkcipher_decrypt_done, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + ablkcipher_unmap(jrdev, edesc, req); + kfree(edesc); + } - return ipsec_esp(edesc, areq, OP_ALG_ENCRYPT, ipsec_esp_encrypt_done); + return ret; } +#define template_aead template_u.aead +#define template_ablkcipher template_u.ablkcipher struct caam_alg_template { char name[CRYPTO_MAX_ALG_NAME]; char driver_name[CRYPTO_MAX_ALG_NAME]; unsigned int blocksize; - struct aead_alg aead; + u32 type; + union { + struct ablkcipher_alg ablkcipher; + struct aead_alg aead; + struct blkcipher_alg blkcipher; + struct cipher_alg cipher; + struct compress_alg compress; + struct rng_alg rng; + } template_u; u32 class1_alg_type; u32 class2_alg_type; u32 alg_op; @@ -896,16 +1679,36 @@ struct caam_alg_template { static struct caam_alg_template driver_algs[] = { /* single-pass ipsec_esp descriptor */ + { + .name = "authenc(hmac(md5),cbc(aes))", + .driver_name = "authenc-hmac-md5-cbc-aes-caam", + .blocksize = AES_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = MD5_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha1),cbc(aes))", .driver_name = "authenc-hmac-sha1-cbc-aes-caam", .blocksize = AES_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, @@ -914,16 +1717,37 @@ static struct caam_alg_template driver_algs[] = { .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha224),cbc(aes))", + .driver_name = "authenc-hmac-sha224-cbc-aes-caam", + .blocksize = AES_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA224 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha256),cbc(aes))", .driver_name = "authenc-hmac-sha256-cbc-aes-caam", .blocksize = AES_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, @@ -933,16 +1757,37 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha384),cbc(aes))", + .driver_name = "authenc-hmac-sha384-cbc-aes-caam", + .blocksize = AES_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA384 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha512),cbc(aes))", .driver_name = "authenc-hmac-sha512-cbc-aes-caam", .blocksize = AES_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, @@ -952,16 +1797,36 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(md5),cbc(des3_ede))", + .driver_name = "authenc-hmac-md5-cbc-des3_ede-caam", + .blocksize = DES3_EDE_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = MD5_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha1),cbc(des3_ede))", .driver_name = "authenc-hmac-sha1-cbc-des3_ede-caam", .blocksize = DES3_EDE_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, @@ -970,16 +1835,37 @@ static struct caam_alg_template driver_algs[] = { .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha224),cbc(des3_ede))", + .driver_name = "authenc-hmac-sha224-cbc-des3_ede-caam", + .blocksize = DES3_EDE_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA224 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha256),cbc(des3_ede))", .driver_name = "authenc-hmac-sha256-cbc-des3_ede-caam", .blocksize = DES3_EDE_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, @@ -989,16 +1875,37 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha384),cbc(des3_ede))", + .driver_name = "authenc-hmac-sha384-cbc-des3_ede-caam", + .blocksize = DES3_EDE_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA384 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha512),cbc(des3_ede))", .driver_name = "authenc-hmac-sha512-cbc-des3_ede-caam", .blocksize = DES3_EDE_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, @@ -1008,16 +1915,36 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(md5),cbc(des))", + .driver_name = "authenc-hmac-md5-cbc-des-caam", + .blocksize = DES_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = MD5_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha1),cbc(des))", .driver_name = "authenc-hmac-sha1-cbc-des-caam", .blocksize = DES_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, @@ -1026,16 +1953,37 @@ static struct caam_alg_template driver_algs[] = { .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha224),cbc(des))", + .driver_name = "authenc-hmac-sha224-cbc-des-caam", + .blocksize = DES_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA224 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha256),cbc(des))", .driver_name = "authenc-hmac-sha256-cbc-des-caam", .blocksize = DES_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, @@ -1045,16 +1993,37 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha384),cbc(des))", + .driver_name = "authenc-hmac-sha384-cbc-des-caam", + .blocksize = DES_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA384 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha512),cbc(des))", .driver_name = "authenc-hmac-sha512-cbc-des-caam", .blocksize = DES_BLOCK_SIZE, - .aead = { - .setkey = aead_authenc_setkey, - .setauthsize = aead_authenc_setauthsize, - .encrypt = aead_authenc_encrypt, - .decrypt = aead_authenc_decrypt, - .givencrypt = aead_authenc_givencrypt, + .type = CRYPTO_ALG_TYPE_AEAD, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, .geniv = "", .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, @@ -1064,6 +2033,55 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC, }, + /* ablkcipher descriptor */ + { + .name = "cbc(aes)", + .driver_name = "cbc-aes-caam", + .blocksize = AES_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_ABLKCIPHER, + .template_ablkcipher = { + .setkey = ablkcipher_setkey, + .encrypt = ablkcipher_encrypt, + .decrypt = ablkcipher_decrypt, + .geniv = "eseqiv", + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, + }, + { + .name = "cbc(des3_ede)", + .driver_name = "cbc-3des-caam", + .blocksize = DES3_EDE_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_ABLKCIPHER, + .template_ablkcipher = { + .setkey = ablkcipher_setkey, + .encrypt = ablkcipher_encrypt, + .decrypt = ablkcipher_decrypt, + .geniv = "eseqiv", + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .ivsize = DES3_EDE_BLOCK_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, + }, + { + .name = "cbc(des)", + .driver_name = "cbc-des-caam", + .blocksize = DES_BLOCK_SIZE, + .type = CRYPTO_ALG_TYPE_ABLKCIPHER, + .template_ablkcipher = { + .setkey = ablkcipher_setkey, + .encrypt = ablkcipher_encrypt, + .decrypt = ablkcipher_decrypt, + .geniv = "eseqiv", + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, + } }; struct caam_crypto_alg { @@ -1102,38 +2120,29 @@ static void caam_cra_exit(struct crypto_tfm *tfm) { struct caam_ctx *ctx = crypto_tfm_ctx(tfm); - if (!dma_mapping_error(ctx->jrdev, ctx->shared_desc_phys)) - dma_unmap_single(ctx->jrdev, ctx->shared_desc_phys, - desc_bytes(ctx->sh_desc), DMA_TO_DEVICE); - kfree(ctx->sh_desc); - - if (!dma_mapping_error(ctx->jrdev, ctx->key_phys)) - dma_unmap_single(ctx->jrdev, ctx->key_phys, - ctx->split_key_pad_len + ctx->enckeylen, + if (ctx->sh_desc_enc_dma && + !dma_mapping_error(ctx->jrdev, ctx->sh_desc_enc_dma)) + dma_unmap_single(ctx->jrdev, ctx->sh_desc_enc_dma, + desc_bytes(ctx->sh_desc_enc), DMA_TO_DEVICE); + if (ctx->sh_desc_dec_dma && + !dma_mapping_error(ctx->jrdev, ctx->sh_desc_dec_dma)) + dma_unmap_single(ctx->jrdev, ctx->sh_desc_dec_dma, + desc_bytes(ctx->sh_desc_dec), DMA_TO_DEVICE); + if (ctx->sh_desc_givenc_dma && + !dma_mapping_error(ctx->jrdev, ctx->sh_desc_givenc_dma)) + dma_unmap_single(ctx->jrdev, ctx->sh_desc_givenc_dma, + desc_bytes(ctx->sh_desc_givenc), DMA_TO_DEVICE); - kfree(ctx->key); } -static void __exit caam_algapi_exit(void) +void caam_algapi_shutdown(struct platform_device *pdev) { - - struct device_node *dev_node; - struct platform_device *pdev; struct device *ctrldev; struct caam_drv_private *priv; struct caam_crypto_alg *t_alg, *n; int i, err; - dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); - if (!dev_node) - return; - - pdev = of_find_device_by_node(dev_node); - if (!pdev) - return; - ctrldev = &pdev->dev; - of_node_put(dev_node); priv = dev_get_drvdata(ctrldev); if (!priv->alg_list.next) @@ -1152,6 +2161,7 @@ static void __exit caam_algapi_exit(void) } kfree(priv->algapi_jr); } +EXPORT_SYMBOL_GPL(caam_algapi_shutdown); static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev, struct caam_alg_template @@ -1175,12 +2185,20 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev, alg->cra_init = caam_cra_init; alg->cra_exit = caam_cra_exit; alg->cra_priority = CAAM_CRA_PRIORITY; - alg->cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; alg->cra_blocksize = template->blocksize; alg->cra_alignmask = 0; - alg->cra_type = &crypto_aead_type; alg->cra_ctxsize = sizeof(struct caam_ctx); - alg->cra_u.aead = template->aead; + alg->cra_flags = CRYPTO_ALG_ASYNC | template->type; + switch (template->type) { + case CRYPTO_ALG_TYPE_ABLKCIPHER: + alg->cra_type = &crypto_ablkcipher_type; + alg->cra_ablkcipher = template->template_ablkcipher; + break; + case CRYPTO_ALG_TYPE_AEAD: + alg->cra_type = &crypto_aead_type; + alg->cra_aead = template->template_aead; + break; + } t_alg->class1_alg_type = template->class1_alg_type; t_alg->class2_alg_type = template->class2_alg_type; @@ -1190,26 +2208,16 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev, return t_alg; } -static int __init caam_algapi_init(void) +int caam_algapi_startup(struct platform_device *pdev) { - struct device_node *dev_node; - struct platform_device *pdev; struct device *ctrldev, **jrdev; struct caam_drv_private *priv; - int i = 0, err = 0; - - dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); - if (!dev_node) - return -ENODEV; - - pdev = of_find_device_by_node(dev_node); - if (!pdev) - return -ENODEV; + int i = 0, err = 0, md_limit = 0; + int des_inst, aes_inst, md_inst; + u64 cha_inst; ctrldev = &pdev->dev; priv = dev_get_drvdata(ctrldev); - of_node_put(dev_node); - INIT_LIST_HEAD(&priv->alg_list); jrdev = kmalloc(sizeof(*jrdev) * priv->total_jobrs, GFP_KERNEL); @@ -1232,11 +2240,47 @@ static int __init caam_algapi_init(void) priv->algapi_jr = jrdev; atomic_set(&priv->tfm_count, -1); - /* register crypto algorithms the device supports */ + /* + * register crypto algorithms the device supports + * first, detect presence of DES, AES, and MD blocks. If MD present, + * determine limit of supported digest size + */ + cha_inst = rd_reg64(&priv->ctrl->perfmon.cha_num); + des_inst = (cha_inst & CHA_ID_DES_MASK) >> CHA_ID_DES_SHIFT; + aes_inst = (cha_inst & CHA_ID_AES_MASK) >> CHA_ID_AES_SHIFT; + md_inst = (cha_inst & CHA_ID_MD_MASK) >> CHA_ID_MD_SHIFT; + if (md_inst) { + md_limit = SHA512_DIGEST_SIZE; + if ((rd_reg64(&priv->ctrl->perfmon.cha_id) & CHA_ID_MD_MASK) + == CHA_ID_MD_LP256) /* LP256 limits digest size */ + md_limit = SHA256_DIGEST_SIZE; + } + for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { - /* TODO: check if h/w supports alg */ struct caam_crypto_alg *t_alg; + /* + * All registrable algs in this module require a blockcipher + * All aead algs require message digests, so check them for + * instantiation and size. + */ + if (driver_algs[i].type == CRYPTO_ALG_TYPE_AEAD) { + /* If no MD instantiated, or MD too small, skip */ + if ((!md_inst) || + (driver_algs[i].template_aead.maxauthsize > + md_limit)) + continue; + } + /* If DES alg, and CHA not instantiated, skip */ + if ((driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_3DES) || + (driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_DES)) + if (!des_inst) + continue; + /* If AES alg, and CHA not instantiated, skip */ + if (driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_AES) + if (!aes_inst) + continue; + t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]); if (IS_ERR(t_alg)) { err = PTR_ERR(t_alg); @@ -1259,6 +2303,48 @@ static int __init caam_algapi_init(void) return err; } +EXPORT_SYMBOL_GPL(caam_algapi_startup); + +#ifdef CONFIG_OF +static void __exit caam_algapi_exit(void) +{ + + struct device_node *dev_node; + struct platform_device *pdev; + + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) + return; + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return; + + caam_algapi_shutdown(pdev); + + of_node_put(dev_node); +} + +static int __init caam_algapi_init(void) +{ + struct device_node *dev_node; + struct platform_device *pdev; + int stat; + + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) + return -ENODEV; + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return -ENODEV; + + stat = caam_algapi_startup(pdev); + + of_node_put(dev_node); + + return stat; +} module_init(caam_algapi_init); module_exit(caam_algapi_exit); @@ -1266,3 +2352,4 @@ module_exit(caam_algapi_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("FSL CAAM support for crypto API"); MODULE_AUTHOR("Freescale Semiconductor - NMG/STC"); +#endif diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c new file mode 100644 index 000000000000..93f42a220a32 --- /dev/null +++ b/drivers/crypto/caam/caamhash.c @@ -0,0 +1,1969 @@ +/* + * caam - Freescale FSL CAAM support for ahash functions of crypto API + * + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. + * + * Based on caamalg.c crypto API driver. + * + * relationship of digest job descriptor or first job descriptor after init to + * shared descriptors: + * + * --------------- --------------- + * | JobDesc #1 |-------------------->| ShareDesc | + * | *(packet 1) | | (hashKey) | + * --------------- | (operation) | + * --------------- + * + * relationship of subsequent job descriptors to shared descriptors: + * + * --------------- --------------- + * | JobDesc #2 |-------------------->| ShareDesc | + * | *(packet 2) | |------------->| (hashKey) | + * --------------- | |-------->| (operation) | + * . | | | (load ctx2) | + * . | | --------------- + * --------------- | | + * | JobDesc #3 |------| | + * | *(packet 3) | | + * --------------- | + * . | + * . | + * --------------- | + * | JobDesc #4 |------------ + * | *(packet 4) | + * --------------- + * + * The SharedDesc never changes for a connection unless rekeyed, but + * each packet will likely be in a different place. So all we need + * to know to process the packet is where the input is, where the + * output goes, and what context we want to process with. Context is + * in the SharedDesc, packet references in the JobDesc. + * + * So, a job desc looks like: + * + * --------------------- + * | Header | + * | ShareDesc Pointer | + * | SEQ_OUT_PTR | + * | (output buffer) | + * | (output length) | + * | SEQ_IN_PTR | + * | (input buffer) | + * | (input length) | + * --------------------- + */ + +#include "compat.h" + +#include "regs.h" +#include "intern.h" +#include "desc_constr.h" +#include "jr.h" +#include "error.h" +#include "sg_sw_sec4.h" +#include "key_gen.h" + +#define CAAM_CRA_PRIORITY 3000 + +/* max hash key is max split key size */ +#define CAAM_MAX_HASH_KEY_SIZE (SHA512_DIGEST_SIZE * 2) + +#define CAAM_MAX_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE +#define CAAM_MAX_HASH_DIGEST_SIZE SHA512_DIGEST_SIZE + +/* length of descriptors text */ +#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3) + +#define DESC_AHASH_BASE (4 * CAAM_CMD_SZ) +#define DESC_AHASH_UPDATE_LEN (6 * CAAM_CMD_SZ) +#define DESC_AHASH_UPDATE_FIRST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ) +#define DESC_AHASH_FINAL_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ) +#define DESC_AHASH_FINUP_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ) +#define DESC_AHASH_DIGEST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ) + +#define DESC_HASH_MAX_USED_BYTES (DESC_AHASH_FINAL_LEN + \ + CAAM_MAX_HASH_KEY_SIZE) +#define DESC_HASH_MAX_USED_LEN (DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ) + +/* caam context sizes for hashes: running digest + 8 */ +#define HASH_MSG_LEN 8 +#define MAX_CTX_LEN (HASH_MSG_LEN + SHA512_DIGEST_SIZE) + +#ifdef DEBUG +/* for print_hex_dumps with line references */ +#define xstr(s) str(s) +#define str(s) #s +#define debug(format, arg...) printk(format, arg) +#else +#define debug(format, arg...) +#endif + +/* ahash per-session context */ +struct caam_hash_ctx { + struct device *jrdev; + u32 sh_desc_update[DESC_HASH_MAX_USED_LEN]; + u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN]; + u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN]; + u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN]; + u32 sh_desc_finup[DESC_HASH_MAX_USED_LEN]; + dma_addr_t sh_desc_update_dma; + dma_addr_t sh_desc_update_first_dma; + dma_addr_t sh_desc_fin_dma; + dma_addr_t sh_desc_digest_dma; + dma_addr_t sh_desc_finup_dma; + u32 alg_type; + u32 alg_op; + u8 key[CAAM_MAX_HASH_KEY_SIZE]; + dma_addr_t key_dma; + int ctx_len; + unsigned int split_key_len; + unsigned int split_key_pad_len; +}; + +/* ahash state */ +struct caam_hash_state { + dma_addr_t buf_dma; + dma_addr_t ctx_dma; + u8 buf_0[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned; + int buflen_0; + u8 buf_1[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned; + int buflen_1; + u8 caam_ctx[MAX_CTX_LEN]; + int (*update)(struct ahash_request *req); + int (*final)(struct ahash_request *req); + int (*finup)(struct ahash_request *req); + int current_buf; +}; + +/* Common job descriptor seq in/out ptr routines */ + +/* Map state->caam_ctx, and append seq_out_ptr command that points to it */ +static inline void map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev, + struct caam_hash_state *state, + int ctx_len) +{ + state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, + ctx_len, DMA_FROM_DEVICE); + append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0); +} + +/* Map req->result, and append seq_out_ptr command that points to it */ +static inline dma_addr_t map_seq_out_ptr_result(u32 *desc, struct device *jrdev, + u8 *result, int digestsize) +{ + dma_addr_t dst_dma; + + dst_dma = dma_map_single(jrdev, result, digestsize, DMA_FROM_DEVICE); + append_seq_out_ptr(desc, dst_dma, digestsize, 0); + + return dst_dma; +} + +/* Map current buffer in state and put it in link table */ +static inline dma_addr_t buf_map_to_sec4_sg(struct device *jrdev, + struct sec4_sg_entry *sec4_sg, + u8 *buf, int buflen) +{ + dma_addr_t buf_dma; + + buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE); + dma_sync_single_for_device(jrdev, buf_dma, buflen, DMA_TO_DEVICE); + dma_to_sec4_sg_one(sec4_sg, buf_dma, buflen, 0); + + return buf_dma; +} + +/* Map req->src and put it in link table */ +static inline void src_map_to_sec4_sg(struct device *jrdev, + struct scatterlist *src, int src_nents, + struct sec4_sg_entry *sec4_sg, + bool chained) +{ + dma_map_sg_chained(jrdev, src, src_nents, DMA_TO_DEVICE, chained); + sg_to_sec4_sg_last(src, src_nents, sec4_sg, 0); +} + +/* + * Only put buffer in link table if it contains data, which is possible, + * since a buffer has previously been used, and needs to be unmapped, + */ +static inline dma_addr_t +try_buf_map_to_sec4_sg(struct device *jrdev, struct sec4_sg_entry *sec4_sg, + u8 *buf, dma_addr_t buf_dma, int buflen, + int last_buflen) +{ + if (buf_dma && !dma_mapping_error(jrdev, buf_dma)) + dma_unmap_single(jrdev, buf_dma, last_buflen, DMA_TO_DEVICE); + if (buflen) + buf_dma = buf_map_to_sec4_sg(jrdev, sec4_sg, buf, buflen); + else + buf_dma = 0; + + return buf_dma; +} + +/* Map state->caam_ctx, and add it to link table */ +static inline void ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev, + struct caam_hash_state *state, + int ctx_len, + struct sec4_sg_entry *sec4_sg, + u32 flag) +{ + state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag); + if ((flag == DMA_TO_DEVICE) || (flag == DMA_BIDIRECTIONAL)) + dma_sync_single_for_device(jrdev, state->ctx_dma, ctx_len, + flag); + dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0); +} + +/* Common shared descriptor commands */ +static inline void append_key_ahash(u32 *desc, struct caam_hash_ctx *ctx) +{ + append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len, + ctx->split_key_len, CLASS_2 | + KEY_DEST_MDHA_SPLIT | KEY_ENC); +} + +/* Append key if it has been set */ +static inline void init_sh_desc_key_ahash(u32 *desc, struct caam_hash_ctx *ctx) +{ + u32 *key_jump_cmd; + + init_sh_desc(desc, HDR_SHARE_SERIAL); + + if (ctx->split_key_len) { + /* Skip if already shared */ + key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | + JUMP_COND_SHRD); + + append_key_ahash(desc, ctx); + + set_jump_tgt_here(desc, key_jump_cmd); + } + + /* Propagate errors from shared to job descriptor */ + append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD); +} + +/* + * For ahash read data from seqin following state->caam_ctx, + * and write resulting class2 context to seqout, which may be state->caam_ctx + * or req->result + */ +static inline void ahash_append_load_str(u32 *desc, int digestsize) +{ + /* Calculate remaining bytes to read */ + append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); + + /* Read remaining bytes */ + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_LAST2 | + FIFOLD_TYPE_MSG | KEY_VLF); + + /* Store class2 context bytes */ + append_seq_store(desc, digestsize, LDST_CLASS_2_CCB | + LDST_SRCDST_BYTE_CONTEXT); +} + +/* + * For ahash update, final and finup, import context, read and write to seqout + */ +static inline void ahash_ctx_data_to_out(u32 *desc, u32 op, u32 state, + int digestsize, + struct caam_hash_ctx *ctx) +{ + init_sh_desc_key_ahash(desc, ctx); + + /* Import context from software */ + append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT | + LDST_CLASS_2_CCB | ctx->ctx_len); + + /* Class 2 operation */ + append_operation(desc, op | state | OP_ALG_ENCRYPT); + + /* + * Load from buf and/or src and write to req->result or state->context + */ + ahash_append_load_str(desc, digestsize); +} + +/* For ahash firsts and digest, read and write to seqout */ +static inline void ahash_data_to_out(u32 *desc, u32 op, u32 state, + int digestsize, struct caam_hash_ctx *ctx) +{ + init_sh_desc_key_ahash(desc, ctx); + + /* Class 2 operation */ + append_operation(desc, op | state | OP_ALG_ENCRYPT); + + /* + * Load from buf and/or src and write to req->result or state->context + */ + ahash_append_load_str(desc, digestsize); +} + +static int ahash_set_sh_desc(struct crypto_ahash *ahash) +{ + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + int digestsize = crypto_ahash_digestsize(ahash); + struct device *jrdev = ctx->jrdev; + u32 have_key = 0; + u32 *desc; + + if (ctx->split_key_len) + have_key = OP_ALG_AAI_HMAC_PRECOMP; + + /* ahash_update shared descriptor */ + desc = ctx->sh_desc_update; + + init_sh_desc(desc, HDR_SHARE_SERIAL); + + /* Import context from software */ + append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT | + LDST_CLASS_2_CCB | ctx->ctx_len); + + /* Class 2 operation */ + append_operation(desc, ctx->alg_type | OP_ALG_AS_UPDATE | + OP_ALG_ENCRYPT); + + /* Load data and write to result or context */ + ahash_append_load_str(desc, ctx->ctx_len); + + ctx->sh_desc_update_dma = dma_map_single(jrdev, desc, desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_update_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); + return -ENOMEM; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ahash update shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + + /* ahash_update_first shared descriptor */ + desc = ctx->sh_desc_update_first; + + ahash_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INIT, + ctx->ctx_len, ctx); + + ctx->sh_desc_update_first_dma = dma_map_single(jrdev, desc, + desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_update_first_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); + return -ENOMEM; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ahash update first shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma, + desc_bytes(desc), DMA_TO_DEVICE); + + /* ahash_final shared descriptor */ + desc = ctx->sh_desc_fin; + + ahash_ctx_data_to_out(desc, have_key | ctx->alg_type, + OP_ALG_AS_FINALIZE, digestsize, ctx); + + ctx->sh_desc_fin_dma = dma_map_single(jrdev, desc, desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_fin_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); + return -ENOMEM; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ahash final shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma, + desc_bytes(desc), DMA_TO_DEVICE); + + /* ahash_finup shared descriptor */ + desc = ctx->sh_desc_finup; + + ahash_ctx_data_to_out(desc, have_key | ctx->alg_type, + OP_ALG_AS_FINALIZE, digestsize, ctx); + + ctx->sh_desc_finup_dma = dma_map_single(jrdev, desc, desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_finup_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); + return -ENOMEM; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ahash finup shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + dma_sync_single_for_device(jrdev, ctx->sh_desc_finup_dma, + desc_bytes(desc), DMA_TO_DEVICE); + + /* ahash_digest shared descriptor */ + desc = ctx->sh_desc_digest; + + ahash_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INITFINAL, + digestsize, ctx); + + ctx->sh_desc_digest_dma = dma_map_single(jrdev, desc, + desc_bytes(desc), + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->sh_desc_digest_dma)) { + dev_err(jrdev, "unable to map shared descriptor\n"); + return -ENOMEM; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ahash digest shdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma, + desc_bytes(desc), DMA_TO_DEVICE); + + return 0; +} + +static u32 gen_split_hash_key(struct caam_hash_ctx *ctx, const u8 *key_in, + u32 keylen) +{ + return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len, + ctx->split_key_pad_len, key_in, keylen, + ctx->alg_op); +} + +/* Digest hash size if it is too large */ +static u32 hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in, + u32 *keylen, u8 *key_out, u32 digestsize) +{ + struct device *jrdev = ctx->jrdev; + u32 *desc; + struct split_key_result result; + dma_addr_t src_dma, dst_dma; + int ret = 0; + + /* + * Hashing descriptor is 6 commands (including header), 2 pointers, + * and 2 extended lengths + */ + desc = kmalloc((CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2 + + CAAM_EXTLEN_SZ * 2), + GFP_KERNEL | GFP_DMA); + + init_job_desc(desc, 0); + + src_dma = dma_map_single(jrdev, (void *)key_in, *keylen, + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, src_dma)) { + dev_err(jrdev, "unable to map key input memory\n"); + kfree(desc); + return -ENOMEM; + } + dma_sync_single_for_device(jrdev, src_dma, *keylen, DMA_TO_DEVICE); + + dst_dma = dma_map_single(jrdev, (void *)key_out, digestsize, + DMA_FROM_DEVICE); + if (dma_mapping_error(jrdev, dst_dma)) { + dev_err(jrdev, "unable to map key output memory\n"); + dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE); + kfree(desc); + return -ENOMEM; + } + + /* Job descriptor to perform unkeyed hash on key_in */ + append_operation(desc, ctx->alg_type | OP_ALG_ENCRYPT | + OP_ALG_AS_INITFINAL); + append_seq_in_ptr(desc, src_dma, *keylen, 0); + append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 | + FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG); + append_seq_out_ptr(desc, dst_dma, digestsize, 0); + append_seq_store(desc, digestsize, LDST_CLASS_2_CCB | + LDST_SRCDST_BYTE_CONTEXT); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "key_in@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key_in, *keylen, 1); + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + + result.err = 0; + init_completion(&result.completion); + + ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); + if (!ret) { + /* in progress */ + wait_for_completion_interruptible(&result.completion); + ret = result.err; +#ifdef DEBUG + print_hex_dump(KERN_ERR, "digested key@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key_in, + digestsize, 1); +#endif + } + *keylen = digestsize; + + dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE); + dma_sync_single_for_cpu(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE); + dma_unmap_single(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE); + + kfree(desc); + + return ret; +} + +static int ahash_setkey(struct crypto_ahash *ahash, + const u8 *key, unsigned int keylen) +{ + /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */ + static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 }; + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct device *jrdev = ctx->jrdev; + int blocksize = crypto_tfm_alg_blocksize(&ahash->base); + int digestsize = crypto_ahash_digestsize(ahash); + int ret = 0; + u8 *hashed_key = NULL; +#ifdef DEBUG + printk(KERN_ERR "keylen %d\n", keylen); +#endif + + if (keylen > blocksize) { + hashed_key = kmalloc(sizeof(u8) * digestsize, GFP_KERNEL | + GFP_DMA); + if (!hashed_key) + return -ENOMEM; + ret = hash_digest_key(ctx, key, &keylen, hashed_key, + digestsize); + if (ret) + goto badkey; + key = hashed_key; + } + + /* Pick class 2 key length from algorithm submask */ + ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >> + OP_ALG_ALGSEL_SHIFT] * 2; + ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16); + +#ifdef DEBUG + printk(KERN_ERR "split_key_len %d split_key_pad_len %d\n", + ctx->split_key_len, ctx->split_key_pad_len); + print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); +#endif + + ret = gen_split_hash_key(ctx, key, keylen); + if (ret) + goto badkey; + + ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len, + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, ctx->key_dma)) { + dev_err(jrdev, "unable to map key i/o memory\n"); + return -ENOMEM; + } + + dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->split_key_pad_len, + DMA_TO_DEVICE); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, + ctx->split_key_pad_len, 1); +#endif + + ret = ahash_set_sh_desc(ahash); + if (ret) { + dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len, + DMA_TO_DEVICE); + } + + kfree(hashed_key); + return ret; +badkey: + kfree(hashed_key); + crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; +} + +/* + * ahash_edesc - s/w-extended ahash descriptor + * @dst_dma: physical mapped address of req->result + * @sec4_sg_dma: physical mapped address of h/w link table + * @chained: if source is chained + * @src_nents: number of segments in input scatterlist + * @sec4_sg_bytes: length of dma mapped sec4_sg space + * @sec4_sg: pointer to h/w link table + * @hw_desc: the h/w job descriptor followed by any referenced link tables + */ +struct ahash_edesc { + dma_addr_t dst_dma; + dma_addr_t sec4_sg_dma; + bool chained; + int src_nents; + int sec4_sg_bytes; + struct sec4_sg_entry *sec4_sg; + u32 hw_desc[0]; +}; + +static inline void ahash_unmap(struct device *dev, + struct ahash_edesc *edesc, + struct ahash_request *req, int dst_len) +{ + if (edesc->src_nents) + dma_unmap_sg_chained(dev, req->src, edesc->src_nents, + DMA_TO_DEVICE, edesc->chained); + if (edesc->dst_dma) { + dma_sync_single_for_cpu(dev, edesc->dst_dma, dst_len, + DMA_FROM_DEVICE); + dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE); + } + + if (edesc->sec4_sg_bytes) + dma_unmap_single(dev, edesc->sec4_sg_dma, + edesc->sec4_sg_bytes, DMA_TO_DEVICE); +} + +static inline void ahash_unmap_ctx(struct device *dev, + struct ahash_edesc *edesc, + struct ahash_request *req, int dst_len, u32 flag) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + if (state->ctx_dma) { + if ((flag == DMA_FROM_DEVICE) || (flag == DMA_BIDIRECTIONAL)) + dma_sync_single_for_cpu(dev, state->ctx_dma, + ctx->ctx_len, flag); + dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag); + } + ahash_unmap(dev, edesc, req, dst_len); +} + +static void ahash_done(struct device *jrdev, u32 *desc, u32 err, + void *context) +{ + struct ahash_request *req = context; + struct ahash_edesc *edesc; + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + int digestsize = crypto_ahash_digestsize(ahash); +#ifdef DEBUG + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + + dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); +#endif + + edesc = (struct ahash_edesc *)((char *)desc - + offsetof(struct ahash_edesc, hw_desc)); + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + + ahash_unmap(jrdev, edesc, req, digestsize); + kfree(edesc); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, + ctx->ctx_len, 1); + if (req->result) + print_hex_dump(KERN_ERR, "result@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->result, + digestsize, 1); +#endif + + req->base.complete(&req->base, err); +} + +static void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err, + void *context) +{ + struct ahash_request *req = context; + struct ahash_edesc *edesc; + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); +#ifdef DEBUG + struct caam_hash_state *state = ahash_request_ctx(req); + int digestsize = crypto_ahash_digestsize(ahash); + + dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); +#endif + + edesc = (struct ahash_edesc *)((char *)desc - + offsetof(struct ahash_edesc, hw_desc)); + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + + ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL); + kfree(edesc); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, + ctx->ctx_len, 1); + if (req->result) + print_hex_dump(KERN_ERR, "result@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->result, + digestsize, 1); +#endif + + req->base.complete(&req->base, err); +} + +static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err, + void *context) +{ + struct ahash_request *req = context; + struct ahash_edesc *edesc; + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + int digestsize = crypto_ahash_digestsize(ahash); +#ifdef DEBUG + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + + dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); +#endif + + edesc = (struct ahash_edesc *)((char *)desc - + offsetof(struct ahash_edesc, hw_desc)); + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + + ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE); + kfree(edesc); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, + ctx->ctx_len, 1); + if (req->result) + print_hex_dump(KERN_ERR, "result@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->result, + digestsize, 1); +#endif + + req->base.complete(&req->base, err); +} + +static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err, + void *context) +{ + struct ahash_request *req = context; + struct ahash_edesc *edesc; + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); +#ifdef DEBUG + struct caam_hash_state *state = ahash_request_ctx(req); + int digestsize = crypto_ahash_digestsize(ahash); + + dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); +#endif + + edesc = (struct ahash_edesc *)((char *)desc - + offsetof(struct ahash_edesc, hw_desc)); + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + + ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE); + kfree(edesc); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, + ctx->ctx_len, 1); + if (req->result) + print_hex_dump(KERN_ERR, "result@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, req->result, + digestsize, 1); +#endif + + req->base.complete(&req->base, err); +} + +/* submit update job descriptor */ +static int ahash_update_ctx(struct ahash_request *req) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + u8 *buf = state->current_buf ? state->buf_1 : state->buf_0; + int *buflen = state->current_buf ? &state->buflen_1 : &state->buflen_0; + u8 *next_buf = state->current_buf ? state->buf_0 : state->buf_1; + int *next_buflen = state->current_buf ? &state->buflen_0 : + &state->buflen_1, last_buflen; + int in_len = *buflen + req->nbytes, to_hash; + u32 *sh_desc = ctx->sh_desc_update, *desc; + dma_addr_t ptr = ctx->sh_desc_update_dma; + int src_nents, sec4_sg_bytes, sec4_sg_src_index; + struct ahash_edesc *edesc; + bool chained = false; + int ret = 0; + int sh_len; + + last_buflen = *next_buflen; + *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1); + to_hash = in_len - *next_buflen; + + if (to_hash) { + src_nents = __sg_count(req->src, req->nbytes - (*next_buflen), + &chained); + sec4_sg_src_index = 1 + (*buflen ? 1 : 0); + sec4_sg_bytes = (sec4_sg_src_index + src_nents) * + sizeof(struct sec4_sg_entry); + + /* + * allocate space for base edesc and hw desc commands, + * link tables + */ + edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN + + sec4_sg_bytes, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, + "could not allocate extended descriptor\n"); + return -ENOMEM; + } + + edesc->src_nents = src_nents; + edesc->chained = chained; + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + + DESC_JOB_IO_LEN; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, + DMA_TO_DEVICE); + + ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, + edesc->sec4_sg, DMA_BIDIRECTIONAL); + + state->buf_dma = try_buf_map_to_sec4_sg(jrdev, + edesc->sec4_sg + 1, + buf, state->buf_dma, + *buflen, last_buflen); + + if (src_nents) { + src_map_to_sec4_sg(jrdev, req->src, src_nents, + edesc->sec4_sg + sec4_sg_src_index, + chained); + if (*next_buflen) { + sg_copy_part(next_buf, req->src, to_hash - + *buflen, req->nbytes); + state->current_buf = !state->current_buf; + } + } else { + (edesc->sec4_sg + sec4_sg_src_index - 1)->len |= + SEC4_SG_LEN_FIN; + } + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; + init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | + HDR_REVERSE); + + append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + + to_hash, LDST_SGF); + + append_seq_out_ptr(desc, state->ctx_dma, ctx->ctx_len, 0); + + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, + sec4_sg_bytes, DMA_TO_DEVICE); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + + ret = caam_jr_enqueue(jrdev, desc, ahash_done_bi, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, + DMA_BIDIRECTIONAL); + kfree(edesc); + } + } else if (*next_buflen) { + sg_copy(buf + *buflen, req->src, req->nbytes); + *buflen = *next_buflen; + *next_buflen = last_buflen; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "buf@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, buf, *buflen, 1); + print_hex_dump(KERN_ERR, "next buf@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, next_buf, + *next_buflen, 1); +#endif + + return ret; +} + +static int ahash_final_ctx(struct ahash_request *req) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + u8 *buf = state->current_buf ? state->buf_1 : state->buf_0; + int buflen = state->current_buf ? state->buflen_1 : state->buflen_0; + int last_buflen = state->current_buf ? state->buflen_0 : + state->buflen_1; + u32 *sh_desc = ctx->sh_desc_fin, *desc; + dma_addr_t ptr = ctx->sh_desc_fin_dma; + int sec4_sg_bytes; + int digestsize = crypto_ahash_digestsize(ahash); + struct ahash_edesc *edesc; + int ret = 0; + int sh_len; + + sec4_sg_bytes = (1 + (buflen ? 1 : 0)) * sizeof(struct sec4_sg_entry); + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN + + sec4_sg_bytes, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, "could not allocate extended descriptor\n"); + return -ENOMEM; + } + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; + init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); + + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + + DESC_JOB_IO_LEN; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, DMA_TO_DEVICE); + edesc->src_nents = 0; + + ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, edesc->sec4_sg, + DMA_TO_DEVICE); + + state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, + buf, state->buf_dma, buflen, + last_buflen); + (edesc->sec4_sg + sec4_sg_bytes - 1)->len |= SEC4_SG_LEN_FIN; + + append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen, + LDST_SGF); + + edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, + digestsize); + + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes, + DMA_TO_DEVICE); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + + ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_src, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE); + kfree(edesc); + } + + return ret; +} + +static int ahash_finup_ctx(struct ahash_request *req) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + u8 *buf = state->current_buf ? state->buf_1 : state->buf_0; + int buflen = state->current_buf ? state->buflen_1 : state->buflen_0; + int last_buflen = state->current_buf ? state->buflen_0 : + state->buflen_1; + u32 *sh_desc = ctx->sh_desc_finup, *desc; + dma_addr_t ptr = ctx->sh_desc_finup_dma; + int sec4_sg_bytes, sec4_sg_src_index; + int src_nents; + int digestsize = crypto_ahash_digestsize(ahash); + struct ahash_edesc *edesc; + bool chained = false; + int ret = 0; + int sh_len; + + src_nents = __sg_count(req->src, req->nbytes, &chained); + sec4_sg_src_index = 1 + (buflen ? 1 : 0); + sec4_sg_bytes = (sec4_sg_src_index + src_nents) * + sizeof(struct sec4_sg_entry); + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN + + sec4_sg_bytes, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, "could not allocate extended descriptor\n"); + return -ENOMEM; + } + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; + init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); + + edesc->src_nents = src_nents; + edesc->chained = chained; + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + + DESC_JOB_IO_LEN; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, DMA_TO_DEVICE); + + ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, edesc->sec4_sg, + DMA_TO_DEVICE); + + state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, + buf, state->buf_dma, buflen, + last_buflen); + + src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + + sec4_sg_src_index, chained); + + append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + + buflen + req->nbytes, LDST_SGF); + + edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, + digestsize); + + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes, + DMA_TO_DEVICE); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + + ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_src, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE); + kfree(edesc); + } + + return ret; +} + +static int ahash_digest(struct ahash_request *req) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + u32 *sh_desc = ctx->sh_desc_digest, *desc; + dma_addr_t ptr = ctx->sh_desc_digest_dma; + int digestsize = crypto_ahash_digestsize(ahash); + int src_nents, sec4_sg_bytes; + dma_addr_t src_dma; + struct ahash_edesc *edesc; + bool chained = false; + int ret = 0; + u32 options; + int sh_len; + + src_nents = sg_count(req->src, req->nbytes, &chained); + dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE, + chained); + sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry); + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kzalloc(sizeof(struct ahash_edesc) + sec4_sg_bytes + + DESC_JOB_IO_LEN, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, "could not allocate extended descriptor\n"); + return -ENOMEM; + } + edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + + DESC_JOB_IO_LEN; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, DMA_TO_DEVICE); + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->src_nents = src_nents; + edesc->chained = chained; + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; + init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); + + if (src_nents) { + sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0); + src_dma = edesc->sec4_sg_dma; + options = LDST_SGF; + } else { + src_dma = sg_dma_address(req->src); + options = 0; + } + append_seq_in_ptr(desc, src_dma, req->nbytes, options); + + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, + edesc->sec4_sg_bytes, DMA_TO_DEVICE); + + edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, + digestsize); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + + ret = caam_jr_enqueue(jrdev, desc, ahash_done, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + ahash_unmap(jrdev, edesc, req, digestsize); + kfree(edesc); + } + + return ret; +} + +/* submit ahash final if it the first job descriptor */ +static int ahash_final_no_ctx(struct ahash_request *req) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + u8 *buf = state->current_buf ? state->buf_1 : state->buf_0; + int buflen = state->current_buf ? state->buflen_1 : state->buflen_0; + u32 *sh_desc = ctx->sh_desc_digest, *desc; + dma_addr_t ptr = ctx->sh_desc_digest_dma; + int digestsize = crypto_ahash_digestsize(ahash); + struct ahash_edesc *edesc; + int ret = 0; + int sh_len; + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN, + GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, "could not allocate extended descriptor\n"); + return -ENOMEM; + } + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; + init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); + + state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE); + + append_seq_in_ptr(desc, state->buf_dma, buflen, 0); + + edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, + digestsize); + edesc->src_nents = 0; + + dma_sync_single_for_device(jrdev, state->buf_dma, buflen, + DMA_TO_DEVICE); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + + ret = caam_jr_enqueue(jrdev, desc, ahash_done, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + ahash_unmap(jrdev, edesc, req, digestsize); + kfree(edesc); + } + + return ret; +} + +/* submit ahash update if it the first job descriptor after update */ +static int ahash_update_no_ctx(struct ahash_request *req) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + u8 *buf = state->current_buf ? state->buf_1 : state->buf_0; + int *buflen = state->current_buf ? &state->buflen_1 : &state->buflen_0; + u8 *next_buf = state->current_buf ? state->buf_0 : state->buf_1; + int *next_buflen = state->current_buf ? &state->buflen_0 : + &state->buflen_1; + int in_len = *buflen + req->nbytes, to_hash; + int sec4_sg_bytes, src_nents; + struct ahash_edesc *edesc; + u32 *desc, *sh_desc = ctx->sh_desc_update_first; + dma_addr_t ptr = ctx->sh_desc_update_first_dma; + bool chained = false; + int ret = 0; + int sh_len; + + *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1); + to_hash = in_len - *next_buflen; + + if (to_hash) { + src_nents = __sg_count(req->src, req->nbytes - (*next_buflen), + &chained); + sec4_sg_bytes = (1 + src_nents) * + sizeof(struct sec4_sg_entry); + + /* + * allocate space for base edesc and hw desc commands, + * link tables + */ + edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN + + sec4_sg_bytes, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, + "could not allocate extended descriptor\n"); + return -ENOMEM; + } + + edesc->src_nents = src_nents; + edesc->chained = chained; + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + + DESC_JOB_IO_LEN; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, + DMA_TO_DEVICE); + + state->buf_dma = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, + buf, *buflen); + src_map_to_sec4_sg(jrdev, req->src, src_nents, + edesc->sec4_sg + 1, chained); + if (*next_buflen) { + sg_copy_part(next_buf, req->src, to_hash - *buflen, + req->nbytes); + state->current_buf = !state->current_buf; + } + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; + init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | + HDR_REVERSE); + + append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF); + + map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len); + + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, + sec4_sg_bytes, DMA_TO_DEVICE); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + + ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_dst, req); + if (!ret) { + ret = -EINPROGRESS; + state->update = ahash_update_ctx; + state->finup = ahash_finup_ctx; + state->final = ahash_final_ctx; + } else { + ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, + DMA_TO_DEVICE); + kfree(edesc); + } + } else if (*next_buflen) { + sg_copy(buf + *buflen, req->src, req->nbytes); + *buflen = *next_buflen; + *next_buflen = 0; + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "buf@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, buf, *buflen, 1); + print_hex_dump(KERN_ERR, "next buf@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, next_buf, + *next_buflen, 1); +#endif + + return ret; +} + +/* submit ahash finup if it the first job descriptor after update */ +static int ahash_finup_no_ctx(struct ahash_request *req) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + u8 *buf = state->current_buf ? state->buf_1 : state->buf_0; + int buflen = state->current_buf ? state->buflen_1 : state->buflen_0; + int last_buflen = state->current_buf ? state->buflen_0 : + state->buflen_1; + u32 *sh_desc = ctx->sh_desc_digest, *desc; + dma_addr_t ptr = ctx->sh_desc_digest_dma; + int sec4_sg_bytes, sec4_sg_src_index, src_nents; + int digestsize = crypto_ahash_digestsize(ahash); + struct ahash_edesc *edesc; + bool chained = false; + int sh_len; + int ret = 0; + + src_nents = __sg_count(req->src, req->nbytes, &chained); + sec4_sg_src_index = 2; + sec4_sg_bytes = (sec4_sg_src_index + src_nents) * + sizeof(struct sec4_sg_entry); + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN + + sec4_sg_bytes, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, "could not allocate extended descriptor\n"); + return -ENOMEM; + } + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; + init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); + + edesc->src_nents = src_nents; + edesc->chained = chained; + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + + DESC_JOB_IO_LEN; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, DMA_TO_DEVICE); + + state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, buf, + state->buf_dma, buflen, + last_buflen); + + src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1, + chained); + + append_seq_in_ptr(desc, edesc->sec4_sg_dma, buflen + + req->nbytes, LDST_SGF); + + edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result, + digestsize); + + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes, + DMA_TO_DEVICE); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + + ret = caam_jr_enqueue(jrdev, desc, ahash_done, req); + if (!ret) { + ret = -EINPROGRESS; + } else { + ahash_unmap(jrdev, edesc, req, digestsize); + kfree(edesc); + } + + return ret; +} + +/* submit first update job descriptor after init */ +static int ahash_update_first(struct ahash_request *req) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; + u8 *next_buf = state->buf_0 + state->current_buf * + CAAM_MAX_HASH_BLOCK_SIZE; + int *next_buflen = &state->buflen_0 + state->current_buf; + int to_hash; + u32 *sh_desc = ctx->sh_desc_update_first, *desc; + dma_addr_t ptr = ctx->sh_desc_update_first_dma; + int sec4_sg_bytes, src_nents; + dma_addr_t src_dma; + u32 options; + struct ahash_edesc *edesc; + bool chained = false; + int ret = 0; + int sh_len; + + *next_buflen = req->nbytes & (crypto_tfm_alg_blocksize(&ahash->base) - + 1); + to_hash = req->nbytes - *next_buflen; + + if (to_hash) { + src_nents = sg_count(req->src, req->nbytes - (*next_buflen), + &chained); + dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, + DMA_TO_DEVICE, chained); + sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry); + + /* + * allocate space for base edesc and hw desc commands, + * link tables + */ + edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN + + sec4_sg_bytes, GFP_DMA | flags); + if (!edesc) { + dev_err(jrdev, + "could not allocate extended descriptor\n"); + return -ENOMEM; + } + + edesc->src_nents = src_nents; + edesc->chained = chained; + edesc->sec4_sg_bytes = sec4_sg_bytes; + edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + + DESC_JOB_IO_LEN; + edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, + sec4_sg_bytes, + DMA_TO_DEVICE); + + if (src_nents) { + sg_to_sec4_sg_last(req->src, src_nents, + edesc->sec4_sg, 0); + src_dma = edesc->sec4_sg_dma; + options = LDST_SGF; + } else { + src_dma = sg_dma_address(req->src); + options = 0; + } + + if (*next_buflen) + sg_copy_part(next_buf, req->src, to_hash, req->nbytes); + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; + init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | + HDR_REVERSE); + + append_seq_in_ptr(desc, src_dma, to_hash, options); + + map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len); + + dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, + sec4_sg_bytes, DMA_TO_DEVICE); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, + desc_bytes(desc), 1); +#endif + + ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_dst, + req); + if (!ret) { + ret = -EINPROGRESS; + state->update = ahash_update_ctx; + state->finup = ahash_finup_ctx; + state->final = ahash_final_ctx; + } else { + ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, + DMA_TO_DEVICE); + kfree(edesc); + } + } else if (*next_buflen) { + state->update = ahash_update_no_ctx; + state->finup = ahash_finup_no_ctx; + state->final = ahash_final_no_ctx; + sg_copy(next_buf, req->src, req->nbytes); + } +#ifdef DEBUG + print_hex_dump(KERN_ERR, "next buf@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, next_buf, + *next_buflen, 1); +#endif + + return ret; +} + +static int ahash_finup_first(struct ahash_request *req) +{ + return ahash_digest(req); +} + +static int ahash_init(struct ahash_request *req) +{ + struct caam_hash_state *state = ahash_request_ctx(req); + /* ENGR00233800: CAAM: running sha_speed in cryptodev crashed */ + memset(state, 0, sizeof(struct caam_hash_state)); + + state->update = ahash_update_first; + state->finup = ahash_finup_first; + state->final = ahash_final_no_ctx; + /* ENGR00233800: CAAM: running sha_speed in cryptodev crashed */ +/* state->current_buf = 0; + state->buflen_0 = 0; + state->buflen_1 = 0; +*/ + return 0; +} + +static int ahash_update(struct ahash_request *req) +{ + struct caam_hash_state *state = ahash_request_ctx(req); + return state->update(req); +} + +static int ahash_finup(struct ahash_request *req) +{ + struct caam_hash_state *state = ahash_request_ctx(req); + + return state->finup(req); +} + +static int ahash_final(struct ahash_request *req) +{ + struct caam_hash_state *state = ahash_request_ctx(req); + + return state->final(req); +} + +static int ahash_export(struct ahash_request *req, void *out) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + + memcpy(out, ctx, sizeof(struct caam_hash_ctx)); + memcpy(out + sizeof(struct caam_hash_ctx), state, + sizeof(struct caam_hash_state)); + return 0; +} + +static int ahash_import(struct ahash_request *req, const void *in) +{ + struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); + struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); + struct caam_hash_state *state = ahash_request_ctx(req); + + memcpy(ctx, in, sizeof(struct caam_hash_ctx)); + memcpy(state, in + sizeof(struct caam_hash_ctx), + sizeof(struct caam_hash_state)); + return 0; +} + +struct caam_hash_template { + char name[CRYPTO_MAX_ALG_NAME]; + char driver_name[CRYPTO_MAX_ALG_NAME]; + char hmac_name[CRYPTO_MAX_ALG_NAME]; + char hmac_driver_name[CRYPTO_MAX_ALG_NAME]; + unsigned int blocksize; + struct ahash_alg template_ahash; + u32 alg_type; + u32 alg_op; +}; + +/* ahash descriptors */ +static struct caam_hash_template driver_hash[] = { + { + .name = "sha1", + .driver_name = "sha1-caam", + .hmac_name = "hmac(sha1)", + .hmac_driver_name = "hmac-sha1-caam", + .blocksize = SHA1_BLOCK_SIZE, + .template_ahash = { + .init = ahash_init, + .update = ahash_update, + .final = ahash_final, + .finup = ahash_finup, + .digest = ahash_digest, + .export = ahash_export, + .import = ahash_import, + .setkey = ahash_setkey, + .halg = { + .digestsize = SHA1_DIGEST_SIZE, + }, + }, + .alg_type = OP_ALG_ALGSEL_SHA1, + .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC, + }, { + .name = "sha224", + .driver_name = "sha224-caam", + .hmac_name = "hmac(sha224)", + .hmac_driver_name = "hmac-sha224-caam", + .blocksize = SHA224_BLOCK_SIZE, + .template_ahash = { + .init = ahash_init, + .update = ahash_update, + .final = ahash_final, + .finup = ahash_finup, + .digest = ahash_digest, + .export = ahash_export, + .import = ahash_import, + .setkey = ahash_setkey, + .halg = { + .digestsize = SHA224_DIGEST_SIZE, + }, + }, + .alg_type = OP_ALG_ALGSEL_SHA224, + .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC, + }, { + .name = "sha256", + .driver_name = "sha256-caam", + .hmac_name = "hmac(sha256)", + .hmac_driver_name = "hmac-sha256-caam", + .blocksize = SHA256_BLOCK_SIZE, + .template_ahash = { + .init = ahash_init, + .update = ahash_update, + .final = ahash_final, + .finup = ahash_finup, + .digest = ahash_digest, + .export = ahash_export, + .import = ahash_import, + .setkey = ahash_setkey, + .halg = { + .digestsize = SHA256_DIGEST_SIZE, + }, + }, + .alg_type = OP_ALG_ALGSEL_SHA256, + .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC, + }, { + .name = "sha384", + .driver_name = "sha384-caam", + .hmac_name = "hmac(sha384)", + .hmac_driver_name = "hmac-sha384-caam", + .blocksize = SHA384_BLOCK_SIZE, + .template_ahash = { + .init = ahash_init, + .update = ahash_update, + .final = ahash_final, + .finup = ahash_finup, + .digest = ahash_digest, + .export = ahash_export, + .import = ahash_import, + .setkey = ahash_setkey, + .halg = { + .digestsize = SHA384_DIGEST_SIZE, + }, + }, + .alg_type = OP_ALG_ALGSEL_SHA384, + .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC, + }, { + .name = "sha512", + .driver_name = "sha512-caam", + .hmac_name = "hmac(sha512)", + .hmac_driver_name = "hmac-sha512-caam", + .blocksize = SHA512_BLOCK_SIZE, + .template_ahash = { + .init = ahash_init, + .update = ahash_update, + .final = ahash_final, + .finup = ahash_finup, + .digest = ahash_digest, + .export = ahash_export, + .import = ahash_import, + .setkey = ahash_setkey, + .halg = { + .digestsize = SHA512_DIGEST_SIZE, + }, + }, + .alg_type = OP_ALG_ALGSEL_SHA512, + .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC, + }, { + .name = "md5", + .driver_name = "md5-caam", + .hmac_name = "hmac(md5)", + .hmac_driver_name = "hmac-md5-caam", + .blocksize = MD5_BLOCK_WORDS * 4, + .template_ahash = { + .init = ahash_init, + .update = ahash_update, + .final = ahash_final, + .finup = ahash_finup, + .digest = ahash_digest, + .export = ahash_export, + .import = ahash_import, + .setkey = ahash_setkey, + .halg = { + .digestsize = MD5_DIGEST_SIZE, + }, + }, + .alg_type = OP_ALG_ALGSEL_MD5, + .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC, + }, +}; + +struct caam_hash_alg { + struct list_head entry; + struct device *ctrldev; + int alg_type; + int alg_op; + struct ahash_alg ahash_alg; +}; + +static int caam_hash_cra_init(struct crypto_tfm *tfm) +{ + struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); + struct crypto_alg *base = tfm->__crt_alg; + struct hash_alg_common *halg = + container_of(base, struct hash_alg_common, base); + struct ahash_alg *alg = + container_of(halg, struct ahash_alg, halg); + struct caam_hash_alg *caam_hash = + container_of(alg, struct caam_hash_alg, ahash_alg); + struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm); + struct caam_drv_private *priv = dev_get_drvdata(caam_hash->ctrldev); + /* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */ + static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE, + HASH_MSG_LEN + SHA1_DIGEST_SIZE, + HASH_MSG_LEN + 32, + HASH_MSG_LEN + SHA256_DIGEST_SIZE, + HASH_MSG_LEN + 64, + HASH_MSG_LEN + SHA512_DIGEST_SIZE }; + int tgt_jr = atomic_inc_return(&priv->tfm_count); + int ret = 0; + + /* + * distribute tfms across job rings to ensure in-order + * crypto request processing per tfm + */ + ctx->jrdev = priv->jrdev[tgt_jr % priv->total_jobrs]; + + /* copy descriptor header template value */ + ctx->alg_type = OP_TYPE_CLASS2_ALG | caam_hash->alg_type; + ctx->alg_op = OP_TYPE_CLASS2_ALG | caam_hash->alg_op; + + ctx->ctx_len = runninglen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >> + OP_ALG_ALGSEL_SHIFT]; + + crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + sizeof(struct caam_hash_state)); + + ret = ahash_set_sh_desc(ahash); + + return ret; +} + +static void caam_hash_cra_exit(struct crypto_tfm *tfm) +{ + struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm); + + if (ctx->sh_desc_update_dma && + !dma_mapping_error(ctx->jrdev, ctx->sh_desc_update_dma)) + dma_unmap_single(ctx->jrdev, ctx->sh_desc_update_dma, + desc_bytes(ctx->sh_desc_update), + DMA_TO_DEVICE); + if (ctx->sh_desc_update_first_dma && + !dma_mapping_error(ctx->jrdev, ctx->sh_desc_update_first_dma)) + dma_unmap_single(ctx->jrdev, ctx->sh_desc_update_first_dma, + desc_bytes(ctx->sh_desc_update_first), + DMA_TO_DEVICE); + if (ctx->sh_desc_fin_dma && + !dma_mapping_error(ctx->jrdev, ctx->sh_desc_fin_dma)) + dma_unmap_single(ctx->jrdev, ctx->sh_desc_fin_dma, + desc_bytes(ctx->sh_desc_fin), DMA_TO_DEVICE); + if (ctx->sh_desc_digest_dma && + !dma_mapping_error(ctx->jrdev, ctx->sh_desc_digest_dma)) + dma_unmap_single(ctx->jrdev, ctx->sh_desc_digest_dma, + desc_bytes(ctx->sh_desc_digest), + DMA_TO_DEVICE); + if (ctx->sh_desc_finup_dma && + !dma_mapping_error(ctx->jrdev, ctx->sh_desc_finup_dma)) + dma_unmap_single(ctx->jrdev, ctx->sh_desc_finup_dma, + desc_bytes(ctx->sh_desc_finup), DMA_TO_DEVICE); +} + +static struct caam_hash_alg * +caam_hash_alloc(struct device *ctrldev, struct caam_hash_template *template, + bool keyed) +{ + struct caam_hash_alg *t_alg; + struct ahash_alg *halg; + struct crypto_alg *alg; + + t_alg = kzalloc(sizeof(struct caam_hash_alg), GFP_KERNEL); + if (!t_alg) { + dev_err(ctrldev, "failed to allocate t_alg\n"); + return ERR_PTR(-ENOMEM); + } + + t_alg->ahash_alg = template->template_ahash; + halg = &t_alg->ahash_alg; + alg = &halg->halg.base; + + if (keyed) { + snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", + template->hmac_name); + snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + template->hmac_driver_name); + } else { + snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", + template->name); + snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + template->driver_name); + } + alg->cra_module = THIS_MODULE; + alg->cra_init = caam_hash_cra_init; + alg->cra_exit = caam_hash_cra_exit; + alg->cra_ctxsize = sizeof(struct caam_hash_ctx); + alg->cra_priority = CAAM_CRA_PRIORITY; + alg->cra_blocksize = template->blocksize; + alg->cra_alignmask = 0; + alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_TYPE_AHASH; + alg->cra_type = &crypto_ahash_type; + + t_alg->alg_type = template->alg_type; + t_alg->alg_op = template->alg_op; + t_alg->ctrldev = ctrldev; + + return t_alg; +} + +int caam_algapi_hash_startup(struct platform_device *pdev) +{ + struct device *ctrldev; + struct caam_drv_private *priv; + int i = 0, err = 0, md_limit = 0, md_inst; + u64 cha_inst; + + ctrldev = &pdev->dev; + priv = dev_get_drvdata(ctrldev); + + INIT_LIST_HEAD(&priv->hash_list); + + atomic_set(&priv->tfm_count, -1); + + /* register algorithms the device supports */ + cha_inst = rd_reg64(&priv->ctrl->perfmon.cha_num); + + md_inst = (cha_inst & CHA_ID_MD_MASK) >> CHA_ID_MD_SHIFT; + if (md_inst) { + md_limit = SHA512_DIGEST_SIZE; + if ((rd_reg64(&priv->ctrl->perfmon.cha_id) & CHA_ID_MD_MASK) + == CHA_ID_MD_LP256) { /* LP256 limits digest size */ + md_limit = SHA256_DIGEST_SIZE; + } + } + for (i = 0; i < ARRAY_SIZE(driver_hash); i++) { + struct caam_hash_alg *t_alg; + + /* If no MD instantiated, or MD too small, skip */ + if ((!md_inst) || + (driver_hash[i].template_ahash.halg.digestsize > + md_limit)) + continue; + /* register hmac version */ + t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], true); + if (IS_ERR(t_alg)) { + err = PTR_ERR(t_alg); + dev_warn(ctrldev, "%s alg allocation failed\n", + driver_hash[i].driver_name); + continue; + } + + err = crypto_register_ahash(&t_alg->ahash_alg); + if (err) { + dev_warn(ctrldev, "%s alg registration failed\n", + t_alg->ahash_alg.halg.base.cra_driver_name); + kfree(t_alg); + } else + list_add_tail(&t_alg->entry, &priv->hash_list); + + /* register unkeyed version */ + t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], false); + if (IS_ERR(t_alg)) { + err = PTR_ERR(t_alg); + dev_warn(ctrldev, "%s alg allocation failed\n", + driver_hash[i].driver_name); + continue; + } + + err = crypto_register_ahash(&t_alg->ahash_alg); + if (err) { + dev_warn(ctrldev, "%s alg registration failed\n", + t_alg->ahash_alg.halg.base.cra_driver_name); + kfree(t_alg); + } else + list_add_tail(&t_alg->entry, &priv->hash_list); + } + + return err; +} + +void caam_algapi_hash_shutdown(struct platform_device *pdev) +{ + struct device *ctrldev; + struct caam_drv_private *priv; + struct caam_hash_alg *t_alg, *n; + + ctrldev = &pdev->dev; + priv = dev_get_drvdata(ctrldev); + + if (!priv->hash_list.next) + return; + + list_for_each_entry_safe(t_alg, n, &priv->hash_list, entry) { + crypto_unregister_ahash(&t_alg->ahash_alg); + list_del(&t_alg->entry); + kfree(t_alg); + } +} + +#ifdef CONFIG_OF +static void __exit caam_algapi_hash_exit(void) +{ + struct device_node *dev_node; + struct platform_device *pdev; + + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) { + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); + if (!dev_node) + return; + } + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return; + + of_node_put(dev_node); +} + +static int __init caam_algapi_hash_init(void) +{ + struct device_node *dev_node; + struct platform_device *pdev; + int err = 0; + + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) { + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); + if (!dev_node) + return -ENODEV; + } + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return -ENODEV; + + of_node_put(dev_node); + + return caam_algapi_hash_startup(pdev); +} + +module_init(caam_algapi_hash_init); +module_exit(caam_algapi_hash_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("FSL CAAM support for ahash functions of crypto API"); +MODULE_AUTHOR("Freescale Semiconductor - NMG"); +#endif diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c new file mode 100644 index 000000000000..a4b4a3871bdf --- /dev/null +++ b/drivers/crypto/caam/caamrng.c @@ -0,0 +1,381 @@ +/* + * caam - Freescale FSL CAAM support for hw_random + * + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. + * + * Based on caamalg.c crypto API driver. + * + * relationship between job descriptors to shared descriptors: + * + * --------------- -------------- + * | JobDesc #0 |-------------------->| ShareDesc | + * | *(buffer 0) | |------------->| (generate) | + * --------------- | | (move) | + * | | (store) | + * --------------- | -------------- + * | JobDesc #1 |------| + * | *(buffer 1) | + * --------------- + * + * A job desc looks like this: + * + * --------------------- + * | Header | + * | ShareDesc Pointer | + * | SEQ_OUT_PTR | + * | (output buffer) | + * --------------------- + * + * The SharedDesc never changes, and each job descriptor points to one of two + * buffers for each device, from which the data will be copied into the + * requested destination + */ + +#include +#include +#include + +#include "compat.h" + +#include "regs.h" +#include "intern.h" +#include "desc_constr.h" +#include "jr.h" +#include "error.h" + +/* + * Maximum buffer size: maximum number of random, cache-aligned bytes that + * will be generated and moved to seq out ptr (extlen not allowed) + */ +#define RN_BUF_SIZE (0xffff / L1_CACHE_BYTES * \ + L1_CACHE_BYTES) + +/* length of descriptors */ +#define DESC_JOB_O_LEN (CAAM_CMD_SZ * 2 + CAAM_PTR_SZ * 2) +#define DESC_RNG_LEN (10 * CAAM_CMD_SZ) + +/* Buffer, its dma address and lock */ +struct buf_data { + u8 buf[RN_BUF_SIZE]; + dma_addr_t addr; + struct completion filled; + u32 hw_desc[DESC_JOB_O_LEN]; +#define BUF_NOT_EMPTY 0 +#define BUF_EMPTY 1 +#define BUF_PENDING 2 /* Empty, but with job pending --don't submit another */ + atomic_t empty; +}; + +/* rng per-device context */ +struct caam_rng_ctx { + struct device *jrdev; + dma_addr_t sh_desc_dma; + u32 sh_desc[DESC_RNG_LEN]; + unsigned int cur_buf_idx; + int current_buf; + struct buf_data bufs[2]; +}; + +static struct caam_rng_ctx rng_ctx; + +static inline void rng_unmap_buf(struct device *jrdev, struct buf_data *bd) +{ + if (bd->addr) { + dma_sync_single_for_cpu(jrdev, bd->addr, RN_BUF_SIZE, + DMA_FROM_DEVICE); + dma_unmap_single(jrdev, bd->addr, RN_BUF_SIZE, + DMA_FROM_DEVICE); + } +} + +static inline void rng_unmap_ctx(struct caam_rng_ctx *ctx) +{ + struct device *jrdev = ctx->jrdev; + + if (ctx->sh_desc_dma) + dma_unmap_single(jrdev, ctx->sh_desc_dma, DESC_RNG_LEN, + DMA_TO_DEVICE); + rng_unmap_buf(jrdev, &ctx->bufs[0]); + rng_unmap_buf(jrdev, &ctx->bufs[1]); +} + +static void rng_done(struct device *jrdev, u32 *desc, u32 err, void *context) +{ + struct buf_data *bd; + + bd = (struct buf_data *)((char *)desc - + offsetof(struct buf_data, hw_desc)); + + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + + atomic_set(&bd->empty, BUF_NOT_EMPTY); + complete(&bd->filled); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "rng refreshed buf@: ", + DUMP_PREFIX_ADDRESS, 16, 4, bd->buf, RN_BUF_SIZE, 1); +#endif +} + +static inline int submit_job(struct caam_rng_ctx *ctx, int to_current) +{ + struct buf_data *bd = &ctx->bufs[!(to_current ^ ctx->current_buf)]; + struct device *jrdev = ctx->jrdev; + u32 *desc = bd->hw_desc; + int err; + + dev_dbg(jrdev, "submitting job %d\n", !(to_current ^ ctx->current_buf)); + init_completion(&bd->filled); + err = caam_jr_enqueue(jrdev, desc, rng_done, ctx); + if (err) + complete(&bd->filled); /* don't wait on failed job*/ + else + atomic_inc(&bd->empty); /* note if pending */ + + return err; +} + +static int caam_read(struct hwrng *rng, void *data, size_t max, bool wait) +{ + struct caam_rng_ctx *ctx = &rng_ctx; + struct buf_data *bd = &ctx->bufs[ctx->current_buf]; + int next_buf_idx, copied_idx; + int err; + + if (atomic_read(&bd->empty)) { + /* try to submit job if there wasn't one */ + if (atomic_read(&bd->empty) == BUF_EMPTY) { + err = submit_job(ctx, 1); + /* if can't submit job, can't even wait */ + if (err) + return 0; + } + /* no immediate data, so exit if not waiting */ + if (!wait) + return 0; + + /* waiting for pending job */ + if (atomic_read(&bd->empty)) + wait_for_completion(&bd->filled); + } + + next_buf_idx = ctx->cur_buf_idx + max; + dev_dbg(ctx->jrdev, "%s: start reading at buffer %d, idx %d\n", + __func__, ctx->current_buf, ctx->cur_buf_idx); + + /* if enough data in current buffer */ + if (next_buf_idx < RN_BUF_SIZE) { + memcpy(data, bd->buf + ctx->cur_buf_idx, max); + ctx->cur_buf_idx = next_buf_idx; + return max; + } + + /* else, copy what's left... */ + copied_idx = RN_BUF_SIZE - ctx->cur_buf_idx; + memcpy(data, bd->buf + ctx->cur_buf_idx, copied_idx); + ctx->cur_buf_idx = 0; + atomic_set(&bd->empty, BUF_EMPTY); + + /* ...refill... */ + submit_job(ctx, 1); + + /* and use next buffer */ + ctx->current_buf = !ctx->current_buf; + dev_dbg(ctx->jrdev, "switched to buffer %d\n", ctx->current_buf); + + /* since there already is some data read, don't wait */ + return copied_idx + caam_read(rng, data + copied_idx, + max - copied_idx, false); +} + +static inline void rng_create_sh_desc(struct caam_rng_ctx *ctx) +{ + struct device *jrdev = ctx->jrdev; + u32 *desc = ctx->sh_desc; + + init_sh_desc(desc, HDR_SHARE_SERIAL); + + /* Propagate errors from shared to job descriptor */ + append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD); + + /* Generate random bytes */ + append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG); + + /* Store bytes */ + append_seq_fifo_store(desc, RN_BUF_SIZE, FIFOST_TYPE_RNGSTORE); + + ctx->sh_desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc), + DMA_TO_DEVICE); + dma_sync_single_for_cpu(jrdev, ctx->sh_desc_dma, desc_bytes(desc), + DMA_TO_DEVICE); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_ADDRESS, 16, 4, + desc, desc_bytes(desc), 1); +#endif +} + +static inline void rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id) +{ + struct device *jrdev = ctx->jrdev; + struct buf_data *bd = &ctx->bufs[buf_id]; + u32 *desc = bd->hw_desc; + int sh_len = desc_len(ctx->sh_desc); + + init_job_desc_shared(desc, ctx->sh_desc_dma, sh_len, HDR_SHARE_DEFER | + HDR_REVERSE); + + bd->addr = dma_map_single(jrdev, bd->buf, RN_BUF_SIZE, DMA_FROM_DEVICE); + + append_seq_out_ptr_intlen(desc, bd->addr, RN_BUF_SIZE, 0); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "rng job desc@: ", DUMP_PREFIX_ADDRESS, 16, 4, + desc, desc_bytes(desc), 1); +#endif +} + +static void caam_cleanup(struct hwrng *rng) +{ + int i; + struct buf_data *bd; + + for (i = 0; i < 2; i++) { + bd = &rng_ctx.bufs[i]; + if (atomic_read(&bd->empty) == BUF_PENDING) + wait_for_completion(&bd->filled); + } + + rng_unmap_ctx(&rng_ctx); +} + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST +static inline void test_len(struct hwrng *rng, size_t len, bool wait) +{ + u8 *buf; + int real_len; + + buf = kzalloc(sizeof(u8) * len, GFP_KERNEL); + real_len = rng->read(rng, buf, len, wait); + if (real_len == 0 && wait) + pr_err("WAITING FAILED\n"); + pr_info("wanted %d bytes, got %d\n", len, real_len); + print_hex_dump(KERN_INFO, "random bytes@: ", DUMP_PREFIX_ADDRESS, + 16, 4, buf, real_len, 1); + kfree(buf); +} + +static inline void test_mode_once(struct hwrng *rng, bool wait) +{ +#define TEST_CHUNK (RN_BUF_SIZE / 4) + + test_len(rng, TEST_CHUNK, wait); + test_len(rng, RN_BUF_SIZE * 2, wait); + test_len(rng, RN_BUF_SIZE * 2 - TEST_CHUNK, wait); +} + +static inline void test_mode(struct hwrng *rng, bool wait) +{ +#define TEST_PASS 1 + int i; + + for (i = 0; i < TEST_PASS; i++) + test_mode_once(rng, wait); +} + +static void self_test(struct hwrng *rng) +{ + pr_info("testing without waiting\n"); + test_mode(rng, false); + pr_info("testing with waiting\n"); + test_mode(rng, true); +} +#endif + +static void caam_init_buf(struct caam_rng_ctx *ctx, int buf_id) +{ + struct buf_data *bd = &ctx->bufs[buf_id]; + + rng_create_job_desc(ctx, buf_id); + atomic_set(&bd->empty, BUF_EMPTY); + submit_job(ctx, buf_id == ctx->current_buf); + wait_for_completion(&bd->filled); +} + +static void caam_init_rng(struct caam_rng_ctx *ctx, struct device *jrdev) +{ + ctx->jrdev = jrdev; + rng_create_sh_desc(ctx); + ctx->current_buf = 0; + ctx->cur_buf_idx = 0; + caam_init_buf(ctx, 0); + caam_init_buf(ctx, 1); +} + +static struct hwrng caam_rng = { + .name = "rng-caam", + .cleanup = caam_cleanup, + .read = caam_read, +}; + +int caam_rng_startup(struct platform_device *pdev) +{ + struct device *ctrldev; + struct caam_drv_private *priv; + + ctrldev = &pdev->dev; + priv = dev_get_drvdata(ctrldev); + + /* Check RNG present in hardware before registration */ + if (!(rd_reg64(&priv->ctrl->perfmon.cha_num) & CHA_ID_RNG_MASK)) + return -ENODEV; + + caam_init_rng(&rng_ctx, priv->jrdev[0]); + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST + self_test(&caam_rng); +#endif + + dev_info(priv->jrdev[0], "registering rng-caam\n"); + return hwrng_register(&caam_rng); +} + +void caam_rng_shutdown(void) +{ + hwrng_unregister(&caam_rng); +} + +#ifdef CONFIG_OF +static void __exit caam_rng_exit(void) +{ + hwrng_unregister(&caam_rng); +} + +static int __init caam_rng_init(void) +{ + struct device_node *dev_node; + struct platform_device *pdev; + + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) { + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); + if (!dev_node) + return -ENODEV; + } + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return -ENODEV; + + of_node_put(dev_node); + +} + +module_init(caam_rng_init); +module_exit(caam_rng_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("FSL CAAM support for hw_random API"); +MODULE_AUTHOR("Freescale Semiconductor - NMG"); +#endif diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h index 950450346f70..28d9670ff834 100644 --- a/drivers/crypto/caam/compat.h +++ b/drivers/crypto/caam/compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. */ #ifndef CAAM_COMPAT_H @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -22,14 +21,29 @@ #include #include #include + +#ifdef CONFIG_OF +#include +#else +#include +#endif + +#ifdef CONFIG_ARM /* needs the clock control subsystem */ +#include +#include +#endif + #include #include #include #include #include +#include #include #include #include +#include +#include #endif /* !defined(CAAM_COMPAT_H) */ diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 9009713a3c2e..6ea81c9d54f4 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -2,13 +2,16 @@ * CAAM control-plane driver backend * Controller-level driver, kernel property detection, initialization * - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. */ #include "compat.h" #include "regs.h" +#include "snvsregs.h" #include "intern.h" #include "jr.h" +#include "desc_constr.h" +#include "error.h" static int caam_remove(struct platform_device *pdev) { @@ -22,6 +25,28 @@ static int caam_remove(struct platform_device *pdev) ctrlpriv = dev_get_drvdata(ctrldev); topregs = (struct caam_full __iomem *)ctrlpriv->ctrl; +#ifndef CONFIG_OF +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO + caam_secvio_shutdown(pdev); +#endif /* SECVIO */ + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SM + caam_sm_shutdown(pdev); +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API + if (ctrlpriv->rng_inst) + caam_rng_shutdown(); +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API + caam_algapi_hash_shutdown(pdev); +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API + caam_algapi_shutdown(pdev); +#endif +#endif /* shut down JobRs */ for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) { ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]); @@ -34,27 +59,161 @@ static int caam_remove(struct platform_device *pdev) debugfs_remove_recursive(ctrlpriv->dfs_root); #endif + /* Unmap SNVS and Secure Memory */ + iounmap(ctrlpriv->snvs); + iounmap(ctrlpriv->sm_base); + /* Unmap controller region */ iounmap(&topregs->ctrl); + /* shut clocks off before finalizing shutdown */ + clk_disable(ctrlpriv->caam_clk); + kfree(ctrlpriv->jrdev); kfree(ctrlpriv); return ret; } +/* + * Descriptor to instantiate RNG State Handle 0 in normal mode and + * load the JDKEK, TDKEK and TDSK registers + */ +static void build_instantiation_desc(u32 *desc) +{ + u32 *jump_cmd; + + init_job_desc(desc, 0); + + /* INIT RNG in non-test mode */ + append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | + OP_ALG_AS_INIT); + + /* wait for done */ + jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1); + set_jump_tgt_here(desc, jump_cmd); + + /* + * load 1 to clear written reg: + * resets the done interrrupt and returns the RNG to idle. + */ + append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW); + + /* generate secure keys (non-test) */ + append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | + OP_ALG_RNG4_SK); +} + +struct instantiate_result { + struct completion completion; + int err; +}; + +static void rng4_init_done(struct device *dev, u32 *desc, u32 err, + void *context) +{ + struct instantiate_result *instantiation = context; + + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + + instantiation->err = err; + complete(&instantiation->completion); +} + +static int instantiate_rng(struct device *jrdev) +{ + struct instantiate_result instantiation; + + dma_addr_t desc_dma; + u32 *desc; + int ret; + + desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA); + if (!desc) { + dev_err(jrdev, "cannot allocate RNG init descriptor memory\n"); + return -ENOMEM; + } + + build_instantiation_desc(desc); + desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc), DMA_TO_DEVICE); + dma_sync_single_for_device(jrdev, desc_dma, desc_bytes(desc), + DMA_TO_DEVICE); + init_completion(&instantiation.completion); + + ret = caam_jr_enqueue(jrdev, desc, rng4_init_done, &instantiation); + if (!ret) { + wait_for_completion_interruptible(&instantiation.completion); + ret = instantiation.err; + if (ret) + dev_err(jrdev, "unable to instantiate RNG\n"); + } + + dma_unmap_single(jrdev, desc_dma, desc_bytes(desc), DMA_TO_DEVICE); + + kfree(desc); + + return ret; +} + +/* + * By default, the TRNG runs for 200 clocks per sample; + * 1600 clocks per sample generates better entropy. + */ +static void kick_trng(struct platform_device *pdev) +{ + struct device *ctrldev = &pdev->dev; + struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev); + struct caam_full __iomem *topregs; + struct rng4tst __iomem *r4tst; + u32 val; + + topregs = (struct caam_full __iomem *)ctrlpriv->ctrl; + r4tst = &topregs->ctrl.r4tst[0]; + + /* put RNG4 into program mode */ + setbits32(&r4tst->rtmctl, RTMCTL_PRGM); + /* Set clocks per sample to the default, and divider to zero */ + val = rd_reg32(&r4tst->rtsdctl); + val = ((val & ~RTSDCTL_ENT_DLY_MASK) | + (RNG4_ENT_CLOCKS_SAMPLE << RTSDCTL_ENT_DLY_SHIFT)) & + ~RTMCTL_OSC_DIV_MASK; + wr_reg32(&r4tst->rtsdctl, val); + /* min. freq. count */ + wr_reg32(&r4tst->rtfrqmin, RNG4_ENT_CLOCKS_SAMPLE / 4); + /* max. freq. count */ + wr_reg32(&r4tst->rtfrqmax, RNG4_ENT_CLOCKS_SAMPLE * 8); + /* put RNG4 into run mode */ + clrbits32(&r4tst->rtmctl, RTMCTL_PRGM); +} + /* Probe routine for CAAM top (controller) level */ static int caam_probe(struct platform_device *pdev) { - int d, ring, rspec; + int d, ring, rspec, status; struct device *dev; - struct device_node *nprop, *np; + struct device_node *np; struct caam_ctrl __iomem *ctrl; struct caam_full __iomem *topregs; + struct snvs_full __iomem *snvsregs; + void __iomem *sm_base; struct caam_drv_private *ctrlpriv; - struct caam_perfmon *perfmon; - struct caam_deco **deco; u32 deconum; +#ifdef CONFIG_DEBUG_FS + struct caam_perfmon *perfmon; +#endif +#ifdef CONFIG_OF + struct device_node *nprop; +#else + struct resource *res; + char *rname, inst; +#endif +#ifdef CONFIG_ARM + int ret = 0; +#endif ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL); if (!ctrlpriv) @@ -63,22 +222,121 @@ static int caam_probe(struct platform_device *pdev) dev = &pdev->dev; dev_set_drvdata(dev, ctrlpriv); ctrlpriv->pdev = pdev; - nprop = pdev->dev.of_node; /* Get configuration properties from device tree */ /* First, get register page */ +#ifdef CONFIG_OF + nprop = pdev->dev.of_node; ctrl = of_iomap(nprop, 0); if (ctrl == NULL) { dev_err(dev, "caam: of_iomap() failed\n"); return -ENOMEM; } +#else + /* Get the named resource for the controller base address */ + res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "iobase_caam"); + if (!res) { + dev_err(dev, "caam: invalid address resource type\n"); + return -ENODEV; + } + /*ctrl = ioremap(res->start, SZ_64K);*/ + ctrl = ioremap(res->start, ((res->end - res->start)+1)); + if (ctrl == NULL) { + dev_err(dev, "caam: ioremap() failed\n"); + return -ENOMEM; + } +#endif + ctrlpriv->ctrl = (struct caam_ctrl __force *)ctrl; /* topregs used to derive pointers to CAAM sub-blocks only */ topregs = (struct caam_full __iomem *)ctrl; - /* Get the IRQ of the controller (for security violations only) */ + /* + * Next, map SNVS register page + * FIXME: MX6 has a separate RTC driver using SNVS. This driver + * will have a mapped pointer to SNVS registers also, which poses + * a conflict if we're not very careful to stay away from registers + * and interrupts that it uses. In the future, pieces of that driver + * may need to migrate down here. In the meantime, use caution with + * this pointer. Also note that the snvs-rtc driver probably controls + * SNVS device clocks. + */ +#ifdef CONFIG_OF + /* Get SNVS register page */ +#else + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_snvs"); + if (!res) { + dev_err(dev, "snvs: invalid address resource type\n"); + return -ENODEV; + } + snvsregs = ioremap(res->start, res->end - res->start + 1); + if (snvsregs == NULL) { + dev_err(dev, "snvs: ioremap() failed\n"); + iounmap(ctrl); + return -ENOMEM; + } +#endif + ctrlpriv->snvs = (struct snvs_full __force *)snvsregs; + + /* Now map CAAM-Secure Memory Space */ +#ifdef CONFIG_OF + /* Get CAAM-SM node and of_iomap() and save */ +#else + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "iobase_caam_sm"); + if (!res) { + dev_err(dev, "caam_sm: invalid address resource type\n"); + return -ENODEV; + } + sm_base = ioremap_nocache(res->start, res->end - res->start + 1); + if (sm_base == NULL) { + dev_err(dev, "caam_sm: ioremap_nocache() failed\n"); + iounmap(ctrl); + iounmap(snvsregs); + return -ENOMEM; + } +#endif + ctrlpriv->sm_base = (void __force *)sm_base; + ctrlpriv->sm_size = res->end - res->start + 1; + + /* + * Get the IRQ for security violations + */ +#ifdef CONFIG_OF ctrlpriv->secvio_irq = of_irq_to_resource(nprop, 0, NULL); +#else + res = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "irq_sec_vio"); + if (!res) { + dev_err(dev, "caam: invalid IRQ resource type\n"); + return -ENODEV; + } + ctrlpriv->secvio_irq = res->start; +#endif + +/* + * ARM targets tend to have clock control subsystems that can + * enable/disable clocking to our device. Turn clocking on to proceed + */ +#ifdef CONFIG_ARM + ctrlpriv->caam_clk = clk_get(&ctrlpriv->pdev->dev, "caam_clk"); + if (IS_ERR(ctrlpriv->caam_clk)) { + ret = PTR_ERR(ctrlpriv->caam_clk); + dev_err(&ctrlpriv->pdev->dev, + "can't identify CAAM bus clk: %d\n", ret); + return -ENODEV; + } + ret = clk_enable(ctrlpriv->caam_clk); + if (ret < 0) { + dev_err(&pdev->dev, "can't enable CAAM bus clock: %d\n", ret); + return -ENODEV; + } + + pr_debug("%s caam_clk:%d\n", __func__, + (int)clk_get_rate(ctrlpriv->caam_clk)); +#endif /* * Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel, @@ -87,8 +345,26 @@ static int caam_probe(struct platform_device *pdev) setbits32(&topregs->ctrl.mcr, MCFGR_WDENABLE | (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0)); +#if (defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MVF)) + /* + * ERRATA: mx6 devices have an issue wherein AXI bus transactions + * may not occur in the correct order. This isn't a problem running + * single descriptors, but can be if running multiple concurrent + * descriptors. Reworking the driver to throttle to single requests + * is impractical, thus the workaround is to limit the AXI pipeline + * to a depth of 1 (from it's default of 4) to preclude this situation + * from occurring. + */ + wr_reg32(&topregs->ctrl.mcr, + (rd_reg32(&topregs->ctrl.mcr) & ~(MCFGR_AXIPIPE_MASK)) | + ((1 << MCFGR_AXIPIPE_SHIFT) & MCFGR_AXIPIPE_MASK)); +#endif + + /* Set DMA masks according to platform ranging */ if (sizeof(dma_addr_t) == sizeof(u64)) dma_set_mask(dev, DMA_BIT_MASK(36)); + else + dma_set_mask(dev, DMA_BIT_MASK(32)); /* Find out how many DECOs are present */ deconum = (rd_reg64(&topregs->ctrl.perfmon.cha_num) & @@ -97,18 +373,41 @@ static int caam_probe(struct platform_device *pdev) ctrlpriv->deco = kmalloc(deconum * sizeof(struct caam_deco *), GFP_KERNEL); - deco = (struct caam_deco __force **)&topregs->deco; - for (d = 0; d < deconum; d++) - ctrlpriv->deco[d] = deco[d]; - /* * Detect and enable JobRs * First, find out how many ring spec'ed, allocate references * for all, then go probe each one. */ rspec = 0; +#ifdef CONFIG_OF for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") rspec++; +#else + np = NULL; + + /* Build the name of the IRQ platform resources to identify */ + rname = kzalloc(strlen(JR_IRQRES_NAME_ROOT) + 1, 0); + if (rname == NULL) { + iounmap(&topregs->ctrl); + return -ENOMEM; + } + + /* + * Emulate behavor of for_each_compatible_node() for non OF targets + * Identify all IRQ platform resources present + */ + for (d = 0; d < 4; d++) { + rname[0] = 0; + inst = '0' + d; + strcat(rname, JR_IRQRES_NAME_ROOT); + strncat(rname, &inst, 1); + res = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, rname); + if (res) + rspec++; + } + kfree(rname); +#endif ctrlpriv->jrdev = kzalloc(sizeof(struct device *) * rspec, GFP_KERNEL); if (ctrlpriv->jrdev == NULL) { iounmap(&topregs->ctrl); @@ -117,7 +416,11 @@ static int caam_probe(struct platform_device *pdev) ring = 0; ctrlpriv->total_jobrs = 0; +#ifdef CONFIG_OF for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") { +#else + for (d = 0; d < rspec; d++) { +#endif caam_jr_probe(pdev, np, ring); ctrlpriv->total_jobrs++; ring++; @@ -139,6 +442,24 @@ static int caam_probe(struct platform_device *pdev) return -ENOMEM; } + /* + * RNG4 based SECs (v5+ | >= i.MX6) need special initialization prior + * to executing any descriptors. If there's a problem with init, + * remove other subsystems and return; internal padding functions + * cannot run without an RNG. This procedure assumes a single RNG4 + * instance. + */ + if ((rd_reg64(&topregs->ctrl.perfmon.cha_id) & CHA_ID_RNG_MASK) + == CHA_ID_RNG_4) { + kick_trng(pdev); + ret = instantiate_rng(ctrlpriv->jrdev[0]); + if (ret) { + caam_remove(pdev); + return -ENODEV; + } + ctrlpriv->rng_inst++; + } + /* NOTE: RTIC detection ought to go here, around Si time */ /* Initialize queue allocator lock */ @@ -164,52 +485,52 @@ static int caam_probe(struct platform_device *pdev) /* Controller-level - performance monitor counters */ ctrlpriv->ctl_rq_dequeued = debugfs_create_u64("rq_dequeued", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->req_dequeued); ctrlpriv->ctl_ob_enc_req = debugfs_create_u64("ob_rq_encrypted", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->ob_enc_req); ctrlpriv->ctl_ib_dec_req = debugfs_create_u64("ib_rq_decrypted", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->ib_dec_req); ctrlpriv->ctl_ob_enc_bytes = debugfs_create_u64("ob_bytes_encrypted", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->ob_enc_bytes); ctrlpriv->ctl_ob_prot_bytes = debugfs_create_u64("ob_bytes_protected", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->ob_prot_bytes); ctrlpriv->ctl_ib_dec_bytes = debugfs_create_u64("ib_bytes_decrypted", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->ib_dec_bytes); ctrlpriv->ctl_ib_valid_bytes = debugfs_create_u64("ib_bytes_validated", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->ib_valid_bytes); /* Controller level - global status values */ ctrlpriv->ctl_faultaddr = debugfs_create_u64("fault_addr", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->faultaddr); ctrlpriv->ctl_faultdetail = debugfs_create_u32("fault_detail", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->faultdetail); ctrlpriv->ctl_faultstatus = debugfs_create_u32("fault_status", - S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &perfmon->status); /* Internal covering keys (useful in non-secure mode only) */ ctrlpriv->ctl_kek_wrap.data = &ctrlpriv->ctrl->kek[0]; ctrlpriv->ctl_kek_wrap.size = KEK_KEY_SIZE * sizeof(u32); ctrlpriv->ctl_kek = debugfs_create_blob("kek", - S_IFCHR | S_IRUSR | + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &ctrlpriv->ctl_kek_wrap); @@ -217,7 +538,7 @@ static int caam_probe(struct platform_device *pdev) ctrlpriv->ctl_tkek_wrap.data = &ctrlpriv->ctrl->tkek[0]; ctrlpriv->ctl_tkek_wrap.size = KEK_KEY_SIZE * sizeof(u32); ctrlpriv->ctl_tkek = debugfs_create_blob("tkek", - S_IFCHR | S_IRUSR | + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &ctrlpriv->ctl_tkek_wrap); @@ -225,14 +546,60 @@ static int caam_probe(struct platform_device *pdev) ctrlpriv->ctl_tdsk_wrap.data = &ctrlpriv->ctrl->tdsk[0]; ctrlpriv->ctl_tdsk_wrap.size = KEK_KEY_SIZE * sizeof(u32); ctrlpriv->ctl_tdsk = debugfs_create_blob("tdsk", - S_IFCHR | S_IRUSR | + S_IRUSR | S_IRGRP | S_IROTH, ctrlpriv->ctl, &ctrlpriv->ctl_tdsk_wrap); #endif - return 0; + +/* + * Non OF configurations use plaform_device, and therefore cannot simply + * go and get a device node by name, which the algapi module startup code + * assumes is possible. Therefore, non OF configurations will have to + * start up the API code explicitly, and forego modularization + */ +#ifndef CONFIG_OF +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API + status = caam_algapi_startup(pdev); + if (status) { + caam_remove(pdev); + return status; + } +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API + status = caam_algapi_hash_startup(pdev); + if (status) { + caam_remove(pdev); + return status; + } +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API + if (ctrlpriv->rng_inst) + caam_rng_startup(pdev); +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SM + status = caam_sm_startup(pdev); + if (status) { + caam_remove(pdev); + return status; + } +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST + caam_sm_example_init(pdev); +#endif /* SM_TEST */ +#endif /* SM */ + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO + caam_secvio_startup(pdev); +#endif /* SECVIO */ + +#endif /* CONFIG_OF */ + return status; } +#ifdef CONFIG_OF static struct of_device_id caam_match[] = { { .compatible = "fsl,sec-v4.0", @@ -240,12 +607,17 @@ static struct of_device_id caam_match[] = { {}, }; MODULE_DEVICE_TABLE(of, caam_match); +#endif /* CONFIG_OF */ static struct platform_driver caam_driver = { .driver = { .name = "caam", .owner = THIS_MODULE, +#ifdef CONFIG_OF .of_match_table = caam_match, +#else + +#endif }, .probe = caam_probe, .remove = __devexit_p(caam_remove), @@ -253,12 +625,20 @@ static struct platform_driver caam_driver = { static int __init caam_base_init(void) { +#ifdef CONFIG_OF + return of_register_platform_driver(&caam_driver); +#else return platform_driver_register(&caam_driver); +#endif } static void __exit caam_base_exit(void) { +#ifdef CONFIG_OF + return of_unregister_platform_driver(&caam_driver); +#else return platform_driver_unregister(&caam_driver); +#endif } module_init(caam_base_init); diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h index 974a75842da9..573d9d1c3f5d 100644 --- a/drivers/crypto/caam/desc.h +++ b/drivers/crypto/caam/desc.h @@ -2,14 +2,39 @@ * CAAM descriptor composition header * Definitions to support CAAM descriptor instruction generation * - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. */ #ifndef DESC_H #define DESC_H +/* + * 16-byte hardware scatter/gather table + * An 8-byte table exists in the hardware spec, but has never been + * implemented to date. The 8/16 option is selected at RTL-compile-time. + * and this selection is visible in the Compile Time Parameters Register + */ + +#define SEC4_SG_LEN_EXT 0x80000000 /* Entry points to table */ +#define SEC4_SG_LEN_FIN 0x40000000 /* Last ent in table */ +#define SEC4_SG_BPID_MASK 0x000000ff +#define SEC4_SG_BPID_SHIFT 16 +#define SEC4_SG_LEN_MASK 0x3fffffff /* Excludes EXT and FINAL */ +#define SEC4_SG_OFFS_MASK 0x00001fff + +struct sec4_sg_entry { +#ifdef CONFIG_64BIT + u64 ptr; +#else + u32 reserved; + u32 ptr; +#endif + u32 len; + u32 bpid_offset; /* BPID in high, offset in lowest bits */ +}; + /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */ -#define MAX_CAAM_DESCSIZE 64 +#define MAX_CAAM_DESCSIZE 64 /* Block size of any entity covered/uncovered with a KEK/TKEK */ #define KEK_BLOCKSIZE 16 @@ -18,38 +43,38 @@ * Supported descriptor command types as they show up * inside a descriptor command word. */ -#define CMD_SHIFT 27 -#define CMD_MASK 0xf8000000 - -#define CMD_KEY (0x00 << CMD_SHIFT) -#define CMD_SEQ_KEY (0x01 << CMD_SHIFT) -#define CMD_LOAD (0x02 << CMD_SHIFT) -#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT) -#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT) -#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT) -#define CMD_STORE (0x0a << CMD_SHIFT) -#define CMD_SEQ_STORE (0x0b << CMD_SHIFT) -#define CMD_FIFO_STORE (0x0c << CMD_SHIFT) -#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT) -#define CMD_MOVE_LEN (0x0e << CMD_SHIFT) -#define CMD_MOVE (0x0f << CMD_SHIFT) -#define CMD_OPERATION (0x10 << CMD_SHIFT) -#define CMD_SIGNATURE (0x12 << CMD_SHIFT) -#define CMD_JUMP (0x14 << CMD_SHIFT) -#define CMD_MATH (0x15 << CMD_SHIFT) -#define CMD_DESC_HDR (0x16 << CMD_SHIFT) -#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT) -#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT) -#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT) +#define CMD_SHIFT 27 +#define CMD_MASK 0xf8000000 + +#define CMD_KEY (0x00 << CMD_SHIFT) +#define CMD_SEQ_KEY (0x01 << CMD_SHIFT) +#define CMD_LOAD (0x02 << CMD_SHIFT) +#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT) +#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT) +#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT) +#define CMD_STORE (0x0a << CMD_SHIFT) +#define CMD_SEQ_STORE (0x0b << CMD_SHIFT) +#define CMD_FIFO_STORE (0x0c << CMD_SHIFT) +#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT) +#define CMD_MOVE_LEN (0x0e << CMD_SHIFT) +#define CMD_MOVE (0x0f << CMD_SHIFT) +#define CMD_OPERATION (0x10 << CMD_SHIFT) +#define CMD_SIGNATURE (0x12 << CMD_SHIFT) +#define CMD_JUMP (0x14 << CMD_SHIFT) +#define CMD_MATH (0x15 << CMD_SHIFT) +#define CMD_DESC_HDR (0x16 << CMD_SHIFT) +#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT) +#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT) +#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT) /* General-purpose class selector for all commands */ -#define CLASS_SHIFT 25 -#define CLASS_MASK (0x03 << CLASS_SHIFT) +#define CLASS_SHIFT 25 +#define CLASS_MASK (0x03 << CLASS_SHIFT) -#define CLASS_NONE (0x00 << CLASS_SHIFT) -#define CLASS_1 (0x01 << CLASS_SHIFT) -#define CLASS_2 (0x02 << CLASS_SHIFT) -#define CLASS_BOTH (0x03 << CLASS_SHIFT) +#define CLASS_NONE (0x00 << CLASS_SHIFT) +#define CLASS_1 (0x01 << CLASS_SHIFT) +#define CLASS_2 (0x02 << CLASS_SHIFT) +#define CLASS_BOTH (0x03 << CLASS_SHIFT) /* * Descriptor header command constructs @@ -60,82 +85,82 @@ * Do Not Run - marks a descriptor inexecutable if there was * a preceding error somewhere */ -#define HDR_DNR 0x01000000 +#define HDR_DNR 0x01000000 /* * ONE - should always be set. Combination of ONE (always * set) and ZRO (always clear) forms an endianness sanity check */ -#define HDR_ONE 0x00800000 -#define HDR_ZRO 0x00008000 +#define HDR_ONE 0x00800000 +#define HDR_ZRO 0x00008000 /* Start Index or SharedDesc Length */ -#define HDR_START_IDX_MASK 0x3f -#define HDR_START_IDX_SHIFT 16 +#define HDR_START_IDX_MASK 0x3f +#define HDR_START_IDX_SHIFT 16 /* If shared descriptor header, 6-bit length */ -#define HDR_DESCLEN_SHR_MASK 0x3f +#define HDR_DESCLEN_SHR_MASK 0x3f /* If non-shared header, 7-bit length */ -#define HDR_DESCLEN_MASK 0x7f +#define HDR_DESCLEN_MASK 0x7f /* This is a TrustedDesc (if not SharedDesc) */ -#define HDR_TRUSTED 0x00004000 +#define HDR_TRUSTED 0x00004000 /* Make into TrustedDesc (if not SharedDesc) */ -#define HDR_MAKE_TRUSTED 0x00002000 +#define HDR_MAKE_TRUSTED 0x00002000 /* Save context if self-shared (if SharedDesc) */ -#define HDR_SAVECTX 0x00001000 +#define HDR_SAVECTX 0x00001000 /* Next item points to SharedDesc */ -#define HDR_SHARED 0x00001000 +#define HDR_SHARED 0x00001000 /* * Reverse Execution Order - execute JobDesc first, then * execute SharedDesc (normally SharedDesc goes first). */ -#define HDR_REVERSE 0x00000800 +#define HDR_REVERSE 0x00000800 /* Propogate DNR property to SharedDesc */ -#define HDR_PROP_DNR 0x00000800 +#define HDR_PROP_DNR 0x00000800 /* JobDesc/SharedDesc share property */ -#define HDR_SD_SHARE_MASK 0x03 -#define HDR_SD_SHARE_SHIFT 8 -#define HDR_JD_SHARE_MASK 0x07 -#define HDR_JD_SHARE_SHIFT 8 +#define HDR_SD_SHARE_MASK 0x03 +#define HDR_SD_SHARE_SHIFT 8 +#define HDR_JD_SHARE_MASK 0x07 +#define HDR_JD_SHARE_SHIFT 8 -#define HDR_SHARE_NEVER (0x00 << HDR_SD_SHARE_SHIFT) -#define HDR_SHARE_WAIT (0x01 << HDR_SD_SHARE_SHIFT) -#define HDR_SHARE_SERIAL (0x02 << HDR_SD_SHARE_SHIFT) -#define HDR_SHARE_ALWAYS (0x03 << HDR_SD_SHARE_SHIFT) -#define HDR_SHARE_DEFER (0x04 << HDR_SD_SHARE_SHIFT) +#define HDR_SHARE_NEVER (0x00 << HDR_SD_SHARE_SHIFT) +#define HDR_SHARE_WAIT (0x01 << HDR_SD_SHARE_SHIFT) +#define HDR_SHARE_SERIAL (0x02 << HDR_SD_SHARE_SHIFT) +#define HDR_SHARE_ALWAYS (0x03 << HDR_SD_SHARE_SHIFT) +#define HDR_SHARE_DEFER (0x04 << HDR_SD_SHARE_SHIFT) /* JobDesc/SharedDesc descriptor length */ -#define HDR_JD_LENGTH_MASK 0x7f -#define HDR_SD_LENGTH_MASK 0x3f +#define HDR_JD_LENGTH_MASK 0x7f +#define HDR_SD_LENGTH_MASK 0x3f /* * KEY/SEQ_KEY Command Constructs */ -/* Key Destination Class: 01 = Class 1, 02 - Class 2 */ -#define KEY_DEST_CLASS_SHIFT 25 /* use CLASS_1 or CLASS_2 */ -#define KEY_DEST_CLASS_MASK (0x03 << KEY_DEST_CLASS_SHIFT) +/* Key Destination Class: 01 = Class 1, 02 - Class 2 */ +#define KEY_DEST_CLASS_SHIFT 25 /* use CLASS_1 or CLASS_2 */ +#define KEY_DEST_CLASS_MASK (0x03 << KEY_DEST_CLASS_SHIFT) /* Scatter-Gather Table/Variable Length Field */ -#define KEY_SGF 0x01000000 -#define KEY_VLF 0x01000000 +#define KEY_SGF 0x01000000 +#define KEY_VLF 0x01000000 /* Immediate - Key follows command in the descriptor */ -#define KEY_IMM 0x00800000 +#define KEY_IMM 0x00800000 /* * Encrypted - Key is encrypted either with the KEK, or * with the TDKEK if TK is set */ -#define KEY_ENC 0x00400000 +#define KEY_ENC 0x00400000 /* * No Write Back - Do not allow key to be FIFO STOREd @@ -156,16 +181,16 @@ * KDEST - Key Destination: 0 - class key register, * 1 - PKHA 'e', 2 - AFHA Sbox, 3 - MDHA split-key */ -#define KEY_DEST_SHIFT 16 -#define KEY_DEST_MASK (0x03 << KEY_DEST_SHIFT) +#define KEY_DEST_SHIFT 16 +#define KEY_DEST_MASK (0x03 << KEY_DEST_SHIFT) -#define KEY_DEST_CLASS_REG (0x00 << KEY_DEST_SHIFT) -#define KEY_DEST_PKHA_E (0x01 << KEY_DEST_SHIFT) -#define KEY_DEST_AFHA_SBOX (0x02 << KEY_DEST_SHIFT) -#define KEY_DEST_MDHA_SPLIT (0x03 << KEY_DEST_SHIFT) +#define KEY_DEST_CLASS_REG (0x00 << KEY_DEST_SHIFT) +#define KEY_DEST_PKHA_E (0x01 << KEY_DEST_SHIFT) +#define KEY_DEST_AFHA_SBOX (0x02 << KEY_DEST_SHIFT) +#define KEY_DEST_MDHA_SPLIT (0x03 << KEY_DEST_SHIFT) /* Length in bytes */ -#define KEY_LENGTH_MASK 0x000003ff +#define KEY_LENGTH_MASK 0x000003ff /* * LOAD/SEQ_LOAD/STORE/SEQ_STORE Command Constructs @@ -175,25 +200,25 @@ * Load/Store Destination: 0 = class independent CCB, * 1 = class 1 CCB, 2 = class 2 CCB, 3 = DECO */ -#define LDST_CLASS_SHIFT 25 -#define LDST_CLASS_MASK (0x03 << LDST_CLASS_SHIFT) -#define LDST_CLASS_IND_CCB (0x00 << LDST_CLASS_SHIFT) -#define LDST_CLASS_1_CCB (0x01 << LDST_CLASS_SHIFT) -#define LDST_CLASS_2_CCB (0x02 << LDST_CLASS_SHIFT) -#define LDST_CLASS_DECO (0x03 << LDST_CLASS_SHIFT) +#define LDST_CLASS_SHIFT 25 +#define LDST_CLASS_MASK (0x03 << LDST_CLASS_SHIFT) +#define LDST_CLASS_IND_CCB (0x00 << LDST_CLASS_SHIFT) +#define LDST_CLASS_1_CCB (0x01 << LDST_CLASS_SHIFT) +#define LDST_CLASS_2_CCB (0x02 << LDST_CLASS_SHIFT) +#define LDST_CLASS_DECO (0x03 << LDST_CLASS_SHIFT) /* Scatter-Gather Table/Variable Length Field */ -#define LDST_SGF 0x01000000 +#define LDST_SGF 0x01000000 #define LDST_VLF LDST_SGF -/* Immediate - Key follows this command in descriptor */ -#define LDST_IMM_MASK 1 -#define LDST_IMM_SHIFT 23 -#define LDST_IMM (LDST_IMM_MASK << LDST_IMM_SHIFT) +/* Immediate - Key follows this command in descriptor */ +#define LDST_IMM_MASK 1 +#define LDST_IMM_SHIFT 23 +#define LDST_IMM (LDST_IMM_MASK << LDST_IMM_SHIFT) -/* SRC/DST - Destination for LOAD, Source for STORE */ -#define LDST_SRCDST_SHIFT 16 -#define LDST_SRCDST_MASK (0x7f << LDST_SRCDST_SHIFT) +/* SRC/DST - Destination for LOAD, Source for STORE */ +#define LDST_SRCDST_SHIFT 16 +#define LDST_SRCDST_MASK (0x7f << LDST_SRCDST_SHIFT) #define LDST_SRCDST_BYTE_CONTEXT (0x20 << LDST_SRCDST_SHIFT) #define LDST_SRCDST_BYTE_KEY (0x40 << LDST_SRCDST_SHIFT) @@ -205,64 +230,64 @@ #define LDST_SRCDST_WORD_DATASZ_REG (0x02 << LDST_SRCDST_SHIFT) #define LDST_SRCDST_WORD_ICVSZ_REG (0x03 << LDST_SRCDST_SHIFT) #define LDST_SRCDST_WORD_CHACTRL (0x06 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_DECOCTRL (0x06 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_DECOCTRL (0x06 << LDST_SRCDST_SHIFT) #define LDST_SRCDST_WORD_IRQCTRL (0x07 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_DECO_PCLOVRD (0x07 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_DECO_PCLOVRD (0x07 << LDST_SRCDST_SHIFT) #define LDST_SRCDST_WORD_CLRW (0x08 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_DECO_MATH0 (0x08 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_DECO_MATH0 (0x08 << LDST_SRCDST_SHIFT) #define LDST_SRCDST_WORD_STAT (0x09 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_DECO_MATH1 (0x09 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_DECO_MATH2 (0x0a << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_DECO_AAD_SZ (0x0b << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_DECO_MATH3 (0x0b << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_ALTDS_CLASS1 (0x0f << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_PKHA_A_SZ (0x10 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT) -#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT) - -/* Offset in source/destination */ -#define LDST_OFFSET_SHIFT 8 -#define LDST_OFFSET_MASK (0xff << LDST_OFFSET_SHIFT) +#define LDST_SRCDST_WORD_DECO_MATH1 (0x09 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_DECO_MATH2 (0x0a << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_DECO_AAD_SZ (0x0b << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_DECO_MATH3 (0x0b << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_ALTDS_CLASS1 (0x0f << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_PKHA_A_SZ (0x10 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT) +#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT) + +/* Offset in source/destination */ +#define LDST_OFFSET_SHIFT 8 +#define LDST_OFFSET_MASK (0xff << LDST_OFFSET_SHIFT) /* LDOFF definitions used when DST = LDST_SRCDST_WORD_DECOCTRL */ /* These could also be shifted by LDST_OFFSET_SHIFT - this reads better */ -#define LDOFF_CHG_SHARE_SHIFT 0 -#define LDOFF_CHG_SHARE_MASK (0x3 << LDOFF_CHG_SHARE_SHIFT) -#define LDOFF_CHG_SHARE_NEVER (0x1 << LDOFF_CHG_SHARE_SHIFT) -#define LDOFF_CHG_SHARE_OK_NO_PROP (0x2 << LDOFF_CHG_SHARE_SHIFT) -#define LDOFF_CHG_SHARE_OK_PROP (0x3 << LDOFF_CHG_SHARE_SHIFT) - -#define LDOFF_ENABLE_AUTO_NFIFO (1 << 2) -#define LDOFF_DISABLE_AUTO_NFIFO (1 << 3) - -#define LDOFF_CHG_NONSEQLIODN_SHIFT 4 -#define LDOFF_CHG_NONSEQLIODN_MASK (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT) -#define LDOFF_CHG_NONSEQLIODN_SEQ (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT) -#define LDOFF_CHG_NONSEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT) -#define LDOFF_CHG_NONSEQLIODN_TRUSTED (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT) - -#define LDOFF_CHG_SEQLIODN_SHIFT 6 -#define LDOFF_CHG_SEQLIODN_MASK (0x3 << LDOFF_CHG_SEQLIODN_SHIFT) -#define LDOFF_CHG_SEQLIODN_SEQ (0x1 << LDOFF_CHG_SEQLIODN_SHIFT) -#define LDOFF_CHG_SEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_SEQLIODN_SHIFT) -#define LDOFF_CHG_SEQLIODN_TRUSTED (0x3 << LDOFF_CHG_SEQLIODN_SHIFT) - -/* Data length in bytes */ -#define LDST_LEN_SHIFT 0 -#define LDST_LEN_MASK (0xff << LDST_LEN_SHIFT) +#define LDOFF_CHG_SHARE_SHIFT 0 +#define LDOFF_CHG_SHARE_MASK (0x3 << LDOFF_CHG_SHARE_SHIFT) +#define LDOFF_CHG_SHARE_NEVER (0x1 << LDOFF_CHG_SHARE_SHIFT) +#define LDOFF_CHG_SHARE_OK_PROP (0x2 << LDOFF_CHG_SHARE_SHIFT) +#define LDOFF_CHG_SHARE_OK_NO_PROP (0x3 << LDOFF_CHG_SHARE_SHIFT) + +#define LDOFF_ENABLE_AUTO_NFIFO (1 << 2) +#define LDOFF_DISABLE_AUTO_NFIFO (1 << 3) + +#define LDOFF_CHG_NONSEQLIODN_SHIFT 4 +#define LDOFF_CHG_NONSEQLIODN_MASK (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT) +#define LDOFF_CHG_NONSEQLIODN_SEQ (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT) +#define LDOFF_CHG_NONSEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT) +#define LDOFF_CHG_NONSEQLIODN_TRUSTED (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT) + +#define LDOFF_CHG_SEQLIODN_SHIFT 6 +#define LDOFF_CHG_SEQLIODN_MASK (0x3 << LDOFF_CHG_SEQLIODN_SHIFT) +#define LDOFF_CHG_SEQLIODN_SEQ (0x1 << LDOFF_CHG_SEQLIODN_SHIFT) +#define LDOFF_CHG_SEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_SEQLIODN_SHIFT) +#define LDOFF_CHG_SEQLIODN_TRUSTED (0x3 << LDOFF_CHG_SEQLIODN_SHIFT) + +/* Data length in bytes */ +#define LDST_LEN_SHIFT 0 +#define LDST_LEN_MASK (0xff << LDST_LEN_SHIFT) /* Special Length definitions when dst=deco-ctrl */ -#define LDLEN_ENABLE_OSL_COUNT (1 << 7) -#define LDLEN_RST_CHA_OFIFO_PTR (1 << 6) -#define LDLEN_RST_OFIFO (1 << 5) -#define LDLEN_SET_OFIFO_OFF_VALID (1 << 4) -#define LDLEN_SET_OFIFO_OFF_RSVD (1 << 3) -#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0 -#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT) +#define LDLEN_ENABLE_OSL_COUNT (1 << 7) +#define LDLEN_RST_CHA_OFIFO_PTR (1 << 6) +#define LDLEN_RST_OFIFO (1 << 5) +#define LDLEN_SET_OFIFO_OFF_VALID (1 << 4) +#define LDLEN_SET_OFIFO_OFF_RSVD (1 << 3) +#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0 +#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT) /* * FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE @@ -274,808 +299,825 @@ * 1 = Load for Class1, 2 = Load for Class2, 3 = Load both * Store Source: 0 = normal, 1 = Class1key, 2 = Class2key */ -#define FIFOLD_CLASS_SHIFT 25 -#define FIFOLD_CLASS_MASK (0x03 << FIFOLD_CLASS_SHIFT) -#define FIFOLD_CLASS_SKIP (0x00 << FIFOLD_CLASS_SHIFT) -#define FIFOLD_CLASS_CLASS1 (0x01 << FIFOLD_CLASS_SHIFT) -#define FIFOLD_CLASS_CLASS2 (0x02 << FIFOLD_CLASS_SHIFT) -#define FIFOLD_CLASS_BOTH (0x03 << FIFOLD_CLASS_SHIFT) - -#define FIFOST_CLASS_SHIFT 25 -#define FIFOST_CLASS_MASK (0x03 << FIFOST_CLASS_SHIFT) -#define FIFOST_CLASS_NORMAL (0x00 << FIFOST_CLASS_SHIFT) -#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT) -#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT) +#define FIFOLD_CLASS_SHIFT 25 +#define FIFOLD_CLASS_MASK (0x03 << FIFOLD_CLASS_SHIFT) +#define FIFOLD_CLASS_SKIP (0x00 << FIFOLD_CLASS_SHIFT) +#define FIFOLD_CLASS_CLASS1 (0x01 << FIFOLD_CLASS_SHIFT) +#define FIFOLD_CLASS_CLASS2 (0x02 << FIFOLD_CLASS_SHIFT) +#define FIFOLD_CLASS_BOTH (0x03 << FIFOLD_CLASS_SHIFT) + +#define FIFOST_CLASS_SHIFT 25 +#define FIFOST_CLASS_MASK (0x03 << FIFOST_CLASS_SHIFT) +#define FIFOST_CLASS_NORMAL (0x00 << FIFOST_CLASS_SHIFT) +#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT) +#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT) /* * Scatter-Gather Table/Variable Length Field * If set for FIFO_LOAD, refers to a SG table. Within * SEQ_FIFO_LOAD, is variable input sequence */ -#define FIFOLDST_SGF_SHIFT 24 -#define FIFOLDST_SGF_MASK (1 << FIFOLDST_SGF_SHIFT) -#define FIFOLDST_VLF_MASK (1 << FIFOLDST_SGF_SHIFT) -#define FIFOLDST_SGF (1 << FIFOLDST_SGF_SHIFT) -#define FIFOLDST_VLF (1 << FIFOLDST_SGF_SHIFT) +#define FIFOLDST_SGF_SHIFT 24 +#define FIFOLDST_SGF_MASK (1 << FIFOLDST_SGF_SHIFT) +#define FIFOLDST_VLF_MASK (1 << FIFOLDST_SGF_SHIFT) +#define FIFOLDST_SGF (1 << FIFOLDST_SGF_SHIFT) +#define FIFOLDST_VLF (1 << FIFOLDST_SGF_SHIFT) /* Immediate - Data follows command in descriptor */ -#define FIFOLD_IMM_SHIFT 23 -#define FIFOLD_IMM_MASK (1 << FIFOLD_IMM_SHIFT) -#define FIFOLD_IMM (1 << FIFOLD_IMM_SHIFT) +#define FIFOLD_IMM_SHIFT 23 +#define FIFOLD_IMM_MASK (1 << FIFOLD_IMM_SHIFT) +#define FIFOLD_IMM (1 << FIFOLD_IMM_SHIFT) /* Continue - Not the last FIFO store to come */ -#define FIFOST_CONT_SHIFT 23 -#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT) -#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT) +#define FIFOST_CONT_SHIFT 23 +#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT) +#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT) /* * Extended Length - use 32-bit extended length that * follows the pointer field. Illegal with IMM set */ -#define FIFOLDST_EXT_SHIFT 22 -#define FIFOLDST_EXT_MASK (1 << FIFOLDST_EXT_SHIFT) -#define FIFOLDST_EXT (1 << FIFOLDST_EXT_SHIFT) +#define FIFOLDST_EXT_SHIFT 22 +#define FIFOLDST_EXT_MASK (1 << FIFOLDST_EXT_SHIFT) +#define FIFOLDST_EXT (1 << FIFOLDST_EXT_SHIFT) /* Input data type.*/ -#define FIFOLD_TYPE_SHIFT 16 -#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */ -#define FIFOLD_TYPE_MASK (0x3f << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_SHIFT 16 +#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */ +#define FIFOLD_TYPE_MASK (0x3f << FIFOLD_TYPE_SHIFT) /* PK types */ -#define FIFOLD_TYPE_PK (0x00 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_MASK (0x30 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK (0x00 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_MASK (0x30 << FIFOLD_TYPE_SHIFT) #define FIFOLD_TYPE_PK_TYPEMASK (0x0f << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_A0 (0x00 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_A1 (0x01 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_A2 (0x02 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_A3 (0x03 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_B0 (0x04 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_B1 (0x05 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_B2 (0x06 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_B3 (0x07 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_A0 (0x00 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_A1 (0x01 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_A2 (0x02 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_A3 (0x03 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_B0 (0x04 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_B1 (0x05 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_B2 (0x06 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_B3 (0x07 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT) /* Other types. Need to OR in last/flush bits as desired */ -#define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_MSG1OUT2 (0x18 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_BITDATA (0x28 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_MSG1OUT2 (0x18 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_BITDATA (0x28 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_SHIFT) /* Last/Flush bits for use with "other" types above */ -#define FIFOLD_TYPE_ACT_MASK (0x07 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_NOACTION (0x00 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_FLUSH1 (0x01 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_LAST1 (0x02 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_LAST2 (0x04 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_ACT_MASK (0x07 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_NOACTION (0x00 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_FLUSH1 (0x01 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_LAST1 (0x02 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_LAST2 (0x04 << FIFOLD_TYPE_SHIFT) #define FIFOLD_TYPE_LAST2FLUSH1 (0x05 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT) -#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT) +#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT) -#define FIFOLDST_LEN_MASK 0xffff -#define FIFOLDST_EXT_LEN_MASK 0xffffffff +#define FIFOLDST_LEN_MASK 0xffff +#define FIFOLDST_EXT_LEN_MASK 0xffffffff /* Output data types */ -#define FIFOST_TYPE_SHIFT 16 -#define FIFOST_TYPE_MASK (0x3f << FIFOST_TYPE_SHIFT) - -#define FIFOST_TYPE_PKHA_A0 (0x00 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_A1 (0x01 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_A2 (0x02 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_A3 (0x03 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_B0 (0x04 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_B1 (0x05 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_B2 (0x06 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_B3 (0x07 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_SHIFT 16 +#define FIFOST_TYPE_MASK (0x3f << FIFOST_TYPE_SHIFT) + +#define FIFOST_TYPE_PKHA_A0 (0x00 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_A1 (0x01 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_A2 (0x02 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_A3 (0x03 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_B0 (0x04 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_B1 (0x05 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_B2 (0x06 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_B3 (0x07 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT) #define FIFOST_TYPE_AF_SBOX_JKEK (0x10 << FIFOST_TYPE_SHIFT) #define FIFOST_TYPE_AF_SBOX_TKEK (0x21 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_KEY_KEK (0x24 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_KEY_TKEK (0x25 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_SPLIT_KEK (0x26 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_SPLIT_TKEK (0x27 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_OUTFIFO_KEK (0x28 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_KEY_KEK (0x24 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_KEY_TKEK (0x25 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_SPLIT_KEK (0x26 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_SPLIT_TKEK (0x27 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_OUTFIFO_KEK (0x28 << FIFOST_TYPE_SHIFT) #define FIFOST_TYPE_OUTFIFO_TKEK (0x29 << FIFOST_TYPE_SHIFT) #define FIFOST_TYPE_MESSAGE_DATA (0x30 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT) -#define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT) +#define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT) /* * OPERATION Command Constructs */ /* Operation type selectors - OP TYPE */ -#define OP_TYPE_SHIFT 24 -#define OP_TYPE_MASK (0x07 << OP_TYPE_SHIFT) +#define OP_TYPE_SHIFT 24 +#define OP_TYPE_MASK (0x07 << OP_TYPE_SHIFT) -#define OP_TYPE_UNI_PROTOCOL (0x00 << OP_TYPE_SHIFT) -#define OP_TYPE_PK (0x01 << OP_TYPE_SHIFT) -#define OP_TYPE_CLASS1_ALG (0x02 << OP_TYPE_SHIFT) -#define OP_TYPE_CLASS2_ALG (0x04 << OP_TYPE_SHIFT) -#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT) -#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT) +#define OP_TYPE_UNI_PROTOCOL (0x00 << OP_TYPE_SHIFT) +#define OP_TYPE_PK (0x01 << OP_TYPE_SHIFT) +#define OP_TYPE_CLASS1_ALG (0x02 << OP_TYPE_SHIFT) +#define OP_TYPE_CLASS2_ALG (0x04 << OP_TYPE_SHIFT) +#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT) +#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT) /* ProtocolID selectors - PROTID */ -#define OP_PCLID_SHIFT 16 -#define OP_PCLID_MASK (0xff << 16) +#define OP_PCLID_SHIFT 16 +#define OP_PCLID_MASK (0xff << 16) /* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */ -#define OP_PCLID_IKEV1_PRF (0x01 << OP_PCLID_SHIFT) -#define OP_PCLID_IKEV2_PRF (0x02 << OP_PCLID_SHIFT) -#define OP_PCLID_SSL30_PRF (0x08 << OP_PCLID_SHIFT) -#define OP_PCLID_TLS10_PRF (0x09 << OP_PCLID_SHIFT) -#define OP_PCLID_TLS11_PRF (0x0a << OP_PCLID_SHIFT) -#define OP_PCLID_DTLS10_PRF (0x0c << OP_PCLID_SHIFT) -#define OP_PCLID_PRF (0x06 << OP_PCLID_SHIFT) -#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT) -#define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT) -#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT) -#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT) -#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT) +#define OP_PCLID_IKEV1_PRF (0x01 << OP_PCLID_SHIFT) +#define OP_PCLID_IKEV2_PRF (0x02 << OP_PCLID_SHIFT) +#define OP_PCLID_SSL30_PRF (0x08 << OP_PCLID_SHIFT) +#define OP_PCLID_TLS10_PRF (0x09 << OP_PCLID_SHIFT) +#define OP_PCLID_TLS11_PRF (0x0a << OP_PCLID_SHIFT) +#define OP_PCLID_DTLS10_PRF (0x0c << OP_PCLID_SHIFT) +#define OP_PCLID_PRF (0x06 << OP_PCLID_SHIFT) +#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT) +#define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT) +#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT) +#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT) +#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT) /* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */ -#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT) -#define OP_PCLID_SRTP (0x02 << OP_PCLID_SHIFT) -#define OP_PCLID_MACSEC (0x03 << OP_PCLID_SHIFT) -#define OP_PCLID_WIFI (0x04 << OP_PCLID_SHIFT) -#define OP_PCLID_WIMAX (0x05 << OP_PCLID_SHIFT) -#define OP_PCLID_SSL30 (0x08 << OP_PCLID_SHIFT) -#define OP_PCLID_TLS10 (0x09 << OP_PCLID_SHIFT) -#define OP_PCLID_TLS11 (0x0a << OP_PCLID_SHIFT) -#define OP_PCLID_TLS12 (0x0b << OP_PCLID_SHIFT) -#define OP_PCLID_DTLS (0x0c << OP_PCLID_SHIFT) +#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT) +#define OP_PCLID_SRTP (0x02 << OP_PCLID_SHIFT) +#define OP_PCLID_MACSEC (0x03 << OP_PCLID_SHIFT) +#define OP_PCLID_WIFI (0x04 << OP_PCLID_SHIFT) +#define OP_PCLID_WIMAX (0x05 << OP_PCLID_SHIFT) +#define OP_PCLID_SSL30 (0x08 << OP_PCLID_SHIFT) +#define OP_PCLID_TLS10 (0x09 << OP_PCLID_SHIFT) +#define OP_PCLID_TLS11 (0x0a << OP_PCLID_SHIFT) +#define OP_PCLID_TLS12 (0x0b << OP_PCLID_SHIFT) +#define OP_PCLID_DTLS (0x0c << OP_PCLID_SHIFT) /* * ProtocolInfo selectors */ -#define OP_PCLINFO_MASK 0xffff +#define OP_PCLINFO_MASK 0xffff /* for OP_PCLID_IPSEC */ -#define OP_PCL_IPSEC_CIPHER_MASK 0xff00 -#define OP_PCL_IPSEC_AUTH_MASK 0x00ff - -#define OP_PCL_IPSEC_DES_IV64 0x0100 -#define OP_PCL_IPSEC_DES 0x0200 -#define OP_PCL_IPSEC_3DES 0x0300 -#define OP_PCL_IPSEC_AES_CBC 0x0c00 -#define OP_PCL_IPSEC_AES_CTR 0x0d00 -#define OP_PCL_IPSEC_AES_XTS 0x1600 -#define OP_PCL_IPSEC_AES_CCM8 0x0e00 -#define OP_PCL_IPSEC_AES_CCM12 0x0f00 -#define OP_PCL_IPSEC_AES_CCM16 0x1000 -#define OP_PCL_IPSEC_AES_GCM8 0x1200 -#define OP_PCL_IPSEC_AES_GCM12 0x1300 -#define OP_PCL_IPSEC_AES_GCM16 0x1400 - -#define OP_PCL_IPSEC_HMAC_NULL 0x0000 -#define OP_PCL_IPSEC_HMAC_MD5_96 0x0001 -#define OP_PCL_IPSEC_HMAC_SHA1_96 0x0002 -#define OP_PCL_IPSEC_AES_XCBC_MAC_96 0x0005 -#define OP_PCL_IPSEC_HMAC_MD5_128 0x0006 -#define OP_PCL_IPSEC_HMAC_SHA1_160 0x0007 -#define OP_PCL_IPSEC_HMAC_SHA2_256_128 0x000c -#define OP_PCL_IPSEC_HMAC_SHA2_384_192 0x000d -#define OP_PCL_IPSEC_HMAC_SHA2_512_256 0x000e +#define OP_PCL_IPSEC_CIPHER_MASK 0xff00 +#define OP_PCL_IPSEC_AUTH_MASK 0x00ff + +#define OP_PCL_IPSEC_DES_IV64 0x0100 +#define OP_PCL_IPSEC_DES 0x0200 +#define OP_PCL_IPSEC_3DES 0x0300 +#define OP_PCL_IPSEC_AES_CBC 0x0c00 +#define OP_PCL_IPSEC_AES_CTR 0x0d00 +#define OP_PCL_IPSEC_AES_XTS 0x1600 +#define OP_PCL_IPSEC_AES_CCM8 0x0e00 +#define OP_PCL_IPSEC_AES_CCM12 0x0f00 +#define OP_PCL_IPSEC_AES_CCM16 0x1000 +#define OP_PCL_IPSEC_AES_GCM8 0x1200 +#define OP_PCL_IPSEC_AES_GCM12 0x1300 +#define OP_PCL_IPSEC_AES_GCM16 0x1400 + +#define OP_PCL_IPSEC_HMAC_NULL 0x0000 +#define OP_PCL_IPSEC_HMAC_MD5_96 0x0001 +#define OP_PCL_IPSEC_HMAC_SHA1_96 0x0002 +#define OP_PCL_IPSEC_AES_XCBC_MAC_96 0x0005 +#define OP_PCL_IPSEC_HMAC_MD5_128 0x0006 +#define OP_PCL_IPSEC_HMAC_SHA1_160 0x0007 +#define OP_PCL_IPSEC_HMAC_SHA2_256_128 0x000c +#define OP_PCL_IPSEC_HMAC_SHA2_384_192 0x000d +#define OP_PCL_IPSEC_HMAC_SHA2_512_256 0x000e /* For SRTP - OP_PCLID_SRTP */ -#define OP_PCL_SRTP_CIPHER_MASK 0xff00 -#define OP_PCL_SRTP_AUTH_MASK 0x00ff +#define OP_PCL_SRTP_CIPHER_MASK 0xff00 +#define OP_PCL_SRTP_AUTH_MASK 0x00ff -#define OP_PCL_SRTP_AES_CTR 0x0d00 +#define OP_PCL_SRTP_AES_CTR 0x0d00 -#define OP_PCL_SRTP_HMAC_SHA1_160 0x0007 +#define OP_PCL_SRTP_HMAC_SHA1_160 0x0007 /* For SSL 3.0 - OP_PCLID_SSL30 */ -#define OP_PCL_SSL30_AES_128_CBC_SHA 0x002f -#define OP_PCL_SSL30_AES_128_CBC_SHA_2 0x0030 -#define OP_PCL_SSL30_AES_128_CBC_SHA_3 0x0031 -#define OP_PCL_SSL30_AES_128_CBC_SHA_4 0x0032 -#define OP_PCL_SSL30_AES_128_CBC_SHA_5 0x0033 -#define OP_PCL_SSL30_AES_128_CBC_SHA_6 0x0034 -#define OP_PCL_SSL30_AES_128_CBC_SHA_7 0x008c -#define OP_PCL_SSL30_AES_128_CBC_SHA_8 0x0090 -#define OP_PCL_SSL30_AES_128_CBC_SHA_9 0x0094 -#define OP_PCL_SSL30_AES_128_CBC_SHA_10 0xc004 -#define OP_PCL_SSL30_AES_128_CBC_SHA_11 0xc009 -#define OP_PCL_SSL30_AES_128_CBC_SHA_12 0xc00e -#define OP_PCL_SSL30_AES_128_CBC_SHA_13 0xc013 -#define OP_PCL_SSL30_AES_128_CBC_SHA_14 0xc018 -#define OP_PCL_SSL30_AES_128_CBC_SHA_15 0xc01d -#define OP_PCL_SSL30_AES_128_CBC_SHA_16 0xc01e -#define OP_PCL_SSL30_AES_128_CBC_SHA_17 0xc01f - -#define OP_PCL_SSL30_AES_256_CBC_SHA 0x0035 -#define OP_PCL_SSL30_AES_256_CBC_SHA_2 0x0036 -#define OP_PCL_SSL30_AES_256_CBC_SHA_3 0x0037 -#define OP_PCL_SSL30_AES_256_CBC_SHA_4 0x0038 -#define OP_PCL_SSL30_AES_256_CBC_SHA_5 0x0039 -#define OP_PCL_SSL30_AES_256_CBC_SHA_6 0x003a -#define OP_PCL_SSL30_AES_256_CBC_SHA_7 0x008d -#define OP_PCL_SSL30_AES_256_CBC_SHA_8 0x0091 -#define OP_PCL_SSL30_AES_256_CBC_SHA_9 0x0095 -#define OP_PCL_SSL30_AES_256_CBC_SHA_10 0xc005 -#define OP_PCL_SSL30_AES_256_CBC_SHA_11 0xc00a -#define OP_PCL_SSL30_AES_256_CBC_SHA_12 0xc00f -#define OP_PCL_SSL30_AES_256_CBC_SHA_13 0xc014 -#define OP_PCL_SSL30_AES_256_CBC_SHA_14 0xc019 -#define OP_PCL_SSL30_AES_256_CBC_SHA_15 0xc020 -#define OP_PCL_SSL30_AES_256_CBC_SHA_16 0xc021 -#define OP_PCL_SSL30_AES_256_CBC_SHA_17 0xc022 - -#define OP_PCL_SSL30_3DES_EDE_CBC_MD5 0x0023 - -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA 0x001f -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_2 0x008b -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_3 0x008f -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_4 0x0093 -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_5 0x000a -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_6 0x000d -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_7 0x0010 -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_8 0x0013 -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_9 0x0016 -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_10 0x001b -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_11 0xc003 -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_12 0xc008 -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_13 0xc00d -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_14 0xc012 -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_15 0xc017 -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_16 0xc01a -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_17 0xc01b -#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_18 0xc01c - -#define OP_PCL_SSL30_DES40_CBC_MD5 0x0029 - -#define OP_PCL_SSL30_DES_CBC_MD5 0x0022 - -#define OP_PCL_SSL30_DES40_CBC_SHA 0x0008 -#define OP_PCL_SSL30_DES40_CBC_SHA_2 0x000b -#define OP_PCL_SSL30_DES40_CBC_SHA_3 0x000e -#define OP_PCL_SSL30_DES40_CBC_SHA_4 0x0011 -#define OP_PCL_SSL30_DES40_CBC_SHA_5 0x0014 -#define OP_PCL_SSL30_DES40_CBC_SHA_6 0x0019 -#define OP_PCL_SSL30_DES40_CBC_SHA_7 0x0026 - -#define OP_PCL_SSL30_DES_CBC_SHA 0x001e -#define OP_PCL_SSL30_DES_CBC_SHA_2 0x0009 -#define OP_PCL_SSL30_DES_CBC_SHA_3 0x000c -#define OP_PCL_SSL30_DES_CBC_SHA_4 0x000f -#define OP_PCL_SSL30_DES_CBC_SHA_5 0x0012 -#define OP_PCL_SSL30_DES_CBC_SHA_6 0x0015 -#define OP_PCL_SSL30_DES_CBC_SHA_7 0x001a - -#define OP_PCL_SSL30_RC4_128_MD5 0x0024 -#define OP_PCL_SSL30_RC4_128_MD5_2 0x0004 -#define OP_PCL_SSL30_RC4_128_MD5_3 0x0018 - -#define OP_PCL_SSL30_RC4_40_MD5 0x002b -#define OP_PCL_SSL30_RC4_40_MD5_2 0x0003 -#define OP_PCL_SSL30_RC4_40_MD5_3 0x0017 - -#define OP_PCL_SSL30_RC4_128_SHA 0x0020 -#define OP_PCL_SSL30_RC4_128_SHA_2 0x008a -#define OP_PCL_SSL30_RC4_128_SHA_3 0x008e -#define OP_PCL_SSL30_RC4_128_SHA_4 0x0092 -#define OP_PCL_SSL30_RC4_128_SHA_5 0x0005 -#define OP_PCL_SSL30_RC4_128_SHA_6 0xc002 -#define OP_PCL_SSL30_RC4_128_SHA_7 0xc007 -#define OP_PCL_SSL30_RC4_128_SHA_8 0xc00c -#define OP_PCL_SSL30_RC4_128_SHA_9 0xc011 -#define OP_PCL_SSL30_RC4_128_SHA_10 0xc016 - -#define OP_PCL_SSL30_RC4_40_SHA 0x0028 +#define OP_PCL_SSL30_AES_128_CBC_SHA 0x002f +#define OP_PCL_SSL30_AES_128_CBC_SHA_2 0x0030 +#define OP_PCL_SSL30_AES_128_CBC_SHA_3 0x0031 +#define OP_PCL_SSL30_AES_128_CBC_SHA_4 0x0032 +#define OP_PCL_SSL30_AES_128_CBC_SHA_5 0x0033 +#define OP_PCL_SSL30_AES_128_CBC_SHA_6 0x0034 +#define OP_PCL_SSL30_AES_128_CBC_SHA_7 0x008c +#define OP_PCL_SSL30_AES_128_CBC_SHA_8 0x0090 +#define OP_PCL_SSL30_AES_128_CBC_SHA_9 0x0094 +#define OP_PCL_SSL30_AES_128_CBC_SHA_10 0xc004 +#define OP_PCL_SSL30_AES_128_CBC_SHA_11 0xc009 +#define OP_PCL_SSL30_AES_128_CBC_SHA_12 0xc00e +#define OP_PCL_SSL30_AES_128_CBC_SHA_13 0xc013 +#define OP_PCL_SSL30_AES_128_CBC_SHA_14 0xc018 +#define OP_PCL_SSL30_AES_128_CBC_SHA_15 0xc01d +#define OP_PCL_SSL30_AES_128_CBC_SHA_16 0xc01e +#define OP_PCL_SSL30_AES_128_CBC_SHA_17 0xc01f + +#define OP_PCL_SSL30_AES_256_CBC_SHA 0x0035 +#define OP_PCL_SSL30_AES_256_CBC_SHA_2 0x0036 +#define OP_PCL_SSL30_AES_256_CBC_SHA_3 0x0037 +#define OP_PCL_SSL30_AES_256_CBC_SHA_4 0x0038 +#define OP_PCL_SSL30_AES_256_CBC_SHA_5 0x0039 +#define OP_PCL_SSL30_AES_256_CBC_SHA_6 0x003a +#define OP_PCL_SSL30_AES_256_CBC_SHA_7 0x008d +#define OP_PCL_SSL30_AES_256_CBC_SHA_8 0x0091 +#define OP_PCL_SSL30_AES_256_CBC_SHA_9 0x0095 +#define OP_PCL_SSL30_AES_256_CBC_SHA_10 0xc005 +#define OP_PCL_SSL30_AES_256_CBC_SHA_11 0xc00a +#define OP_PCL_SSL30_AES_256_CBC_SHA_12 0xc00f +#define OP_PCL_SSL30_AES_256_CBC_SHA_13 0xc014 +#define OP_PCL_SSL30_AES_256_CBC_SHA_14 0xc019 +#define OP_PCL_SSL30_AES_256_CBC_SHA_15 0xc020 +#define OP_PCL_SSL30_AES_256_CBC_SHA_16 0xc021 +#define OP_PCL_SSL30_AES_256_CBC_SHA_17 0xc022 + +#define OP_PCL_SSL30_3DES_EDE_CBC_MD5 0x0023 + +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA 0x001f +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_2 0x008b +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_3 0x008f +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_4 0x0093 +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_5 0x000a +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_6 0x000d +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_7 0x0010 +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_8 0x0013 +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_9 0x0016 +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_10 0x001b +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_11 0xc003 +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_12 0xc008 +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_13 0xc00d +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_14 0xc012 +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_15 0xc017 +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_16 0xc01a +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_17 0xc01b +#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_18 0xc01c + +#define OP_PCL_SSL30_DES40_CBC_MD5 0x0029 + +#define OP_PCL_SSL30_DES_CBC_MD5 0x0022 + +#define OP_PCL_SSL30_DES40_CBC_SHA 0x0008 +#define OP_PCL_SSL30_DES40_CBC_SHA_2 0x000b +#define OP_PCL_SSL30_DES40_CBC_SHA_3 0x000e +#define OP_PCL_SSL30_DES40_CBC_SHA_4 0x0011 +#define OP_PCL_SSL30_DES40_CBC_SHA_5 0x0014 +#define OP_PCL_SSL30_DES40_CBC_SHA_6 0x0019 +#define OP_PCL_SSL30_DES40_CBC_SHA_7 0x0026 + +#define OP_PCL_SSL30_DES_CBC_SHA 0x001e +#define OP_PCL_SSL30_DES_CBC_SHA_2 0x0009 +#define OP_PCL_SSL30_DES_CBC_SHA_3 0x000c +#define OP_PCL_SSL30_DES_CBC_SHA_4 0x000f +#define OP_PCL_SSL30_DES_CBC_SHA_5 0x0012 +#define OP_PCL_SSL30_DES_CBC_SHA_6 0x0015 +#define OP_PCL_SSL30_DES_CBC_SHA_7 0x001a + +#define OP_PCL_SSL30_RC4_128_MD5 0x0024 +#define OP_PCL_SSL30_RC4_128_MD5_2 0x0004 +#define OP_PCL_SSL30_RC4_128_MD5_3 0x0018 + +#define OP_PCL_SSL30_RC4_40_MD5 0x002b +#define OP_PCL_SSL30_RC4_40_MD5_2 0x0003 +#define OP_PCL_SSL30_RC4_40_MD5_3 0x0017 + +#define OP_PCL_SSL30_RC4_128_SHA 0x0020 +#define OP_PCL_SSL30_RC4_128_SHA_2 0x008a +#define OP_PCL_SSL30_RC4_128_SHA_3 0x008e +#define OP_PCL_SSL30_RC4_128_SHA_4 0x0092 +#define OP_PCL_SSL30_RC4_128_SHA_5 0x0005 +#define OP_PCL_SSL30_RC4_128_SHA_6 0xc002 +#define OP_PCL_SSL30_RC4_128_SHA_7 0xc007 +#define OP_PCL_SSL30_RC4_128_SHA_8 0xc00c +#define OP_PCL_SSL30_RC4_128_SHA_9 0xc011 +#define OP_PCL_SSL30_RC4_128_SHA_10 0xc016 + +#define OP_PCL_SSL30_RC4_40_SHA 0x0028 /* For TLS 1.0 - OP_PCLID_TLS10 */ -#define OP_PCL_TLS10_AES_128_CBC_SHA 0x002f -#define OP_PCL_TLS10_AES_128_CBC_SHA_2 0x0030 -#define OP_PCL_TLS10_AES_128_CBC_SHA_3 0x0031 -#define OP_PCL_TLS10_AES_128_CBC_SHA_4 0x0032 -#define OP_PCL_TLS10_AES_128_CBC_SHA_5 0x0033 -#define OP_PCL_TLS10_AES_128_CBC_SHA_6 0x0034 -#define OP_PCL_TLS10_AES_128_CBC_SHA_7 0x008c -#define OP_PCL_TLS10_AES_128_CBC_SHA_8 0x0090 -#define OP_PCL_TLS10_AES_128_CBC_SHA_9 0x0094 -#define OP_PCL_TLS10_AES_128_CBC_SHA_10 0xc004 -#define OP_PCL_TLS10_AES_128_CBC_SHA_11 0xc009 -#define OP_PCL_TLS10_AES_128_CBC_SHA_12 0xc00e -#define OP_PCL_TLS10_AES_128_CBC_SHA_13 0xc013 -#define OP_PCL_TLS10_AES_128_CBC_SHA_14 0xc018 -#define OP_PCL_TLS10_AES_128_CBC_SHA_15 0xc01d -#define OP_PCL_TLS10_AES_128_CBC_SHA_16 0xc01e -#define OP_PCL_TLS10_AES_128_CBC_SHA_17 0xc01f - -#define OP_PCL_TLS10_AES_256_CBC_SHA 0x0035 -#define OP_PCL_TLS10_AES_256_CBC_SHA_2 0x0036 -#define OP_PCL_TLS10_AES_256_CBC_SHA_3 0x0037 -#define OP_PCL_TLS10_AES_256_CBC_SHA_4 0x0038 -#define OP_PCL_TLS10_AES_256_CBC_SHA_5 0x0039 -#define OP_PCL_TLS10_AES_256_CBC_SHA_6 0x003a -#define OP_PCL_TLS10_AES_256_CBC_SHA_7 0x008d -#define OP_PCL_TLS10_AES_256_CBC_SHA_8 0x0091 -#define OP_PCL_TLS10_AES_256_CBC_SHA_9 0x0095 -#define OP_PCL_TLS10_AES_256_CBC_SHA_10 0xc005 -#define OP_PCL_TLS10_AES_256_CBC_SHA_11 0xc00a -#define OP_PCL_TLS10_AES_256_CBC_SHA_12 0xc00f -#define OP_PCL_TLS10_AES_256_CBC_SHA_13 0xc014 -#define OP_PCL_TLS10_AES_256_CBC_SHA_14 0xc019 -#define OP_PCL_TLS10_AES_256_CBC_SHA_15 0xc020 -#define OP_PCL_TLS10_AES_256_CBC_SHA_16 0xc021 -#define OP_PCL_TLS10_AES_256_CBC_SHA_17 0xc022 - -/* #define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0x0023 */ - -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA 0x001f -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_2 0x008b -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_3 0x008f -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_4 0x0093 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_5 0x000a -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_6 0x000d -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_7 0x0010 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_8 0x0013 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_9 0x0016 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_10 0x001b -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_11 0xc003 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_12 0xc008 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_13 0xc00d -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_14 0xc012 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_15 0xc017 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_16 0xc01a -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_17 0xc01b -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_18 0xc01c - -#define OP_PCL_TLS10_DES40_CBC_MD5 0x0029 - -#define OP_PCL_TLS10_DES_CBC_MD5 0x0022 - -#define OP_PCL_TLS10_DES40_CBC_SHA 0x0008 -#define OP_PCL_TLS10_DES40_CBC_SHA_2 0x000b -#define OP_PCL_TLS10_DES40_CBC_SHA_3 0x000e -#define OP_PCL_TLS10_DES40_CBC_SHA_4 0x0011 -#define OP_PCL_TLS10_DES40_CBC_SHA_5 0x0014 -#define OP_PCL_TLS10_DES40_CBC_SHA_6 0x0019 -#define OP_PCL_TLS10_DES40_CBC_SHA_7 0x0026 - - -#define OP_PCL_TLS10_DES_CBC_SHA 0x001e -#define OP_PCL_TLS10_DES_CBC_SHA_2 0x0009 -#define OP_PCL_TLS10_DES_CBC_SHA_3 0x000c -#define OP_PCL_TLS10_DES_CBC_SHA_4 0x000f -#define OP_PCL_TLS10_DES_CBC_SHA_5 0x0012 -#define OP_PCL_TLS10_DES_CBC_SHA_6 0x0015 -#define OP_PCL_TLS10_DES_CBC_SHA_7 0x001a - -#define OP_PCL_TLS10_RC4_128_MD5 0x0024 -#define OP_PCL_TLS10_RC4_128_MD5_2 0x0004 -#define OP_PCL_TLS10_RC4_128_MD5_3 0x0018 - -#define OP_PCL_TLS10_RC4_40_MD5 0x002b -#define OP_PCL_TLS10_RC4_40_MD5_2 0x0003 -#define OP_PCL_TLS10_RC4_40_MD5_3 0x0017 - -#define OP_PCL_TLS10_RC4_128_SHA 0x0020 -#define OP_PCL_TLS10_RC4_128_SHA_2 0x008a -#define OP_PCL_TLS10_RC4_128_SHA_3 0x008e -#define OP_PCL_TLS10_RC4_128_SHA_4 0x0092 -#define OP_PCL_TLS10_RC4_128_SHA_5 0x0005 -#define OP_PCL_TLS10_RC4_128_SHA_6 0xc002 -#define OP_PCL_TLS10_RC4_128_SHA_7 0xc007 -#define OP_PCL_TLS10_RC4_128_SHA_8 0xc00c -#define OP_PCL_TLS10_RC4_128_SHA_9 0xc011 -#define OP_PCL_TLS10_RC4_128_SHA_10 0xc016 - -#define OP_PCL_TLS10_RC4_40_SHA 0x0028 - -#define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0xff23 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA160 0xff30 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA224 0xff34 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA256 0xff36 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA384 0xff33 -#define OP_PCL_TLS10_3DES_EDE_CBC_SHA512 0xff35 -#define OP_PCL_TLS10_AES_128_CBC_SHA160 0xff80 -#define OP_PCL_TLS10_AES_128_CBC_SHA224 0xff84 -#define OP_PCL_TLS10_AES_128_CBC_SHA256 0xff86 -#define OP_PCL_TLS10_AES_128_CBC_SHA384 0xff83 -#define OP_PCL_TLS10_AES_128_CBC_SHA512 0xff85 -#define OP_PCL_TLS10_AES_192_CBC_SHA160 0xff20 -#define OP_PCL_TLS10_AES_192_CBC_SHA224 0xff24 -#define OP_PCL_TLS10_AES_192_CBC_SHA256 0xff26 -#define OP_PCL_TLS10_AES_192_CBC_SHA384 0xff23 -#define OP_PCL_TLS10_AES_192_CBC_SHA512 0xff25 -#define OP_PCL_TLS10_AES_256_CBC_SHA160 0xff60 -#define OP_PCL_TLS10_AES_256_CBC_SHA224 0xff64 -#define OP_PCL_TLS10_AES_256_CBC_SHA256 0xff66 -#define OP_PCL_TLS10_AES_256_CBC_SHA384 0xff63 -#define OP_PCL_TLS10_AES_256_CBC_SHA512 0xff65 +#define OP_PCL_TLS10_AES_128_CBC_SHA 0x002f +#define OP_PCL_TLS10_AES_128_CBC_SHA_2 0x0030 +#define OP_PCL_TLS10_AES_128_CBC_SHA_3 0x0031 +#define OP_PCL_TLS10_AES_128_CBC_SHA_4 0x0032 +#define OP_PCL_TLS10_AES_128_CBC_SHA_5 0x0033 +#define OP_PCL_TLS10_AES_128_CBC_SHA_6 0x0034 +#define OP_PCL_TLS10_AES_128_CBC_SHA_7 0x008c +#define OP_PCL_TLS10_AES_128_CBC_SHA_8 0x0090 +#define OP_PCL_TLS10_AES_128_CBC_SHA_9 0x0094 +#define OP_PCL_TLS10_AES_128_CBC_SHA_10 0xc004 +#define OP_PCL_TLS10_AES_128_CBC_SHA_11 0xc009 +#define OP_PCL_TLS10_AES_128_CBC_SHA_12 0xc00e +#define OP_PCL_TLS10_AES_128_CBC_SHA_13 0xc013 +#define OP_PCL_TLS10_AES_128_CBC_SHA_14 0xc018 +#define OP_PCL_TLS10_AES_128_CBC_SHA_15 0xc01d +#define OP_PCL_TLS10_AES_128_CBC_SHA_16 0xc01e +#define OP_PCL_TLS10_AES_128_CBC_SHA_17 0xc01f + +#define OP_PCL_TLS10_AES_256_CBC_SHA 0x0035 +#define OP_PCL_TLS10_AES_256_CBC_SHA_2 0x0036 +#define OP_PCL_TLS10_AES_256_CBC_SHA_3 0x0037 +#define OP_PCL_TLS10_AES_256_CBC_SHA_4 0x0038 +#define OP_PCL_TLS10_AES_256_CBC_SHA_5 0x0039 +#define OP_PCL_TLS10_AES_256_CBC_SHA_6 0x003a +#define OP_PCL_TLS10_AES_256_CBC_SHA_7 0x008d +#define OP_PCL_TLS10_AES_256_CBC_SHA_8 0x0091 +#define OP_PCL_TLS10_AES_256_CBC_SHA_9 0x0095 +#define OP_PCL_TLS10_AES_256_CBC_SHA_10 0xc005 +#define OP_PCL_TLS10_AES_256_CBC_SHA_11 0xc00a +#define OP_PCL_TLS10_AES_256_CBC_SHA_12 0xc00f +#define OP_PCL_TLS10_AES_256_CBC_SHA_13 0xc014 +#define OP_PCL_TLS10_AES_256_CBC_SHA_14 0xc019 +#define OP_PCL_TLS10_AES_256_CBC_SHA_15 0xc020 +#define OP_PCL_TLS10_AES_256_CBC_SHA_16 0xc021 +#define OP_PCL_TLS10_AES_256_CBC_SHA_17 0xc022 + +/* #define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0x0023 */ + +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA 0x001f +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_2 0x008b +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_3 0x008f +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_4 0x0093 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_5 0x000a +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_6 0x000d +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_7 0x0010 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_8 0x0013 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_9 0x0016 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_10 0x001b +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_11 0xc003 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_12 0xc008 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_13 0xc00d +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_14 0xc012 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_15 0xc017 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_16 0xc01a +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_17 0xc01b +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_18 0xc01c + +#define OP_PCL_TLS10_DES40_CBC_MD5 0x0029 + +#define OP_PCL_TLS10_DES_CBC_MD5 0x0022 + +#define OP_PCL_TLS10_DES40_CBC_SHA 0x0008 +#define OP_PCL_TLS10_DES40_CBC_SHA_2 0x000b +#define OP_PCL_TLS10_DES40_CBC_SHA_3 0x000e +#define OP_PCL_TLS10_DES40_CBC_SHA_4 0x0011 +#define OP_PCL_TLS10_DES40_CBC_SHA_5 0x0014 +#define OP_PCL_TLS10_DES40_CBC_SHA_6 0x0019 +#define OP_PCL_TLS10_DES40_CBC_SHA_7 0x0026 + + +#define OP_PCL_TLS10_DES_CBC_SHA 0x001e +#define OP_PCL_TLS10_DES_CBC_SHA_2 0x0009 +#define OP_PCL_TLS10_DES_CBC_SHA_3 0x000c +#define OP_PCL_TLS10_DES_CBC_SHA_4 0x000f +#define OP_PCL_TLS10_DES_CBC_SHA_5 0x0012 +#define OP_PCL_TLS10_DES_CBC_SHA_6 0x0015 +#define OP_PCL_TLS10_DES_CBC_SHA_7 0x001a + +#define OP_PCL_TLS10_RC4_128_MD5 0x0024 +#define OP_PCL_TLS10_RC4_128_MD5_2 0x0004 +#define OP_PCL_TLS10_RC4_128_MD5_3 0x0018 + +#define OP_PCL_TLS10_RC4_40_MD5 0x002b +#define OP_PCL_TLS10_RC4_40_MD5_2 0x0003 +#define OP_PCL_TLS10_RC4_40_MD5_3 0x0017 + +#define OP_PCL_TLS10_RC4_128_SHA 0x0020 +#define OP_PCL_TLS10_RC4_128_SHA_2 0x008a +#define OP_PCL_TLS10_RC4_128_SHA_3 0x008e +#define OP_PCL_TLS10_RC4_128_SHA_4 0x0092 +#define OP_PCL_TLS10_RC4_128_SHA_5 0x0005 +#define OP_PCL_TLS10_RC4_128_SHA_6 0xc002 +#define OP_PCL_TLS10_RC4_128_SHA_7 0xc007 +#define OP_PCL_TLS10_RC4_128_SHA_8 0xc00c +#define OP_PCL_TLS10_RC4_128_SHA_9 0xc011 +#define OP_PCL_TLS10_RC4_128_SHA_10 0xc016 + +#define OP_PCL_TLS10_RC4_40_SHA 0x0028 + +#define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0xff23 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA160 0xff30 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA224 0xff34 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA256 0xff36 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA384 0xff33 +#define OP_PCL_TLS10_3DES_EDE_CBC_SHA512 0xff35 +#define OP_PCL_TLS10_AES_128_CBC_SHA160 0xff80 +#define OP_PCL_TLS10_AES_128_CBC_SHA224 0xff84 +#define OP_PCL_TLS10_AES_128_CBC_SHA256 0xff86 +#define OP_PCL_TLS10_AES_128_CBC_SHA384 0xff83 +#define OP_PCL_TLS10_AES_128_CBC_SHA512 0xff85 +#define OP_PCL_TLS10_AES_192_CBC_SHA160 0xff20 +#define OP_PCL_TLS10_AES_192_CBC_SHA224 0xff24 +#define OP_PCL_TLS10_AES_192_CBC_SHA256 0xff26 +#define OP_PCL_TLS10_AES_192_CBC_SHA384 0xff23 +#define OP_PCL_TLS10_AES_192_CBC_SHA512 0xff25 +#define OP_PCL_TLS10_AES_256_CBC_SHA160 0xff60 +#define OP_PCL_TLS10_AES_256_CBC_SHA224 0xff64 +#define OP_PCL_TLS10_AES_256_CBC_SHA256 0xff66 +#define OP_PCL_TLS10_AES_256_CBC_SHA384 0xff63 +#define OP_PCL_TLS10_AES_256_CBC_SHA512 0xff65 /* For TLS 1.1 - OP_PCLID_TLS11 */ -#define OP_PCL_TLS11_AES_128_CBC_SHA 0x002f -#define OP_PCL_TLS11_AES_128_CBC_SHA_2 0x0030 -#define OP_PCL_TLS11_AES_128_CBC_SHA_3 0x0031 -#define OP_PCL_TLS11_AES_128_CBC_SHA_4 0x0032 -#define OP_PCL_TLS11_AES_128_CBC_SHA_5 0x0033 -#define OP_PCL_TLS11_AES_128_CBC_SHA_6 0x0034 -#define OP_PCL_TLS11_AES_128_CBC_SHA_7 0x008c -#define OP_PCL_TLS11_AES_128_CBC_SHA_8 0x0090 -#define OP_PCL_TLS11_AES_128_CBC_SHA_9 0x0094 -#define OP_PCL_TLS11_AES_128_CBC_SHA_10 0xc004 -#define OP_PCL_TLS11_AES_128_CBC_SHA_11 0xc009 -#define OP_PCL_TLS11_AES_128_CBC_SHA_12 0xc00e -#define OP_PCL_TLS11_AES_128_CBC_SHA_13 0xc013 -#define OP_PCL_TLS11_AES_128_CBC_SHA_14 0xc018 -#define OP_PCL_TLS11_AES_128_CBC_SHA_15 0xc01d -#define OP_PCL_TLS11_AES_128_CBC_SHA_16 0xc01e -#define OP_PCL_TLS11_AES_128_CBC_SHA_17 0xc01f - -#define OP_PCL_TLS11_AES_256_CBC_SHA 0x0035 -#define OP_PCL_TLS11_AES_256_CBC_SHA_2 0x0036 -#define OP_PCL_TLS11_AES_256_CBC_SHA_3 0x0037 -#define OP_PCL_TLS11_AES_256_CBC_SHA_4 0x0038 -#define OP_PCL_TLS11_AES_256_CBC_SHA_5 0x0039 -#define OP_PCL_TLS11_AES_256_CBC_SHA_6 0x003a -#define OP_PCL_TLS11_AES_256_CBC_SHA_7 0x008d -#define OP_PCL_TLS11_AES_256_CBC_SHA_8 0x0091 -#define OP_PCL_TLS11_AES_256_CBC_SHA_9 0x0095 -#define OP_PCL_TLS11_AES_256_CBC_SHA_10 0xc005 -#define OP_PCL_TLS11_AES_256_CBC_SHA_11 0xc00a -#define OP_PCL_TLS11_AES_256_CBC_SHA_12 0xc00f -#define OP_PCL_TLS11_AES_256_CBC_SHA_13 0xc014 -#define OP_PCL_TLS11_AES_256_CBC_SHA_14 0xc019 -#define OP_PCL_TLS11_AES_256_CBC_SHA_15 0xc020 -#define OP_PCL_TLS11_AES_256_CBC_SHA_16 0xc021 -#define OP_PCL_TLS11_AES_256_CBC_SHA_17 0xc022 - -/* #define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0x0023 */ - -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA 0x001f -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_2 0x008b -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_3 0x008f -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_4 0x0093 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_5 0x000a -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_6 0x000d -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_7 0x0010 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_8 0x0013 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_9 0x0016 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_10 0x001b -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_11 0xc003 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_12 0xc008 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_13 0xc00d -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_14 0xc012 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_15 0xc017 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_16 0xc01a -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_17 0xc01b -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_18 0xc01c - -#define OP_PCL_TLS11_DES40_CBC_MD5 0x0029 - -#define OP_PCL_TLS11_DES_CBC_MD5 0x0022 - -#define OP_PCL_TLS11_DES40_CBC_SHA 0x0008 -#define OP_PCL_TLS11_DES40_CBC_SHA_2 0x000b -#define OP_PCL_TLS11_DES40_CBC_SHA_3 0x000e -#define OP_PCL_TLS11_DES40_CBC_SHA_4 0x0011 -#define OP_PCL_TLS11_DES40_CBC_SHA_5 0x0014 -#define OP_PCL_TLS11_DES40_CBC_SHA_6 0x0019 -#define OP_PCL_TLS11_DES40_CBC_SHA_7 0x0026 - -#define OP_PCL_TLS11_DES_CBC_SHA 0x001e -#define OP_PCL_TLS11_DES_CBC_SHA_2 0x0009 -#define OP_PCL_TLS11_DES_CBC_SHA_3 0x000c -#define OP_PCL_TLS11_DES_CBC_SHA_4 0x000f -#define OP_PCL_TLS11_DES_CBC_SHA_5 0x0012 -#define OP_PCL_TLS11_DES_CBC_SHA_6 0x0015 -#define OP_PCL_TLS11_DES_CBC_SHA_7 0x001a - -#define OP_PCL_TLS11_RC4_128_MD5 0x0024 -#define OP_PCL_TLS11_RC4_128_MD5_2 0x0004 -#define OP_PCL_TLS11_RC4_128_MD5_3 0x0018 - -#define OP_PCL_TLS11_RC4_40_MD5 0x002b -#define OP_PCL_TLS11_RC4_40_MD5_2 0x0003 -#define OP_PCL_TLS11_RC4_40_MD5_3 0x0017 - -#define OP_PCL_TLS11_RC4_128_SHA 0x0020 -#define OP_PCL_TLS11_RC4_128_SHA_2 0x008a -#define OP_PCL_TLS11_RC4_128_SHA_3 0x008e -#define OP_PCL_TLS11_RC4_128_SHA_4 0x0092 -#define OP_PCL_TLS11_RC4_128_SHA_5 0x0005 -#define OP_PCL_TLS11_RC4_128_SHA_6 0xc002 -#define OP_PCL_TLS11_RC4_128_SHA_7 0xc007 -#define OP_PCL_TLS11_RC4_128_SHA_8 0xc00c -#define OP_PCL_TLS11_RC4_128_SHA_9 0xc011 -#define OP_PCL_TLS11_RC4_128_SHA_10 0xc016 - -#define OP_PCL_TLS11_RC4_40_SHA 0x0028 - -#define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0xff23 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA160 0xff30 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA224 0xff34 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA256 0xff36 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA384 0xff33 -#define OP_PCL_TLS11_3DES_EDE_CBC_SHA512 0xff35 -#define OP_PCL_TLS11_AES_128_CBC_SHA160 0xff80 -#define OP_PCL_TLS11_AES_128_CBC_SHA224 0xff84 -#define OP_PCL_TLS11_AES_128_CBC_SHA256 0xff86 -#define OP_PCL_TLS11_AES_128_CBC_SHA384 0xff83 -#define OP_PCL_TLS11_AES_128_CBC_SHA512 0xff85 -#define OP_PCL_TLS11_AES_192_CBC_SHA160 0xff20 -#define OP_PCL_TLS11_AES_192_CBC_SHA224 0xff24 -#define OP_PCL_TLS11_AES_192_CBC_SHA256 0xff26 -#define OP_PCL_TLS11_AES_192_CBC_SHA384 0xff23 -#define OP_PCL_TLS11_AES_192_CBC_SHA512 0xff25 -#define OP_PCL_TLS11_AES_256_CBC_SHA160 0xff60 -#define OP_PCL_TLS11_AES_256_CBC_SHA224 0xff64 -#define OP_PCL_TLS11_AES_256_CBC_SHA256 0xff66 -#define OP_PCL_TLS11_AES_256_CBC_SHA384 0xff63 -#define OP_PCL_TLS11_AES_256_CBC_SHA512 0xff65 +#define OP_PCL_TLS11_AES_128_CBC_SHA 0x002f +#define OP_PCL_TLS11_AES_128_CBC_SHA_2 0x0030 +#define OP_PCL_TLS11_AES_128_CBC_SHA_3 0x0031 +#define OP_PCL_TLS11_AES_128_CBC_SHA_4 0x0032 +#define OP_PCL_TLS11_AES_128_CBC_SHA_5 0x0033 +#define OP_PCL_TLS11_AES_128_CBC_SHA_6 0x0034 +#define OP_PCL_TLS11_AES_128_CBC_SHA_7 0x008c +#define OP_PCL_TLS11_AES_128_CBC_SHA_8 0x0090 +#define OP_PCL_TLS11_AES_128_CBC_SHA_9 0x0094 +#define OP_PCL_TLS11_AES_128_CBC_SHA_10 0xc004 +#define OP_PCL_TLS11_AES_128_CBC_SHA_11 0xc009 +#define OP_PCL_TLS11_AES_128_CBC_SHA_12 0xc00e +#define OP_PCL_TLS11_AES_128_CBC_SHA_13 0xc013 +#define OP_PCL_TLS11_AES_128_CBC_SHA_14 0xc018 +#define OP_PCL_TLS11_AES_128_CBC_SHA_15 0xc01d +#define OP_PCL_TLS11_AES_128_CBC_SHA_16 0xc01e +#define OP_PCL_TLS11_AES_128_CBC_SHA_17 0xc01f + +#define OP_PCL_TLS11_AES_256_CBC_SHA 0x0035 +#define OP_PCL_TLS11_AES_256_CBC_SHA_2 0x0036 +#define OP_PCL_TLS11_AES_256_CBC_SHA_3 0x0037 +#define OP_PCL_TLS11_AES_256_CBC_SHA_4 0x0038 +#define OP_PCL_TLS11_AES_256_CBC_SHA_5 0x0039 +#define OP_PCL_TLS11_AES_256_CBC_SHA_6 0x003a +#define OP_PCL_TLS11_AES_256_CBC_SHA_7 0x008d +#define OP_PCL_TLS11_AES_256_CBC_SHA_8 0x0091 +#define OP_PCL_TLS11_AES_256_CBC_SHA_9 0x0095 +#define OP_PCL_TLS11_AES_256_CBC_SHA_10 0xc005 +#define OP_PCL_TLS11_AES_256_CBC_SHA_11 0xc00a +#define OP_PCL_TLS11_AES_256_CBC_SHA_12 0xc00f +#define OP_PCL_TLS11_AES_256_CBC_SHA_13 0xc014 +#define OP_PCL_TLS11_AES_256_CBC_SHA_14 0xc019 +#define OP_PCL_TLS11_AES_256_CBC_SHA_15 0xc020 +#define OP_PCL_TLS11_AES_256_CBC_SHA_16 0xc021 +#define OP_PCL_TLS11_AES_256_CBC_SHA_17 0xc022 + +/* #define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0x0023 */ + +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA 0x001f +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_2 0x008b +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_3 0x008f +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_4 0x0093 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_5 0x000a +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_6 0x000d +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_7 0x0010 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_8 0x0013 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_9 0x0016 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_10 0x001b +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_11 0xc003 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_12 0xc008 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_13 0xc00d +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_14 0xc012 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_15 0xc017 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_16 0xc01a +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_17 0xc01b +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_18 0xc01c + +#define OP_PCL_TLS11_DES40_CBC_MD5 0x0029 + +#define OP_PCL_TLS11_DES_CBC_MD5 0x0022 + +#define OP_PCL_TLS11_DES40_CBC_SHA 0x0008 +#define OP_PCL_TLS11_DES40_CBC_SHA_2 0x000b +#define OP_PCL_TLS11_DES40_CBC_SHA_3 0x000e +#define OP_PCL_TLS11_DES40_CBC_SHA_4 0x0011 +#define OP_PCL_TLS11_DES40_CBC_SHA_5 0x0014 +#define OP_PCL_TLS11_DES40_CBC_SHA_6 0x0019 +#define OP_PCL_TLS11_DES40_CBC_SHA_7 0x0026 + +#define OP_PCL_TLS11_DES_CBC_SHA 0x001e +#define OP_PCL_TLS11_DES_CBC_SHA_2 0x0009 +#define OP_PCL_TLS11_DES_CBC_SHA_3 0x000c +#define OP_PCL_TLS11_DES_CBC_SHA_4 0x000f +#define OP_PCL_TLS11_DES_CBC_SHA_5 0x0012 +#define OP_PCL_TLS11_DES_CBC_SHA_6 0x0015 +#define OP_PCL_TLS11_DES_CBC_SHA_7 0x001a + +#define OP_PCL_TLS11_RC4_128_MD5 0x0024 +#define OP_PCL_TLS11_RC4_128_MD5_2 0x0004 +#define OP_PCL_TLS11_RC4_128_MD5_3 0x0018 + +#define OP_PCL_TLS11_RC4_40_MD5 0x002b +#define OP_PCL_TLS11_RC4_40_MD5_2 0x0003 +#define OP_PCL_TLS11_RC4_40_MD5_3 0x0017 + +#define OP_PCL_TLS11_RC4_128_SHA 0x0020 +#define OP_PCL_TLS11_RC4_128_SHA_2 0x008a +#define OP_PCL_TLS11_RC4_128_SHA_3 0x008e +#define OP_PCL_TLS11_RC4_128_SHA_4 0x0092 +#define OP_PCL_TLS11_RC4_128_SHA_5 0x0005 +#define OP_PCL_TLS11_RC4_128_SHA_6 0xc002 +#define OP_PCL_TLS11_RC4_128_SHA_7 0xc007 +#define OP_PCL_TLS11_RC4_128_SHA_8 0xc00c +#define OP_PCL_TLS11_RC4_128_SHA_9 0xc011 +#define OP_PCL_TLS11_RC4_128_SHA_10 0xc016 + +#define OP_PCL_TLS11_RC4_40_SHA 0x0028 + +#define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0xff23 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA160 0xff30 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA224 0xff34 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA256 0xff36 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA384 0xff33 +#define OP_PCL_TLS11_3DES_EDE_CBC_SHA512 0xff35 +#define OP_PCL_TLS11_AES_128_CBC_SHA160 0xff80 +#define OP_PCL_TLS11_AES_128_CBC_SHA224 0xff84 +#define OP_PCL_TLS11_AES_128_CBC_SHA256 0xff86 +#define OP_PCL_TLS11_AES_128_CBC_SHA384 0xff83 +#define OP_PCL_TLS11_AES_128_CBC_SHA512 0xff85 +#define OP_PCL_TLS11_AES_192_CBC_SHA160 0xff20 +#define OP_PCL_TLS11_AES_192_CBC_SHA224 0xff24 +#define OP_PCL_TLS11_AES_192_CBC_SHA256 0xff26 +#define OP_PCL_TLS11_AES_192_CBC_SHA384 0xff23 +#define OP_PCL_TLS11_AES_192_CBC_SHA512 0xff25 +#define OP_PCL_TLS11_AES_256_CBC_SHA160 0xff60 +#define OP_PCL_TLS11_AES_256_CBC_SHA224 0xff64 +#define OP_PCL_TLS11_AES_256_CBC_SHA256 0xff66 +#define OP_PCL_TLS11_AES_256_CBC_SHA384 0xff63 +#define OP_PCL_TLS11_AES_256_CBC_SHA512 0xff65 /* For TLS 1.2 - OP_PCLID_TLS12 */ -#define OP_PCL_TLS12_AES_128_CBC_SHA 0x002f -#define OP_PCL_TLS12_AES_128_CBC_SHA_2 0x0030 -#define OP_PCL_TLS12_AES_128_CBC_SHA_3 0x0031 -#define OP_PCL_TLS12_AES_128_CBC_SHA_4 0x0032 -#define OP_PCL_TLS12_AES_128_CBC_SHA_5 0x0033 -#define OP_PCL_TLS12_AES_128_CBC_SHA_6 0x0034 -#define OP_PCL_TLS12_AES_128_CBC_SHA_7 0x008c -#define OP_PCL_TLS12_AES_128_CBC_SHA_8 0x0090 -#define OP_PCL_TLS12_AES_128_CBC_SHA_9 0x0094 -#define OP_PCL_TLS12_AES_128_CBC_SHA_10 0xc004 -#define OP_PCL_TLS12_AES_128_CBC_SHA_11 0xc009 -#define OP_PCL_TLS12_AES_128_CBC_SHA_12 0xc00e -#define OP_PCL_TLS12_AES_128_CBC_SHA_13 0xc013 -#define OP_PCL_TLS12_AES_128_CBC_SHA_14 0xc018 -#define OP_PCL_TLS12_AES_128_CBC_SHA_15 0xc01d -#define OP_PCL_TLS12_AES_128_CBC_SHA_16 0xc01e -#define OP_PCL_TLS12_AES_128_CBC_SHA_17 0xc01f - -#define OP_PCL_TLS12_AES_256_CBC_SHA 0x0035 -#define OP_PCL_TLS12_AES_256_CBC_SHA_2 0x0036 -#define OP_PCL_TLS12_AES_256_CBC_SHA_3 0x0037 -#define OP_PCL_TLS12_AES_256_CBC_SHA_4 0x0038 -#define OP_PCL_TLS12_AES_256_CBC_SHA_5 0x0039 -#define OP_PCL_TLS12_AES_256_CBC_SHA_6 0x003a -#define OP_PCL_TLS12_AES_256_CBC_SHA_7 0x008d -#define OP_PCL_TLS12_AES_256_CBC_SHA_8 0x0091 -#define OP_PCL_TLS12_AES_256_CBC_SHA_9 0x0095 -#define OP_PCL_TLS12_AES_256_CBC_SHA_10 0xc005 -#define OP_PCL_TLS12_AES_256_CBC_SHA_11 0xc00a -#define OP_PCL_TLS12_AES_256_CBC_SHA_12 0xc00f -#define OP_PCL_TLS12_AES_256_CBC_SHA_13 0xc014 -#define OP_PCL_TLS12_AES_256_CBC_SHA_14 0xc019 -#define OP_PCL_TLS12_AES_256_CBC_SHA_15 0xc020 -#define OP_PCL_TLS12_AES_256_CBC_SHA_16 0xc021 -#define OP_PCL_TLS12_AES_256_CBC_SHA_17 0xc022 - -/* #define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0x0023 */ - -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA 0x001f -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_2 0x008b -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_3 0x008f -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_4 0x0093 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_5 0x000a -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_6 0x000d -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_7 0x0010 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_8 0x0013 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_9 0x0016 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_10 0x001b -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_11 0xc003 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_12 0xc008 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_13 0xc00d -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_14 0xc012 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_15 0xc017 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_16 0xc01a -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_17 0xc01b -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_18 0xc01c - -#define OP_PCL_TLS12_DES40_CBC_MD5 0x0029 - -#define OP_PCL_TLS12_DES_CBC_MD5 0x0022 - -#define OP_PCL_TLS12_DES40_CBC_SHA 0x0008 -#define OP_PCL_TLS12_DES40_CBC_SHA_2 0x000b -#define OP_PCL_TLS12_DES40_CBC_SHA_3 0x000e -#define OP_PCL_TLS12_DES40_CBC_SHA_4 0x0011 -#define OP_PCL_TLS12_DES40_CBC_SHA_5 0x0014 -#define OP_PCL_TLS12_DES40_CBC_SHA_6 0x0019 -#define OP_PCL_TLS12_DES40_CBC_SHA_7 0x0026 - -#define OP_PCL_TLS12_DES_CBC_SHA 0x001e -#define OP_PCL_TLS12_DES_CBC_SHA_2 0x0009 -#define OP_PCL_TLS12_DES_CBC_SHA_3 0x000c -#define OP_PCL_TLS12_DES_CBC_SHA_4 0x000f -#define OP_PCL_TLS12_DES_CBC_SHA_5 0x0012 -#define OP_PCL_TLS12_DES_CBC_SHA_6 0x0015 -#define OP_PCL_TLS12_DES_CBC_SHA_7 0x001a - -#define OP_PCL_TLS12_RC4_128_MD5 0x0024 -#define OP_PCL_TLS12_RC4_128_MD5_2 0x0004 -#define OP_PCL_TLS12_RC4_128_MD5_3 0x0018 - -#define OP_PCL_TLS12_RC4_40_MD5 0x002b -#define OP_PCL_TLS12_RC4_40_MD5_2 0x0003 -#define OP_PCL_TLS12_RC4_40_MD5_3 0x0017 - -#define OP_PCL_TLS12_RC4_128_SHA 0x0020 -#define OP_PCL_TLS12_RC4_128_SHA_2 0x008a -#define OP_PCL_TLS12_RC4_128_SHA_3 0x008e -#define OP_PCL_TLS12_RC4_128_SHA_4 0x0092 -#define OP_PCL_TLS12_RC4_128_SHA_5 0x0005 -#define OP_PCL_TLS12_RC4_128_SHA_6 0xc002 -#define OP_PCL_TLS12_RC4_128_SHA_7 0xc007 -#define OP_PCL_TLS12_RC4_128_SHA_8 0xc00c -#define OP_PCL_TLS12_RC4_128_SHA_9 0xc011 -#define OP_PCL_TLS12_RC4_128_SHA_10 0xc016 - -#define OP_PCL_TLS12_RC4_40_SHA 0x0028 - -/* #define OP_PCL_TLS12_AES_128_CBC_SHA256 0x003c */ -#define OP_PCL_TLS12_AES_128_CBC_SHA256_2 0x003e -#define OP_PCL_TLS12_AES_128_CBC_SHA256_3 0x003f -#define OP_PCL_TLS12_AES_128_CBC_SHA256_4 0x0040 -#define OP_PCL_TLS12_AES_128_CBC_SHA256_5 0x0067 -#define OP_PCL_TLS12_AES_128_CBC_SHA256_6 0x006c - -/* #define OP_PCL_TLS12_AES_256_CBC_SHA256 0x003d */ -#define OP_PCL_TLS12_AES_256_CBC_SHA256_2 0x0068 -#define OP_PCL_TLS12_AES_256_CBC_SHA256_3 0x0069 -#define OP_PCL_TLS12_AES_256_CBC_SHA256_4 0x006a -#define OP_PCL_TLS12_AES_256_CBC_SHA256_5 0x006b -#define OP_PCL_TLS12_AES_256_CBC_SHA256_6 0x006d +#define OP_PCL_TLS12_AES_128_CBC_SHA 0x002f +#define OP_PCL_TLS12_AES_128_CBC_SHA_2 0x0030 +#define OP_PCL_TLS12_AES_128_CBC_SHA_3 0x0031 +#define OP_PCL_TLS12_AES_128_CBC_SHA_4 0x0032 +#define OP_PCL_TLS12_AES_128_CBC_SHA_5 0x0033 +#define OP_PCL_TLS12_AES_128_CBC_SHA_6 0x0034 +#define OP_PCL_TLS12_AES_128_CBC_SHA_7 0x008c +#define OP_PCL_TLS12_AES_128_CBC_SHA_8 0x0090 +#define OP_PCL_TLS12_AES_128_CBC_SHA_9 0x0094 +#define OP_PCL_TLS12_AES_128_CBC_SHA_10 0xc004 +#define OP_PCL_TLS12_AES_128_CBC_SHA_11 0xc009 +#define OP_PCL_TLS12_AES_128_CBC_SHA_12 0xc00e +#define OP_PCL_TLS12_AES_128_CBC_SHA_13 0xc013 +#define OP_PCL_TLS12_AES_128_CBC_SHA_14 0xc018 +#define OP_PCL_TLS12_AES_128_CBC_SHA_15 0xc01d +#define OP_PCL_TLS12_AES_128_CBC_SHA_16 0xc01e +#define OP_PCL_TLS12_AES_128_CBC_SHA_17 0xc01f + +#define OP_PCL_TLS12_AES_256_CBC_SHA 0x0035 +#define OP_PCL_TLS12_AES_256_CBC_SHA_2 0x0036 +#define OP_PCL_TLS12_AES_256_CBC_SHA_3 0x0037 +#define OP_PCL_TLS12_AES_256_CBC_SHA_4 0x0038 +#define OP_PCL_TLS12_AES_256_CBC_SHA_5 0x0039 +#define OP_PCL_TLS12_AES_256_CBC_SHA_6 0x003a +#define OP_PCL_TLS12_AES_256_CBC_SHA_7 0x008d +#define OP_PCL_TLS12_AES_256_CBC_SHA_8 0x0091 +#define OP_PCL_TLS12_AES_256_CBC_SHA_9 0x0095 +#define OP_PCL_TLS12_AES_256_CBC_SHA_10 0xc005 +#define OP_PCL_TLS12_AES_256_CBC_SHA_11 0xc00a +#define OP_PCL_TLS12_AES_256_CBC_SHA_12 0xc00f +#define OP_PCL_TLS12_AES_256_CBC_SHA_13 0xc014 +#define OP_PCL_TLS12_AES_256_CBC_SHA_14 0xc019 +#define OP_PCL_TLS12_AES_256_CBC_SHA_15 0xc020 +#define OP_PCL_TLS12_AES_256_CBC_SHA_16 0xc021 +#define OP_PCL_TLS12_AES_256_CBC_SHA_17 0xc022 + +/* #define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0x0023 */ + +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA 0x001f +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_2 0x008b +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_3 0x008f +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_4 0x0093 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_5 0x000a +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_6 0x000d +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_7 0x0010 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_8 0x0013 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_9 0x0016 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_10 0x001b +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_11 0xc003 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_12 0xc008 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_13 0xc00d +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_14 0xc012 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_15 0xc017 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_16 0xc01a +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_17 0xc01b +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_18 0xc01c + +#define OP_PCL_TLS12_DES40_CBC_MD5 0x0029 + +#define OP_PCL_TLS12_DES_CBC_MD5 0x0022 + +#define OP_PCL_TLS12_DES40_CBC_SHA 0x0008 +#define OP_PCL_TLS12_DES40_CBC_SHA_2 0x000b +#define OP_PCL_TLS12_DES40_CBC_SHA_3 0x000e +#define OP_PCL_TLS12_DES40_CBC_SHA_4 0x0011 +#define OP_PCL_TLS12_DES40_CBC_SHA_5 0x0014 +#define OP_PCL_TLS12_DES40_CBC_SHA_6 0x0019 +#define OP_PCL_TLS12_DES40_CBC_SHA_7 0x0026 + +#define OP_PCL_TLS12_DES_CBC_SHA 0x001e +#define OP_PCL_TLS12_DES_CBC_SHA_2 0x0009 +#define OP_PCL_TLS12_DES_CBC_SHA_3 0x000c +#define OP_PCL_TLS12_DES_CBC_SHA_4 0x000f +#define OP_PCL_TLS12_DES_CBC_SHA_5 0x0012 +#define OP_PCL_TLS12_DES_CBC_SHA_6 0x0015 +#define OP_PCL_TLS12_DES_CBC_SHA_7 0x001a + +#define OP_PCL_TLS12_RC4_128_MD5 0x0024 +#define OP_PCL_TLS12_RC4_128_MD5_2 0x0004 +#define OP_PCL_TLS12_RC4_128_MD5_3 0x0018 + +#define OP_PCL_TLS12_RC4_40_MD5 0x002b +#define OP_PCL_TLS12_RC4_40_MD5_2 0x0003 +#define OP_PCL_TLS12_RC4_40_MD5_3 0x0017 + +#define OP_PCL_TLS12_RC4_128_SHA 0x0020 +#define OP_PCL_TLS12_RC4_128_SHA_2 0x008a +#define OP_PCL_TLS12_RC4_128_SHA_3 0x008e +#define OP_PCL_TLS12_RC4_128_SHA_4 0x0092 +#define OP_PCL_TLS12_RC4_128_SHA_5 0x0005 +#define OP_PCL_TLS12_RC4_128_SHA_6 0xc002 +#define OP_PCL_TLS12_RC4_128_SHA_7 0xc007 +#define OP_PCL_TLS12_RC4_128_SHA_8 0xc00c +#define OP_PCL_TLS12_RC4_128_SHA_9 0xc011 +#define OP_PCL_TLS12_RC4_128_SHA_10 0xc016 + +#define OP_PCL_TLS12_RC4_40_SHA 0x0028 + +/* #define OP_PCL_TLS12_AES_128_CBC_SHA256 0x003c */ +#define OP_PCL_TLS12_AES_128_CBC_SHA256_2 0x003e +#define OP_PCL_TLS12_AES_128_CBC_SHA256_3 0x003f +#define OP_PCL_TLS12_AES_128_CBC_SHA256_4 0x0040 +#define OP_PCL_TLS12_AES_128_CBC_SHA256_5 0x0067 +#define OP_PCL_TLS12_AES_128_CBC_SHA256_6 0x006c + +/* #define OP_PCL_TLS12_AES_256_CBC_SHA256 0x003d */ +#define OP_PCL_TLS12_AES_256_CBC_SHA256_2 0x0068 +#define OP_PCL_TLS12_AES_256_CBC_SHA256_3 0x0069 +#define OP_PCL_TLS12_AES_256_CBC_SHA256_4 0x006a +#define OP_PCL_TLS12_AES_256_CBC_SHA256_5 0x006b +#define OP_PCL_TLS12_AES_256_CBC_SHA256_6 0x006d /* AEAD_AES_xxx_CCM/GCM remain to be defined... */ -#define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0xff23 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA160 0xff30 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA224 0xff34 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA256 0xff36 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA384 0xff33 -#define OP_PCL_TLS12_3DES_EDE_CBC_SHA512 0xff35 -#define OP_PCL_TLS12_AES_128_CBC_SHA160 0xff80 -#define OP_PCL_TLS12_AES_128_CBC_SHA224 0xff84 -#define OP_PCL_TLS12_AES_128_CBC_SHA256 0xff86 -#define OP_PCL_TLS12_AES_128_CBC_SHA384 0xff83 -#define OP_PCL_TLS12_AES_128_CBC_SHA512 0xff85 -#define OP_PCL_TLS12_AES_192_CBC_SHA160 0xff20 -#define OP_PCL_TLS12_AES_192_CBC_SHA224 0xff24 -#define OP_PCL_TLS12_AES_192_CBC_SHA256 0xff26 -#define OP_PCL_TLS12_AES_192_CBC_SHA384 0xff23 -#define OP_PCL_TLS12_AES_192_CBC_SHA512 0xff25 -#define OP_PCL_TLS12_AES_256_CBC_SHA160 0xff60 -#define OP_PCL_TLS12_AES_256_CBC_SHA224 0xff64 -#define OP_PCL_TLS12_AES_256_CBC_SHA256 0xff66 -#define OP_PCL_TLS12_AES_256_CBC_SHA384 0xff63 -#define OP_PCL_TLS12_AES_256_CBC_SHA512 0xff65 +#define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0xff23 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA160 0xff30 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA224 0xff34 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA256 0xff36 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA384 0xff33 +#define OP_PCL_TLS12_3DES_EDE_CBC_SHA512 0xff35 +#define OP_PCL_TLS12_AES_128_CBC_SHA160 0xff80 +#define OP_PCL_TLS12_AES_128_CBC_SHA224 0xff84 +#define OP_PCL_TLS12_AES_128_CBC_SHA256 0xff86 +#define OP_PCL_TLS12_AES_128_CBC_SHA384 0xff83 +#define OP_PCL_TLS12_AES_128_CBC_SHA512 0xff85 +#define OP_PCL_TLS12_AES_192_CBC_SHA160 0xff20 +#define OP_PCL_TLS12_AES_192_CBC_SHA224 0xff24 +#define OP_PCL_TLS12_AES_192_CBC_SHA256 0xff26 +#define OP_PCL_TLS12_AES_192_CBC_SHA384 0xff23 +#define OP_PCL_TLS12_AES_192_CBC_SHA512 0xff25 +#define OP_PCL_TLS12_AES_256_CBC_SHA160 0xff60 +#define OP_PCL_TLS12_AES_256_CBC_SHA224 0xff64 +#define OP_PCL_TLS12_AES_256_CBC_SHA256 0xff66 +#define OP_PCL_TLS12_AES_256_CBC_SHA384 0xff63 +#define OP_PCL_TLS12_AES_256_CBC_SHA512 0xff65 /* For DTLS - OP_PCLID_DTLS */ -#define OP_PCL_DTLS_AES_128_CBC_SHA 0x002f -#define OP_PCL_DTLS_AES_128_CBC_SHA_2 0x0030 -#define OP_PCL_DTLS_AES_128_CBC_SHA_3 0x0031 -#define OP_PCL_DTLS_AES_128_CBC_SHA_4 0x0032 -#define OP_PCL_DTLS_AES_128_CBC_SHA_5 0x0033 -#define OP_PCL_DTLS_AES_128_CBC_SHA_6 0x0034 -#define OP_PCL_DTLS_AES_128_CBC_SHA_7 0x008c -#define OP_PCL_DTLS_AES_128_CBC_SHA_8 0x0090 -#define OP_PCL_DTLS_AES_128_CBC_SHA_9 0x0094 -#define OP_PCL_DTLS_AES_128_CBC_SHA_10 0xc004 -#define OP_PCL_DTLS_AES_128_CBC_SHA_11 0xc009 -#define OP_PCL_DTLS_AES_128_CBC_SHA_12 0xc00e -#define OP_PCL_DTLS_AES_128_CBC_SHA_13 0xc013 -#define OP_PCL_DTLS_AES_128_CBC_SHA_14 0xc018 -#define OP_PCL_DTLS_AES_128_CBC_SHA_15 0xc01d -#define OP_PCL_DTLS_AES_128_CBC_SHA_16 0xc01e -#define OP_PCL_DTLS_AES_128_CBC_SHA_17 0xc01f - -#define OP_PCL_DTLS_AES_256_CBC_SHA 0x0035 -#define OP_PCL_DTLS_AES_256_CBC_SHA_2 0x0036 -#define OP_PCL_DTLS_AES_256_CBC_SHA_3 0x0037 -#define OP_PCL_DTLS_AES_256_CBC_SHA_4 0x0038 -#define OP_PCL_DTLS_AES_256_CBC_SHA_5 0x0039 -#define OP_PCL_DTLS_AES_256_CBC_SHA_6 0x003a -#define OP_PCL_DTLS_AES_256_CBC_SHA_7 0x008d -#define OP_PCL_DTLS_AES_256_CBC_SHA_8 0x0091 -#define OP_PCL_DTLS_AES_256_CBC_SHA_9 0x0095 -#define OP_PCL_DTLS_AES_256_CBC_SHA_10 0xc005 -#define OP_PCL_DTLS_AES_256_CBC_SHA_11 0xc00a -#define OP_PCL_DTLS_AES_256_CBC_SHA_12 0xc00f -#define OP_PCL_DTLS_AES_256_CBC_SHA_13 0xc014 -#define OP_PCL_DTLS_AES_256_CBC_SHA_14 0xc019 -#define OP_PCL_DTLS_AES_256_CBC_SHA_15 0xc020 -#define OP_PCL_DTLS_AES_256_CBC_SHA_16 0xc021 -#define OP_PCL_DTLS_AES_256_CBC_SHA_17 0xc022 - -/* #define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0x0023 */ - -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA 0x001f -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_2 0x008b -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_3 0x008f -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_4 0x0093 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_5 0x000a -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_6 0x000d -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_7 0x0010 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_8 0x0013 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_9 0x0016 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_10 0x001b -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_11 0xc003 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_12 0xc008 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_13 0xc00d -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_14 0xc012 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_15 0xc017 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_16 0xc01a -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_17 0xc01b -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_18 0xc01c - -#define OP_PCL_DTLS_DES40_CBC_MD5 0x0029 - -#define OP_PCL_DTLS_DES_CBC_MD5 0x0022 - -#define OP_PCL_DTLS_DES40_CBC_SHA 0x0008 -#define OP_PCL_DTLS_DES40_CBC_SHA_2 0x000b -#define OP_PCL_DTLS_DES40_CBC_SHA_3 0x000e -#define OP_PCL_DTLS_DES40_CBC_SHA_4 0x0011 -#define OP_PCL_DTLS_DES40_CBC_SHA_5 0x0014 -#define OP_PCL_DTLS_DES40_CBC_SHA_6 0x0019 -#define OP_PCL_DTLS_DES40_CBC_SHA_7 0x0026 - - -#define OP_PCL_DTLS_DES_CBC_SHA 0x001e -#define OP_PCL_DTLS_DES_CBC_SHA_2 0x0009 -#define OP_PCL_DTLS_DES_CBC_SHA_3 0x000c -#define OP_PCL_DTLS_DES_CBC_SHA_4 0x000f -#define OP_PCL_DTLS_DES_CBC_SHA_5 0x0012 -#define OP_PCL_DTLS_DES_CBC_SHA_6 0x0015 -#define OP_PCL_DTLS_DES_CBC_SHA_7 0x001a - - -#define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0xff23 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA160 0xff30 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA224 0xff34 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA256 0xff36 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA384 0xff33 -#define OP_PCL_DTLS_3DES_EDE_CBC_SHA512 0xff35 -#define OP_PCL_DTLS_AES_128_CBC_SHA160 0xff80 -#define OP_PCL_DTLS_AES_128_CBC_SHA224 0xff84 -#define OP_PCL_DTLS_AES_128_CBC_SHA256 0xff86 -#define OP_PCL_DTLS_AES_128_CBC_SHA384 0xff83 -#define OP_PCL_DTLS_AES_128_CBC_SHA512 0xff85 -#define OP_PCL_DTLS_AES_192_CBC_SHA160 0xff20 -#define OP_PCL_DTLS_AES_192_CBC_SHA224 0xff24 -#define OP_PCL_DTLS_AES_192_CBC_SHA256 0xff26 -#define OP_PCL_DTLS_AES_192_CBC_SHA384 0xff23 -#define OP_PCL_DTLS_AES_192_CBC_SHA512 0xff25 -#define OP_PCL_DTLS_AES_256_CBC_SHA160 0xff60 -#define OP_PCL_DTLS_AES_256_CBC_SHA224 0xff64 -#define OP_PCL_DTLS_AES_256_CBC_SHA256 0xff66 -#define OP_PCL_DTLS_AES_256_CBC_SHA384 0xff63 -#define OP_PCL_DTLS_AES_256_CBC_SHA512 0xff65 +#define OP_PCL_DTLS_AES_128_CBC_SHA 0x002f +#define OP_PCL_DTLS_AES_128_CBC_SHA_2 0x0030 +#define OP_PCL_DTLS_AES_128_CBC_SHA_3 0x0031 +#define OP_PCL_DTLS_AES_128_CBC_SHA_4 0x0032 +#define OP_PCL_DTLS_AES_128_CBC_SHA_5 0x0033 +#define OP_PCL_DTLS_AES_128_CBC_SHA_6 0x0034 +#define OP_PCL_DTLS_AES_128_CBC_SHA_7 0x008c +#define OP_PCL_DTLS_AES_128_CBC_SHA_8 0x0090 +#define OP_PCL_DTLS_AES_128_CBC_SHA_9 0x0094 +#define OP_PCL_DTLS_AES_128_CBC_SHA_10 0xc004 +#define OP_PCL_DTLS_AES_128_CBC_SHA_11 0xc009 +#define OP_PCL_DTLS_AES_128_CBC_SHA_12 0xc00e +#define OP_PCL_DTLS_AES_128_CBC_SHA_13 0xc013 +#define OP_PCL_DTLS_AES_128_CBC_SHA_14 0xc018 +#define OP_PCL_DTLS_AES_128_CBC_SHA_15 0xc01d +#define OP_PCL_DTLS_AES_128_CBC_SHA_16 0xc01e +#define OP_PCL_DTLS_AES_128_CBC_SHA_17 0xc01f + +#define OP_PCL_DTLS_AES_256_CBC_SHA 0x0035 +#define OP_PCL_DTLS_AES_256_CBC_SHA_2 0x0036 +#define OP_PCL_DTLS_AES_256_CBC_SHA_3 0x0037 +#define OP_PCL_DTLS_AES_256_CBC_SHA_4 0x0038 +#define OP_PCL_DTLS_AES_256_CBC_SHA_5 0x0039 +#define OP_PCL_DTLS_AES_256_CBC_SHA_6 0x003a +#define OP_PCL_DTLS_AES_256_CBC_SHA_7 0x008d +#define OP_PCL_DTLS_AES_256_CBC_SHA_8 0x0091 +#define OP_PCL_DTLS_AES_256_CBC_SHA_9 0x0095 +#define OP_PCL_DTLS_AES_256_CBC_SHA_10 0xc005 +#define OP_PCL_DTLS_AES_256_CBC_SHA_11 0xc00a +#define OP_PCL_DTLS_AES_256_CBC_SHA_12 0xc00f +#define OP_PCL_DTLS_AES_256_CBC_SHA_13 0xc014 +#define OP_PCL_DTLS_AES_256_CBC_SHA_14 0xc019 +#define OP_PCL_DTLS_AES_256_CBC_SHA_15 0xc020 +#define OP_PCL_DTLS_AES_256_CBC_SHA_16 0xc021 +#define OP_PCL_DTLS_AES_256_CBC_SHA_17 0xc022 + +/* #define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0x0023 */ + +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA 0x001f +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_2 0x008b +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_3 0x008f +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_4 0x0093 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_5 0x000a +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_6 0x000d +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_7 0x0010 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_8 0x0013 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_9 0x0016 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_10 0x001b +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_11 0xc003 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_12 0xc008 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_13 0xc00d +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_14 0xc012 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_15 0xc017 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_16 0xc01a +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_17 0xc01b +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_18 0xc01c + +#define OP_PCL_DTLS_DES40_CBC_MD5 0x0029 + +#define OP_PCL_DTLS_DES_CBC_MD5 0x0022 + +#define OP_PCL_DTLS_DES40_CBC_SHA 0x0008 +#define OP_PCL_DTLS_DES40_CBC_SHA_2 0x000b +#define OP_PCL_DTLS_DES40_CBC_SHA_3 0x000e +#define OP_PCL_DTLS_DES40_CBC_SHA_4 0x0011 +#define OP_PCL_DTLS_DES40_CBC_SHA_5 0x0014 +#define OP_PCL_DTLS_DES40_CBC_SHA_6 0x0019 +#define OP_PCL_DTLS_DES40_CBC_SHA_7 0x0026 + + +#define OP_PCL_DTLS_DES_CBC_SHA 0x001e +#define OP_PCL_DTLS_DES_CBC_SHA_2 0x0009 +#define OP_PCL_DTLS_DES_CBC_SHA_3 0x000c +#define OP_PCL_DTLS_DES_CBC_SHA_4 0x000f +#define OP_PCL_DTLS_DES_CBC_SHA_5 0x0012 +#define OP_PCL_DTLS_DES_CBC_SHA_6 0x0015 +#define OP_PCL_DTLS_DES_CBC_SHA_7 0x001a + + +#define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0xff23 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA160 0xff30 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA224 0xff34 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA256 0xff36 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA384 0xff33 +#define OP_PCL_DTLS_3DES_EDE_CBC_SHA512 0xff35 +#define OP_PCL_DTLS_AES_128_CBC_SHA160 0xff80 +#define OP_PCL_DTLS_AES_128_CBC_SHA224 0xff84 +#define OP_PCL_DTLS_AES_128_CBC_SHA256 0xff86 +#define OP_PCL_DTLS_AES_128_CBC_SHA384 0xff83 +#define OP_PCL_DTLS_AES_128_CBC_SHA512 0xff85 +#define OP_PCL_DTLS_AES_192_CBC_SHA160 0xff20 +#define OP_PCL_DTLS_AES_192_CBC_SHA224 0xff24 +#define OP_PCL_DTLS_AES_192_CBC_SHA256 0xff26 +#define OP_PCL_DTLS_AES_192_CBC_SHA384 0xff23 +#define OP_PCL_DTLS_AES_192_CBC_SHA512 0xff25 +#define OP_PCL_DTLS_AES_256_CBC_SHA160 0xff60 +#define OP_PCL_DTLS_AES_256_CBC_SHA224 0xff64 +#define OP_PCL_DTLS_AES_256_CBC_SHA256 0xff66 +#define OP_PCL_DTLS_AES_256_CBC_SHA384 0xff63 +#define OP_PCL_DTLS_AES_256_CBC_SHA512 0xff65 /* 802.16 WiMAX protinfos */ -#define OP_PCL_WIMAX_OFDM 0x0201 -#define OP_PCL_WIMAX_OFDMA 0x0231 +#define OP_PCL_WIMAX_OFDM 0x0201 +#define OP_PCL_WIMAX_OFDMA 0x0231 /* 802.11 WiFi protinfos */ -#define OP_PCL_WIFI 0xac04 +#define OP_PCL_WIFI 0xac04 /* MacSec protinfos */ -#define OP_PCL_MACSEC 0x0001 +#define OP_PCL_MACSEC 0x0001 /* PKI unidirectional protocol protinfo bits */ -#define OP_PCL_PKPROT_TEST 0x0008 -#define OP_PCL_PKPROT_DECRYPT 0x0004 -#define OP_PCL_PKPROT_ECC 0x0002 -#define OP_PCL_PKPROT_F2M 0x0001 +#define OP_PCL_PKPROT_TEST 0x0008 +#define OP_PCL_PKPROT_DECRYPT 0x0004 +#define OP_PCL_PKPROT_ECC 0x0002 +#define OP_PCL_PKPROT_F2M 0x0001 + +/* Blob protocol protinfo bits */ +#define OP_PCL_BLOB_TK 0x0200 +#define OP_PCL_BLOB_EKT 0x0100 + +#define OP_PCL_BLOB_K2KR_MEM 0x0000 +#define OP_PCL_BLOB_K2KR_C1KR 0x0010 +#define OP_PCL_BLOB_K2KR_C2KR 0x0030 +#define OP_PCL_BLOB_K2KR_AFHAS 0x0050 +#define OP_PCL_BLOB_K2KR_C2KR_SPLIT 0x0070 + +#define OP_PCL_BLOB_PTXT_SECMEM 0x0008 +#define OP_PCL_BLOB_BLACK 0x0004 + +#define OP_PCL_BLOB_FMT_NORMAL 0x0000 +#define OP_PCL_BLOB_FMT_MSTR 0x0002 +#define OP_PCL_BLOB_FMT_TEST 0x0003 /* For non-protocol/alg-only op commands */ #define OP_ALG_TYPE_SHIFT 24 @@ -1162,6 +1204,11 @@ #define OP_ALG_AAI_GSM (0x10 << OP_ALG_AAI_SHIFT) #define OP_ALG_AAI_EDGE (0x20 << OP_ALG_AAI_SHIFT) +/* RNG4 set */ +#define OP_ALG_RNG4_SHIFT 4 +#define OP_ALG_RNG4_MASK (0x1f3 << OP_ALG_RNG4_SHIFT) + +#define OP_ALG_RNG4_SK (0x100 << OP_ALG_RNG4_SHIFT) #define OP_ALG_AS_SHIFT 2 #define OP_ALG_AS_MASK (0x3 << OP_ALG_AS_SHIFT) @@ -1181,114 +1228,114 @@ #define OP_ALG_ENCRYPT 1 /* PKHA algorithm type set */ -#define OP_ALG_PK 0x00800000 -#define OP_ALG_PK_FUN_MASK 0x3f /* clrmem, modmath, or cpymem */ +#define OP_ALG_PK 0x00800000 +#define OP_ALG_PK_FUN_MASK 0x3f /* clrmem, modmath, or cpymem */ /* PKHA mode clear memory functions */ -#define OP_ALG_PKMODE_A_RAM 0x80000 -#define OP_ALG_PKMODE_B_RAM 0x40000 -#define OP_ALG_PKMODE_E_RAM 0x20000 -#define OP_ALG_PKMODE_N_RAM 0x10000 -#define OP_ALG_PKMODE_CLEARMEM 0x00001 +#define OP_ALG_PKMODE_A_RAM 0x80000 +#define OP_ALG_PKMODE_B_RAM 0x40000 +#define OP_ALG_PKMODE_E_RAM 0x20000 +#define OP_ALG_PKMODE_N_RAM 0x10000 +#define OP_ALG_PKMODE_CLEARMEM 0x00001 /* PKHA mode modular-arithmetic functions */ -#define OP_ALG_PKMODE_MOD_IN_MONTY 0x80000 -#define OP_ALG_PKMODE_MOD_OUT_MONTY 0x40000 -#define OP_ALG_PKMODE_MOD_F2M 0x20000 -#define OP_ALG_PKMODE_MOD_R2_IN 0x10000 -#define OP_ALG_PKMODE_PRJECTV 0x00800 -#define OP_ALG_PKMODE_TIME_EQ 0x400 -#define OP_ALG_PKMODE_OUT_B 0x000 -#define OP_ALG_PKMODE_OUT_A 0x100 -#define OP_ALG_PKMODE_MOD_ADD 0x002 -#define OP_ALG_PKMODE_MOD_SUB_AB 0x003 -#define OP_ALG_PKMODE_MOD_SUB_BA 0x004 -#define OP_ALG_PKMODE_MOD_MULT 0x005 -#define OP_ALG_PKMODE_MOD_EXPO 0x006 -#define OP_ALG_PKMODE_MOD_REDUCT 0x007 -#define OP_ALG_PKMODE_MOD_INV 0x008 -#define OP_ALG_PKMODE_MOD_ECC_ADD 0x009 -#define OP_ALG_PKMODE_MOD_ECC_DBL 0x00a -#define OP_ALG_PKMODE_MOD_ECC_MULT 0x00b -#define OP_ALG_PKMODE_MOD_MONT_CNST 0x00c -#define OP_ALG_PKMODE_MOD_CRT_CNST 0x00d -#define OP_ALG_PKMODE_MOD_GCD 0x00e -#define OP_ALG_PKMODE_MOD_PRIMALITY 0x00f +#define OP_ALG_PKMODE_MOD_IN_MONTY 0x80000 +#define OP_ALG_PKMODE_MOD_OUT_MONTY 0x40000 +#define OP_ALG_PKMODE_MOD_F2M 0x20000 +#define OP_ALG_PKMODE_MOD_R2_IN 0x10000 +#define OP_ALG_PKMODE_PRJECTV 0x00800 +#define OP_ALG_PKMODE_TIME_EQ 0x400 +#define OP_ALG_PKMODE_OUT_B 0x000 +#define OP_ALG_PKMODE_OUT_A 0x100 +#define OP_ALG_PKMODE_MOD_ADD 0x002 +#define OP_ALG_PKMODE_MOD_SUB_AB 0x003 +#define OP_ALG_PKMODE_MOD_SUB_BA 0x004 +#define OP_ALG_PKMODE_MOD_MULT 0x005 +#define OP_ALG_PKMODE_MOD_EXPO 0x006 +#define OP_ALG_PKMODE_MOD_REDUCT 0x007 +#define OP_ALG_PKMODE_MOD_INV 0x008 +#define OP_ALG_PKMODE_MOD_ECC_ADD 0x009 +#define OP_ALG_PKMODE_MOD_ECC_DBL 0x00a +#define OP_ALG_PKMODE_MOD_ECC_MULT 0x00b +#define OP_ALG_PKMODE_MOD_MONT_CNST 0x00c +#define OP_ALG_PKMODE_MOD_CRT_CNST 0x00d +#define OP_ALG_PKMODE_MOD_GCD 0x00e +#define OP_ALG_PKMODE_MOD_PRIMALITY 0x00f /* PKHA mode copy-memory functions */ -#define OP_ALG_PKMODE_SRC_REG_SHIFT 13 -#define OP_ALG_PKMODE_SRC_REG_MASK (7 << OP_ALG_PKMODE_SRC_REG_SHIFT) -#define OP_ALG_PKMODE_DST_REG_SHIFT 10 -#define OP_ALG_PKMODE_DST_REG_MASK (7 << OP_ALG_PKMODE_DST_REG_SHIFT) -#define OP_ALG_PKMODE_SRC_SEG_SHIFT 8 -#define OP_ALG_PKMODE_SRC_SEG_MASK (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT) -#define OP_ALG_PKMODE_DST_SEG_SHIFT 6 -#define OP_ALG_PKMODE_DST_SEG_MASK (3 << OP_ALG_PKMODE_DST_SEG_SHIFT) - -#define OP_ALG_PKMODE_SRC_REG_A (0 << OP_ALG_PKMODE_SRC_REG_SHIFT) -#define OP_ALG_PKMODE_SRC_REG_B (1 << OP_ALG_PKMODE_SRC_REG_SHIFT) -#define OP_ALG_PKMODE_SRC_REG_N (3 << OP_ALG_PKMODE_SRC_REG_SHIFT) -#define OP_ALG_PKMODE_DST_REG_A (0 << OP_ALG_PKMODE_DST_REG_SHIFT) -#define OP_ALG_PKMODE_DST_REG_B (1 << OP_ALG_PKMODE_DST_REG_SHIFT) -#define OP_ALG_PKMODE_DST_REG_E (2 << OP_ALG_PKMODE_DST_REG_SHIFT) -#define OP_ALG_PKMODE_DST_REG_N (3 << OP_ALG_PKMODE_DST_REG_SHIFT) -#define OP_ALG_PKMODE_SRC_SEG_0 (0 << OP_ALG_PKMODE_SRC_SEG_SHIFT) -#define OP_ALG_PKMODE_SRC_SEG_1 (1 << OP_ALG_PKMODE_SRC_SEG_SHIFT) -#define OP_ALG_PKMODE_SRC_SEG_2 (2 << OP_ALG_PKMODE_SRC_SEG_SHIFT) -#define OP_ALG_PKMODE_SRC_SEG_3 (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT) -#define OP_ALG_PKMODE_DST_SEG_0 (0 << OP_ALG_PKMODE_DST_SEG_SHIFT) -#define OP_ALG_PKMODE_DST_SEG_1 (1 << OP_ALG_PKMODE_DST_SEG_SHIFT) -#define OP_ALG_PKMODE_DST_SEG_2 (2 << OP_ALG_PKMODE_DST_SEG_SHIFT) -#define OP_ALG_PKMODE_DST_SEG_3 (3 << OP_ALG_PKMODE_DST_SEG_SHIFT) -#define OP_ALG_PKMODE_CPYMEM_N_SZ 0x80 -#define OP_ALG_PKMODE_CPYMEM_SRC_SZ 0x81 +#define OP_ALG_PKMODE_SRC_REG_SHIFT 13 +#define OP_ALG_PKMODE_SRC_REG_MASK (7 << OP_ALG_PKMODE_SRC_REG_SHIFT) +#define OP_ALG_PKMODE_DST_REG_SHIFT 10 +#define OP_ALG_PKMODE_DST_REG_MASK (7 << OP_ALG_PKMODE_DST_REG_SHIFT) +#define OP_ALG_PKMODE_SRC_SEG_SHIFT 8 +#define OP_ALG_PKMODE_SRC_SEG_MASK (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT) +#define OP_ALG_PKMODE_DST_SEG_SHIFT 6 +#define OP_ALG_PKMODE_DST_SEG_MASK (3 << OP_ALG_PKMODE_DST_SEG_SHIFT) + +#define OP_ALG_PKMODE_SRC_REG_A (0 << OP_ALG_PKMODE_SRC_REG_SHIFT) +#define OP_ALG_PKMODE_SRC_REG_B (1 << OP_ALG_PKMODE_SRC_REG_SHIFT) +#define OP_ALG_PKMODE_SRC_REG_N (3 << OP_ALG_PKMODE_SRC_REG_SHIFT) +#define OP_ALG_PKMODE_DST_REG_A (0 << OP_ALG_PKMODE_DST_REG_SHIFT) +#define OP_ALG_PKMODE_DST_REG_B (1 << OP_ALG_PKMODE_DST_REG_SHIFT) +#define OP_ALG_PKMODE_DST_REG_E (2 << OP_ALG_PKMODE_DST_REG_SHIFT) +#define OP_ALG_PKMODE_DST_REG_N (3 << OP_ALG_PKMODE_DST_REG_SHIFT) +#define OP_ALG_PKMODE_SRC_SEG_0 (0 << OP_ALG_PKMODE_SRC_SEG_SHIFT) +#define OP_ALG_PKMODE_SRC_SEG_1 (1 << OP_ALG_PKMODE_SRC_SEG_SHIFT) +#define OP_ALG_PKMODE_SRC_SEG_2 (2 << OP_ALG_PKMODE_SRC_SEG_SHIFT) +#define OP_ALG_PKMODE_SRC_SEG_3 (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT) +#define OP_ALG_PKMODE_DST_SEG_0 (0 << OP_ALG_PKMODE_DST_SEG_SHIFT) +#define OP_ALG_PKMODE_DST_SEG_1 (1 << OP_ALG_PKMODE_DST_SEG_SHIFT) +#define OP_ALG_PKMODE_DST_SEG_2 (2 << OP_ALG_PKMODE_DST_SEG_SHIFT) +#define OP_ALG_PKMODE_DST_SEG_3 (3 << OP_ALG_PKMODE_DST_SEG_SHIFT) +#define OP_ALG_PKMODE_CPYMEM_N_SZ 0x80 +#define OP_ALG_PKMODE_CPYMEM_SRC_SZ 0x81 /* * SEQ_IN_PTR Command Constructs */ /* Release Buffers */ -#define SQIN_RBS 0x04000000 +#define SQIN_RBS 0x04000000 /* Sequence pointer is really a descriptor */ -#define SQIN_INL 0x02000000 +#define SQIN_INL 0x02000000 /* Sequence pointer is a scatter-gather table */ -#define SQIN_SGF 0x01000000 +#define SQIN_SGF 0x01000000 /* Appends to a previous pointer */ -#define SQIN_PRE 0x00800000 +#define SQIN_PRE 0x00800000 /* Use extended length following pointer */ -#define SQIN_EXT 0x00400000 +#define SQIN_EXT 0x00400000 /* Restore sequence with pointer/length */ -#define SQIN_RTO 0x00200000 +#define SQIN_RTO 0x00200000 /* Replace job descriptor */ -#define SQIN_RJD 0x00100000 +#define SQIN_RJD 0x00100000 -#define SQIN_LEN_SHIFT 0 -#define SQIN_LEN_MASK (0xffff << SQIN_LEN_SHIFT) +#define SQIN_LEN_SHIFT 0 +#define SQIN_LEN_MASK (0xffff << SQIN_LEN_SHIFT) /* * SEQ_OUT_PTR Command Constructs */ /* Sequence pointer is a scatter-gather table */ -#define SQOUT_SGF 0x01000000 +#define SQOUT_SGF 0x01000000 /* Appends to a previous pointer */ -#define SQOUT_PRE 0x00800000 +#define SQOUT_PRE 0x00800000 /* Restore sequence with pointer/length */ -#define SQOUT_RTO 0x00200000 +#define SQOUT_RTO 0x00200000 /* Use extended length following pointer */ -#define SQOUT_EXT 0x00400000 +#define SQOUT_EXT 0x00400000 -#define SQOUT_LEN_SHIFT 0 -#define SQOUT_LEN_MASK (0xffff << SQOUT_LEN_SHIFT) +#define SQOUT_LEN_SHIFT 0 +#define SQOUT_LEN_MASK (0xffff << SQOUT_LEN_SHIFT) /* @@ -1296,196 +1343,196 @@ */ /* TYPE field is all that's relevant */ -#define SIGN_TYPE_SHIFT 16 -#define SIGN_TYPE_MASK (0x0f << SIGN_TYPE_SHIFT) +#define SIGN_TYPE_SHIFT 16 +#define SIGN_TYPE_MASK (0x0f << SIGN_TYPE_SHIFT) -#define SIGN_TYPE_FINAL (0x00 << SIGN_TYPE_SHIFT) +#define SIGN_TYPE_FINAL (0x00 << SIGN_TYPE_SHIFT) #define SIGN_TYPE_FINAL_RESTORE (0x01 << SIGN_TYPE_SHIFT) #define SIGN_TYPE_FINAL_NONZERO (0x02 << SIGN_TYPE_SHIFT) -#define SIGN_TYPE_IMM_2 (0x0a << SIGN_TYPE_SHIFT) -#define SIGN_TYPE_IMM_3 (0x0b << SIGN_TYPE_SHIFT) -#define SIGN_TYPE_IMM_4 (0x0c << SIGN_TYPE_SHIFT) +#define SIGN_TYPE_IMM_2 (0x0a << SIGN_TYPE_SHIFT) +#define SIGN_TYPE_IMM_3 (0x0b << SIGN_TYPE_SHIFT) +#define SIGN_TYPE_IMM_4 (0x0c << SIGN_TYPE_SHIFT) /* * MOVE Command Constructs */ -#define MOVE_AUX_SHIFT 25 -#define MOVE_AUX_MASK (3 << MOVE_AUX_SHIFT) -#define MOVE_AUX_MS (2 << MOVE_AUX_SHIFT) -#define MOVE_AUX_LS (1 << MOVE_AUX_SHIFT) - -#define MOVE_WAITCOMP_SHIFT 24 -#define MOVE_WAITCOMP_MASK (1 << MOVE_WAITCOMP_SHIFT) -#define MOVE_WAITCOMP (1 << MOVE_WAITCOMP_SHIFT) - -#define MOVE_SRC_SHIFT 20 -#define MOVE_SRC_MASK (0x0f << MOVE_SRC_SHIFT) -#define MOVE_SRC_CLASS1CTX (0x00 << MOVE_SRC_SHIFT) -#define MOVE_SRC_CLASS2CTX (0x01 << MOVE_SRC_SHIFT) -#define MOVE_SRC_OUTFIFO (0x02 << MOVE_SRC_SHIFT) -#define MOVE_SRC_DESCBUF (0x03 << MOVE_SRC_SHIFT) -#define MOVE_SRC_MATH0 (0x04 << MOVE_SRC_SHIFT) -#define MOVE_SRC_MATH1 (0x05 << MOVE_SRC_SHIFT) -#define MOVE_SRC_MATH2 (0x06 << MOVE_SRC_SHIFT) -#define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT) -#define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT) -#define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT) - -#define MOVE_DEST_SHIFT 16 -#define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT) -#define MOVE_DEST_CLASS1CTX (0x00 << MOVE_DEST_SHIFT) -#define MOVE_DEST_CLASS2CTX (0x01 << MOVE_DEST_SHIFT) -#define MOVE_DEST_OUTFIFO (0x02 << MOVE_DEST_SHIFT) -#define MOVE_DEST_DESCBUF (0x03 << MOVE_DEST_SHIFT) -#define MOVE_DEST_MATH0 (0x04 << MOVE_DEST_SHIFT) -#define MOVE_DEST_MATH1 (0x05 << MOVE_DEST_SHIFT) -#define MOVE_DEST_MATH2 (0x06 << MOVE_DEST_SHIFT) -#define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT) -#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT) -#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT) -#define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT) -#define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT) -#define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT) - -#define MOVE_OFFSET_SHIFT 8 -#define MOVE_OFFSET_MASK (0xff << MOVE_OFFSET_SHIFT) - -#define MOVE_LEN_SHIFT 0 -#define MOVE_LEN_MASK (0xff << MOVE_LEN_SHIFT) - -#define MOVELEN_MRSEL_SHIFT 0 -#define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT) +#define MOVE_AUX_SHIFT 25 +#define MOVE_AUX_MASK (3 << MOVE_AUX_SHIFT) +#define MOVE_AUX_MS (2 << MOVE_AUX_SHIFT) +#define MOVE_AUX_LS (1 << MOVE_AUX_SHIFT) + +#define MOVE_WAITCOMP_SHIFT 24 +#define MOVE_WAITCOMP_MASK (1 << MOVE_WAITCOMP_SHIFT) +#define MOVE_WAITCOMP (1 << MOVE_WAITCOMP_SHIFT) + +#define MOVE_SRC_SHIFT 20 +#define MOVE_SRC_MASK (0x0f << MOVE_SRC_SHIFT) +#define MOVE_SRC_CLASS1CTX (0x00 << MOVE_SRC_SHIFT) +#define MOVE_SRC_CLASS2CTX (0x01 << MOVE_SRC_SHIFT) +#define MOVE_SRC_OUTFIFO (0x02 << MOVE_SRC_SHIFT) +#define MOVE_SRC_DESCBUF (0x03 << MOVE_SRC_SHIFT) +#define MOVE_SRC_MATH0 (0x04 << MOVE_SRC_SHIFT) +#define MOVE_SRC_MATH1 (0x05 << MOVE_SRC_SHIFT) +#define MOVE_SRC_MATH2 (0x06 << MOVE_SRC_SHIFT) +#define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT) +#define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT) +#define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT) + +#define MOVE_DEST_SHIFT 16 +#define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT) +#define MOVE_DEST_CLASS1CTX (0x00 << MOVE_DEST_SHIFT) +#define MOVE_DEST_CLASS2CTX (0x01 << MOVE_DEST_SHIFT) +#define MOVE_DEST_OUTFIFO (0x02 << MOVE_DEST_SHIFT) +#define MOVE_DEST_DESCBUF (0x03 << MOVE_DEST_SHIFT) +#define MOVE_DEST_MATH0 (0x04 << MOVE_DEST_SHIFT) +#define MOVE_DEST_MATH1 (0x05 << MOVE_DEST_SHIFT) +#define MOVE_DEST_MATH2 (0x06 << MOVE_DEST_SHIFT) +#define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT) +#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT) +#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT) +#define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT) +#define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT) +#define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT) + +#define MOVE_OFFSET_SHIFT 8 +#define MOVE_OFFSET_MASK (0xff << MOVE_OFFSET_SHIFT) + +#define MOVE_LEN_SHIFT 0 +#define MOVE_LEN_MASK (0xff << MOVE_LEN_SHIFT) + +#define MOVELEN_MRSEL_SHIFT 0 +#define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT) /* * MATH Command Constructs */ -#define MATH_IFB_SHIFT 26 -#define MATH_IFB_MASK (1 << MATH_IFB_SHIFT) -#define MATH_IFB (1 << MATH_IFB_SHIFT) +#define MATH_IFB_SHIFT 26 +#define MATH_IFB_MASK (1 << MATH_IFB_SHIFT) +#define MATH_IFB (1 << MATH_IFB_SHIFT) -#define MATH_NFU_SHIFT 25 -#define MATH_NFU_MASK (1 << MATH_NFU_SHIFT) -#define MATH_NFU (1 << MATH_NFU_SHIFT) +#define MATH_NFU_SHIFT 25 +#define MATH_NFU_MASK (1 << MATH_NFU_SHIFT) +#define MATH_NFU (1 << MATH_NFU_SHIFT) -#define MATH_STL_SHIFT 24 -#define MATH_STL_MASK (1 << MATH_STL_SHIFT) -#define MATH_STL (1 << MATH_STL_SHIFT) +#define MATH_STL_SHIFT 24 +#define MATH_STL_MASK (1 << MATH_STL_SHIFT) +#define MATH_STL (1 << MATH_STL_SHIFT) /* Function selectors */ -#define MATH_FUN_SHIFT 20 -#define MATH_FUN_MASK (0x0f << MATH_FUN_SHIFT) -#define MATH_FUN_ADD (0x00 << MATH_FUN_SHIFT) -#define MATH_FUN_ADDC (0x01 << MATH_FUN_SHIFT) -#define MATH_FUN_SUB (0x02 << MATH_FUN_SHIFT) -#define MATH_FUN_SUBB (0x03 << MATH_FUN_SHIFT) -#define MATH_FUN_OR (0x04 << MATH_FUN_SHIFT) -#define MATH_FUN_AND (0x05 << MATH_FUN_SHIFT) -#define MATH_FUN_XOR (0x06 << MATH_FUN_SHIFT) -#define MATH_FUN_LSHIFT (0x07 << MATH_FUN_SHIFT) -#define MATH_FUN_RSHIFT (0x08 << MATH_FUN_SHIFT) -#define MATH_FUN_SHLD (0x09 << MATH_FUN_SHIFT) -#define MATH_FUN_ZBYT (0x0a << MATH_FUN_SHIFT) +#define MATH_FUN_SHIFT 20 +#define MATH_FUN_MASK (0x0f << MATH_FUN_SHIFT) +#define MATH_FUN_ADD (0x00 << MATH_FUN_SHIFT) +#define MATH_FUN_ADDC (0x01 << MATH_FUN_SHIFT) +#define MATH_FUN_SUB (0x02 << MATH_FUN_SHIFT) +#define MATH_FUN_SUBB (0x03 << MATH_FUN_SHIFT) +#define MATH_FUN_OR (0x04 << MATH_FUN_SHIFT) +#define MATH_FUN_AND (0x05 << MATH_FUN_SHIFT) +#define MATH_FUN_XOR (0x06 << MATH_FUN_SHIFT) +#define MATH_FUN_LSHIFT (0x07 << MATH_FUN_SHIFT) +#define MATH_FUN_RSHIFT (0x08 << MATH_FUN_SHIFT) +#define MATH_FUN_SHLD (0x09 << MATH_FUN_SHIFT) +#define MATH_FUN_ZBYT (0x0a << MATH_FUN_SHIFT) /* Source 0 selectors */ -#define MATH_SRC0_SHIFT 16 -#define MATH_SRC0_MASK (0x0f << MATH_SRC0_SHIFT) -#define MATH_SRC0_REG0 (0x00 << MATH_SRC0_SHIFT) -#define MATH_SRC0_REG1 (0x01 << MATH_SRC0_SHIFT) -#define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT) -#define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT) -#define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT) -#define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT) -#define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT) -#define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT) -#define MATH_SRC0_VARSEQOUTLEN (0x0b << MATH_SRC0_SHIFT) -#define MATH_SRC0_ZERO (0x0c << MATH_SRC0_SHIFT) +#define MATH_SRC0_SHIFT 16 +#define MATH_SRC0_MASK (0x0f << MATH_SRC0_SHIFT) +#define MATH_SRC0_REG0 (0x00 << MATH_SRC0_SHIFT) +#define MATH_SRC0_REG1 (0x01 << MATH_SRC0_SHIFT) +#define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT) +#define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT) +#define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT) +#define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT) +#define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT) +#define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT) +#define MATH_SRC0_VARSEQOUTLEN (0x0b << MATH_SRC0_SHIFT) +#define MATH_SRC0_ZERO (0x0c << MATH_SRC0_SHIFT) /* Source 1 selectors */ -#define MATH_SRC1_SHIFT 12 -#define MATH_SRC1_MASK (0x0f << MATH_SRC1_SHIFT) -#define MATH_SRC1_REG0 (0x00 << MATH_SRC1_SHIFT) -#define MATH_SRC1_REG1 (0x01 << MATH_SRC1_SHIFT) -#define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT) -#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT) -#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT) -#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT) -#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT) -#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT) +#define MATH_SRC1_SHIFT 12 +#define MATH_SRC1_MASK (0x0f << MATH_SRC1_SHIFT) +#define MATH_SRC1_REG0 (0x00 << MATH_SRC1_SHIFT) +#define MATH_SRC1_REG1 (0x01 << MATH_SRC1_SHIFT) +#define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT) +#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT) +#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT) +#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT) +#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT) +#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT) /* Destination selectors */ -#define MATH_DEST_SHIFT 8 -#define MATH_DEST_MASK (0x0f << MATH_DEST_SHIFT) -#define MATH_DEST_REG0 (0x00 << MATH_DEST_SHIFT) -#define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT) -#define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT) -#define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT) -#define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT) -#define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT) -#define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT) -#define MATH_DEST_VARSEQOUTLEN (0x0b << MATH_DEST_SHIFT) -#define MATH_DEST_NONE (0x0f << MATH_DEST_SHIFT) +#define MATH_DEST_SHIFT 8 +#define MATH_DEST_MASK (0x0f << MATH_DEST_SHIFT) +#define MATH_DEST_REG0 (0x00 << MATH_DEST_SHIFT) +#define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT) +#define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT) +#define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT) +#define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT) +#define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT) +#define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT) +#define MATH_DEST_VARSEQOUTLEN (0x0b << MATH_DEST_SHIFT) +#define MATH_DEST_NONE (0x0f << MATH_DEST_SHIFT) /* Length selectors */ -#define MATH_LEN_SHIFT 0 -#define MATH_LEN_MASK (0x0f << MATH_LEN_SHIFT) -#define MATH_LEN_1BYTE 0x01 -#define MATH_LEN_2BYTE 0x02 -#define MATH_LEN_4BYTE 0x04 -#define MATH_LEN_8BYTE 0x08 +#define MATH_LEN_SHIFT 0 +#define MATH_LEN_MASK (0x0f << MATH_LEN_SHIFT) +#define MATH_LEN_1BYTE 0x01 +#define MATH_LEN_2BYTE 0x02 +#define MATH_LEN_4BYTE 0x04 +#define MATH_LEN_8BYTE 0x08 /* * JUMP Command Constructs */ -#define JUMP_CLASS_SHIFT 25 +#define JUMP_CLASS_SHIFT 25 #define JUMP_CLASS_MASK (3 << JUMP_CLASS_SHIFT) #define JUMP_CLASS_NONE 0 #define JUMP_CLASS_CLASS1 (1 << JUMP_CLASS_SHIFT) #define JUMP_CLASS_CLASS2 (2 << JUMP_CLASS_SHIFT) #define JUMP_CLASS_BOTH (3 << JUMP_CLASS_SHIFT) -#define JUMP_JSL_SHIFT 24 -#define JUMP_JSL_MASK (1 << JUMP_JSL_SHIFT) -#define JUMP_JSL (1 << JUMP_JSL_SHIFT) +#define JUMP_JSL_SHIFT 24 +#define JUMP_JSL_MASK (1 << JUMP_JSL_SHIFT) +#define JUMP_JSL (1 << JUMP_JSL_SHIFT) -#define JUMP_TYPE_SHIFT 22 -#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT) -#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT) -#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT) -#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT) -#define JUMP_TYPE_HALT_USER (0x03 << JUMP_TYPE_SHIFT) +#define JUMP_TYPE_SHIFT 22 +#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT) +#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT) +#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT) +#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT) +#define JUMP_TYPE_HALT_USER (0x03 << JUMP_TYPE_SHIFT) -#define JUMP_TEST_SHIFT 16 -#define JUMP_TEST_MASK (0x03 << JUMP_TEST_SHIFT) -#define JUMP_TEST_ALL (0x00 << JUMP_TEST_SHIFT) -#define JUMP_TEST_INVALL (0x01 << JUMP_TEST_SHIFT) -#define JUMP_TEST_ANY (0x02 << JUMP_TEST_SHIFT) -#define JUMP_TEST_INVANY (0x03 << JUMP_TEST_SHIFT) +#define JUMP_TEST_SHIFT 16 +#define JUMP_TEST_MASK (0x03 << JUMP_TEST_SHIFT) +#define JUMP_TEST_ALL (0x00 << JUMP_TEST_SHIFT) +#define JUMP_TEST_INVALL (0x01 << JUMP_TEST_SHIFT) +#define JUMP_TEST_ANY (0x02 << JUMP_TEST_SHIFT) +#define JUMP_TEST_INVANY (0x03 << JUMP_TEST_SHIFT) /* Condition codes. JSL bit is factored in */ -#define JUMP_COND_SHIFT 8 -#define JUMP_COND_MASK (0x100ff << JUMP_COND_SHIFT) -#define JUMP_COND_PK_0 (0x80 << JUMP_COND_SHIFT) -#define JUMP_COND_PK_GCD_1 (0x40 << JUMP_COND_SHIFT) -#define JUMP_COND_PK_PRIME (0x20 << JUMP_COND_SHIFT) -#define JUMP_COND_MATH_N (0x08 << JUMP_COND_SHIFT) -#define JUMP_COND_MATH_Z (0x04 << JUMP_COND_SHIFT) -#define JUMP_COND_MATH_C (0x02 << JUMP_COND_SHIFT) -#define JUMP_COND_MATH_NV (0x01 << JUMP_COND_SHIFT) - -#define JUMP_COND_JRP ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL) -#define JUMP_COND_SHRD ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL) -#define JUMP_COND_SELF ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL) -#define JUMP_COND_CALM ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL) -#define JUMP_COND_NIP ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL) -#define JUMP_COND_NIFP ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL) -#define JUMP_COND_NOP ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL) -#define JUMP_COND_NCP ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL) - -#define JUMP_OFFSET_SHIFT 0 -#define JUMP_OFFSET_MASK (0xff << JUMP_OFFSET_SHIFT) +#define JUMP_COND_SHIFT 8 +#define JUMP_COND_MASK (0x100ff << JUMP_COND_SHIFT) +#define JUMP_COND_PK_0 (0x80 << JUMP_COND_SHIFT) +#define JUMP_COND_PK_GCD_1 (0x40 << JUMP_COND_SHIFT) +#define JUMP_COND_PK_PRIME (0x20 << JUMP_COND_SHIFT) +#define JUMP_COND_MATH_N (0x08 << JUMP_COND_SHIFT) +#define JUMP_COND_MATH_Z (0x04 << JUMP_COND_SHIFT) +#define JUMP_COND_MATH_C (0x02 << JUMP_COND_SHIFT) +#define JUMP_COND_MATH_NV (0x01 << JUMP_COND_SHIFT) + +#define JUMP_COND_JRP ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL) +#define JUMP_COND_SHRD ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL) +#define JUMP_COND_SELF ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL) +#define JUMP_COND_CALM ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL) +#define JUMP_COND_NIP ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL) +#define JUMP_COND_NIFP ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL) +#define JUMP_COND_NOP ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL) +#define JUMP_COND_NCP ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL) + +#define JUMP_OFFSET_SHIFT 0 +#define JUMP_OFFSET_MASK (0xff << JUMP_OFFSET_SHIFT) /* * NFIFO ENTRY @@ -1500,20 +1547,20 @@ #define NFIFOENTRY_DEST_BOTH (3 << NFIFOENTRY_DEST_SHIFT) #define NFIFOENTRY_LC2_SHIFT 29 -#define NFIFOENTRY_LC2_MASK (1 << NFIFOENTRY_LC2_SHIFT) -#define NFIFOENTRY_LC2 (1 << NFIFOENTRY_LC2_SHIFT) +#define NFIFOENTRY_LC2_MASK (1 << NFIFOENTRY_LC2_SHIFT) +#define NFIFOENTRY_LC2 (1 << NFIFOENTRY_LC2_SHIFT) #define NFIFOENTRY_LC1_SHIFT 28 -#define NFIFOENTRY_LC1_MASK (1 << NFIFOENTRY_LC1_SHIFT) -#define NFIFOENTRY_LC1 (1 << NFIFOENTRY_LC1_SHIFT) +#define NFIFOENTRY_LC1_MASK (1 << NFIFOENTRY_LC1_SHIFT) +#define NFIFOENTRY_LC1 (1 << NFIFOENTRY_LC1_SHIFT) #define NFIFOENTRY_FC2_SHIFT 27 -#define NFIFOENTRY_FC2_MASK (1 << NFIFOENTRY_FC2_SHIFT) -#define NFIFOENTRY_FC2 (1 << NFIFOENTRY_FC2_SHIFT) +#define NFIFOENTRY_FC2_MASK (1 << NFIFOENTRY_FC2_SHIFT) +#define NFIFOENTRY_FC2 (1 << NFIFOENTRY_FC2_SHIFT) #define NFIFOENTRY_FC1_SHIFT 26 -#define NFIFOENTRY_FC1_MASK (1 << NFIFOENTRY_FC1_SHIFT) -#define NFIFOENTRY_FC1 (1 << NFIFOENTRY_FC1_SHIFT) +#define NFIFOENTRY_FC1_MASK (1 << NFIFOENTRY_FC1_SHIFT) +#define NFIFOENTRY_FC1 (1 << NFIFOENTRY_FC1_SHIFT) #define NFIFOENTRY_STYPE_SHIFT 24 #define NFIFOENTRY_STYPE_MASK (3 << NFIFOENTRY_STYPE_SHIFT) @@ -1525,60 +1572,59 @@ #define NFIFOENTRY_DTYPE_SHIFT 20 #define NFIFOENTRY_DTYPE_MASK (0xF << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_SBOX (0x0 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_AAD (0x1 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT) - -#define NFIFOENTRY_DTYPE_PK_A0 (0x0 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_A1 (0x1 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_A2 (0x2 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_A3 (0x3 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_B0 (0x4 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_B1 (0x5 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_B2 (0x6 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_B3 (0x7 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_N (0x8 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_E (0x9 << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_A (0xC << NFIFOENTRY_DTYPE_SHIFT) -#define NFIFOENTRY_DTYPE_PK_B (0xD << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_SBOX (0x0 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_AAD (0x1 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT) + +#define NFIFOENTRY_DTYPE_PK_A0 (0x0 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_A1 (0x1 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_A2 (0x2 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_A3 (0x3 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_B0 (0x4 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_B1 (0x5 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_B2 (0x6 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_B3 (0x7 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_N (0x8 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_E (0x9 << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_A (0xC << NFIFOENTRY_DTYPE_SHIFT) +#define NFIFOENTRY_DTYPE_PK_B (0xD << NFIFOENTRY_DTYPE_SHIFT) #define NFIFOENTRY_BND_SHIFT 19 -#define NFIFOENTRY_BND_MASK (1 << NFIFOENTRY_BND_SHIFT) -#define NFIFOENTRY_BND (1 << NFIFOENTRY_BND_SHIFT) +#define NFIFOENTRY_BND_MASK (1 << NFIFOENTRY_BND_SHIFT) +#define NFIFOENTRY_BND (1 << NFIFOENTRY_BND_SHIFT) #define NFIFOENTRY_PTYPE_SHIFT 16 #define NFIFOENTRY_PTYPE_MASK (0x7 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_PTYPE_ZEROS (0x0 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_PTYPE_RND_NOZEROS (0x1 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_PTYPE_INCREMENT (0x2 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_PTYPE_RND (0x3 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_PTYPE_ZEROS_NZ (0x4 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_PTYPE_RND_NZ_LZ (0x5 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_PTYPE_N (0x6 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_PTYPE_RND_NZ_N (0x7 << NFIFOENTRY_PTYPE_SHIFT) +#define NFIFOENTRY_PTYPE_ZEROS (0x0 << NFIFOENTRY_PTYPE_SHIFT) +#define NFIFOENTRY_PTYPE_RND_NOZEROS (0x1 << NFIFOENTRY_PTYPE_SHIFT) +#define NFIFOENTRY_PTYPE_INCREMENT (0x2 << NFIFOENTRY_PTYPE_SHIFT) +#define NFIFOENTRY_PTYPE_RND (0x3 << NFIFOENTRY_PTYPE_SHIFT) +#define NFIFOENTRY_PTYPE_ZEROS_NZ (0x4 << NFIFOENTRY_PTYPE_SHIFT) +#define NFIFOENTRY_PTYPE_RND_NZ_LZ (0x5 << NFIFOENTRY_PTYPE_SHIFT) +#define NFIFOENTRY_PTYPE_N (0x6 << NFIFOENTRY_PTYPE_SHIFT) +#define NFIFOENTRY_PTYPE_RND_NZ_N (0x7 << NFIFOENTRY_PTYPE_SHIFT) -#define NFIFOENTRY_OC_SHIFT 15 -#define NFIFOENTRY_OC_MASK (1 << NFIFOENTRY_OC_SHIFT) -#define NFIFOENTRY_OC (1 << NFIFOENTRY_OC_SHIFT) +#define NFIFOENTRY_OC_SHIFT 15 +#define NFIFOENTRY_OC_MASK (1 << NFIFOENTRY_OC_SHIFT) +#define NFIFOENTRY_OC (1 << NFIFOENTRY_OC_SHIFT) #define NFIFOENTRY_AST_SHIFT 14 -#define NFIFOENTRY_AST_MASK (1 << NFIFOENTRY_OC_SHIFT) -#define NFIFOENTRY_AST (1 << NFIFOENTRY_OC_SHIFT) +#define NFIFOENTRY_AST_MASK (1 << NFIFOENTRY_OC_SHIFT) +#define NFIFOENTRY_AST (1 << NFIFOENTRY_OC_SHIFT) -#define NFIFOENTRY_BM_SHIFT 11 -#define NFIFOENTRY_BM_MASK (1 << NFIFOENTRY_BM_SHIFT) -#define NFIFOENTRY_BM (1 << NFIFOENTRY_BM_SHIFT) - -#define NFIFOENTRY_PS_SHIFT 10 -#define NFIFOENTRY_PS_MASK (1 << NFIFOENTRY_PS_SHIFT) -#define NFIFOENTRY_PS (1 << NFIFOENTRY_PS_SHIFT) +#define NFIFOENTRY_BM_SHIFT 11 +#define NFIFOENTRY_BM_MASK (1 << NFIFOENTRY_BM_SHIFT) +#define NFIFOENTRY_BM (1 << NFIFOENTRY_BM_SHIFT) +#define NFIFOENTRY_PS_SHIFT 10 +#define NFIFOENTRY_PS_MASK (1 << NFIFOENTRY_PS_SHIFT) +#define NFIFOENTRY_PS (1 << NFIFOENTRY_PS_SHIFT) #define NFIFOENTRY_DLEN_SHIFT 0 #define NFIFOENTRY_DLEN_MASK (0xFFF << NFIFOENTRY_DLEN_SHIFT) @@ -1586,20 +1632,4 @@ #define NFIFOENTRY_PLEN_SHIFT 0 #define NFIFOENTRY_PLEN_MASK (0xFF << NFIFOENTRY_PLEN_SHIFT) -/* - * PDB internal definitions - */ - -/* IPSec ESP CBC Encap/Decap Options */ -#define PDBOPTS_ESPCBC_ARSNONE 0x00 /* no antireplay window */ -#define PDBOPTS_ESPCBC_ARS32 0x40 /* 32-entry antireplay window */ -#define PDBOPTS_ESPCBC_ARS64 0xc0 /* 64-entry antireplay window */ -#define PDBOPTS_ESPCBC_IVSRC 0x20 /* IV comes from internal random gen */ -#define PDBOPTS_ESPCBC_ESN 0x10 /* extended sequence included */ -#define PDBOPTS_ESPCBC_OUTFMT 0x08 /* output only decapsulation (decap) */ -#define PDBOPTS_ESPCBC_IPHDRSRC 0x08 /* IP header comes from PDB (encap) */ -#define PDBOPTS_ESPCBC_INCIPHDR 0x04 /* Prepend IP header to output frame */ -#define PDBOPTS_ESPCBC_IPVSN 0x02 /* process IPv6 header */ -#define PDBOPTS_ESPCBC_TUNNEL 0x01 /* tunnel mode next-header byte */ - #endif /* DESC_H */ diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h index 46915800c26f..0393c98f5b9c 100644 --- a/drivers/crypto/caam/desc_constr.h +++ b/drivers/crypto/caam/desc_constr.h @@ -1,7 +1,7 @@ /* * caam descriptor construction helper functions * - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. */ #include "desc.h" @@ -9,7 +9,8 @@ #define IMMEDIATE (1 << 23) #define CAAM_CMD_SZ sizeof(u32) #define CAAM_PTR_SZ sizeof(dma_addr_t) -#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * 64) +#define CAAM_EXTLEN_SZ sizeof(u32) +#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE) #ifdef DEBUG #define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\ @@ -18,6 +19,10 @@ #define PRINT_POS #endif +#define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \ + LDST_SRCDST_WORD_DECOCTRL | \ + (LDOFF_CHG_SHARE_OK_NO_PROP << \ + LDST_OFFSET_SHIFT)) #define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \ LDST_SRCDST_WORD_DECOCTRL | \ (LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT)) @@ -47,7 +52,7 @@ static inline void *sh_desc_pdb(u32 *desc) static inline void init_desc(u32 *desc, u32 options) { - *desc = options | HDR_ONE | 1; + *desc = (options | HDR_ONE) + 1; } static inline void init_sh_desc(u32 *desc, u32 options) @@ -58,9 +63,9 @@ static inline void init_sh_desc(u32 *desc, u32 options) static inline void init_sh_desc_pdb(u32 *desc, u32 options, size_t pdb_bytes) { - u32 pdb_len = pdb_bytes / CAAM_CMD_SZ + 1; + u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ; - init_sh_desc(desc, ((pdb_len << HDR_START_IDX_SHIFT) + pdb_len) | + init_sh_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT) + pdb_len) | options); } @@ -113,6 +118,15 @@ static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len, append_ptr(desc, ptr); } +/* Write length after pointer, rather than inside command */ +static inline void append_cmd_ptr_extlen(u32 *desc, dma_addr_t ptr, + unsigned int len, u32 command) +{ + append_cmd(desc, command); + append_ptr(desc, ptr); + append_cmd(desc, len); +} + static inline void append_cmd_data(u32 *desc, void *data, int len, u32 command) { @@ -162,13 +176,22 @@ static inline void append_##cmd(u32 *desc, dma_addr_t ptr, unsigned int len, \ append_cmd_ptr(desc, ptr, len, CMD_##op | options); \ } APPEND_CMD_PTR(key, KEY) -APPEND_CMD_PTR(seq_in_ptr, SEQ_IN_PTR) -APPEND_CMD_PTR(seq_out_ptr, SEQ_OUT_PTR) APPEND_CMD_PTR(load, LOAD) APPEND_CMD_PTR(store, STORE) APPEND_CMD_PTR(fifo_load, FIFO_LOAD) APPEND_CMD_PTR(fifo_store, FIFO_STORE) +#define APPEND_SEQ_PTR_INTLEN(cmd, op) \ +static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, dma_addr_t ptr, \ + unsigned int len, \ + u32 options) \ +{ \ + PRINT_POS; \ + append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \ +} +APPEND_SEQ_PTR_INTLEN(in, IN) +APPEND_SEQ_PTR_INTLEN(out, OUT) + #define APPEND_CMD_PTR_TO_IMM(cmd, op) \ static inline void append_##cmd##_as_imm(u32 *desc, void *data, \ unsigned int len, u32 options) \ @@ -179,6 +202,33 @@ static inline void append_##cmd##_as_imm(u32 *desc, void *data, \ APPEND_CMD_PTR_TO_IMM(load, LOAD); APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD); +#define APPEND_CMD_PTR_EXTLEN(cmd, op) \ +static inline void append_##cmd##_extlen(u32 *desc, dma_addr_t ptr, \ + unsigned int len, u32 options) \ +{ \ + PRINT_POS; \ + append_cmd_ptr_extlen(desc, ptr, len, CMD_##op | SQIN_EXT | options); \ +} +APPEND_CMD_PTR_EXTLEN(seq_in_ptr, SEQ_IN_PTR) +APPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR) + +/* + * Determine whether to store length internally or externally depending on + * the size of its type + */ +#define APPEND_CMD_PTR_LEN(cmd, op, type) \ +static inline void append_##cmd(u32 *desc, dma_addr_t ptr, \ + type len, u32 options) \ +{ \ + PRINT_POS; \ + if (sizeof(type) > sizeof(u16)) \ + append_##cmd##_extlen(desc, ptr, len, options); \ + else \ + append_##cmd##_intlen(desc, ptr, len, options); \ +} +APPEND_CMD_PTR_LEN(seq_in_ptr, SEQ_IN_PTR, u32) +APPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_PTR, u32) + /* * 2nd variant for commands whose specified immediate length differs * from length of immediate data provided, e.g., split keys @@ -203,3 +253,56 @@ static inline void append_##cmd##_imm_##type(u32 *desc, type immediate, \ append_cmd(desc, immediate); \ } APPEND_CMD_RAW_IMM(load, LOAD, u32); + +/* + * Append math command. Only the last part of destination and source need to + * be specified + */ +#define APPEND_MATH(op, desc, dest, src_0, src_1, len) \ +append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \ + MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32) (len & MATH_LEN_MASK)); + +#define append_math_add(desc, dest, src0, src1, len) \ + APPEND_MATH(ADD, desc, dest, src0, src1, len) +#define append_math_sub(desc, dest, src0, src1, len) \ + APPEND_MATH(SUB, desc, dest, src0, src1, len) +#define append_math_add_c(desc, dest, src0, src1, len) \ + APPEND_MATH(ADDC, desc, dest, src0, src1, len) +#define append_math_sub_b(desc, dest, src0, src1, len) \ + APPEND_MATH(SUBB, desc, dest, src0, src1, len) +#define append_math_and(desc, dest, src0, src1, len) \ + APPEND_MATH(AND, desc, dest, src0, src1, len) +#define append_math_or(desc, dest, src0, src1, len) \ + APPEND_MATH(OR, desc, dest, src0, src1, len) +#define append_math_xor(desc, dest, src0, src1, len) \ + APPEND_MATH(XOR, desc, dest, src0, src1, len) +#define append_math_lshift(desc, dest, src0, src1, len) \ + APPEND_MATH(LSHIFT, desc, dest, src0, src1, len) +#define append_math_rshift(desc, dest, src0, src1, len) \ + APPEND_MATH(RSHIFT, desc, dest, src0, src1, len) + +/* Exactly one source is IMM. Data is passed in as u32 value */ +#define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \ +do { \ + APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \ + append_cmd(desc, data); \ +} while (0); + +#define append_math_add_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data) +#define append_math_sub_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(SUB, desc, dest, src0, src1, data) +#define append_math_add_c_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(ADDC, desc, dest, src0, src1, data) +#define append_math_sub_b_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(SUBB, desc, dest, src0, src1, data) +#define append_math_and_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(AND, desc, dest, src0, src1, data) +#define append_math_or_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(OR, desc, dest, src0, src1, data) +#define append_math_xor_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(XOR, desc, dest, src0, src1, data) +#define append_math_lshift_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data) +#define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \ + APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data) diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c index 7e2d54bffad6..1c5bd0334578 100644 --- a/drivers/crypto/caam/error.c +++ b/drivers/crypto/caam/error.c @@ -1,7 +1,7 @@ /* * CAAM Error Reporting * - * Copyright 2009-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2009-2012 Freescale Semiconductor, Inc. */ #include "compat.h" @@ -104,7 +104,8 @@ static void report_deco_status(u32 status, char *outstr) { 0x00, "None. No error." }, { 0x01, "SGT Length Error. The descriptor is trying to read " "more data than is contained in the SGT table." }, - { 0x02, "Reserved." }, + { 0x02, "SGT Null Entry Error. Extension bit was set, but " + "SGT entry was null." }, { 0x03, "Job Ring Control Error. There is a bad value in the " "Job Ring Control register." }, { 0x04, "Invalid Descriptor Command. The Descriptor Command " diff --git a/drivers/crypto/caam/error.h b/drivers/crypto/caam/error.h index 02c7baa1748e..177cbc40fa10 100644 --- a/drivers/crypto/caam/error.h +++ b/drivers/crypto/caam/error.h @@ -1,7 +1,7 @@ /* * CAAM Error Reporting code header * - * Copyright 2009-2011 Freescale Semiconductor, Inc. + * Copyright 2012 Freescale Semiconductor, Inc. */ #ifndef CAAM_ERROR_H diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index a34be01b0b29..83c5adef00f5 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -2,7 +2,7 @@ * CAAM/SEC 4.x driver backend * Private/internal definitions between modules * - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. * */ @@ -12,6 +12,9 @@ #define JOBR_UNASSIGNED 0 #define JOBR_ASSIGNED 1 +/* Default clock/sample settings for an RNG4 entropy source */ +#define RNG4_ENT_CLOCKS_SAMPLE 1600 + /* Currently comes from Kconfig param as a ^2 (driver-required) */ #define JOBR_DEPTH (1 << CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE) @@ -26,6 +29,23 @@ #define JOBR_INTC_COUNT_THLD 0 #endif +#ifndef CONFIG_OF +#define JR_IRQRES_NAME_ROOT "irq_jr" +#define JR_MEMRES_NAME_ROOT "offset_jr" +#endif + +#ifdef CONFIG_ARM +/* + * FIXME: ARM tree doesn't seem to provide this, ergo it seems to be + * in "platform limbo". Find a better place, perhaps. + */ +static inline void irq_dispose_mapping(unsigned int virq) +{ + return; +} +#endif + + /* * Storage for tracking each in-process entry moving across a ring * Each entry on an output ring needs one of these @@ -75,6 +95,9 @@ struct caam_drv_private { struct caam_deco **deco; /* DECO/CCB views */ struct caam_assurance *ac; struct caam_queue_if *qi; /* QI control region */ + struct snvs_full __iomem *snvs; /* SNVS HP+LP register space */ + dma_addr_t __iomem *sm_base; /* Secure memory storage base */ + u32 sm_size; /* * Detected geometry block. Filled in from device tree if powerpc, @@ -83,6 +106,7 @@ struct caam_drv_private { u8 total_jobrs; /* Total Job Rings in device */ u8 qi_present; /* Nonzero if QI present in device */ int secvio_irq; /* Security violation interrupt number */ + int rng_inst; /* Total instantiated RNGs */ /* which jr allocated to scatterlist crypto */ atomic_t tfm_count ____cacheline_aligned; @@ -90,7 +114,20 @@ struct caam_drv_private { struct device **algapi_jr; /* list of registered crypto algorithms (mk generic context handle?) */ struct list_head alg_list; + /* list of registered hash algorithms (mk generic context handle?) */ + struct list_head hash_list; + +#ifdef CONFIG_ARM + struct clk *caam_clk; +#endif +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SM + struct device *smdev; /* Secure Memory dev */ +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO + struct device *secviodev; +#endif /* * debugfs entries for developer view into driver/device * variables at runtime. @@ -108,6 +145,43 @@ struct caam_drv_private { #endif }; -void caam_jr_algapi_init(struct device *dev); -void caam_jr_algapi_remove(struct device *dev); +/* + * These startup/shutdown functions exist to enable API startup/shutdown + * outside of the OF device detection framework. It's necessary for ARM + * kernels as presently delivered. + * + * Once ARM kernels are shipping with OF support, these functions can + * be re-integrated into the normal probe startup/exit functions, + * and these prototypes can then be removed. + */ +#ifndef CONFIG_OF +void caam_algapi_shutdown(struct platform_device *pdev); +int caam_algapi_startup(struct platform_device *pdev); + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API +int caam_algapi_hash_startup(struct platform_device *pdev); +void caam_algapi_hash_shutdown(struct platform_device *pdev); +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API +int caam_rng_startup(struct platform_device *pdev); +void caam_rng_shutdown(void); +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SM +int caam_sm_startup(struct platform_device *pdev); +void caam_sm_shutdown(struct platform_device *pdev); +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST +int caam_sm_example_init(struct platform_device *pdev); +#endif + +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO +int caam_secvio_startup(struct platform_device *pdev); +void caam_secvio_shutdown(struct platform_device *pdev); +#endif /* SECVIO */ + +#endif /* CONFIG_OF */ + #endif /* INTERN_H */ diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index 340fa322c0f0..40bca549e236 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -2,7 +2,7 @@ * CAAM/SEC 4.x transport/backend driver * JobR backend functionality * - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. */ #include "compat.h" @@ -57,9 +57,18 @@ static void caam_jr_dequeue(unsigned long devarg) struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg); u32 *userdesc, userstatus; + dma_addr_t outbusaddr; void *userarg; unsigned long flags; + outbusaddr = rd_reg64(&jrp->rregs->outring_base); + /* CAAM: Fix incorrect invalidate call for output ring */ + /* + dma_sync_single_for_cpu(dev, outbusaddr, + sizeof(struct jr_outentry) * JOBR_DEPTH, + DMA_FROM_DEVICE); + */ + /* -----END---- */ spin_lock_irqsave(&jrp->outlock, flags); head = ACCESS_ONCE(jrp->head); @@ -69,11 +78,15 @@ static void caam_jr_dequeue(unsigned long devarg) rd_reg32(&jrp->rregs->outring_used)) { hw_idx = jrp->out_ring_read_index; + /* CAAM: Fix incorrect invalidate call for output ring */ + dma_sync_single_for_cpu(dev, outbusaddr, + sizeof(struct jr_outentry) * JOBR_DEPTH, + DMA_FROM_DEVICE); + /* -----END---- */ for (i = 0; CIRC_CNT(head, tail + i, JOBR_DEPTH) >= 1; i++) { sw_idx = (tail + i) & (JOBR_DEPTH - 1); smp_read_barrier_depends(); - if (jrp->outring[hw_idx].desc == jrp->entinfo[sw_idx].desc_addr_dma) break; /* found */ @@ -240,7 +253,7 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, struct caam_jrentry_info *head_entry; unsigned long flags; int head, tail, desc_size; - dma_addr_t desc_dma; + dma_addr_t desc_dma, inpbusaddr; desc_size = (*desc & HDR_JD_LENGTH_MASK) * sizeof(u32); desc_dma = dma_map_single(dev, desc, desc_size, DMA_TO_DEVICE); @@ -249,6 +262,12 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, return -EIO; } + dma_sync_single_for_device(dev, desc_dma, desc_size, DMA_TO_DEVICE); + + inpbusaddr = rd_reg64(&jrp->rregs->inpring_base); + dma_sync_single_for_device(dev, inpbusaddr, + sizeof(dma_addr_t) * JOBR_DEPTH, + DMA_TO_DEVICE); spin_lock_irqsave(&jrp->inplock, flags); head = jrp->head; @@ -270,6 +289,10 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, jrp->inpring[jrp->inp_ring_write_index] = desc_dma; + dma_sync_single_for_device(dev, inpbusaddr, + sizeof(dma_addr_t) * JOBR_DEPTH, + DMA_TO_DEVICE); + smp_wmb(); jrp->inp_ring_write_index = (jrp->inp_ring_write_index + 1) & @@ -343,7 +366,7 @@ static int caam_jr_init(struct device *dev) (unsigned long)dev); error = request_irq(jrp->irq, caam_jr_interrupt, IRQF_SHARED, - "caam-jobr", dev); + "caam-jr", dev); if (error) { dev_err(dev, "can't connect JobR %d interrupt (%d)\n", jrp->ridx, jrp->irq); @@ -377,7 +400,7 @@ static int caam_jr_init(struct device *dev) /* Setup rings */ inpbusaddr = dma_map_single(dev, jrp->inpring, sizeof(u32 *) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); + DMA_TO_DEVICE); if (dma_mapping_error(dev, inpbusaddr)) { dev_err(dev, "caam_jr_init(): can't map input ring\n"); kfree(jrp->inpring); @@ -388,12 +411,12 @@ static int caam_jr_init(struct device *dev) outbusaddr = dma_map_single(dev, jrp->outring, sizeof(struct jr_outentry) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); + DMA_FROM_DEVICE); if (dma_mapping_error(dev, outbusaddr)) { dev_err(dev, "caam_jr_init(): can't map output ring\n"); dma_unmap_single(dev, inpbusaddr, sizeof(u32 *) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); + DMA_TO_DEVICE); kfree(jrp->inpring); kfree(jrp->outring); kfree(jrp->entinfo); @@ -446,11 +469,9 @@ int caam_jr_shutdown(struct device *dev) outbusaddr = rd_reg64(&jrp->rregs->outring_base); dma_unmap_single(dev, outbusaddr, sizeof(struct jr_outentry) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); + DMA_FROM_DEVICE); dma_unmap_single(dev, inpbusaddr, sizeof(u32 *) * JOBR_DEPTH, - DMA_BIDIRECTIONAL); - kfree(jrp->outring); - kfree(jrp->inpring); + DMA_TO_DEVICE); kfree(jrp->entinfo); return ret; @@ -467,8 +488,12 @@ int caam_jr_probe(struct platform_device *pdev, struct device_node *np, struct platform_device *jr_pdev; struct caam_drv_private *ctrlpriv; struct caam_drv_private_jr *jrpriv; - u32 *jroffset; int error; + /* FIXME: perhaps "struct resource *" for OF and non? */ + u32 *jroffset, *irqres; +#ifndef CONFIG_OF + char *rname, rinst; +#endif ctrldev = &pdev->dev; ctrlpriv = dev_get_drvdata(ctrldev); @@ -489,12 +514,35 @@ int caam_jr_probe(struct platform_device *pdev, struct device_node *np, * need to add in the offset to this JobR. Don't know if I * like this long-term, but it'll run */ +#ifdef CONFIG_OF jroffset = (u32 *)of_get_property(np, "reg", NULL); +#else + rname = kmalloc(strlen(JR_MEMRES_NAME_ROOT) + 1, 0); + if (rname == NULL) { + dev_err(ctrldev, "can't alloc resource detection buffer %d\n", + ring); + kfree(jrpriv); + return -ENOMEM; + } + rname[0] = 0; + rinst = '0' + ring; + strcat(rname, JR_MEMRES_NAME_ROOT); + strncat(rname, &rinst, 1); + jroffset = (u32 *)platform_get_resource_byname(pdev, IORESOURCE_MEM, + rname); + kfree(rname); +#endif jrpriv->rregs = (struct caam_job_ring __iomem *)((void *)ctrlpriv->ctrl + *jroffset); /* Build a local dev for each detected queue */ +#ifdef CONFIG_OF jr_pdev = of_platform_device_create(np, NULL, ctrldev); +#else + jr_pdev = platform_device_register_data(ctrldev, "caam_jr", ring, + jrpriv, + sizeof(struct caam_drv_private_jr)); +#endif if (jr_pdev == NULL) { kfree(jrpriv); return -EINVAL; @@ -504,7 +552,24 @@ int caam_jr_probe(struct platform_device *pdev, struct device_node *np, ctrlpriv->jrdev[ring] = jrdev; /* Identify the interrupt */ +#ifdef CONFIG_OF jrpriv->irq = of_irq_to_resource(np, 0, NULL); +#else + rname = kmalloc(strlen(JR_IRQRES_NAME_ROOT) + 1, 0); + if (rname == NULL) { + dev_err(ctrldev, "can't alloc resource detection buffer %d\n", + ring); + kfree(jrpriv); + return -ENOMEM; + } + rname[0] = 0; + strcat(rname, JR_IRQRES_NAME_ROOT); + strncat(rname, &rinst, 1); + irqres = (u32 *)platform_get_resource_byname(pdev, IORESOURCE_IRQ, + rname); + jrpriv->irq = *irqres; + kfree(rname); +#endif /* Now do the platform independent part */ error = caam_jr_init(jrdev); /* now turn on hardware */ diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c new file mode 100644 index 000000000000..8e67628b3c1b --- /dev/null +++ b/drivers/crypto/caam/key_gen.c @@ -0,0 +1,124 @@ +/* + * CAAM/SEC 4.x functions for handling key-generation jobs + * + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. + * + */ +#include "compat.h" +#include "jr.h" +#include "error.h" +#include "desc_constr.h" +#include "key_gen.h" + +void split_key_done(struct device *dev, u32 *desc, u32 err, + void *context) +{ + struct split_key_result *res = context; + +#ifdef DEBUG + dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); +#endif + + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + + dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + + res->err = err; + + complete(&res->completion); +} +EXPORT_SYMBOL(split_key_done); +/* +get a split ipad/opad key + +Split key generation----------------------------------------------- + +[00] 0xb0810008 jobdesc: stidx=1 share=never len=8 +[01] 0x04000014 key: class2->keyreg len=20 + @0xffe01000 +[03] 0x84410014 operation: cls2-op sha1 hmac init dec +[04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm +[05] 0xa4000001 jump: class2 local all ->1 [06] +[06] 0x64260028 fifostr: class2 mdsplit-jdk len=40 + @0xffe04000 +*/ +u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, + int split_key_pad_len, const u8 *key_in, u32 keylen, + u32 alg_op) +{ + u32 *desc; + struct split_key_result result; + dma_addr_t dma_addr_in, dma_addr_out; + int ret = 0; + + desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); + + init_job_desc(desc, 0); + + dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen, + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, dma_addr_in)) { + dev_err(jrdev, "unable to map key input memory\n"); + kfree(desc); + return -ENOMEM; + } + dma_sync_single_for_device(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE); + append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG); + + /* Sets MDHA up into an HMAC-INIT */ + append_operation(desc, alg_op | OP_ALG_DECRYPT | OP_ALG_AS_INIT); + + /* + * do a FIFO_LOAD of zero, this will trigger the internal key expansion + * into both pads inside MDHA + */ + append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB | + FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2); + + /* + * FIFO_STORE with the explicit split-key content store + * (0x26 output type) + */ + dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len, + DMA_FROM_DEVICE); + if (dma_mapping_error(jrdev, dma_addr_out)) { + dev_err(jrdev, "unable to map key output memory\n"); + kfree(desc); + return -ENOMEM; + } + append_fifo_store(desc, dma_addr_out, split_key_len, + LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK); + +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1); + print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); +#endif + + result.err = 0; + init_completion(&result.completion); + + ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); + if (!ret) { + /* in progress */ + wait_for_completion_interruptible(&result.completion); + ret = result.err; +#ifdef DEBUG + print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key_out, + split_key_pad_len, 1); +#endif + } + dma_sync_single_for_cpu(jrdev, dma_addr_out, split_key_pad_len, + DMA_FROM_DEVICE); + dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len, + DMA_FROM_DEVICE); + dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE); + + kfree(desc); + + return ret; +} diff --git a/drivers/crypto/caam/key_gen.h b/drivers/crypto/caam/key_gen.h new file mode 100644 index 000000000000..2306b3260614 --- /dev/null +++ b/drivers/crypto/caam/key_gen.h @@ -0,0 +1,17 @@ +/* + * CAAM/SEC 4.x definitions for handling key-generation jobs + * + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. + * + */ + +struct split_key_result { + struct completion completion; + int err; +}; + +void split_key_done(struct device *dev, u32 *desc, u32 err, void *context); + +u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, + int split_key_pad_len, const u8 *key_in, u32 keylen, + u32 alg_op); diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index aee394e39056..248dd932fe44 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -1,7 +1,7 @@ /* * CAAM hardware register-level view * - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. */ #ifndef REGS_H @@ -74,15 +74,21 @@ #endif #else #ifdef __LITTLE_ENDIAN -#define wr_reg32(reg, data) __raw_writel(reg, data) -#define rd_reg32(reg) __raw_readl(reg) +#define wr_reg32(reg, data) writel(data, reg) +#define rd_reg32(reg) readl(reg) #ifdef CONFIG_64BIT -#define wr_reg64(reg, data) __raw_writeq(reg, data) -#define rd_reg64(reg) __raw_readq(reg) +#define wr_reg64(reg, data) writeq(data, reg) +#define rd_reg64(reg) readq(reg) #endif #endif #endif +#ifdef CONFIG_ARM +/* These are common macros for Power, put here for ARMs */ +#define setbits32(_addr, _v) writel((readl(_addr) | (_v)), (_addr)) +#define clrbits32(_addr, _v) writel((readl(_addr) & ~(_v)), (_addr)) +#endif + #ifndef CONFIG_64BIT static inline void wr_reg64(u64 __iomem *reg, u64 data) { @@ -106,6 +112,97 @@ struct jr_outentry { u32 jrstatus; /* Status for completed descriptor */ } __packed; +/* + * CHA version ID / instantiation bitfields + * Defined for use within cha_id in perfmon + * Note that the same shift/mask selectors can be used to pull out number + * of instantiated blocks within cha_num in perfmon, the locations are + * the same. + */ + +/* Job Ring */ +#define CHA_ID_JR_SHIFT 60 +#define CHA_ID_JR_MASK (0xfull << CHA_ID_JR_SHIFT) + +/* DEscriptor COntroller */ +#define CHA_ID_DECO_SHIFT 56 +#define CHA_ID_DECO_MASK (0xfull << CHA_ID_DECO_SHIFT) +#define CHA_NUM_DECONUM_SHIFT 56 /* legacy definition */ +#define CHA_NUM_DECONUM_MASK (0xfull << CHA_NUM_DECONUM_SHIFT) + +/* ZUC-Authentication */ +#define CHA_ID_ZA_SHIFT 44 +#define CHA_ID_ZA_MASK (0xfull << CHA_ID_ZA_SHIFT) + +/* ZUC-Encryption */ +#define CHA_ID_ZE_SHIFT 40 +#define CHA_ID_ZE_MASK (0xfull << CHA_ID_ZE_SHIFT) + +/* SNOW f9 */ +#define CHA_ID_SNW9_SHIFT 36 +#define CHA_ID_SNW9_MASK (0xfull << CHA_ID_SNW9_SHIFT) + +/* CRC */ +#define CHA_ID_CRC_SHIFT 32 +#define CHA_ID_CRC_MASK (0xfull << CHA_ID_CRC_SHIFT) + +/* Public Key */ +#define CHA_ID_PK_SHIFT 28 +#define CHA_ID_PK_MASK (0xfull << CHA_ID_PK_SHIFT) + +/* Kasumi */ +#define CHA_ID_KAS_SHIFT 24 +#define CHA_ID_KAS_MASK (0xfull << CHA_ID_KAS_SHIFT) + +/* SNOW f8 */ +#define CHA_ID_SNW8_SHIFT 20 +#define CHA_ID_SNW8_MASK (0xfull << CHA_ID_SNW8_SHIFT) + +/* + * Random Generator + * RNG4 = FIPS-verification-compliant, requires init kickstart for use + */ +#define CHA_ID_RNG_SHIFT 16 +#define CHA_ID_RNG_MASK (0xfull << CHA_ID_RNG_SHIFT) +#define CHA_ID_RNG_A (0x1ull << CHA_ID_RNG_SHIFT) +#define CHA_ID_RNG_B (0x2ull << CHA_ID_RNG_SHIFT) +#define CHA_ID_RNG_C (0x3ull << CHA_ID_RNG_SHIFT) +#define CHA_ID_RNG_4 (0x4ull << CHA_ID_RNG_SHIFT) + +/* + * Message Digest + * LP256 = Low Power (MD5/SHA1/SHA224/SHA256 + HMAC) + * LP512 = Low Power (LP256 + SHA384/SHA512) + * HP = High Power (LP512 + SMAC) + */ +#define CHA_ID_MD_SHIFT 12 +#define CHA_ID_MD_MASK (0xfull << CHA_ID_MD_SHIFT) +#define CHA_ID_MD_LP256 (0x0ull << CHA_ID_MD_SHIFT) +#define CHA_ID_MD_LP512 (0x1ull << CHA_ID_MD_SHIFT) +#define CHA_ID_MD_HP (0x2ull << CHA_ID_MD_SHIFT) + +/* ARC4 Streamcipher */ +#define CHA_ID_ARC4_SHIFT 8 +#define CHA_ID_ARC4_MASK (0xfull << CHA_ID_ARC4_SHIFT) +#define CHA_ID_ARC4_LP (0x0ull << CHA_ID_ARC4_SHIFT) +#define CHA_ID_ARC4_HP (0x1ull << CHA_ID_ARC4_SHIFT) + +/* DES Blockcipher Accelerator */ +#define CHA_ID_DES_SHIFT 4 +#define CHA_ID_DES_MASK (0xfull << CHA_ID_DES_SHIFT) + +/* + * AES Blockcipher + Combo Mode Accelerator + * LP = Low Power (includes ECB/CBC/CFB128/OFB/CTR/CCM/CMAC/XCBC-MAC) + * HP = High Power (LP + CBCXCBC/CTRXCBC/XTS/GCM) + * DIFFPWR = ORed in if differential-power-analysis resistance implemented + */ +#define CHA_ID_AES_SHIFT 0 +#define CHA_ID_AES_MASK (0xfull << CHA_ID_AES_SHIFT) +#define CHA_ID_AES_LP (0x3ull << CHA_ID_AES_SHIFT) +#define CHA_ID_AES_HP (0x4ull << CHA_ID_AES_SHIFT) +#define CHA_ID_AES_DIFFPWR (0x1ull << CHA_ID_AES_SHIFT) + /* * caam_perfmon - Performance Monitor/Secure Memory Status/ * CAAM Global Status/Component Version IDs @@ -113,10 +210,6 @@ struct jr_outentry { * Spans f00-fff wherever instantiated */ -/* Number of DECOs */ -#define CHA_NUM_DECONUM_SHIFT 56 -#define CHA_NUM_DECONUM_MASK (0xfull << CHA_NUM_DECONUM_SHIFT) - struct caam_perfmon { /* Performance Monitor Registers f00-f9f */ u64 req_dequeued; /* PC_REQ_DEQ - Dequeued Requests */ @@ -133,15 +226,21 @@ struct caam_perfmon { #define CTPR_QI_SHIFT 57 #define CTPR_QI_MASK (0x1ull << CTPR_QI_SHIFT) u64 comp_parms; /* CTPR - Compile Parameters Register */ - u64 rsvd1[2]; + + /* Secure Memory State Visibility */ + u32 rsvd1; + u32 smstatus; /* Secure memory status */ + u32 rsvd2; + u32 smpartown; /* Secure memory partition owner */ /* CAAM Global Status fc0-fdf */ u64 faultaddr; /* FAR - Fault Address */ u32 faultliodn; /* FALR - Fault Address LIODN */ u32 faultdetail; /* FADR - Fault Addr Detail */ - u32 rsvd2; + u32 rsvd3; u32 status; /* CSTA - CAAM Status */ - u64 rsvd3; + u32 smpart; /* Secure Memory Partition Parameters */ + u32 smvid; /* Secure Memory Version ID */ /* Component Instantiation Parameters fe0-fff */ u32 rtic_id; /* RVID - RTIC Version ID */ @@ -151,6 +250,62 @@ struct caam_perfmon { u64 caam_id; /* CAAMVID - CAAM Version ID */ }; +#define SMSTATUS_PART_SHIFT 28 +#define SMSTATUS_PART_MASK (0xf << SMSTATUS_PART_SHIFT) +#define SMSTATUS_PAGE_SHIFT 16 +#define SMSTATUS_PAGE_MASK (0x7ff << SMSTATUS_PAGE_SHIFT) +#define SMSTATUS_MID_SHIFT 8 +#define SMSTATUS_MID_MASK (0x3f << SMSTATUS_MID_SHIFT) +#define SMSTATUS_ACCERR_SHIFT 4 +#define SMSTATUS_ACCERR_MASK (0xf << SMSTATUS_ACCERR_SHIFT) +#define SMSTATUS_ACCERR_NONE 0 +#define SMSTATUS_ACCERR_ALLOC 1 /* Page not allocated */ +#define SMSTATUS_ACCESS_ID 2 /* Not granted by ID */ +#define SMSTATUS_ACCESS_WRITE 3 /* Writes not allowed */ +#define SMSTATUS_ACCESS_READ 4 /* Reads not allowed */ +#define SMSTATUS_ACCESS_NONKEY 6 /* Non-key reads not allowed */ +#define SMSTATUS_ACCESS_BLOB 9 /* Blob access not allowed */ +#define SMSTATUS_ACCESS_DESCB 10 /* Descriptor Blob access spans pages */ +#define SMSTATUS_ACCESS_NON_SM 11 /* Outside Secure Memory range */ +#define SMSTATUS_ACCESS_XPAGE 12 /* Access crosses pages */ +#define SMSTATUS_ACCESS_INITPG 13 /* Page still initializing */ +#define SMSTATUS_STATE_SHIFT 0 +#define SMSTATUS_STATE_MASK (0xf << SMSTATUS_STATE_SHIFT) +#define SMSTATUS_STATE_RESET 0 +#define SMSTATUS_STATE_INIT 1 +#define SMSTATUS_STATE_NORMAL 2 +#define SMSTATUS_STATE_FAIL 3 + +/* up to 15 rings, 2 bits shifted by ring number */ +#define SMPARTOWN_RING_SHIFT 2 +#define SMPARTOWN_RING_MASK 3 +#define SMPARTOWN_AVAILABLE 0 +#define SMPARTOWN_NOEXIST 1 +#define SMPARTOWN_UNAVAILABLE 2 +#define SMPARTOWN_OURS 3 + +/* Maximum number of pages possible */ +#define SMPART_MAX_NUMPG_SHIFT 16 +#define SMPART_MAX_NUMPG_MASK (0x3f << SMPART_MAX_NUMPG_SHIFT) + +/* Maximum partition number */ +#define SMPART_MAX_PNUM_SHIFT 12 +#define SMPART_MAX_PNUM_MASK (0xf << SMPART_MAX_PNUM_SHIFT) + +/* Highest possible page number */ +#define SMPART_MAX_PG_SHIFT 0 +#define SMPART_MAX_PG_MASK (0x3f << SMPART_MAX_PG_SHIFT) + +/* Max size of a page */ +#define SMVID_PG_SIZE_SHIFT 16 +#define SMVID_PG_SIZE_MASK (0x7 << SMVID_PG_SIZE_SHIFT) + +/* Major/Minor Version ID */ +#define SMVID_MAJ_VERS_SHIFT 8 +#define SMVID_MAJ_VERS (0xf << SMVID_MAJ_VERS_SHIFT) +#define SMVID_MIN_VERS_SHIFT 0 +#define SMVID_MIN_VERS (0xf << SMVID_MIN_VERS_SHIFT) + /* LIODN programming for DMA configuration */ #define MSTRID_LOCK_LIODN 0x80000000 #define MSTRID_LOCK_MAKETRUSTED 0x00010000 /* only for JR masterid */ @@ -167,7 +322,7 @@ struct partid { u32 pidr; /* partition ID, DECO */ }; -/* RNG test mode (replicated twice in some configurations) */ +/* RNGB test mode (replicated twice in some configurations) */ /* Padded out to 0x100 */ struct rngtst { u32 mode; /* RTSTMODEx - Test mode */ @@ -200,6 +355,32 @@ struct rngtst { u32 rsvd14[15]; }; +/* RNG4 TRNG test registers */ +struct rng4tst { +#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */ +#define RTMCTL_OSC_DIV_MASK 0xc /* select oscillator divider value */ + u32 rtmctl; /* misc. control register */ + u32 rtscmisc; /* statistical check misc. register */ + u32 rtpkrrng; /* poker range register */ + union { + u32 rtpkrmax; /* PRGM=1: poker max. limit register */ + u32 rtpkrsq; /* PRGM=0: poker square calc. result register */ + }; +#define RTSDCTL_ENT_DLY_SHIFT 16 +#define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT) + u32 rtsdctl; /* seed control register */ + union { + u32 rtsblim; /* PRGM=1: sparse bit limit register */ + u32 rttotsam; /* PRGM=0: total samples register */ + }; + u32 rtfrqmin; /* frequency count min. limit register */ + union { + u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */ + u32 rtfrqcnt; /* PRGM=0: freq. count register */ + }; + u32 rsvd1[56]; +}; + /* * caam_ctrl - basic core configuration * starts base + 0x0000 padded out to 0x1000 @@ -249,7 +430,10 @@ struct caam_ctrl { /* RNG Test/Verification/Debug Access 600-7ff */ /* (Useful in Test/Debug modes only...) */ - struct rngtst rtst[2]; + union { + struct rngtst rtst[2]; + struct rng4tst r4tst[2]; + }; u32 rsvd9[448]; @@ -323,7 +507,18 @@ struct caam_job_ring { u32 rsvd11; u32 jrcommand; /* JRCRx - JobR command */ - u32 rsvd12[932]; + u32 rsvd12[33]; + + /* Secure Memory Configuration - if you have it */ + u32 sm_cmd; /* SMCJRx - Secure memory command */ + u32 rsvd13; + u32 sm_status; /* SMCSJRx - Secure memory status */ + u32 rsvd14; + u32 sm_perm; /* SMAPJRx - Secure memory access perms */ + u32 sm_group2; /* SMAP2JRx - Secure memory access group 2 */ + u32 sm_group1; /* SMAP1JRx - Secure memory access group 1 */ + + u32 rsvd15[891]; /* Performance Monitor f00-fff */ struct caam_perfmon perfmon; @@ -446,6 +641,62 @@ struct caam_job_ring { #define JRCR_RESET 0x01 +/* secure memory command */ +#define SMC_PAGE_SHIFT 16 +#define SMC_PAGE_MASK (0xffff << SMC_PAGE_SHIFT) +#define SMC_PART_SHIFT 8 +#define SMC_PART_MASK (0x0f << SMC_PART_SHIFT) +#define SMC_CMD_SHIFT 0 +#define SMC_CMD_MASK (0x0f << SMC_CMD_SHIFT) + +#define SMC_CMD_ALLOC_PAGE 0x01 /* allocate page to this partition */ +#define SMC_CMD_DEALLOC_PAGE 0x02 /* deallocate page from partition */ +#define SMC_CMD_DEALLOC_PART 0x03 /* deallocate partition */ +#define SMC_CMD_PAGE_INQUIRY 0x05 /* find partition associate with page */ + +/* secure memory (command) status */ +#define SMCS_PAGE_SHIFT 16 +#define SMCS_PAGE_MASK (0x0fff << SMCS_PAGE_SHIFT) +#define SMCS_CMDERR_SHIFT 14 +#define SMCS_CMDERR_MASK (3 << SMCS_CMDERR_SHIFT) +#define SMCS_ALCERR_SHIFT 12 +#define SMCS_ALCERR_MASK (3 << SMCS_ALCERR_SHIFT) +#define SMCS_PGOWN_SHIFT 6 +#define SMCS_PGWON_MASK (3 << SMCS_PGOWN_SHIFT) +#define SMCS_PART_SHIFT 0 +#define SMCS_PART_MASK (0xf << SMCS_PART_SHIFT) + +#define SMCS_CMDERR_NONE 0 +#define SMCS_CMDERR_INCOMP 1 /* Command not yet complete */ +#define SMCS_CMDERR_SECFAIL 2 /* Security failure occurred */ +#define SMCS_CMDERR_OVERFLOW 3 /* Command overflow */ + +#define SMCS_ALCERR_NONE 0 +#define SMCS_ALCERR_PSPERR 1 /* Partion marked PSP (dealloc only) */ +#define SMCS_ALCERR_PAGEAVAIL 2 /* Page not available */ +#define SMCS_ALCERR_PARTOWN 3 /* Partition ownership error */ + +#define SMCS_PGOWN_AVAIL 0 /* Page is available */ +#define SMCS_PGOWN_NOEXIST 1 /* Page initializing or nonexistent */ +#define SMCS_PGOWN_NOOWN 2 /* Page owned by another processor */ +#define SMCS_PGOWN_OWNED 3 /* Page belongs to this processor */ + +/* secure memory access permissions */ +#define SMCS_PERM_KEYMOD_SHIFT 16 +#define SMCA_PERM_KEYMOD_MASK (0xff << SMCS_PERM_KEYMOD_SHIFT) +#define SMCA_PERM_CSP_ZERO 0x8000 /* Zero when deallocated or released */ +#define SMCA_PERM_PSP_LOCK 0x4000 /* Part./pages can't be deallocated */ +#define SMCA_PERM_PERM_LOCK 0x2000 /* Lock permissions */ +#define SMCA_PERM_GRP_LOCK 0x1000 /* Lock access groups */ +#define SMCA_PERM_RINGID_SHIFT 10 +#define SMCA_PERM_RINGID_MASK (3 << SMCA_PERM_RINGID_SHIFT) +#define SMCA_PERM_G2_BLOB 0x0080 /* Group 2 blob import/export */ +#define SMCA_PERM_G2_WRITE 0x0020 /* Group 2 write */ +#define SMCA_PERM_G2_READ 0x0010 /* Group 2 read */ +#define SMCA_PERM_G1_BLOB 0x0008 /* Group 1... */ +#define SMCA_PERM_G1_WRITE 0x0002 +#define SMCA_PERM_G1_READ 0x0001 + /* * caam_assurance - Assurance Controller View * base + 0x6000 padded out to 0x1000 @@ -657,7 +908,6 @@ struct caam_full { u64 rsvd[512]; struct caam_assurance assure; struct caam_queue_if qi; - struct caam_deco *deco; }; #endif /* REGS_H */ diff --git a/drivers/crypto/caam/secvio.c b/drivers/crypto/caam/secvio.c new file mode 100644 index 000000000000..b0719e4173b4 --- /dev/null +++ b/drivers/crypto/caam/secvio.c @@ -0,0 +1,310 @@ + +/* + * CAAM/SEC 4.x Security Violation Handler + * Copyright 2012 Freescale Semiconductor, Inc., All Rights Reserved + */ + +#include "compat.h" +#include "intern.h" +#include "secvio.h" +#include "regs.h" + +/* + * These names are associated with each violation handler. + * The source names were taken from MX6, and are based on recommendations + * for most common SoCs. + */ +static const u8 *violation_src_name[] = { + "CAAM Security Violation", + "JTAG Alarm", + "Watchdog", + "(reserved)", + "External Boot", + "Tamper Detect", +}; + +/* Top-level security violation interrupt */ +static irqreturn_t caam_secvio_interrupt(int irq, void *snvsdev) +{ + struct device *dev = snvsdev; + struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); + u32 irqstate; + + /* Check the HP secvio status register */ + irqstate = rd_reg32(&svpriv->svregs->hp.secvio_status) | + HP_SECVIOST_SECVIOMASK; + if (!irqstate) + return IRQ_NONE; + + /* Mask out one or more causes for deferred service */ + clrbits32(&svpriv->svregs->hp.secvio_int_ctl, irqstate); + + /* Now ACK causes */ + setbits32(&svpriv->svregs->hp.secvio_status, irqstate); + + /* And run deferred service */ + preempt_disable(); + tasklet_schedule(&svpriv->irqtask[smp_processor_id()]); + preempt_enable(); + + return IRQ_HANDLED; +} + +/* Deferred service handler. Tasklet arg is simply the SNVS dev */ +static void caam_secvio_dispatch(unsigned long indev) +{ + struct device *dev = (struct device *)indev; + struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); + unsigned long flags, cause; + int i; + + + /* + * Capture the interrupt cause, using masked interrupts as + * identification. This only works if all are enabled; if + * this changes in the future, a "cause queue" will have to + * be built + */ + cause = rd_reg32(&svpriv->svregs->hp.secvio_int_ctl) & + (HP_SECVIO_INTEN_SRC5 | HP_SECVIO_INTEN_SRC4 | + HP_SECVIO_INTEN_SRC3 | HP_SECVIO_INTEN_SRC2 | + HP_SECVIO_INTEN_SRC1 | HP_SECVIO_INTEN_SRC0); + + /* Look through causes, call each handler if exists */ + for (i = 0; i < MAX_SECVIO_SOURCES; i++) + if (cause & (1 << i)) { + spin_lock_irqsave(&svpriv->svlock, flags); + svpriv->intsrc[i].handler(dev, i, + svpriv->intsrc[i].ext); + spin_unlock_irqrestore(&svpriv->svlock, flags); + }; + + /* Re-enable now-serviced interrupts */ + setbits32(&svpriv->svregs->hp.secvio_int_ctl, cause); +} + +/* + * Default cause handler, used in lieu of an application-defined handler. + * All it does at this time is print a console message. It could force a halt. + */ +static void caam_secvio_default(struct device *dev, u32 cause, void *ext) +{ + struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); + + dev_err(dev, "Unhandled Security Violation Interrupt %d = %s\n", + cause, svpriv->intsrc[cause].intname); +} + +/* + * Install an application-defined handler for a specified cause + * Arguments: + * - dev points to SNVS-owning device + * - cause interrupt source cause + * - handler application-defined handler, gets called with dev + * source cause, and locally-defined handler argument + * - cause_description points to a string to override the default cause + * name, this can be used as an alternate for error + * messages and such. If left NULL, the default + * description string is used. + * - ext pointer to any extra data needed by the handler. + */ +int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause, + void (*handler)(struct device *dev, u32 cause, + void *ext), + u8 *cause_description, void *ext) +{ + unsigned long flags; + struct caam_drv_private_secvio *svpriv; + + svpriv = dev_get_drvdata(dev); + + if ((handler == NULL) || (cause > SECVIO_CAUSE_SOURCE_5)) + return -EINVAL; + + spin_lock_irqsave(&svpriv->svlock, flags); + svpriv->intsrc[cause].handler = handler; + if (cause_description != NULL) + svpriv->intsrc[cause].intname = cause_description; + if (ext != NULL) + svpriv->intsrc[cause].ext = ext; + spin_unlock_irqrestore(&svpriv->svlock, flags); + + return 0; +} +EXPORT_SYMBOL(caam_secvio_install_handler); + +/* + * Remove an application-defined handler for a specified cause (and, by + * implication, restore the "default". + * Arguments: + * - dev points to SNVS-owning device + * - cause interrupt source cause + */ +int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause) +{ + unsigned long flags; + struct caam_drv_private_secvio *svpriv; + + svpriv = dev_get_drvdata(dev); + + if (cause > SECVIO_CAUSE_SOURCE_5) + return -EINVAL; + + spin_lock_irqsave(&svpriv->svlock, flags); + svpriv->intsrc[cause].intname = violation_src_name[cause]; + svpriv->intsrc[cause].handler = caam_secvio_default; + svpriv->intsrc[cause].ext = NULL; + spin_unlock_irqrestore(&svpriv->svlock, flags); + return 0; +} +EXPORT_SYMBOL(caam_secvio_remove_handler); + +int caam_secvio_startup(struct platform_device *pdev) +{ + struct device *ctrldev, *svdev; + struct caam_drv_private *ctrlpriv; + struct caam_drv_private_secvio *svpriv; + struct platform_device *svpdev; + int i, error; + + ctrldev = &pdev->dev; + ctrlpriv = dev_get_drvdata(ctrldev); + + /* + * Set up the private block for secure memory + * Only one instance is possible + */ + svpriv = kzalloc(sizeof(struct caam_drv_private_secvio), GFP_KERNEL); + if (svpriv == NULL) { + dev_err(ctrldev, "can't alloc private mem for secvio\n"); + return -ENOMEM; + } + svpriv->parentdev = ctrldev; + + /* Create the security violation dev */ +#ifdef CONFIG_OF + svpdev = of_platform_device_create(np, NULL, ctrldev); +#else + svpdev = platform_device_register_data(ctrldev, "caam_secvio", 0, + svpriv, + sizeof(struct caam_drv_private_secvio)); +#endif + if (svpdev == NULL) { + kfree(svpriv); + return -EINVAL; + } + svdev = &svpdev->dev; + dev_set_drvdata(svdev, svpriv); + ctrlpriv->secviodev = svdev; + svpriv->svregs = ctrlpriv->snvs; + + /* + * Now we have all the dev data set up. Init interrupt + * source descriptions + */ + for (i = 0; i < MAX_SECVIO_SOURCES; i++) { + svpriv->intsrc[i].intname = violation_src_name[i]; + svpriv->intsrc[i].handler = caam_secvio_default; + } + + /* Connect main handler */ + for_each_possible_cpu(i) + tasklet_init(&svpriv->irqtask[i], caam_secvio_dispatch, + (unsigned long)svdev); + + error = request_irq(ctrlpriv->secvio_irq, caam_secvio_interrupt, + IRQF_SHARED, "caam-secvio", svdev); + if (error) { + dev_err(svdev, "can't connect secvio interrupt\n"); + irq_dispose_mapping(ctrlpriv->secvio_irq); + ctrlpriv->secvio_irq = 0; + return -EINVAL; + } + + /* Enable all sources */ + wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, HP_SECVIO_INTEN_ALL); + + dev_info(svdev, "security violation service handlers armed\n"); + + return 0; +} + +void caam_secvio_shutdown(struct platform_device *pdev) +{ + struct device *ctrldev, *svdev; + struct caam_drv_private *priv; + struct caam_drv_private_secvio *svpriv; + int i; + + ctrldev = &pdev->dev; + priv = dev_get_drvdata(ctrldev); + svdev = priv->secviodev; + svpriv = dev_get_drvdata(svdev); + + /* Shut off all sources */ + wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, 0); + + /* Remove tasklets and release interrupt */ + for_each_possible_cpu(i) + tasklet_kill(&svpriv->irqtask[i]); + + free_irq(priv->secvio_irq, svdev); + + kfree(svpriv); +} + + +#ifdef CONFIG_OF +static void __exit caam_secvio_exit(void) +{ + struct device_node *dev_node; + struct platform_device *pdev; + + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) { + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); + if (!dev_node) + return -ENODEV; + } + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return -ENODEV; + + of_node_put(dev_node); + + caam_sm_shutdown(pdev); +} + +static int __init caam_secvio_init(void) +{ + struct device_node *dev_node; + struct platform_device *pdev; + + /* + * Do of_find_compatible_node() then of_find_device_by_node() + * once a functional device tree is available + */ + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) { + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); + if (!dev_node) + return -ENODEV; + } + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return -ENODEV; + + of_node_put(dev_node); + + return caam_secvio_startup(pdev); +} + +module_init(caam_secvio_init); +module_exit(caam_secvio_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("FSL CAAM/SNVS Security Violation Handler"); +MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); +#endif diff --git a/drivers/crypto/caam/secvio.h b/drivers/crypto/caam/secvio.h new file mode 100644 index 000000000000..2f7d5f6270d8 --- /dev/null +++ b/drivers/crypto/caam/secvio.h @@ -0,0 +1,64 @@ + +/* + * CAAM Security Violation Handler + * Copyright (c) 2012 Freescale Semiconductor, Inc., All Rights Reserved + */ + +#ifndef SECVIO_H +#define SECVIO_H + +#include "snvsregs.h" + + +/* + * Defines the published interfaces to install/remove application-specified + * handlers for catching violations + */ + +#define MAX_SECVIO_SOURCES 6 + +/* these are the untranslated causes */ +enum secvio_cause { + SECVIO_CAUSE_SOURCE_0, + SECVIO_CAUSE_SOURCE_1, + SECVIO_CAUSE_SOURCE_2, + SECVIO_CAUSE_SOURCE_3, + SECVIO_CAUSE_SOURCE_4, + SECVIO_CAUSE_SOURCE_5 +}; + +/* These are common "recommended" cause definitions for most devices */ +#define SECVIO_CAUSE_CAAM_VIOLATION SECVIO_CAUSE_SOURCE_0 +#define SECVIO_CAUSE JTAG_ALARM SECVIO_CAUSE_SOURCE_1 +#define SECVIO_CAUSE_WATCHDOG SECVIO_CAUSE_SOURCE_2 +#define SECVIO_CAUSE_EXTERNAL_BOOT SECVIO_CAUSE_SOURCE_4 +#define SECVIO_CAUSE_TAMPER_DETECT SECVIO_CAUSE_SOURCE_5 + +int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause, + void (*handler)(struct device *dev, u32 cause, + void *ext), + u8 *cause_description, void *ext); +int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause); + +/* + * Private data definitions for the secvio "driver" + */ + +struct secvio_int_src { + const u8 *intname; /* Points to a descriptive name for source */ + void *ext; /* Extended data to pass to the handler */ + void (*handler)(struct device *dev, u32 cause, void *ext); +}; + +struct caam_drv_private_secvio { + struct device *parentdev; /* points back to the controller */ + spinlock_t svlock ____cacheline_aligned; + struct tasklet_struct irqtask[NR_CPUS]; + struct snvs_full __iomem *svregs; /* both HP and LP domains */ + + /* Registered handlers for each violation */ + struct secvio_int_src intsrc[MAX_SECVIO_SOURCES]; + +}; + +#endif /* SECVIO_H */ diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h new file mode 100644 index 000000000000..e05fc58c9637 --- /dev/null +++ b/drivers/crypto/caam/sg_sw_sec4.h @@ -0,0 +1,165 @@ +/* + * CAAM/SEC 4.x functions for using scatterlists in caam driver + * + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. + * + */ + +struct sec4_sg_entry; + +/* + * convert single dma address to h/w link table format + */ +static inline void dma_to_sec4_sg_one(struct sec4_sg_entry *sec4_sg_ptr, + dma_addr_t dma, u32 len, u32 offset) +{ +#ifndef CONFIG_64BIT + sec4_sg_ptr->reserved = 0; /* ensure MSB half is zeroed */ +#endif + sec4_sg_ptr->ptr = dma; + sec4_sg_ptr->len |= (len & SEC4_SG_LEN_MASK); + /* Does not add in buffer pool ID's at this time */ + sec4_sg_ptr->bpid_offset = (offset & SEC4_SG_OFFS_MASK); +#ifdef DEBUG + print_hex_dump(KERN_ERR, "sec4_sg_ptr@: ", + DUMP_PREFIX_ADDRESS, 16, 4, sec4_sg_ptr, + sizeof(struct sec4_sg_entry), 1); +#endif +} + +/* + * convert scatterlist to h/w link table format + * but does not have final bit; instead, returns last entry + */ +static inline struct sec4_sg_entry * +sg_to_sec4_sg(struct scatterlist *sg, int sg_count, + struct sec4_sg_entry *sec4_sg_ptr, u32 offset) +{ + while (sg_count) { + dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg), + sg_dma_len(sg), offset); + sec4_sg_ptr++; + sg = scatterwalk_sg_next(sg); + sg_count--; + } + return sec4_sg_ptr - 1; +} + +/* + * convert scatterlist to h/w link table format + * scatterlist must have been previously dma mapped + */ +static inline void sg_to_sec4_sg_last(struct scatterlist *sg, int sg_count, + struct sec4_sg_entry *sec4_sg_ptr, + u32 offset) +{ + sec4_sg_ptr = sg_to_sec4_sg(sg, sg_count, sec4_sg_ptr, offset); + sec4_sg_ptr->len |= SEC4_SG_LEN_FIN; +} + +/* count number of elements in scatterlist */ +static inline int __sg_count(struct scatterlist *sg_list, int nbytes, + bool *chained) +{ + struct scatterlist *sg = sg_list; + int sg_nents = 0; + + while (nbytes > 0) { + sg_nents++; + nbytes -= sg->length; + if (!sg_is_last(sg) && (sg + 1)->length == 0) + *chained = true; + sg = scatterwalk_sg_next(sg); + } + + return sg_nents; +} + +/* derive number of elements in scatterlist, but return 0 for 1 */ +static inline int sg_count(struct scatterlist *sg_list, int nbytes, + bool *chained) +{ + int sg_nents = __sg_count(sg_list, nbytes, chained); + + if (likely(sg_nents == 1)) + return 0; + + return sg_nents; +} + +static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg, + unsigned int nents, enum dma_data_direction dir, + bool chained) +{ + if (unlikely(chained)) { + int i; + for (i = 0; i < nents; i++) { + dma_map_sg(dev, sg, 1, dir); + sg = scatterwalk_sg_next(sg); + } + } else { + dma_map_sg(dev, sg, nents, dir); + } + + if ((dir == DMA_TO_DEVICE) || (dir == DMA_BIDIRECTIONAL)) + dma_sync_sg_for_device(dev, sg, nents, dir); + + return nents; +} + +static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg, + unsigned int nents, enum dma_data_direction dir, + bool chained) +{ + if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)) + dma_sync_sg_for_cpu(dev, sg, nents, dir); + + if (unlikely(chained)) { + int i; + for (i = 0; i < nents; i++) { + dma_unmap_sg(dev, sg, 1, dir); + sg = scatterwalk_sg_next(sg); + } + } else { + dma_unmap_sg(dev, sg, nents, dir); + } + return nents; +} + +/* Copy from len bytes of sg to dest, starting from beginning */ +static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len) +{ + struct scatterlist *current_sg = sg; + int cpy_index = 0, next_cpy_index = current_sg->length; + + while (next_cpy_index < len) { + memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg), + current_sg->length); + current_sg = scatterwalk_sg_next(current_sg); + cpy_index = next_cpy_index; + next_cpy_index += current_sg->length; + } + if (cpy_index < len) + memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg), + len - cpy_index); +} + +/* Copy sg data, from to_skip to end, to dest */ +static inline void sg_copy_part(u8 *dest, struct scatterlist *sg, + int to_skip, unsigned int end) +{ + struct scatterlist *current_sg = sg; + int sg_index, cpy_index; + + sg_index = current_sg->length; + while (sg_index <= to_skip) { + current_sg = scatterwalk_sg_next(current_sg); + sg_index += current_sg->length; + } + cpy_index = sg_index - to_skip; + memcpy(dest, (u8 *) sg_virt(current_sg) + + current_sg->length - cpy_index, cpy_index); + current_sg = scatterwalk_sg_next(current_sg); + if (end - sg_index) + sg_copy(dest + cpy_index, current_sg, end - sg_index); +} diff --git a/drivers/crypto/caam/sm.h b/drivers/crypto/caam/sm.h new file mode 100644 index 000000000000..fba4c5679add --- /dev/null +++ b/drivers/crypto/caam/sm.h @@ -0,0 +1,86 @@ + +/* + * CAAM Secure Memory/Keywrap API Definitions + * Copyright (c) 2008, 2012 Freescale Semiconductor, Inc. + */ + +#ifndef SM_H +#define SM_H + + +/* Storage access permissions */ +#define SM_PERM_READ 0x01 +#define SM_PERM_WRITE 0x02 +#define SM_PERM_BLOB 0x03 + + +/* Keystore maintenance functions */ +void sm_init_keystore(struct device *dev); +u32 sm_detect_keystore_units(struct device *dev); +int sm_establish_keystore(struct device *dev, u32 unit); +void sm_release_keystore(struct device *dev, u32 unit); + +/* Keystore accessor functions */ +extern int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, + u32 *slot); +extern int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot); +extern int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot, + const u8 *key_data, u32 key_length); +extern int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot, + u32 key_length, u8 *key_data); +extern int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, + u32 inslot, u32 outslot, u16 secretlen, + u8 *keymod, u16 keymodlen); +extern int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, + u32 inslot, u32 outslot, u16 secretlen, + u8 *keymod, u16 keymodlen); + +/* Data structure to hold per-slot information */ +struct keystore_data_slot_info { + u8 allocated; /* Track slot assignments */ + u32 key_length; /* Size of the key */ +}; + +/* Data structure to hold keystore information */ +struct keystore_data { + void *base_address; /* Base of the Secure Partition */ + u32 slot_count; /* Number of slots in the keystore */ + struct keystore_data_slot_info *slot; /* Per-slot information */ +}; + +/* store the detected attributes of a secure memory page */ +struct sm_page_descriptor { + u16 phys_pagenum; /* may be discontiguous */ + u16 own_part; /* Owning partition */ + void *pg_base; /* Calculated virtual address */ + struct keystore_data *ksdata; +}; + +struct caam_drv_private_sm { + struct device *parentdev; /* this ends up as the controller */ + struct device *smringdev; /* ring that owns this instance */ + spinlock_t kslock ____cacheline_aligned; + + /* Default parameters for geometry */ + u32 max_pages; /* maximum pages this instance can support */ + u32 top_partition; /* highest partition number in this instance */ + u32 top_page; /* highest page number in this instance */ + u32 page_size; /* page size */ + u32 slot_size; /* selected size of each storage block */ + + /* Partition/Page Allocation Map */ + u32 localpages; /* Number of pages we can access */ + struct sm_page_descriptor *pagedesc; /* Allocated per-page */ + + /* Installed handlers for keystore access */ + int (*data_init)(struct device *dev, u32 unit); + void (*data_cleanup)(struct device *dev, u32 unit); + int (*slot_alloc)(struct device *dev, u32 unit, u32 size, u32 *slot); + int (*slot_dealloc)(struct device *dev, u32 unit, u32 slot); + void *(*slot_get_address)(struct device *dev, u32 unit, u32 handle); + u32 (*slot_get_base)(struct device *dev, u32 unit, u32 handle); + u32 (*slot_get_offset)(struct device *dev, u32 unit, u32 handle); + u32 (*slot_get_slot_size)(struct device *dev, u32 unit, u32 handle); +}; + +#endif /* SM_H */ diff --git a/drivers/crypto/caam/sm_store.c b/drivers/crypto/caam/sm_store.c new file mode 100644 index 000000000000..b2c508a6da75 --- /dev/null +++ b/drivers/crypto/caam/sm_store.c @@ -0,0 +1,890 @@ + +/* + * CAAM Secure Memory Storage Interface + * Copyright (c) 2008, 2012 Freescale Semiconductor, Inc. + * + * Loosely based on the SHW Keystore API for SCC/SCC2 + * Experimental implementation and NOT intended for upstream use. Expect + * this interface to be amended significantly in the future once it becomes + * integrated into live applications. + * + * Known issues: + * + * - Executes one instance of an secure memory "driver". This is tied to the + * fact that job rings can't run as standalone instances in the present + * configuration. + * + * - It does not expose a userspace interface. The value of a userspace + * interface for access to secrets is a point for further architectural + * discussion. + * + * - Partition/permission management is not part of this interface. It + * depends on some level of "knowledge" agreed upon between bootloader, + * provisioning applications, and OS-hosted software (which uses this + * driver). + * + * - No means of identifying the location or purpose of secrets managed by + * this interface exists; "slot location" and format of a given secret + * needs to be agreed upon between bootloader, provisioner, and OS-hosted + * application. + */ + +#include "compat.h" +#include "regs.h" +#include "jr.h" +#include "desc.h" +#include "intern.h" +#include "error.h" +#include "sm.h" + + +#ifdef SM_DEBUG_CONT +void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + u32 i, *smdata; + + dev_info(dev, "physical page %d content at 0x%08x\n", + pgdesc->phys_pagenum, pgdesc->pg_base); + smdata = pgdesc->pg_base; + for (i = 0; i < (smpriv->page_size / sizeof(u32)); i += 4) + dev_info(dev, "[0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)&smdata[i], smdata[i], smdata[i+1], smdata[i+2], + smdata[i+3]); +} +#endif + +/* + * Construct a secure memory blob encapsulation job descriptor + * + * - desc pointer to hold new (to be allocated) pointer to the generated + * descriptor for later use. Calling thread can kfree the + * descriptor after execution. + * - keymod Physical pointer to key modifier (contiguous piece). + * - keymodsz Size of key modifier in bytes (should normally be 8). + * - secretbuf Physical pointer (within an accessible secure memory page) + * of the secret to be encapsulated. + * - outbuf Physical pointer (within an accessible secure memory page) + * of the encapsulated output. This will be larger than the + * input secret because of the added encapsulation data. + * - secretsz Size of input secret, in bytes. + * - auth If nonzero, use AES-CCM for encapsulation, else use ECB + * + * Note: this uses 32-bit pointers at present + */ +#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */ +static int blob_encap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz, + dma_addr_t secretbuf, dma_addr_t outbuf, + u16 secretsz, bool auth) +{ + u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; + u16 dsize, idx; + + memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); + idx = 1; + + /* Load key modifier */ + tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY | + ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) | + (keymodsz & LDST_LEN_MASK); + + tmpdesc[idx++] = (u32)keymod; + + /* Encapsulate to secure memory */ + tmpdesc[idx++] = CMD_SEQ_IN_PTR | secretsz; + tmpdesc[idx++] = (u32)secretbuf; + + /* Add space for BKEK and MAC tag */ + tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + (32 + 16)); + + tmpdesc[idx++] = (u32)outbuf; + tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB | + OP_PCL_BLOB_PTXT_SECMEM; + if (auth) + tmpdesc[idx] |= OP_PCL_BLOB_EKT; + + idx++; + tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); + dsize = idx * sizeof(u32); + + tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); + if (tdesc == NULL) + return 0; + + memcpy(tdesc, tmpdesc, dsize); + *desc = tdesc; + return dsize; +} + +/* + * Construct a secure memory blob decapsulation job descriptor + * + * - desc pointer to hold new (to be allocated) pointer to the generated + * descriptor for later use. Calling thread can kfree the + * descriptor after execution. + * - keymod Physical pointer to key modifier (contiguous piece). + * - keymodsz Size of key modifier in bytes (should normally be 16). + * - blobbuf Physical pointer (within an accessible secure memory page) + * of the blob to be decapsulated. + * - outbuf Physical pointer (within an accessible secure memory page) + * of the decapsulated output. + * - secretsz Size of input blob, in bytes. + * - auth If nonzero, assume AES-CCM for decapsulation, else use ECB + * + * Note: this uses 32-bit pointers at present + */ +static int blob_decap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz, + dma_addr_t blobbuf, dma_addr_t outbuf, + u16 blobsz, bool auth) +{ + u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; + u16 dsize, idx; + + memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); + idx = 1; + + /* Load key modifier */ + tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY | + ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) | + (keymodsz & LDST_LEN_MASK); + + tmpdesc[idx++] = (u32)keymod; + + /* Compensate BKEK + MAC tag */ + tmpdesc[idx++] = CMD_SEQ_IN_PTR | (blobsz + 32 + 16); + + tmpdesc[idx++] = (u32)blobbuf; + tmpdesc[idx++] = CMD_SEQ_OUT_PTR | blobsz; + tmpdesc[idx++] = (u32)outbuf; + + /* Decapsulate from secure memory partition to black blob */ + tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB | + OP_PCL_BLOB_PTXT_SECMEM | OP_PCL_BLOB_BLACK; + if (auth) + tmpdesc[idx] |= OP_PCL_BLOB_EKT; + + idx++; + tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); + dsize = idx * sizeof(u32); + + tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); + if (tdesc == NULL) + return 0; + + memcpy(tdesc, tmpdesc, dsize); + *desc = tdesc; + return dsize; +} + +/* + * Pseudo-synchronous ring access functions for carrying out key + * encapsulation and decapsulation + */ + +struct sm_key_job_result { + int error; + struct completion completion; +}; + +void sm_key_job_done(struct device *dev, u32 *desc, u32 err, void *context) +{ + struct sm_key_job_result *res = context; + + res->error = err; /* save off the error for postprocessing */ + complete(&res->completion); /* mark us complete */ +} + +static int sm_key_job(struct device *ksdev, u32 *jobdesc) +{ + struct sm_key_job_result testres; + struct caam_drv_private_sm *kspriv; + int rtn = 0; + + kspriv = dev_get_drvdata(ksdev); + + init_completion(&testres.completion); + + rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, sm_key_job_done, + &testres); + if (!rtn) { + wait_for_completion_interruptible(&testres.completion); + rtn = testres.error; + } + return rtn; +} + +/* + * Following section establishes the default methods for keystore access + * They are NOT intended for use external to this module + * + * In the present version, these are the only means for the higher-level + * interface to deal with the mechanics of accessing the phyiscal keystore + */ + + +int slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; + u32 i; + +#ifdef SM_DEBUG + dev_info(dev, "slot_alloc(): requesting slot for %d bytes\n", size); +#endif + + if (size > smpriv->slot_size) + return -EKEYREJECTED; + + for (i = 0; i < ksdata->slot_count; i++) { + if (ksdata->slot[i].allocated == 0) { + ksdata->slot[i].allocated = 1; + (*slot) = i; +#ifdef SM_DEBUG + dev_info(dev, "slot_alloc(): new slot %d allocated\n", + *slot); +#endif + return 0; + } + } + + return -ENOSPC; +} + +int slot_dealloc(struct device *dev, u32 unit, u32 slot) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; + u8 __iomem *slotdata; + +#ifdef SM_DEBUG + dev_info(dev, "slot_dealloc(): releasing slot %d\n", slot); +#endif + if (slot >= ksdata->slot_count) + return -EINVAL; + slotdata = ksdata->base_address + slot * smpriv->slot_size; + + if (ksdata->slot[slot].allocated == 1) { + /* Forcibly overwrite the data from the keystore */ + memset(ksdata->base_address + slot * smpriv->slot_size, 0, + smpriv->slot_size); + + ksdata->slot[slot].allocated = 0; +#ifdef SM_DEBUG + dev_info(dev, "slot_dealloc(): slot %d released\n", slot); +#endif + return 0; + } + + return -EINVAL; +} + +void *slot_get_address(struct device *dev, u32 unit, u32 slot) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; + + if (slot >= ksdata->slot_count) + return NULL; + +#ifdef SM_DEBUG + dev_info(dev, "slot_get_address(): slot %d is 0x%08x\n", slot, + (u32)ksdata->base_address + slot * smpriv->slot_size); +#endif + + return ksdata->base_address + slot * smpriv->slot_size; +} + +u32 slot_get_base(struct device *dev, u32 unit, u32 slot) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; + + /* + * There could potentially be more than one secure partition object + * associated with this keystore. For now, there is just one. + */ + + (void)slot; + +#ifdef SM_DEBUG + dev_info(dev, "slot_get_base(): slot %d = 0x%08x\n", + slot, (u32)ksdata->base_address); +#endif + + return (u32)(ksdata->base_address); +} + +u32 slot_get_offset(struct device *dev, u32 unit, u32 slot) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; + + if (slot >= ksdata->slot_count) + return -EINVAL; + +#ifdef SM_DEBUG + dev_info(dev, "slot_get_offset(): slot %d = %d\n", slot, + slot * smpriv->slot_size); +#endif + + return slot * smpriv->slot_size; +} + +u32 slot_get_slot_size(struct device *dev, u32 unit, u32 slot) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + + +#ifdef SM_DEBUG + dev_info(dev, "slot_get_slot_size(): slot %d = %d\n", slot, + smpriv->slot_size); +#endif + /* All slots are the same size in the default implementation */ + return smpriv->slot_size; +} + + + +int kso_init_data(struct device *dev, u32 unit) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + int retval = -EINVAL; + struct keystore_data *keystore_data = NULL; + u32 slot_count; + u32 keystore_data_size; + + /* + * Calculate the required size of the keystore data structure, based + * on the number of keys that can fit in the partition. + */ + slot_count = smpriv->page_size / smpriv->slot_size; +#ifdef SM_DEBUG + dev_info(dev, "kso_init_data: %d slots initializing\n", slot_count); +#endif + + keystore_data_size = sizeof(struct keystore_data) + + slot_count * + sizeof(struct keystore_data_slot_info); + + keystore_data = kzalloc(keystore_data_size, GFP_KERNEL); + + if (keystore_data == NULL) { + retval = -ENOSPC; + goto out; + } + +#ifdef SM_DEBUG + dev_info(dev, "kso_init_data: keystore data size = %d\n", + keystore_data_size); +#endif + + /* + * Place the slot information structure directly after the keystore data + * structure. + */ + keystore_data->slot = (struct keystore_data_slot_info *) + (keystore_data + 1); + keystore_data->slot_count = slot_count; + + smpriv->pagedesc[unit].ksdata = keystore_data; + smpriv->pagedesc[unit].ksdata->base_address = + smpriv->pagedesc[unit].pg_base; + + retval = 0; + +out: + if (retval != 0) + if (keystore_data != NULL) + kfree(keystore_data); + + + return retval; +} + +void kso_cleanup_data(struct device *dev, u32 unit) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + struct keystore_data *keystore_data = NULL; + + if (smpriv->pagedesc[unit].ksdata != NULL) + keystore_data = smpriv->pagedesc[unit].ksdata; + + /* Release the allocated keystore management data */ + kfree(smpriv->pagedesc[unit].ksdata); + + return; +} + + + +/* + * Keystore management section + */ + +void sm_init_keystore(struct device *dev) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + + smpriv->data_init = kso_init_data; + smpriv->data_cleanup = kso_cleanup_data; + smpriv->slot_alloc = slot_alloc; + smpriv->slot_dealloc = slot_dealloc; + smpriv->slot_get_address = slot_get_address; + smpriv->slot_get_base = slot_get_base; + smpriv->slot_get_offset = slot_get_offset; + smpriv->slot_get_slot_size = slot_get_slot_size; +#ifdef SM_DEBUG + dev_info(dev, "sm_init_keystore(): handlers installed\n"); +#endif +} +EXPORT_SYMBOL(sm_init_keystore); + +/* Return available pages/units */ +u32 sm_detect_keystore_units(struct device *dev) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + + return smpriv->localpages; +} +EXPORT_SYMBOL(sm_detect_keystore_units); + +/* + * Do any keystore specific initializations + */ +int sm_establish_keystore(struct device *dev, u32 unit) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + +#ifdef SM_DEBUG + dev_info(dev, "sm_establish_keystore(): unit %d initializing\n", unit); +#endif + + if (smpriv->data_init == NULL) + return -EINVAL; + + /* Call the data_init function for any user setup */ + return smpriv->data_init(dev, unit); +} +EXPORT_SYMBOL(sm_establish_keystore); + +void sm_release_keystore(struct device *dev, u32 unit) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + +#ifdef SM_DEBUG + dev_info(dev, "sm_establish_keystore(): unit %d releasing\n", unit); +#endif + if ((smpriv != NULL) && (smpriv->data_cleanup != NULL)) + smpriv->data_cleanup(dev, unit); + + return; +} +EXPORT_SYMBOL(sm_release_keystore); + +/* + * Subsequent interfacce (sm_keystore_*) forms the accessor interfacce to + * the keystore + */ +int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + int retval = -EINVAL; + + spin_lock(&smpriv->kslock); + + if ((smpriv->slot_alloc == NULL) || + (smpriv->pagedesc[unit].ksdata == NULL)) + goto out; + + retval = smpriv->slot_alloc(dev, unit, size, slot); + +out: + spin_unlock(&smpriv->kslock); + return retval; +} +EXPORT_SYMBOL(sm_keystore_slot_alloc); + +int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + int retval = -EINVAL; + + spin_lock(&smpriv->kslock); + + if ((smpriv->slot_alloc == NULL) || + (smpriv->pagedesc[unit].ksdata == NULL)) + goto out; + + retval = smpriv->slot_dealloc(dev, unit, slot); +out: + spin_unlock(&smpriv->kslock); + return retval; +} +EXPORT_SYMBOL(sm_keystore_slot_dealloc); + +int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot, + const u8 *key_data, u32 key_length) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + int retval = -EINVAL; + u32 slot_size; + u32 i; + u8 __iomem *slot_location; + + spin_lock(&smpriv->kslock); + + slot_size = smpriv->slot_get_slot_size(dev, unit, slot); + + if (key_length > slot_size) { + retval = -EFBIG; + goto out; + } + + slot_location = smpriv->slot_get_address(dev, unit, slot); + + for (i = 0; i < key_length; i++) + slot_location[i] = key_data[i]; + + retval = 0; + +out: + spin_unlock(&smpriv->kslock); + return retval; +} +EXPORT_SYMBOL(sm_keystore_slot_load); + +int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot, + u32 key_length, u8 *key_data) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + int retval = -EINVAL; + u8 __iomem *slot_addr; + u32 slot_size; + + spin_lock(&smpriv->kslock); + + slot_addr = smpriv->slot_get_address(dev, unit, slot); + slot_size = smpriv->slot_get_slot_size(dev, unit, slot); + + if (key_length > slot_size) { + retval = -EKEYREJECTED; + goto out; + } + + memcpy(key_data, slot_addr, key_length); + retval = 0; + +out: + spin_unlock(&smpriv->kslock); + return retval; +} +EXPORT_SYMBOL(sm_keystore_slot_read); + +int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, u32 inslot, + u32 outslot, u16 secretlen, u8 *keymod, + u16 keymodlen) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + int retval = 0; + u32 slot_length, dsize, jstat; + u32 __iomem *encapdesc = NULL; + u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr; + dma_addr_t keymod_dma; + + /* Ensure that the full blob will fit in the key slot */ + slot_length = smpriv->slot_get_slot_size(dev, unit, outslot); + if ((secretlen + 48) > slot_length) + goto out; + + /* Get the base addresses of both keystore slots */ + inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot); + outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot); + + /* Build the key modifier */ + lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA); + memcpy(lkeymod, keymod, keymodlen); + keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE); + dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); + + /* Build the encapsulation job descriptor */ + dsize = blob_encap_desc(&encapdesc, keymod_dma, keymodlen, + __pa(inpslotaddr), __pa(outslotaddr), + secretlen, 0); + if (!dsize) { + dev_err(dev, "can't alloc an encap descriptor\n"); + retval = -ENOMEM; + goto out; + } + jstat = sm_key_job(dev, encapdesc); + + dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); + kfree(encapdesc); + +out: + return retval; + +} +EXPORT_SYMBOL(sm_keystore_slot_encapsulate); + +int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, u32 inslot, + u32 outslot, u16 secretlen, u8 *keymod, + u16 keymodlen) +{ + struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); + int retval = 0; + u32 slot_length, dsize, jstat; + u32 __iomem *decapdesc = NULL; + u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr; + dma_addr_t keymod_dma; + + /* Ensure that the decap data will fit in the key slot */ + slot_length = smpriv->slot_get_slot_size(dev, unit, outslot); + if (secretlen > slot_length) + goto out; + + /* Get the base addresses of both keystore slots */ + inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot); + outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot); + + /* Build the key modifier */ + lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA); + memcpy(lkeymod, keymod, keymodlen); + keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE); + dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); + + /* Build the decapsulation job descriptor */ + dsize = blob_decap_desc(&decapdesc, keymod_dma, keymodlen, + __pa(inpslotaddr), __pa(outslotaddr), + secretlen, 0); + if (!dsize) { + dev_err(dev, "can't alloc a decap descriptor\n"); + retval = -ENOMEM; + goto out; + } + jstat = sm_key_job(dev, decapdesc); + + dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); + kfree(decapdesc); + +out: + return retval; + +} +EXPORT_SYMBOL(sm_keystore_slot_decapsulate); + + +/* + * Initialization/shutdown subsystem + * Assumes statically-invoked startup/shutdown from the controller driver + * for the present time, to be reworked when a device tree becomes + * available. This code will not modularize in present form. + * + * Also, simply uses ring 0 for execution at the present + */ + +int caam_sm_startup(struct platform_device *pdev) +{ + struct device *ctrldev, *smdev; + struct caam_drv_private *ctrlpriv; + struct caam_drv_private_sm *smpriv; + struct caam_drv_private_jr *jrpriv; /* need this for reg page */ + struct platform_device *sm_pdev; + struct sm_page_descriptor *lpagedesc; + u32 page, pgstat, lpagect, detectedpage; + + ctrldev = &pdev->dev; + ctrlpriv = dev_get_drvdata(ctrldev); + + /* + * Set up the private block for secure memory + * Only one instance is possible + */ + smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL); + if (smpriv == NULL) { + dev_err(ctrldev, "can't alloc private mem for secure memory\n"); + return -ENOMEM; + } + smpriv->parentdev = ctrldev; /* copy of parent dev is handy */ + + /* Create the dev */ +#ifdef CONFIG_OF + sm_pdev = of_platform_device_create(np, NULL, ctrldev); +#else + sm_pdev = platform_device_register_data(ctrldev, "caam_sm", 0, + smpriv, + sizeof(struct caam_drv_private_sm)); +#endif + if (sm_pdev == NULL) { + kfree(smpriv); + return -EINVAL; + } + smdev = &sm_pdev->dev; + dev_set_drvdata(smdev, smpriv); + ctrlpriv->smdev = smdev; + + /* + * Collect configuration limit data for reference + * This batch comes from the partition data/vid registers in perfmon + */ + smpriv->max_pages = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) + & SMPART_MAX_NUMPG_MASK) >> + SMPART_MAX_NUMPG_SHIFT) + 1; + smpriv->top_partition = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) + & SMPART_MAX_PNUM_MASK) >> + SMPART_MAX_PNUM_SHIFT) + 1; + smpriv->top_page = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) + & SMPART_MAX_PG_MASK) >> SMPART_MAX_PG_SHIFT) + 1; + smpriv->page_size = 1024 << ((rd_reg32(&ctrlpriv->ctrl->perfmon.smvid) + & SMVID_PG_SIZE_MASK) >> SMVID_PG_SIZE_SHIFT); + smpriv->slot_size = 1 << CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE; + +#ifdef SM_DEBUG + dev_info(smdev, "max pages = %d, top partition = %d\n", + smpriv->max_pages, smpriv->top_partition); + dev_info(smdev, "top page = %d, page size = %d (total = %d)\n", + smpriv->top_page, smpriv->page_size, + smpriv->top_page * smpriv->page_size); + dev_info(smdev, "selected slot size = %d\n", smpriv->slot_size); +#endif + + /* + * Now probe for partitions/pages to which we have access. Note that + * these have likely been set up by a bootloader or platform + * provisioning application, so we have to assume that we "inherit" + * a configuration and work within the constraints of what it might be. + * + * Assume use of the zeroth ring in the present iteration (until + * we can divorce the controller and ring drivers, and then assign + * an SM instance to any ring instance). + */ + smpriv->smringdev = ctrlpriv->jrdev[0]; + jrpriv = dev_get_drvdata(smpriv->smringdev); + lpagect = 0; + lpagedesc = kzalloc(sizeof(struct sm_page_descriptor) + * smpriv->max_pages, GFP_KERNEL); + if (lpagedesc == NULL) { + kfree(smpriv); + return -ENOMEM; + } + + for (page = 0; page < smpriv->max_pages; page++) { + wr_reg32(&jrpriv->rregs->sm_cmd, + ((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) | + (SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK)); + pgstat = rd_reg32(&jrpriv->rregs->sm_status); + if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT) + == SMCS_PGOWN_OWNED) { /* our page? */ + lpagedesc[page].phys_pagenum = + (pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT; + lpagedesc[page].own_part = + (pgstat & SMCS_PART_SHIFT) >> SMCS_PART_MASK; + lpagedesc[page].pg_base = ctrlpriv->sm_base + + ((smpriv->page_size * page) / sizeof(u32)); + lpagect++; +#ifdef SM_DEBUG + dev_info(smdev, + "physical page %d, owning partition = %d\n", + lpagedesc[page].phys_pagenum, + lpagedesc[page].own_part); +#endif + } + } + + smpriv->pagedesc = kmalloc(sizeof(struct sm_page_descriptor) * lpagect, + GFP_KERNEL); + if (smpriv->pagedesc == NULL) { + kfree(lpagedesc); + kfree(smpriv); + return -ENOMEM; + } + smpriv->localpages = lpagect; + + detectedpage = 0; + for (page = 0; page < smpriv->max_pages; page++) { + if (lpagedesc[page].pg_base != NULL) { /* e.g. live entry */ + memcpy(&smpriv->pagedesc[detectedpage], + &lpagedesc[page], + sizeof(struct sm_page_descriptor)); +#ifdef SM_DEBUG_CONT + sm_show_page(smdev, &smpriv->pagedesc[detectedpage]); +#endif + detectedpage++; + } + } + + kfree(lpagedesc); + + sm_init_keystore(smdev); + + return 0; +} + +void caam_sm_shutdown(struct platform_device *pdev) +{ + struct device *ctrldev, *smdev; + struct caam_drv_private *priv; + struct caam_drv_private_sm *smpriv; + + ctrldev = &pdev->dev; + priv = dev_get_drvdata(ctrldev); + smdev = priv->smdev; + smpriv = dev_get_drvdata(smdev); + + kfree(smpriv->pagedesc); + kfree(smpriv); +} + +#ifdef CONFIG_OF +static void __exit caam_sm_exit(void) +{ + struct device_node *dev_node; + struct platform_device *pdev; + + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) { + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); + if (!dev_node) + return -ENODEV; + } + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return -ENODEV; + + of_node_put(dev_node); + + caam_sm_shutdown(pdev); +} + +static int __init caam_sm_init(void) +{ + struct device_node *dev_node; + struct platform_device *pdev; + + /* + * Do of_find_compatible_node() then of_find_device_by_node() + * once a functional device tree is available + */ + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); + if (!dev_node) { + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); + if (!dev_node) + return -ENODEV; + } + + pdev = of_find_device_by_node(dev_node); + if (!pdev) + return -ENODEV; + + of_node_put(dev_node); + + return caam_sm_startup(pdev); +} + +module_init(caam_sm_init); +module_exit(caam_sm_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("FSL CAAM Secure Memory / Keystore"); +MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); +#endif diff --git a/drivers/crypto/caam/sm_test.c b/drivers/crypto/caam/sm_test.c new file mode 100644 index 000000000000..1e00b61584fc --- /dev/null +++ b/drivers/crypto/caam/sm_test.c @@ -0,0 +1,796 @@ + +/* + * Secure Memory / Keystore Exemplification Module + * Copyright (c) 2012 Freescale Semiconductor. All Rights Reserved + * + * Serves as a functional example, and as a self-contained unit test for + * the functionality contained in sm_store.c. + * + * The example function, caam_sm_example_init(), runs a thread that: + * + * - initializes a set of fixed keys + * - stores one copy in clear buffers + * - stores them again in secure memory + * - extracts stored keys back out for use + * - intializes 3 data buffers for a test: + * (1) containing cleartext + * (2) to hold ciphertext encrypted with an extracted black key + * (3) to hold extracted cleartext decrypted with an equivalent clear key + * + * The function then builds simple job descriptors that reference the key + * material and buffers as initialized, and executes an encryption job + * with a black key, and a decryption job using a the same key held in the + * clear. The output of the decryption job is compared to the original + * cleartext; if they don't compare correctly, one can assume a key problem + * exists, where the function will exit with an error. + * + * This module can use a substantial amount of refactoring, which may occur + * after the API gets some mileage. Furthermore, expect this module to + * eventually disappear once the API is integrated into "real" software. + */ + +#include "compat.h" +#include "intern.h" +#include "desc.h" +#include "error.h" +#include "jr.h" +#include "sm.h" + +static u8 skeymod[] = { + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 +}; +static u8 symkey[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f +}; + +static u8 symdata[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x0f, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +static int mk_job_desc(u32 *desc, dma_addr_t key, u16 keysz, dma_addr_t indata, + dma_addr_t outdata, u16 sz, u32 cipherdir, u32 keymode) +{ + desc[1] = CMD_KEY | CLASS_1 | (keysz & KEY_LENGTH_MASK) | keymode; + desc[2] = (u32)key; + desc[3] = CMD_OPERATION | OP_TYPE_CLASS1_ALG | OP_ALG_AAI_ECB | + cipherdir; + desc[4] = CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | + FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1 | sz; + desc[5] = (u32)indata; + desc[6] = CMD_FIFO_STORE | FIFOST_TYPE_MESSAGE_DATA | sz; + desc[7] = (u32)outdata; + + desc[0] = CMD_DESC_HDR | HDR_ONE | (8 & HDR_DESCLEN_MASK); + return 8 * sizeof(u32); +} + +struct exec_test_result { + int error; + struct completion completion; +}; + +void exec_test_done(struct device *dev, u32 *desc, u32 err, void *context) +{ + struct exec_test_result *res = context; + + if (err) { + char tmp[CAAM_ERROR_STR_MAX]; + dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); + } + + res->error = err; + complete(&res->completion); +} + +static int exec_test_job(struct device *ksdev, u32 *jobdesc) +{ + struct exec_test_result testres; + struct caam_drv_private_sm *kspriv; + int rtn = 0; + + kspriv = dev_get_drvdata(ksdev); + + init_completion(&testres.completion); + + rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, exec_test_done, + &testres); + if (!rtn) { + wait_for_completion_interruptible(&testres.completion); + rtn = testres.error; + } + return rtn; +} + + +int caam_sm_example_init(struct platform_device *pdev) +{ + struct device *ctrldev, *ksdev; + struct caam_drv_private *ctrlpriv; + struct caam_drv_private_sm *kspriv; + u32 unit, units, jdescsz; + int stat, jstat, rtnval = 0; + u8 __iomem *syminp, *symint, *symout = NULL; + dma_addr_t syminp_dma, symint_dma, symout_dma; + u8 __iomem *black_key_des, *black_key_aes128; + u8 __iomem *black_key_aes256; + dma_addr_t black_key_des_dma, black_key_aes128_dma; + dma_addr_t black_key_aes256_dma; + u8 __iomem *clear_key_des, *clear_key_aes128, *clear_key_aes256; + dma_addr_t clear_key_des_dma, clear_key_aes128_dma; + dma_addr_t clear_key_aes256_dma; + u32 __iomem *jdesc; + u32 keyslot_des, keyslot_aes128, keyslot_aes256 = 0; + + jdesc = NULL; + black_key_des = black_key_aes128 = black_key_aes256 = NULL; + clear_key_des = clear_key_aes128 = clear_key_aes256 = NULL; + + /* We can lose this cruft once we can get a pdev by name */ + ctrldev = &pdev->dev; + ctrlpriv = dev_get_drvdata(ctrldev); + ksdev = ctrlpriv->smdev; + kspriv = dev_get_drvdata(ksdev); + if (kspriv == NULL) + return -ENODEV; + + /* Now that we have the dev for the single SM instance, connect */ +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test_init() running\n"); +#endif + /* Probe to see what keystores are available to us */ + units = sm_detect_keystore_units(ksdev); + if (!units) + dev_err(ksdev, "caam_sm_test: no keystore units available\n"); + + /* + * MX6 bootloader stores some stuff in unit 0, so let's + * use 1 or above + */ + if (units < 2) { + dev_err(ksdev, "caam_sm_test: insufficient keystore units\n"); + return -ENODEV; + } + unit = 1; + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: %d keystore units available\n", units); +#endif + + /* Initialize/Establish Keystore */ + sm_establish_keystore(ksdev, unit); /* Initalize store in #1 */ + + /* + * Top of main test thread + */ + + /* Allocate test data blocks (input, intermediate, output) */ + syminp = kmalloc(256, GFP_KERNEL | GFP_DMA); + symint = kmalloc(256, GFP_KERNEL | GFP_DMA); + symout = kmalloc(256, GFP_KERNEL | GFP_DMA); + if ((syminp == NULL) || (symint == NULL) || (symout == NULL)) { + rtnval = -ENOMEM; + dev_err(ksdev, "caam_sm_test: can't get test data buffers\n"); + goto freemem; + } + + /* Allocate storage for 3 black keys: encapsulated 8, 16, 32 */ + black_key_des = kmalloc(16, GFP_KERNEL | GFP_DMA); /* padded to 16... */ + black_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA); + black_key_aes256 = kmalloc(16, GFP_KERNEL | GFP_DMA); + if ((black_key_des == NULL) || (black_key_aes128 == NULL) || + (black_key_aes256 == NULL)) { + rtnval = -ENOMEM; + dev_err(ksdev, "caam_sm_test: can't black key buffers\n"); + goto freemem; + } + + clear_key_des = kmalloc(8, GFP_KERNEL | GFP_DMA); + clear_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA); + clear_key_aes256 = kmalloc(32, GFP_KERNEL | GFP_DMA); + if ((clear_key_des == NULL) || (clear_key_aes128 == NULL) || + (clear_key_aes256 == NULL)) { + rtnval = -ENOMEM; + dev_err(ksdev, "caam_sm_test: can't get clear key buffers\n"); + goto freemem; + } + + /* Allocate storage for job descriptor */ + jdesc = kmalloc(8 * sizeof(u32), GFP_KERNEL | GFP_DMA); + if (jdesc == NULL) { + rtnval = -ENOMEM; + dev_err(ksdev, "caam_sm_test: can't get descriptor buffers\n"); + goto freemem; + } + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: all buffers allocated\n"); +#endif + + /* Load up input data block, clear outputs */ + memcpy(syminp, symdata, 256); + memset(symint, 0, 256); + memset(symout, 0, 256); +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + syminp[0], syminp[1], syminp[2], syminp[3], + syminp[4], syminp[5], syminp[6], syminp[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[0], symint[1], symint[2], symint[3], + symint[4], symint[5], symint[6], symint[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symout[0], symout[1], symout[2], symout[3], + symout[4], symout[5], symout[6], symout[7]); + + dev_info(ksdev, "caam_sm_test: data buffers initialized\n"); +#endif + + /* Load up clear keys */ + memcpy(clear_key_des, symkey, 8); + memcpy(clear_key_aes128, symkey, 16); + memcpy(clear_key_aes256, symkey, 32); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: all clear keys loaded\n"); +#endif + + /* + * Place clear keys in keystore. + * All the interesting stuff happens here. + */ + /* 8 bit DES key */ + stat = sm_keystore_slot_alloc(ksdev, unit, 8, &keyslot_des); + if (stat) + goto freemem; +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: 8 byte key slot in %d\n" keyslot_des); +#endif + stat = sm_keystore_slot_load(ksdev, unit, keyslot_des, clear_key_des, + 8); + if (stat) { +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: can't load 8 byte key in %d\n", + keyslot_des); +#endif + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); + goto freemem; + } + + /* 16 bit AES key */ + stat = sm_keystore_slot_alloc(ksdev, unit, 16, &keyslot_aes128); + if (stat) { + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); + goto freemem; + } +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: 16 byte key slot in %d\n", + keyslot_aes128); +#endif + stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes128, + clear_key_aes128, 16); + if (stat) { +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: can't load 16 byte key in %d\n", + keyslot_aes128); +#endif + sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); + goto freemem; + } + + /* 32 bit AES key */ + stat = sm_keystore_slot_alloc(ksdev, unit, 32, &keyslot_aes256); + if (stat) { + sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); + goto freemem; + } +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: 32 byte key slot in %d\n", + keyslot_aes256); +#endif + stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes256, + clear_key_aes256, 32); + if (stat) { +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: can't load 32 byte key in %d\n", + keyslot_aes128); +#endif + sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256); + sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); + sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); + goto freemem; + } + + /* Encapsulate all keys as SM blobs */ + stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_des, + keyslot_des, 8, skeymod, 8); + if (stat) { + dev_info(ksdev, "caam_sm_test: can't encapsulate DES key\n"); + goto freekeys; + } + + stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes128, + keyslot_aes128, 16, skeymod, 8); + if (stat) { + dev_info(ksdev, "caam_sm_test: can't encapsulate AES128 key\n"); + goto freekeys; + } + + stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes256, + keyslot_aes256, 32, skeymod, 8); + if (stat) { + dev_info(ksdev, "caam_sm_test: can't encapsulate AES256 key\n"); + goto freekeys; + } + + /* Now decapsulate as black key blobs */ + stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_des, + keyslot_des, 8, skeymod, 8); + if (stat) { + dev_info(ksdev, "caam_sm_test: can't decapsulate DES key\n"); + goto freekeys; + } + + stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes128, + keyslot_aes128, 16, skeymod, 8); + if (stat) { + dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n"); + goto freekeys; + } + + stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes256, + keyslot_aes256, 32, skeymod, 8); + if (stat) { + dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n"); + goto freekeys; + } + + /* Extract 8/16/32 byte black keys */ + sm_keystore_slot_read(ksdev, unit, keyslot_des, 8, black_key_des); + sm_keystore_slot_read(ksdev, unit, keyslot_aes128, 16, + black_key_aes128); + sm_keystore_slot_read(ksdev, unit, keyslot_aes256, 32, + black_key_aes256); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: all black keys extracted\n"); +#endif + + /* DES encrypt using 8 byte black key */ + black_key_des_dma = dma_map_single(ksdev, black_key_des, 8, + DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE); + syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); + symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); + + jdescsz = mk_job_desc(jdesc, black_key_des_dma, 8, syminp_dma, + symint_dma, 256, + OP_ALG_ENCRYPT | OP_ALG_ALGSEL_DES, 0); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "jobdesc:\n"); + dev_info(ksdev, "0x%08x\n", jdesc[0]); + dev_info(ksdev, "0x%08x\n", jdesc[1]); + dev_info(ksdev, "0x%08x\n", jdesc[2]); + dev_info(ksdev, "0x%08x\n", jdesc[3]); + dev_info(ksdev, "0x%08x\n", jdesc[4]); + dev_info(ksdev, "0x%08x\n", jdesc[5]); + dev_info(ksdev, "0x%08x\n", jdesc[6]); + dev_info(ksdev, "0x%08x\n", jdesc[7]); +#endif + + jstat = exec_test_job(ksdev, jdesc); + + dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); + dma_unmap_single(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "input block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + syminp[0], syminp[1], syminp[2], syminp[3], + syminp[4], syminp[5], syminp[6], syminp[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + syminp[8], syminp[9], syminp[10], syminp[11], + syminp[12], syminp[13], syminp[14], syminp[15]); + dev_info(ksdev, "intermediate block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[0], symint[1], symint[2], symint[3], + symint[4], symint[5], symint[6], symint[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[8], symint[9], symint[10], symint[11], + symint[12], symint[13], symint[14], symint[15]); + dev_info(ksdev, "caam_sm_test: encrypt cycle with 8 byte key\n"); +#endif + + /* DES decrypt using 8 byte clear key */ + clear_key_des_dma = dma_map_single(ksdev, clear_key_des, 8, + DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE); + symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); + symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); + + jdescsz = mk_job_desc(jdesc, clear_key_des_dma, 8, symint_dma, + symout_dma, 256, + OP_ALG_DECRYPT | OP_ALG_ALGSEL_DES, 0); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "jobdesc:\n"); + dev_info(ksdev, "0x%08x\n", jdesc[0]); + dev_info(ksdev, "0x%08x\n", jdesc[1]); + dev_info(ksdev, "0x%08x\n", jdesc[2]); + dev_info(ksdev, "0x%08x\n", jdesc[3]); + dev_info(ksdev, "0x%08x\n", jdesc[4]); + dev_info(ksdev, "0x%08x\n", jdesc[5]); + dev_info(ksdev, "0x%08x\n", jdesc[6]); + dev_info(ksdev, "0x%08x\n", jdesc[7]); +#endif + + jstat = exec_test_job(ksdev, jdesc); + + dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); + dma_unmap_single(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "intermediate block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[0], symint[1], symint[2], symint[3], + symint[4], symint[5], symint[6], symint[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[8], symint[9], symint[10], symint[11], + symint[12], symint[13], symint[14], symint[15]); + dev_info(ksdev, "decrypted block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symout[0], symout[1], symout[2], symout[3], + symout[4], symout[5], symout[6], symout[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symout[8], symout[9], symout[10], symout[11], + symout[12], symout[13], symout[14], symout[15]); + dev_info(ksdev, "caam_sm_test: decrypt cycle with 8 byte key\n"); +#endif + + /* Check result */ + if (memcmp(symout, syminp, 256)) { + dev_info(ksdev, "caam_sm_test: 8-byte key test mismatch\n"); + rtnval = -1; + goto freekeys; + } else + dev_info(ksdev, "caam_sm_test: 8-byte key test match OK\n"); + + /* AES-128 encrypt using 16 byte black key */ + black_key_aes128_dma = dma_map_single(ksdev, black_key_aes128, 16, + DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, black_key_aes128_dma, 16, + DMA_TO_DEVICE); + syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); + symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); + + jdescsz = mk_job_desc(jdesc, black_key_aes128_dma, 16, syminp_dma, + symint_dma, 256, + OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "jobdesc:\n"); + dev_info(ksdev, "0x%08x\n", jdesc[0]); + dev_info(ksdev, "0x%08x\n", jdesc[1]); + dev_info(ksdev, "0x%08x\n", jdesc[2]); + dev_info(ksdev, "0x%08x\n", jdesc[3]); + dev_info(ksdev, "0x%08x\n", jdesc[4]); + dev_info(ksdev, "0x%08x\n", jdesc[5]); + dev_info(ksdev, "0x%08x\n", jdesc[6]); + dev_info(ksdev, "0x%08x\n", jdesc[7]); +#endif + + jstat = exec_test_job(ksdev, jdesc); + + dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); + dma_unmap_single(ksdev, black_key_aes128_dma, 16, DMA_TO_DEVICE); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "input block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + syminp[0], syminp[1], syminp[2], syminp[3], + syminp[4], syminp[5], syminp[6], syminp[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + syminp[8], syminp[9], syminp[10], syminp[11], + syminp[12], syminp[13], syminp[14], syminp[15]); + dev_info(ksdev, "intermediate block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[0], symint[1], symint[2], symint[3], + symint[4], symint[5], symint[6], symint[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[8], symint[9], symint[10], symint[11], + symint[12], symint[13], symint[14], symint[15]); + dev_info(ksdev, "caam_sm_test: encrypt cycle with 16 byte key\n"); +#endif + + /* AES-128 decrypt using 16 byte clear key */ + clear_key_aes128_dma = dma_map_single(ksdev, clear_key_aes128, 16, + DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, clear_key_aes128_dma, 16, + DMA_TO_DEVICE); + symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); + symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); + + jdescsz = mk_job_desc(jdesc, clear_key_aes128_dma, 16, symint_dma, + symout_dma, 256, + OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "jobdesc:\n"); + dev_info(ksdev, "0x%08x\n", jdesc[0]); + dev_info(ksdev, "0x%08x\n", jdesc[1]); + dev_info(ksdev, "0x%08x\n", jdesc[2]); + dev_info(ksdev, "0x%08x\n", jdesc[3]); + dev_info(ksdev, "0x%08x\n", jdesc[4]); + dev_info(ksdev, "0x%08x\n", jdesc[5]); + dev_info(ksdev, "0x%08x\n", jdesc[6]); + dev_info(ksdev, "0x%08x\n", jdesc[7]); +#endif + jstat = exec_test_job(ksdev, jdesc); + + dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); + dma_unmap_single(ksdev, clear_key_aes128_dma, 16, DMA_TO_DEVICE); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "intermediate block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[0], symint[1], symint[2], symint[3], + symint[4], symint[5], symint[6], symint[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[8], symint[9], symint[10], symint[11], + symint[12], symint[13], symint[14], symint[15]); + dev_info(ksdev, "decrypted block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symout[0], symout[1], symout[2], symout[3], + symout[4], symout[5], symout[6], symout[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symout[8], symout[9], symout[10], symout[11], + symout[12], symout[13], symout[14], symout[15]); + dev_info(ksdev, "caam_sm_test: decrypt cycle with 16 byte key\n"); +#endif + + /* Check result */ + if (memcmp(symout, syminp, 256)) { + dev_info(ksdev, "caam_sm_test: 16-byte key test mismatch\n"); + rtnval = -1; + goto freekeys; + } else + dev_info(ksdev, "caam_sm_test: 16-byte key test match OK\n"); + + /* AES-256 encrypt using 32 byte black key */ + black_key_aes256_dma = dma_map_single(ksdev, black_key_aes256, 32, + DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, black_key_aes256_dma, 32, + DMA_TO_DEVICE); + syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); + symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); + + jdescsz = mk_job_desc(jdesc, black_key_aes256_dma, 32, syminp_dma, + symint_dma, 256, + OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "jobdesc:\n"); + dev_info(ksdev, "0x%08x\n", jdesc[0]); + dev_info(ksdev, "0x%08x\n", jdesc[1]); + dev_info(ksdev, "0x%08x\n", jdesc[2]); + dev_info(ksdev, "0x%08x\n", jdesc[3]); + dev_info(ksdev, "0x%08x\n", jdesc[4]); + dev_info(ksdev, "0x%08x\n", jdesc[5]); + dev_info(ksdev, "0x%08x\n", jdesc[6]); + dev_info(ksdev, "0x%08x\n", jdesc[7]); +#endif + + jstat = exec_test_job(ksdev, jdesc); + + dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); + dma_unmap_single(ksdev, black_key_aes256_dma, 32, DMA_TO_DEVICE); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "input block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + syminp[0], syminp[1], syminp[2], syminp[3], + syminp[4], syminp[5], syminp[6], syminp[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + syminp[8], syminp[9], syminp[10], syminp[11], + syminp[12], syminp[13], syminp[14], syminp[15]); + dev_info(ksdev, "intermediate block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[0], symint[1], symint[2], symint[3], + symint[4], symint[5], symint[6], symint[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[8], symint[9], symint[10], symint[11], + symint[12], symint[13], symint[14], symint[15]); + dev_info(ksdev, "caam_sm_test: encrypt cycle with 32 byte key\n"); +#endif + + /* AES-256 decrypt using 32-byte black key */ + clear_key_aes256_dma = dma_map_single(ksdev, clear_key_aes256, 32, + DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, clear_key_aes256_dma, 32, + DMA_TO_DEVICE); + symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); + dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); + symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); + + jdescsz = mk_job_desc(jdesc, clear_key_aes256_dma, 32, symint_dma, + symout_dma, 256, + OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "jobdesc:\n"); + dev_info(ksdev, "0x%08x\n", jdesc[0]); + dev_info(ksdev, "0x%08x\n", jdesc[1]); + dev_info(ksdev, "0x%08x\n", jdesc[2]); + dev_info(ksdev, "0x%08x\n", jdesc[3]); + dev_info(ksdev, "0x%08x\n", jdesc[4]); + dev_info(ksdev, "0x%08x\n", jdesc[5]); + dev_info(ksdev, "0x%08x\n", jdesc[6]); + dev_info(ksdev, "0x%08x\n", jdesc[7]); +#endif + + jstat = exec_test_job(ksdev, jdesc); + + dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); + dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); + dma_unmap_single(ksdev, clear_key_aes256_dma, 32, DMA_TO_DEVICE); + +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "intermediate block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[0], symint[1], symint[2], symint[3], + symint[4], symint[5], symint[6], symint[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symint[8], symint[9], symint[10], symint[11], + symint[12], symint[13], symint[14], symint[15]); + dev_info(ksdev, "decrypted block:\n"); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symout[0], symout[1], symout[2], symout[3], + symout[4], symout[5], symout[6], symout[7]); + dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ + "0x%02x 0x%02x 0x%02x 0x%02x\n", + symout[8], symout[9], symout[10], symout[11], + symout[12], symout[13], symout[14], symout[15]); + dev_info(ksdev, "caam_sm_test: decrypt cycle with 32 byte key\n"); +#endif + + /* Check result */ + if (memcmp(symout, syminp, 256)) { + dev_info(ksdev, "caam_sm_test: 32-byte key test mismatch\n"); + rtnval = -1; + goto freekeys; + } else + dev_info(ksdev, "caam_sm_test: 32-byte key test match OK\n"); + + + /* Remove 8/16/32 byte keys from keystore */ +freekeys: + stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); + if (stat) + dev_info(ksdev, "caam_sm_test: can't release slot %d\n", + keyslot_des); + + stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); + if (stat) + dev_info(ksdev, "caam_sm_test: can't release slot %d\n", + keyslot_aes128); + + stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256); + if (stat) + dev_info(ksdev, "caam_sm_test: can't release slot %d\n", + keyslot_aes256); + + + /* Free resources */ +freemem: +#ifdef SM_TEST_DETAIL + dev_info(ksdev, "caam_sm_test: cleaning up\n"); +#endif + kfree(syminp); + kfree(symint); + kfree(symout); + kfree(clear_key_des); + kfree(clear_key_aes128); + kfree(clear_key_aes256); + kfree(black_key_des); + kfree(black_key_aes128); + kfree(black_key_aes256); + kfree(jdesc); + + /* Disconnect from keystore and leave */ + sm_release_keystore(ksdev, unit); + + return rtnval; +} + +void caam_sm_example_shutdown(void) +{ + /* unused in present version */ +} + +/* Module-based initialization needs to wait for dev tree */ +#ifdef CONFIG_OF +module_init(caam_sm_example_init); +module_exit(caam_sm_example_shutdown); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("FSL CAAM Keystore Usage Example"); +MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); +#endif diff --git a/drivers/crypto/caam/snvsregs.h b/drivers/crypto/caam/snvsregs.h new file mode 100644 index 000000000000..0ac415e2602b --- /dev/null +++ b/drivers/crypto/caam/snvsregs.h @@ -0,0 +1,237 @@ +/* + * SNVS hardware register-level view + * + * Copyright (c) 2012 Freescale Semiconductor, Inc., All Rights Reserved + */ + +#ifndef SNVSREGS_H +#define SNVSREGS_H + +#include +#include + +/* + * SNVS High Power Domain + * Includes security violations, HA counter, RTC, alarm + */ +struct snvs_hp { + u32 lock; + u32 cmd; + u32 ctl; + u32 secvio_int_en; /* Security Violation Interrupt Enable */ + u32 secvio_int_ctl; /* Security Violation Interrupt Control */ + u32 status; + u32 secvio_status; /* Security Violation Status */ + u32 ha_counteriv; /* High Assurance Counter IV */ + u32 ha_counter; /* High Assurance Counter */ + u32 rtc_msb; /* Real Time Clock/Counter MSB */ + u32 rtc_lsb; /* Real Time Counter LSB */ + u32 time_alarm_msb; /* Time Alarm MSB */ + u32 time_alarm_lsb; /* Time Alarm LSB */ +}; + +#define HP_LOCK_HAC_LCK 0x00040000 +#define HP_LOCK_HPSICR_LCK 0x00020000 +#define HP_LOCK_HPSVCR_LCK 0x00010000 +#define HP_LOCK_MKEYSEL_LCK 0x00000200 +#define HP_LOCK_TAMPCFG_LCK 0x00000100 +#define HP_LOCK_TAMPFLT_LCK 0x00000080 +#define HP_LOCK_SECVIO_LCK 0x00000040 +#define HP_LOCK_GENP_LCK 0x00000020 +#define HP_LOCK_MONOCTR_LCK 0x00000010 +#define HP_LOCK_CALIB_LCK 0x00000008 +#define HP_LOCK_SRTC_LCK 0x00000004 +#define HP_LOCK_ZMK_RD_LCK 0x00000002 +#define HP_LOCK_ZMK_WT_LCK 0x00000001 + +#define HP_CMD_NONPRIV_AXS 0x80000000 +#define HP_CMD_HAC_STOP 0x00080000 +#define HP_CMD_HAC_CLEAR 0x00040000 +#define HP_CMD_HAC_LOAD 0x00020000 +#define HP_CMD_HAC_CFG_EN 0x00010000 +#define HP_CMD_SNVS_MSTR_KEY 0x00002000 +#define HP_CMD_PROG_ZMK 0x00001000 +#define HP_CMD_SW_LPSV 0x00000400 +#define HP_CMD_SW_FSV 0x00000200 +#define HP_CMD_SW_SV 0x00000100 +#define HP_CMD_LP_SWR_DIS 0x00000020 +#define HP_CMD_LP_SWR 0x00000010 +#define HP_CMD_SSM_SFNS_DIS 0x00000004 +#define HP_CMD_SSM_ST_DIS 0x00000002 +#define HP_CMD_SMM_ST 0x00000001 + +#define HP_CTL_TIME_SYNC 0x00010000 +#define HP_CTL_CAL_VAL_SHIFT 10 +#define HP_CTL_CAL_VAL_MASK (0x1f << HP_CTL_CALIB_SHIFT) +#define HP_CTL_CALIB_EN 0x00000100 +#define HP_CTL_PI_FREQ_SHIFT 4 +#define HP_CTL_PI_FREQ_MASK (0xf << HP_CTL_PI_FREQ_SHIFT) +#define HP_CTL_PI_EN 0x00000008 +#define HP_CTL_TIMEALARM_EN 0x00000002 +#define HP_CTL_RTC_EN 0x00000001 + +#define HP_SECVIO_INTEN_EN 0x10000000 +#define HP_SECVIO_INTEN_SRC5 0x00000020 +#define HP_SECVIO_INTEN_SRC4 0x00000010 +#define HP_SECVIO_INTEN_SRC3 0x00000008 +#define HP_SECVIO_INTEN_SRC2 0x00000004 +#define HP_SECVIO_INTEN_SRC1 0x00000002 +#define HP_SECVIO_INTEN_SRC0 0x00000001 +#define HP_SECVIO_INTEN_ALL 0x8000003f + +#define HP_SECVIO_ICTL_CFG_SHIFT 30 +#define HP_SECVIO_ICTL_CFG_MASK (0x3 << HP_SECVIO_ICTL_CFG_SHIFT) +#define HP_SECVIO_ICTL_CFG5_SHIFT 5 +#define HP_SECVIO_ICTL_CFG5_MASK (0x3 << HP_SECVIO_ICTL_CFG5_SHIFT) +#define HP_SECVIO_ICTL_CFG_DISABLE 0 +#define HP_SECVIO_ICTL_CFG_NONFATAL 1 +#define HP_SECVIO_ICTL_CFG_FATAL 2 +#define HP_SECVIO_ICTL_CFG4_FATAL 0x00000010 +#define HP_SECVIO_ICTL_CFG3_FATAL 0x00000008 +#define HP_SECVIO_ICTL_CFG2_FATAL 0x00000004 +#define HP_SECVIO_ICTL_CFG1_FATAL 0x00000002 +#define HP_SECVIO_ICTL_CFG0_FATAL 0x00000001 + +#define HP_STATUS_ZMK_ZERO 0x80000000 +#define HP_STATUS_OTPMK_ZERO 0x08000000 +#define HP_STATUS_OTPMK_SYN_SHIFT 16 +#define HP_STATUS_OTPMK_SYN_MASK (0x1ff << HP_STATUS_OTPMK_SYN_SHIFT) +#define HP_STATUS_SSM_ST_SHIFT 8 +#define HP_STATUS_SSM_ST_MASK (0xf << HP_STATUS_SSM_ST_SHIFT) +#define HP_STATUS_SSM_ST_INIT 0 +#define HP_STATUS_SSM_ST_HARDFAIL 1 +#define HP_STATUS_SSM_ST_SOFTFAIL 3 +#define HP_STATUS_SSM_ST_INITINT 8 +#define HP_STATUS_SSM_ST_CHECK 9 +#define HP_STATUS_SSM_ST_NONSECURE 11 +#define HP_STATUS_SSM_ST_TRUSTED 13 +#define HP_STATUS_SSM_ST_SECURE 15 + +#define HP_SECVIOST_ZMK_ECC_FAIL 0x08000000 /* write to clear */ +#define HP_SECVIOST_ZMK_SYN_SHIFT 16 +#define HP_SECVIOST_ZMK_SYN_MASK (0x1ff << HP_SECVIOST_ZMK_SYN_SHIFT) +#define HP_SECVIOST_SECVIO5 0x00000020 +#define HP_SECVIOST_SECVIO4 0x00000010 +#define HP_SECVIOST_SECVIO3 0x00000008 +#define HP_SECVIOST_SECVIO2 0x00000004 +#define HP_SECVIOST_SECVIO1 0x00000002 +#define HP_SECVIOST_SECVIO0 0x00000001 +#define HP_SECVIOST_SECVIOMASK 0x0000003f + +/* + * SNVS Low Power Domain + * Includes glitch detector, SRTC, alarm, monotonic counter, ZMK + */ +struct snvs_lp { + u32 lock; + u32 ctl; + u32 mstr_key_ctl; /* Master Key Control */ + u32 secvio_ctl; /* Security Violation Control */ + u32 tamper_filt_cfg; /* Tamper Glitch Filters Configuration */ + u32 tamper_det_cfg; /* Tamper Detectors Configuration */ + u32 status; + u32 srtc_msb; /* Secure Real Time Clock/Counter MSB */ + u32 srtc_lsb; /* Secure Real Time Clock/Counter LSB */ + u32 time_alarm; /* Time Alarm */ + u32 smc_msb; /* Secure Monotonic Counter MSB */ + u32 smc_lsb; /* Secure Monotonic Counter LSB */ + u32 pwr_glitch_det; /* Power Glitch Detector */ + u32 gen_purpose; + u32 zmk[8]; /* Zeroizable Master Key */ +}; + +#define LP_LOCK_MKEYSEL_LCK 0x00000200 +#define LP_LOCK_TAMPDET_LCK 0x00000100 +#define LP_LOCK_TAMPFLT_LCK 0x00000080 +#define LP_LOCK_SECVIO_LCK 0x00000040 +#define LP_LOCK_GENP_LCK 0x00000020 +#define LP_LOCK_MONOCTR_LCK 0x00000010 +#define LP_LOCK_CALIB_LCK 0x00000008 +#define LP_LOCK_SRTC_LCK 0x00000004 +#define LP_LOCK_ZMK_RD_LCK 0x00000002 +#define LP_LOCK_ZMK_WT_LCK 0x00000001 + +#define LP_CTL_CAL_VAL_SHIFT 10 +#define LP_CTL_CAL_VAL_MASK (0x1f << LP_CTL_CAL_VAL_SHIFT) +#define LP_CTL_CALIB_EN 0x00000100 +#define LP_CTL_SRTC_INVAL_EN 0x00000010 +#define LP_CTL_WAKE_INT_EN 0x00000008 +#define LP_CTL_MONOCTR_EN 0x00000004 +#define LP_CTL_TIMEALARM_EN 0x00000002 +#define LP_CTL_SRTC_EN 0x00000001 + +#define LP_MKEYCTL_ZMKECC_SHIFT 8 +#define LP_MKEYCTL_ZMKECC_MASK (0xff << LP_MKEYCTL_ZMKECC_SHIFT) +#define LP_MKEYCTL_ZMKECC_EN 0x00000010 +#define LP_MKEYCTL_ZMKECC_VAL 0x00000008 +#define LP_MKEYCTL_ZMKECC_PROG 0x00000004 +#define LP_MKEYCTL_MKSEL_SHIFT 0 +#define LP_MKEYCTL_MKSEL_MASK (3 << LP_MKEYCTL_MKSEL_SHIFT) +#define LP_MKEYCTL_MK_OTP 0 +#define LP_MKEYCTL_MK_ZMK 2 +#define LP_MKEYCTL_MK_COMB 3 + +#define LP_SECVIO_CTL_SRC5 0x20 +#define LP_SECVIO_CTL_SRC4 0x10 +#define LP_SECVIO_CTL_SRC3 0x08 +#define LP_SECVIO_CTL_SRC2 0x04 +#define LP_SECVIO_CTL_SRC1 0x02 +#define LP_SECVIO_CTL_SRC0 0x01 + +#define LP_TAMPFILT_EXT2_EN 0x80000000 +#define LP_TAMPFILT_EXT2_SHIFT 24 +#define LP_TAMPFILT_EXT2_MASK (0x1f << LP_TAMPFILT_EXT2_SHIFT) +#define LP_TAMPFILT_EXT1_EN 0x00800000 +#define LP_TAMPFILT_EXT1_SHIFT 16 +#define LP_TAMPFILT_EXT1_MASK (0x1f << LP_TAMPFILT_EXT1_SHIFT) +#define LP_TAMPFILT_WM_EN 0x00000080 +#define LP_TAMPFILT_WM_SHIFT 0 +#define LP_TAMPFILT_WM_MASK (0x1f << LP_TAMPFILT_WM_SHIFT) + +#define LP_TAMPDET_OSC_BPS 0x10000000 +#define LP_TAMPDET_VRC_SHIFT 24 +#define LP_TAMPDET_VRC_MASK (3 << LP_TAMPFILT_VRC_SHIFT) +#define LP_TAMPDET_HTDC_SHIFT 20 +#define LP_TAMPDET_HTDC_MASK (3 << LP_TAMPFILT_HTDC_SHIFT) +#define LP_TAMPDET_LTDC_SHIFT 16 +#define LP_TAMPDET_LTDC_MASK (3 << LP_TAMPFILT_LTDC_SHIFT) +#define LP_TAMPDET_POR_OBS 0x00008000 +#define LP_TAMPDET_PFD_OBS 0x00004000 +#define LP_TAMPDET_ET2_EN 0x00000400 +#define LP_TAMPDET_ET1_EN 0x00000200 +#define LP_TAMPDET_WMT2_EN 0x00000100 +#define LP_TAMPDET_WMT1_EN 0x00000080 +#define LP_TAMPDET_VT_EN 0x00000040 +#define LP_TAMPDET_TT_EN 0x00000020 +#define LP_TAMPDET_CT_EN 0x00000010 +#define LP_TAMPDET_MCR_EN 0x00000004 +#define LP_TAMPDET_SRTCR_EN 0x00000002 + +#define LP_STATUS_SECURE +#define LP_STATUS_NONSECURE +#define LP_STATUS_SCANEXIT 0x00100000 /* all write 1 clear here on */ +#define LP_STATUS_EXT_SECVIO 0x00010000 +#define LP_STATUS_ET2 0x00000400 +#define LP_STATUS_ET1 0x00000200 +#define LP_STATUS_WMT2 0x00000100 +#define LP_STATUS_WMT1 0x00000080 +#define LP_STATUS_VTD 0x00000040 +#define LP_STATUS_TTD 0x00000020 +#define LP_STATUS_CTD 0x00000010 +#define LP_STATUS_PGD 0x00000008 +#define LP_STATUS_MCR 0x00000004 +#define LP_STATUS_SRTCR 0x00000002 +#define LP_STATUS_LPTA 0x00000001 + +/* Full SNVS register page, including version/options */ +struct snvs_full { + struct snvs_hp hp; + struct snvs_lp lp; + u32 rsvd[731]; /* deadspace 0x08c-0xbf7 */ + + /* Version / Revision / Option ID space - end of register page */ + u32 vid; /* 0xbf8 HP Version ID (VID 1) */ + u32 opt_rev; /* 0xbfc HP Options / Revision (VID 2) */ +}; + +#endif /* SNVSREGS_H */ -- cgit v1.2.3 From 3498f76a6b94cc54d9b116d419de64245be6ab2b Mon Sep 17 00:00:00 2001 From: Jason Jin Date: Tue, 11 Dec 2012 18:43:15 +0800 Subject: Default configuration update for CAAM driver manually integrate from the CAAM part by Jason Signed-off-by: Jason Jin --- arch/arm/configs/mvf600_defconfig | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/arch/arm/configs/mvf600_defconfig b/arch/arm/configs/mvf600_defconfig index 510f87d8a409..648e8f5e4d13 100644 --- a/arch/arm/configs/mvf600_defconfig +++ b/arch/arm/configs/mvf600_defconfig @@ -1810,25 +1810,28 @@ CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_PCOMP2=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set CONFIG_CRYPTO_WORKQUEUE=y # CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_TEST=m -# CONFIG_CRYPTO_CRYPTODEV is not set +CONFIG_CRYPTO_CRYPTODEV=y # # Authenticated Encryption with Associated Data @@ -1840,10 +1843,10 @@ CONFIG_CRYPTO_TEST=m # # Block modes # -CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CBC is not set # CONFIG_CRYPTO_CTR is not set # CONFIG_CRYPTO_CTS is not set -CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_ECB is not set # CONFIG_CRYPTO_LRW is not set # CONFIG_CRYPTO_PCBC is not set # CONFIG_CRYPTO_XTS is not set @@ -1862,7 +1865,7 @@ CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set -CONFIG_CRYPTO_MICHAEL_MIC=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_RMD128 is not set # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_RMD256 is not set @@ -1878,7 +1881,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANUBIS is not set -CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set @@ -1902,10 +1905,24 @@ CONFIG_CRYPTO_LZO=y # # Random Number Generation # -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_USER_API_HASH is not set -# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC=y +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD=255 +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=2048 +CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y +# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST is not set +CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE=7 +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y +CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y # CONFIG_BINARY_PRINTF is not set # -- cgit v1.2.3 From c3a8aceebb13cbc4d50bd8a3a781f4ec9ef14951 Mon Sep 17 00:00:00 2001 From: Justin Waters Date: Wed, 19 Sep 2012 14:11:53 -0400 Subject: fsl_nfc: Add default partitioning Allows the NAND to properly probe if cmdline partitioning is not specified. Otherwise, it will fail silently. --- drivers/mtd/nand/fsl_nfc.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/fsl_nfc.c b/drivers/mtd/nand/fsl_nfc.c index 58f590d6f64e..f84c785e4383 100644 --- a/drivers/mtd/nand/fsl_nfc.c +++ b/drivers/mtd/nand/fsl_nfc.c @@ -934,20 +934,11 @@ fsl_nfc_probe(struct platform_device *pdev) /* Register device in MTD */ retval = parse_mtd_partitions(mtd, fsl_nfc_pprobes, &parts, 0); - if (retval < 0) { - printk(KERN_ERR DRV_NAME ": Error parsing MTD partitions!\n"); - free_irq(prv->irq, mtd); - retval = -EINVAL; - goto error; - } - - printk(KERN_DEBUG "parse partition: partnr = %d\n", retval); - - retval = mtd_device_register(mtd, parts, retval); - if (retval) { - printk(KERN_ERR DRV_NAME ": Error adding MTD device!\n"); - free_irq(prv->irq, mtd); - goto error; + if (retval > 0) + mtd_device_register(mtd, parts, retval); + else { + pr_info("Registering %s as whole device\n", mtd->name); + mtd_device_register(mtd, NULL, 0); } return 0; -- cgit v1.2.3 From 9d7ee1114441401aee095ca522d75ed530e2e894 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Tue, 27 Nov 2012 10:52:37 -0800 Subject: Initial phyCORE-Vybrid changes Signed-off-by: Russell Robinson Jr --- arch/arm/configs/pcm052_defconfig | 1961 ++++++++++++++++++++++++++ arch/arm/mach-mvf/Kconfig | 33 + arch/arm/mach-mvf/Makefile | 1 + arch/arm/mach-mvf/board-pcm052.c | 564 ++++++++ arch/arm/mach-mvf/clock.c | 36 +- arch/arm/plat-mxc/devices/platform-imx-i2c.c | 3 + arch/arm/plat-mxc/include/mach/iomux-mvf.h | 56 +- arch/arm/plat-mxc/include/mach/iomux-v3.h | 3 +- arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h | 2 +- arch/arm/tools/mach-types | 1 + drivers/video/mvf_dcu.c | 36 +- 11 files changed, 2663 insertions(+), 33 deletions(-) create mode 100644 arch/arm/configs/pcm052_defconfig create mode 100644 arch/arm/mach-mvf/board-pcm052.c diff --git a/arch/arm/configs/pcm052_defconfig b/arch/arm/configs/pcm052_defconfig new file mode 100644 index 000000000000..2ba4cafb5815 --- /dev/null +++ b/arch/arm/configs/pcm052_defconfig @@ -0,0 +1,1961 @@ +# +# Automatically generated make config: don't edit +# Linux/arm 3.0.15 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_SCHED_CLOCK=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# CONFIG_OPROFILE is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +CONFIG_ARCH_MXC=y +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_NUC93X is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS4 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_TCC_926 is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +CONFIG_IMX_HAVE_PLATFORM_DMA=y +CONFIG_IMX_HAVE_PLATFORM_FEC=y +CONFIG_IMX_HAVE_PLATFORM_FLEXCAN=y +CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC=y +CONFIG_IMX_HAVE_PLATFORM_GPMI_NFC=y +CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT=y +CONFIG_IMX_HAVE_PLATFORM_IMX_SNVS_RTC=y +CONFIG_IMX_HAVE_PLATFORM_IMX_I2C=y +CONFIG_IMX_HAVE_PLATFORM_IMX_SSI=y +CONFIG_IMX_HAVE_PLATFORM_IMX_UART=y +CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI=y +CONFIG_IMX_HAVE_PLATFORM_MXC_NAND=y +CONFIG_IMX_HAVE_PLATFORM_MXC_PWM=y +CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX=y +CONFIG_IMX_HAVE_PLATFORM_IMX_IPUV3=y +CONFIG_IMX_HAVE_PLATFORM_IMX_VPU=y +CONFIG_IMX_HAVE_PLATFORM_AHCI=y +CONFIG_IMX_HAVE_PLATFORM_IMX_OCOTP=y +CONFIG_IMX_HAVE_PLATFORM_LDB=y +CONFIG_IMX_HAVE_PLATFORM_IMX_SPDIF=y +CONFIG_IMX_HAVE_PLATFORM_VIV_GPU=y +CONFIG_IMX_HAVE_PLATFORM_MXC_HDMI=y +CONFIG_IMX_HAVE_PLATFORM_FSL_OTG=y +CONFIG_IMX_HAVE_PLATFORM_FSL_USB_WAKEUP=y +CONFIG_IMX_HAVE_PLATFORM_IMX_PM=y +CONFIG_IMX_HAVE_PLATFORM_IMX_ASRC=y +CONFIG_IMX_HAVE_PLATFORM_MVF_SPI=y +CONFIG_IMX_HAVE_PLATFORM_MVF_DCU=y +CONFIG_IMX_HAVE_PLATFORM_MVF_SAI=y + +# +# Freescale MXC Implementations +# +# CONFIG_ARCH_MX1 is not set +# CONFIG_ARCH_MX2 is not set +# CONFIG_ARCH_MX25 is not set +# CONFIG_ARCH_MX3 is not set +# CONFIG_ARCH_MX503 is not set +# CONFIG_ARCH_MX51 is not set +# CONFIG_ARCH_MX6 is not set +CONFIG_ARCH_MVF=y +CONFIG_FORCE_MAX_ZONEORDER=13 +CONFIG_ARCH_MVFA5=y +CONFIG_SOC_MVFA5=y +# CONFIG_MACH_MVFA5_TWR_VF700 is not set +CONFIG_MACH_PCM052=y +CONFIG_ISP1504_MXC=y +# CONFIG_MXC_IRQ_PRIOR is not set +# CONFIG_MXC_PWM is not set +# CONFIG_MXC_DEBUG_BOARD is not set +CONFIG_HAVE_PIT=y +CONFIG_MXC_USE_PIT=y +CONFIG_ARCH_MXC_IOMUX_V3=y +CONFIG_ARCH_MXC_AUDMUX_V2=y +CONFIG_IRAM_ALLOC=y +CONFIG_DMA_ZONE_SIZE=16 + +# +# System MMU +# + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_SWP_EMULATE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_GIC=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_VMSPLIT_3G is not set +CONFIG_VMSPLIT_2G=y +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +# CONFIG_USE_OF is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs rw nfsroot=10.193.20.106:/tftpboot/10.193.20.115 ip=10.193.20.115:10.193.20.106:10.193.20.254:255.255.255.0::eth0:off console=ttymxc1,115200 mem=128M" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_SUSPEND is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_RUNTIME_CLK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_FSL_NFC=y +CONFIG_MTD_NAND_FSL_NFC_SWECC=y +# CONFIG_MTD_NAND_MXC is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_MII is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_NATIONAL8384x_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +CONFIG_MICREL_PHY=y +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_FEC=y +CONFIG_FEC1=y +# CONFIG_FEC_1588 is not set +# CONFIG_FTMAC100 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_WLAN=y +# CONFIG_USB_ZD1201 is not set +# CONFIG_HOSTAP is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WAN is not set + +# +# CAIF transport drivers +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +# CONFIG_TSDEV_COMPATIBLE is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_IMX is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_STMPE is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_MXC is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +CONFIG_TOUCHSCREEN_STMPE=y +# CONFIG_TOUCHSCREEN_P1003 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_CRTOUCH is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_ISL29023 is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_CONSOLE_TRANSLATIONS is not set +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_IMX=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_MVF_QSPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_IMX is not set +CONFIG_SPI_MVF=y +# CONFIG_SPI_MVF_DSPI_EDMA is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_BASIC_MMIO is not set +# CONFIG_GPIO_IT8761E is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_STMPE is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set +CONFIG_MFD_SUPPORT=y +CONFIG_MFD_CORE=y +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_TWL4030_CORE is not set +CONFIG_MFD_STMPE=y +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_PMIC_DIALOG is not set +# CONFIG_MFD_MC_PMIC is not set +# CONFIG_MFD_MC34708 is not set +# CONFIG_MFD_PFUZE is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_MAX17135 is not set +# CONFIG_MFD_MXC_HDMI is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +# CONFIG_FB_WMT_GE_ROPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_MVF_DCU=y +# CONFIG_MVF_DCU_BLANKING_TEST is not set +# CONFIG_FB_TMIO is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_FB_MXC_ELCDIF_FB is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_LOGO_TS_CLUT224=y +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +# CONFIG_SND_MIXER_OSS is not set +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +CONFIG_SND_SOC=y +# CONFIG_SND_SOC_CACHE_LZO is not set +# CONFIG_SND_IMX_SOC is not set +CONFIG_SND_MVF_SOC=y +CONFIG_SND_MVF_SOC_TWR=y +CONFIG_SND_SOC_MVF_SGTL5000=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_SGTL5000=y +# CONFIG_SOUND_PRIME is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ARC=y +CONFIG_USB_EHCI_ARC_OTG=y +# CONFIG_USB_STATIC_IRAM is not set +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_EHCI_MXC is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_ARC=y +CONFIG_USB_ARC=y +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_FUSB300 is not set +# CONFIG_USB_GADGET_R8A66597 is not set +# CONFIG_USB_GADGET_PXA_U2O is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_MXC_OTG is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_MXC is not set +# CONFIG_RTC_DRV_MXC_V2 is not set +CONFIG_RTC_DRV_SNVS=y +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_DW_DMAC is not set +CONFIG_MVF_EDMA=y +CONFIG_MVF_EDMA_TEST=m +# CONFIG_MXC_PXP is not set +# CONFIG_MXC_PXP_V2 is not set +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_MMIO=y + +# +# MXC support drivers +# +# CONFIG_MXC_IPU is not set + +# +# MXC SSI support +# +# CONFIG_MXC_SSI is not set + +# +# MXC Digital Audio Multiplexer support +# +# CONFIG_MXC_DAM is not set + +# +# MXC PMIC support +# +# CONFIG_MXC_PMIC_MC13783 is not set +# CONFIG_MXC_PMIC_MC13892 is not set +# CONFIG_MXC_PMIC_MC34704 is not set +# CONFIG_MXC_PMIC_MC9SDZ60 is not set +# CONFIG_MXC_PMIC_MC9S08DZ60 is not set + +# +# MXC Security Drivers +# +# CONFIG_MXC_SECURITY_SCC is not set +# CONFIG_MXC_SECURITY_RNG is not set + +# +# MXC MPEG4 Encoder Kernel module support +# +# CONFIG_MXC_HMP4E is not set + +# +# MXC HARDWARE EVENT +# +# CONFIG_MXC_HWEVENT is not set + +# +# MXC VPU(Video Processing Unit) support +# + +# +# MXC Asynchronous Sample Rate Converter support +# + +# +# MXC Bluetooth support +# + +# +# Broadcom GPS ioctrl support +# + +# +# MXC Media Local Bus Driver +# + +# +# i.MX ADC support +# +# CONFIG_IMX_ADC is not set + +# +# ANATOP_THERMAL +# + +# +# MXC MIPI Support +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_STACKTRACE=y +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_LKDTM is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_EVENT_POWER_TRACING_DEPRECATED=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_TEST=m +# CONFIG_CRYPTO_CRYPTODEV is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +CONFIG_CRYPTO_MICHAEL_MIC=y +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set diff --git a/arch/arm/mach-mvf/Kconfig b/arch/arm/mach-mvf/Kconfig index 931ef6af6dd4..0ef1f8a09d37 100644 --- a/arch/arm/mach-mvf/Kconfig +++ b/arch/arm/mach-mvf/Kconfig @@ -59,4 +59,37 @@ config MACH_MVFA5_TWR_VF700 Include support for MVF TWR-VF700 platform. This includes specific configurations for the board and its peripherals. +config MACH_PCM052 + bool "Support phyCORE-Vybrid (MVF Cortex-A5) platform" + select ARCH_MVFA5 + select SOC_MVFA5 + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_DMA + select IMX_HAVE_PLATFORM_FEC + select IMX_HAVE_PLATFORM_GPMI_NFC + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_VIV_GPU + select IMX_HAVE_PLATFORM_IMX_VPU + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_FSL_OTG + select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP + select IMX_HAVE_PLATFORM_AHCI + select IMX_HAVE_PLATFORM_IMX_OCOTP + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_SNVS_RTC + select IMX_HAVE_PLATFORM_IMX_PM + select IMX_HAVE_PLATFORM_MXC_HDMI + select IMX_HAVE_PLATFORM_IMX_ASRC + select IMX_HAVE_PLATFORM_FLEXCAN + select IMX_HAVE_PLATFORM_MVF_SPI + select IMX_HAVE_PLATFORM_MVF_DCU + select IMX_HAVE_PLATFORM_MVF_SAI + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for PHYTEC phyCORE-Vybrid platform. This includes + specific configurations for the board and its peripherals. + endif diff --git a/arch/arm/mach-mvf/Makefile b/arch/arm/mach-mvf/Makefile index e25fb28b7216..fad70a4a9dc7 100644 --- a/arch/arm/mach-mvf/Makefile +++ b/arch/arm/mach-mvf/Makefile @@ -8,3 +8,4 @@ obj-y += l2switch.o obj-$(CONFIG_ARCH_MVFA5) += clock.o mvf_suspend.o obj-$(CONFIG_MACH_MVFA5_TWR_VF700) += board-twr-vf700.o +obj-$(CONFIG_MACH_PCM052) += board-pcm052.o diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c new file mode 100644 index 000000000000..dc583b4a69f5 --- /dev/null +++ b/arch/arm/mach-mvf/board-pcm052.c @@ -0,0 +1,564 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "devices-mvf.h" +#include "usb.h" +#include "crm_regs.h" + +#define PCM052_SD1_CD 85 +#define PCM052_TS_IRQ 32 + +#ifdef PCM952_REV0 +#undef PCM952_REV0 +#endif + +static iomux_v3_cfg_t pcm052_pads[] = { + + /*SDHC1*/ + MVF600_PAD14_PTA24__SDHC1_CLK, + MVF600_PAD15_PTA25__SDHC1_CMD, + MVF600_PAD16_PTA26__SDHC1_DAT0, + MVF600_PAD17_PTA27__SDHC1_DAT1, + MVF600_PAD18_PTA28__SDHC1_DAT2, + MVF600_PAD19_PTA29__SDHC1_DAT3, + /*set PTD6 as GPIO for sdhc card detecting*/ + MVF600_PAD85_PTD6__SDHC1_SW_CD, + + /*I2C2*/ + MVF600_PAD12_PTA22__I2C2_SCL, + MVF600_PAD13_PTA23__I2C2_SDA, + + /*CAN0*/ + MVF600_PAD36_PTB14__CAN0_RX, + MVF600_PAD37_PTB15__CAN0_TX, + + /*CAN1*/ + MVF600_PAD38_PTB16__CAN1_RX, + MVF600_PAD39_PTB17__CAN1_TX, + + /*DSPI0*/ + MVF600_PAD41_PTB19__DSPI0_PCS0, + MVF600_PAD42_PTB20__DSPI0_SIN, + MVF600_PAD43_PTB21__DSPI0_SOUT, + MVF600_PAD44_PTB22__DSPI0_SCK, + + /*FEC0*/ + MVF600_PAD0_PTA6__RMII_CLKIN, + MVF600_PAD45_PTC0__RMII0_MDC, + MVF600_PAD46_PTC1__RMII0_MDIO, + MVF600_PAD47_PTC2__RMII0_CRS_DV, + MVF600_PAD48_PTC3__RMII0_RXD1, + MVF600_PAD49_PTC4__RMII0_RXD0, + MVF600_PAD50_PTC5__RMII0_RXER, + MVF600_PAD51_PTC6__RMII0_TXD1, + MVF600_PAD52_PTC7__RMII0_TXD0, + MVF600_PAD53_PTC8__RMII0_TXEN, + +#if defined(CONFIG_FEC1) || defined(CONFIG_FSL_L2_SWITCH) + /*FEC1*/ + MVF600_PAD54_PTC9__RMII1_MDC, + MVF600_PAD55_PTC10__RMII1_MDIO, + MVF600_PAD56_PTC11__RMII1_CRS_DV, + MVF600_PAD57_PTC12__RMII1_RXD1, + MVF600_PAD58_PTC13__RMII1_RXD0, + MVF600_PAD59_PTC14__RMII1_RXER, + MVF600_PAD60_PTC15__RMII1_TXD1, + MVF600_PAD61_PTC16__RMII1_TXD0, + MVF600_PAD62_PTC17__RMII1_TXEN, +#endif + + /*SAI2*/ +// MVF600_PAD6_PTA16_SAI2_TX_BCLK, + MVF600_PAD8_PTA18_SAI2_TX_DATA, +// MVF600_PAD3_PTA10_SAI2_TX_SYNC, // originally PAD9_PTA19 + MVF600_PAD11_PTA21_SAI2_RX_BCLK, +// MVF600_PAD23_PTB1_SAI2_RX_DATA, // originally PAD12_PTA22 +// MVF600_PAD13_PTA23_SAI2_RX_SYNC, // UNUSED +// MVF600_PAD40_PTB18_EXT_AUDIO_MCLK, // UNUSED +// MVF600_PAD33_PTB11__CKO2, // phyCORE MCLK + + /*DCU0*/ + MVF600_PAD25_PTB3_LCD_ENABLE, + MVF600_PAD105_PTE0_DCU0_HSYNC, + MVF600_PAD106_PTE1_DCU0_VSYNC, + MVF600_PAD107_PTE2_DCU0_PCLK, + MVF600_PAD109_PTE4_DCU0_DE, + MVF600_PAD110_PTE5_DCU0_R0, + MVF600_PAD111_PTE6_DCU0_R1, + MVF600_PAD112_PTE7_DCU0_R2, + MVF600_PAD113_PTE8_DCU0_R3, + MVF600_PAD114_PTE9_DCU0_R4, + MVF600_PAD115_PTE10_DCU0_R5, + MVF600_PAD116_PTE11_DCU0_R6, + MVF600_PAD117_PTE12_DCU0_R7, + MVF600_PAD118_PTE13_DCU0_G0, + MVF600_PAD119_PTE14_DCU0_G1, + MVF600_PAD120_PTE15_DCU0_G2, + MVF600_PAD121_PTE16_DCU0_G3, + MVF600_PAD122_PTE17_DCU0_G4, + MVF600_PAD123_PTE18_DCU0_G5, + MVF600_PAD124_PTE19_DCU0_G6, + MVF600_PAD125_PTE20_DCU0_G7, + MVF600_PAD126_PTE21_DCU0_B0, + MVF600_PAD127_PTE22_DCU0_B1, + MVF600_PAD128_PTE23_DCU0_B2, + MVF600_PAD129_PTE24_DCU0_B3, + MVF600_PAD130_PTE25_DCU0_B4, + MVF600_PAD131_PTE26_DCU0_B5, + MVF600_PAD132_PTE27_DCU0_B6, + MVF600_PAD133_PTE28_DCU0_B7, + + /*UART1*/ + MVF600_PAD26_PTB4_UART1_TX, + MVF600_PAD27_PTB5_UART1_RX, + + /*USB0/1 VBUS_EN*/ +#ifdef PCM952_REV0 + MVF600_PAD6_PTA16__USB0_VBUS_EN, +#else + MVF600_PAD134_PTA7__USB0_VBUS_EN, +#endif + MVF600_PAD7_PTA17__USB_OC_N, + + /* + * FlexTimer PWM channels + * FTM0 CH0~3 are connected to demo LED0~3 + * PAD30 mux with LCD enable signal + */ + MVF600_PAD22_PTB0_FTM0CH0, + MVF600_PAD23_PTB1_FTM0CH1, + MVF600_PAD24_PTB2_FTM0CH2, +// MVF600_PAD25_PTB3_FTM0CH3, + + MVF600_PAD28_PTB6_FTM0CH6, + MVF600_PAD29_PTB7_FTM0CH7, + /*MVF600_PAD30_PTB8_FTM1CH0,*/ + MVF600_PAD31_PTB9_FTM1CH1, + + /* Touch Screen */ + MVF600_PAD32_PTB10_TS_IRQ, + + /* Quad SPI */ + MVF600_PAD79_PTD0_QSPI0_A_SCK, + MVF600_PAD80_PTD1_QSPI0_A_CS0, + MVF600_PAD81_PTD2_QSPI0_A_D3, + MVF600_PAD82_PTD3_QSPI0_A_D2, + MVF600_PAD83_PTD4_QSPI0_A_D1, + MVF600_PAD84_PTD5_QSPI0_A_D0, + MVF600_PAD86_PTD7_QSPI0_B_SCK, + MVF600_PAD87_PTD8_QSPI0_B_CS0, + MVF600_PAD88_PTD9_QSPI0_B_D3, + MVF600_PAD89_PTD10_QSPI0_B_D2, + MVF600_PAD90_PTD11_QSPI0_B_D1, + MVF600_PAD91_PTD12_QSPI0_B_D0, +}; + +static struct mxc_audio_platform_data pcm052_audio_data; + +static int pcm052_sgtl5000_init(void) +{ + pcm052_audio_data.sysclk = 24576000; + return 0; +} + +static struct mvf_sai_platform_data mvf_sai_pdata = { + .flags = MVF_SAI_DMA | MVF_SAI_TRA_SYN | MVF_SAI_USE_I2S_SLAVE, +}; + +static struct mxc_audio_platform_data pcm052_audio_data = { + .sai_num = 1, + .src_port = 2, + .ext_port = 2, + .init = pcm052_sgtl5000_init, +}; + +static struct platform_device pcm052_audio_device = { + .name = "mvf-sgtl5000", +}; + +static struct imxuart_platform_data mvf_uart1_pdata = { + .flags = IMXUART_FIFO | IMXUART_EDMA, + .dma_req_rx = DMA_MUX03_UART1_RX, + .dma_req_tx = DMA_MUX03_UART1_TX, +}; + +static inline void pcm052_init_uart(void) +{ + mvf_add_imx_uart(1, &mvf_uart1_pdata); +} + +static struct fec_platform_data fec_data __initdata = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static struct switch_platform_data switch_data __initdata = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static int pcm052_spi_cs[] = { + 134, +}; + +static const struct spi_mvf_master pcm052_spi_data __initconst = { + .bus_num = 0, + .chipselect = pcm052_spi_cs, + .num_chipselect = ARRAY_SIZE(pcm052_spi_cs), + .cs_control = NULL, +}; + +static int pcm052_qspi_cs[] = { + 80, + 87, +}; + +static const struct spi_mvf_master pcm052_qspi_data __initconst = { + .bus_num = 0, + .chipselect = pcm052_qspi_cs, + .num_chipselect = ARRAY_SIZE(pcm052_qspi_cs), + .cs_control = NULL, +}; + +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +static struct mtd_partition at26df081a_partitions[] = { + { + .name = "at26df081a", + .size = (1024 * 64 * 16), + .offset = 0x00000000, + .mask_flags = 0, + } +}; + +static struct flash_platform_data at26df081a_platform_data = { + .name = "Atmel at26df081a SPI Flash chip", + .parts = at26df081a_partitions, + .nr_parts = ARRAY_SIZE(at26df081a_partitions), + .type = "at26df081a", +}; + +static struct spi_mvf_chip at26df081a_chip_info = { + .mode = SPI_MODE_3, + .bits_per_word = 8, + .void_write_data = 0, + .dbr = 0, + .pbr = 0, + .br = 0, + .pcssck = 0, + .pasc = 0, + .pdt = 0, + .cssck = 0, + .asc = 0, + .dt = 0, +}; + +static struct mtd_partition s25fl256s_partitions[] = { + { + .name = "s25fl256s", + .size = (1024 * 64 * 256), + .offset = 0x00000000, + .mask_flags = 0, + } +}; + +static struct flash_platform_data s25fl256s_spi_flash_data = { + .name = "Spansion s25fl128s SPI Flash chip", + .parts = s25fl256s_partitions, + .nr_parts = ARRAY_SIZE(s25fl256s_partitions), + .type = "s25fl128s", +}; +#endif + +static struct spi_board_info mvf_spi_board_info[] __initdata = { +#if defined(CONFIG_MTD_M25P80) +#if defined(CONFIG_SPI_MVF_QSPI) + { + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + .platform_data = &s25fl256s_spi_flash_data, + }, +#endif +#if defined(CONFIG_SPI_MVF) + { + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 16000000, + .bus_num = 0, + .chip_select = 0, + .platform_data = &at26df081a_platform_data, + .controller_data = &at26df081a_chip_info + }, +#endif +#endif +}; + +static void spi_device_init(void) +{ + spi_register_board_info(mvf_spi_board_info, + ARRAY_SIZE(mvf_spi_board_info)); +} + +#if 1 +static void pcm052_suspend_enter(void) +{ + /* suspend preparation */ +} + +static void pcm052_suspend_exit(void) +{ + /* resmue resore */ +} +static const struct pm_platform_data pcm052_pm_data __initconst = { + .name = "mvf_pm", + .suspend_enter = pcm052_suspend_enter, + .suspend_exit = pcm052_suspend_exit, +}; +#endif + +static struct mvf_dcu_platform_data mvf_dcu_pdata = { + .mode_str = "pm070wl4", + .default_bpp = 24, +}; + +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ +} +/* + * Not defined the cd/wp so far, set it always present for debug*/ +static const struct esdhc_platform_data pcm052_sd1_data __initconst = { + .cd_gpio = PCM052_SD1_CD, + .wp_gpio = -1, +}; + +static struct at24_platform_data board_eeprom = { + .byte_len = 4096, + .page_size = 32, + .flags = AT24_FLAG_ADDR16, +}; + +static struct stmpe_gpio_platform_data pba_gpio_stm_data = { + .gpio_base = -1, + .norequest_mask = STMPE_GPIO_NOREQ_811_TOUCH, +}; + +static struct stmpe_ts_platform_data pba_ts_stm_pdata = { + .sample_time = 4, + .mod_12b = 1, + .ref_sel = 0, + .adc_freq = 1, + .ave_ctrl = 3, + .touch_det_delay = 3, + .settling = 3, + .fraction_z = 7, + .i_drive = 0, +}; + +static struct stmpe_platform_data pba_stm_pdata = { + .blocks = STMPE_BLOCK_GPIO | STMPE_BLOCK_TOUCHSCREEN, + .irq_base = NR_IRQS, + .irq_trigger = IRQF_TRIGGER_RISING, + .irq_invert_polarity = true, + .gpio = &pba_gpio_stm_data, + .ts = &pba_ts_stm_pdata, +}; + +static struct imxi2c_platform_data pcm052_i2c_data = { + .bitrate = 100000, +}; + +static struct i2c_board_info pcm052_i2c2_board_info[] __initdata = { + { + I2C_BOARD_INFO("sgtl5000", 0x0a), + }, + { + I2C_BOARD_INFO("at24", 0x50), + .platform_data = &board_eeprom, + }, + { + I2C_BOARD_INFO("stmpe811", 0x41), + .irq = PCM052_TS_IRQ, + .platform_data = &pba_stm_pdata, + }, +}; + +static struct mxc_nand_platform_data mvf_data __initdata = { + .width = 2, +}; + +static struct led_pwm mvf_led __initdata = { + .name = "mvf_leds", + .pwm_id = 1, + .active_low = 0, + .max_brightness = 6, + .pwm_period_ns = 100000000, +}; + +static struct led_pwm_platform_data mvf_led_data __initdata = { + .num_leds = 1, + .leds = &mvf_led, +}; + +static void __init pcm052_init_usb(void) +{ + imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR); + /*mvf_set_otghost_vbus_func(pcm052_usbotg_vbus);*/ +#ifdef CONFIG_USB_GADGET_ARC + mvf_usb_dr_init(); +#endif +#ifdef CONFIG_USB_EHCI_ARC + mvf_usb_dr2_init(); +#endif +} + +/*! + * Board specific initialization. + */ +static void __init pcm052_board_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(pcm052_pads, + ARRAY_SIZE(pcm052_pads)); + pcm052_init_uart(); + +#ifdef CONFIG_FEC + mvf_init_fec(fec_data); +#endif + +#ifdef CONFIG_FSL_L2_SWITCH + mvf_init_switch(switch_data); +#endif + + mvf_add_snvs_rtc(); + + mvf_add_sdhci_esdhc_imx(1, &pcm052_sd1_data); + + mvf_add_imx_i2c(2, &pcm052_i2c_data); + i2c_register_board_info(2, pcm052_i2c2_board_info, + ARRAY_SIZE(pcm052_i2c2_board_info)); + + mvf_add_dspi(0, &pcm052_spi_data); + mvf_add_qspi(0, &pcm052_qspi_data); + spi_device_init(); + + mvfa5_add_dcu(0, &mvf_dcu_pdata); + +// mxc_register_device(&pcm052_audio_device, &pcm052_audio_data); +// mvfa5_add_sai(2, &mvf_sai_pdata); + +// mvf_add_wdt(0); + + pcm052_init_usb(); + + mvf_add_nand(&mvf_data); + +// mvf_add_mxc_pwm(0); +// mvf_add_pwm_leds(&mvf_led_data); + +} + +static void __init mvf_timer_init(void) +{ +#if 0 + struct clk *uart_clk; + uart_clk = clk_get_sys("mvf-uart.0", NULL); + early_console_setup(MVF_UART1_BASE_ADDR, uart_clk); +#endif + mvf_clocks_init(32768, 24000000, 0, 0); +} + +static struct sys_timer pcm052_timer = { + .init = mvf_timer_init, +}; + +/* + * initialize __mach_desc_ data structure. + */ +MACHINE_START(PCM052, "PHYTEC phyCORE-Vybrid Board") + /* Maintainer: Freescale Semiconductor, Inc. */ + .boot_params = MVF_PHYS_OFFSET + 0x100, + .fixup = fixup_mxc_board, + .map_io = mvf_map_io, + .init_irq = mvf_init_irq, + .init_machine = pcm052_board_init, + .timer = &pcm052_timer, +MACHINE_END diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index 5ac0ff1766fb..c7279adba4d2 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -1652,7 +1652,34 @@ static struct clk i2c_clk[] = { .id = 0, .parent = &ipg_clk, .enable_reg = MXC_CCM_CCGR4, - .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET, + .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + __INIT_CLK_DEBUG(i2c_clk_1) + .id = 1, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + __INIT_CLK_DEBUG(i2c_clk_2) + .id = 2, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR10, + .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + __INIT_CLK_DEBUG(i2c_clk_3) + .id = 3, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR10, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, .enable = _clk_enable, .disable = _clk_disable, }, @@ -1897,7 +1924,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk), /* arm core clk */ _REGISTER_CLOCK(NULL, "periph_clk", periph_clk), /* platform bus clk */ _REGISTER_CLOCK(NULL, "ipg_clk", ipg_clk), - _REGISTER_CLOCK(NULL, "audio ext clk", audio_external_clk), +// _REGISTER_CLOCK(NULL, "audio ext clk", audio_external_clk), _REGISTER_CLOCK(NULL, "mvf-uart.0", uart_clk[0]), _REGISTER_CLOCK(NULL, "mvf-uart.1", uart_clk[0]), _REGISTER_CLOCK(NULL, "mvf-uart.2", uart_clk[0]), @@ -1911,8 +1938,9 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk), _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc1_clk), _REGISTER_CLOCK("mvf-dcu.0", NULL, dcu0_clk), - _REGISTER_CLOCK("mvf-sai.0", NULL, sai2_clk), - _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[0]), +// _REGISTER_CLOCK("mvf-sai.0", NULL, sai2_clk), +// _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[2]), + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2]), _REGISTER_CLOCK(NULL, "usb-clk", usb_clk), _REGISTER_CLOCK(NULL, "mvf-usb.0", usb_phy0_clk), _REGISTER_CLOCK(NULL, "mvf-usb.1", usb_phy1_clk), diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c index 215f3b6157bb..88c6c8c7ab60 100755 --- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c +++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c @@ -113,6 +113,9 @@ const struct imx_imx_i2c_data mvf_i2c_data[] __initconst = { #define mvf_i2c_data_entry(_id, _hwid) \ imx_imx_i2c_data_entry(MVF, _id, _hwid, SZ_4K) mvf_i2c_data_entry(0, 0), + mvf_i2c_data_entry(1, 1), + mvf_i2c_data_entry(2, 2), + mvf_i2c_data_entry(3, 3), }; #endif struct platform_device *__init imx_add_imx_i2c( diff --git a/arch/arm/plat-mxc/include/mach/iomux-mvf.h b/arch/arm/plat-mxc/include/mach/iomux-mvf.h index b1bbb0955010..fbc0571f8b9f 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mvf.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mvf.h @@ -47,7 +47,8 @@ typedef enum iomux_config { #define MVF600_ENET_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ PAD_CTL_DSE_50ohm) -#define MVF600_I2C_PAD_CTRL (PAD_CTL_DSE_50ohm | PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH) +#define MVF600_I2C_PAD_CTRL (PAD_CTL_DSE_50ohm | PAD_CTL_PUS_47K_UP | \ + PAD_CTL_SPEED_HIGH | PAD_CTL_ODE) #define MVF600_SAI_PAD_CTRL (PAD_CTL_DSE_50ohm | PAD_CTL_HYS | \ PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP) @@ -87,9 +88,9 @@ typedef enum iomux_config { IOMUX_PAD(0x0048, 0x0048, 5, 0x0000, 0, MVF600_SDHC_PAD_CTRL) #define MVF600_PAD19_PTA29__SDHC1_DAT3 \ IOMUX_PAD(0x004C, 0x004C, 5, 0x0000, 0, MVF600_SDHC_PAD_CTRL) -/*set PTA7 as GPIO for sdhc card detecting*/ -#define MVF600_PAD134_PTA7__SDHC1_SW_CD \ - IOMUX_PAD(0x0218, 0x0218, 0, 0x0000, 0, \ +/*set PTD6 as GPIO for sdhc card detecting*/ +#define MVF600_PAD85_PTD6__SDHC1_SW_CD \ + IOMUX_PAD(0x0154, 0x0154, 0, 0x0000, 0, \ MVF600_GPIO_GENERAL_CTRL | PAD_CTL_IBE_ENABLE) /*I2C0*/ @@ -99,6 +100,18 @@ typedef enum iomux_config { #define MVF600_PAD37_PTB15__I2C0_SDA \ IOMUX_PAD(0x0094, 0x0094, 2, 0x0340, 1, \ MVF600_I2C_PAD_CTRL | PAD_CTL_OBE_IBE_ENABLE) +/*I2C2*/ +#define MVF600_PAD12_PTA22__I2C2_SCL \ + IOMUX_PAD(0x0030, 0x0030, 6, 0x034C, 0, \ + MVF600_I2C_PAD_CTRL | PAD_CTL_OBE_IBE_ENABLE) +#define MVF600_PAD13_PTA23__I2C2_SDA \ + IOMUX_PAD(0x0034, 0x0034, 6, 0x0350, 0, \ + MVF600_I2C_PAD_CTRL | PAD_CTL_OBE_IBE_ENABLE) +/*CAN0*/ +#define MVF600_PAD36_PTB14__CAN0_RX \ + IOMUX_PAD(0x0090, 0x0090, 1, 0x0000, 0, 0) +#define MVF600_PAD37_PTB15__CAN0_TX \ + IOMUX_PAD(0x0094, 0x0094, 1, 0x0000, 0, 0) /*CAN1*/ #define MVF600_PAD38_PTB16__CAN1_RX \ @@ -183,12 +196,16 @@ typedef enum iomux_config { MVF600_ENET_PAD_CTRL | PAD_CTL_OBE_ENABLE) /*USB0/1 VBUS, using the GPIO*/ -#define MVF600_PAD85_PTD6__USB0_VBUS_EN \ - IOMUX_PAD(0x0154, 0x0154, 0, 0x0000, 0, \ - MVF600_GPIO_GENERAL_CTRL) -#define MVF600_PAD92_PTD13__USB1_VBUS_EN \ - IOMUX_PAD(0x0170, 0x0170, 0, 0x0000, 0, \ - MVF600_GPIO_GENERAL_CTRL) +#define MVF600_PAD134_PTA7__USB0_VBUS_EN \ + IOMUX_PAD(0x0218, 0x0218, 0, 0x0000, 0, \ + MVF600_GPIO_GENERAL_CTRL | PAD_CTL_OBE_ENABLE) +#define MVF600_PAD6_PTA16__USB0_VBUS_EN \ + IOMUX_PAD(0x0018, 0x0018, 0, 0x0000, 0, \ + MVF600_GPIO_GENERAL_CTRL | PAD_CTL_OBE_ENABLE) + +#define MVF600_PAD7_PTA17__USB_OC_N \ + IOMUX_PAD(0x001C, 0x001C, 2, 0x0000, 0, \ + PAD_CTL_DSE_20ohm | PAD_CTL_IBE_ENABLE) /*ESAI0(share with FEC1)*/ #define MVF600_PAD54_PTC9__ESAI_SCKT \ @@ -230,19 +247,22 @@ typedef enum iomux_config { #define MVF600_PAD11_PTA21_SAI2_RX_BCLK \ IOMUX_PAD(0x002C, 0x002C, 5, 0x0364, 0, \ MVF600_SAI_PAD_CTRL | PAD_CTL_IBE_ENABLE) -#define MVF600_PAD12_PTA22_SAI2_RX_DATA \ - IOMUX_PAD(0x0030, 0x0030, 5, 0x0368, 0, \ +#define MVF600_PAD23_PTB1_SAI2_RX_DATA \ + IOMUX_PAD(0x005C, 0x005C, 5, 0x0368, 1, \ MVF600_SAI_PAD_CTRL | PAD_CTL_IBE_ENABLE) -#define MVF600_PAD13_PTA23_SAI2_RX_SYNC \ - IOMUX_PAD(0x0034, 0x0034, 5, 0x036c, 0, \ +#define MVF600_PAD24_PTB2_SAI2_RX_SYNC \ + IOMUX_PAD(0x0060, 0x0060, 5, 0x036c, 1, \ MVF600_SAI_PAD_CTRL | PAD_CTL_IBE_ENABLE) #define MVF600_PAD40_PTB18_EXT_AUDIO_MCLK \ IOMUX_PAD(0x00A0, 0x00A0, 2, 0x02ec, 2, \ MVF600_SAI_PAD_CTRL | PAD_CTL_IBE_ENABLE) +#define MVF600_PAD33_PTB11__CKO2 \ + IOMUX_PAD(0x0084, 0x0084, 6, 0x24038, 0x040D, \ + MVF600_SAI_PAD_CTRL | PAD_CTL_IBE_ENABLE) /*DCU0*/ -#define MVF600_PAD30_PTB8_LCD_ENABLE \ - IOMUX_PAD(0x78, 0x78, 0, 0x0000, 0, MVF600_DCU_PAD_CTRL) +#define MVF600_PAD25_PTB3_LCD_ENABLE \ + IOMUX_PAD(0x64, 0x64, 0, 0x0000, 0, MVF600_DCU_PAD_CTRL) #define MVF600_PAD105_PTE0_DCU0_HSYNC \ IOMUX_PAD(0x01A4, 0x01A4, 1, 0x0000, 0, MVF600_DCU_PAD_CTRL) #define MVF600_PAD106_PTE1_DCU0_VSYNC \ @@ -335,8 +355,8 @@ typedef enum iomux_config { IOMUX_PAD(0x007C, 0x007C, 1, 0x0330, 0, MVF600_FTM1_CH_CTRL) /* Touch Screen */ -#define MVF600_PAD21_PTA31_TS_IRQ \ - IOMUX_PAD(0x0054, 0x0054, 0, 0x0000, 0, \ +#define MVF600_PAD32_PTB10_TS_IRQ \ + IOMUX_PAD(0x0080, 0x0080, 0, 0x0000, 0, \ MVF600_GPIO_GENERAL_CTRL | PAD_CTL_IBE_ENABLE) /*QSPI*/ diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h index 78b8aa2503f5..97a8ca7c7f9a 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-v3.h +++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h @@ -116,7 +116,8 @@ typedef u64 iomux_v3_cfg_t; #define PAD_CTL_SRE_SLOW (0 << 0) #elif defined(CONFIG_ARCH_MVF) -#define PAD_CTL_SPEED_LOW (1 << 12) +/* FIXED: (1 << 12) is also MED (100 MHz according to TRM) */ +#define PAD_CTL_SPEED_LOW (0 << 12) #define PAD_CTL_SPEED_MED (2 << 12) #define PAD_CTL_SPEED_HIGH (3 << 12) diff --git a/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h b/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h index 9a5ba8e396a9..38fcdd4916bf 100644 --- a/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h +++ b/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h @@ -32,7 +32,7 @@ struct dfb_chroma_key { __u8 blue_min; }; -#define DCU_LCD_ENABLE_PIN 30 +#define DCU_LCD_ENABLE_PIN 25 #define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key) #define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index b805e9660348..15ea8529057b 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -1121,3 +1121,4 @@ mvf_twr_vf400 MACH_MVFA5_TWR_VF400 MVFA5_TWR_VF400 4148 mvf_twr_vf500 MACH_MVFA5_TWR_VF500 MVFA5_TWR_VF500 4147 mvf_twr_vf600 MACH_MVFA5_TWR_VF600 MVFA5_TWR_VF600 4146 mvf_twr_vf700 MACH_MVFA5_TWR_VF700 MVFA5_TWR_VF700 2125 +pcm052 MACH_PCM052 PCM052 4391 diff --git a/drivers/video/mvf_dcu.c b/drivers/video/mvf_dcu.c index d9fc6fa664c7..829d9443f59a 100644 --- a/drivers/video/mvf_dcu.c +++ b/drivers/video/mvf_dcu.c @@ -37,15 +37,17 @@ #define DRIVER_NAME "mvf-dcu" static struct fb_videomode __devinitdata mvf_dcu_default_mode = { - .xres = 480, - .yres = 272, - .left_margin = 2, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 41, + .pixclock = 31250, + .xres = 800, + .yres = 480, + .left_margin = 42, + .right_margin = 86, + .upper_margin = 10, + .lower_margin = 33, + .hsync_len = 128, .vsync_len = 2, - .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | + FB_SYNC_HOR_HIGH_ACT, .vmode = FB_VMODE_NONINTERLACED, }; @@ -63,6 +65,22 @@ static struct fb_videomode __devinitdata mvf_dcu_mode_db[] = { .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, .vmode = FB_VMODE_NONINTERLACED, }, + { + .name = "pm070wl4", + .pixclock = 31250, + .xres = 800, + .yres = 480, + .left_margin = 42, + .right_margin = 86, + .upper_margin = 10, + .lower_margin = 33, + .hsync_len = 128, + .vsync_len = 2, + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | + FB_SYNC_HOR_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + }, + }; static DEFINE_SPINLOCK(dcu_lock); @@ -1001,7 +1019,7 @@ static int __devinit mvf_dcu_probe(struct platform_device *pdev) gpio_request_one(DCU_LCD_ENABLE_PIN, GPIOF_OUT_INIT_LOW, "DCU"); msleep(2); - gpio_set_value(DCU_LCD_ENABLE_PIN, 1); + gpio_set_value(DCU_LCD_ENABLE_PIN, 0); writel(0x20000000, MVF_IO_ADDRESS(MVF_TCON0_BASE_ADDR)); -- cgit v1.2.3 From 139da31fb4b4d98f8fdb7f3a62662b73b9d8b705 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Mon, 17 Dec 2012 11:38:33 -0800 Subject: pcm052: enable EEPROM driver in config, fix TSC IRQs Signed-off-by: Russell Robinson Jr --- arch/arm/configs/pcm052_defconfig | 35 +++++++++++++++++++++++++++- arch/arm/mach-mvf/board-pcm052.c | 4 ++-- arch/arm/plat-mxc/devices/platform-mvf-dcu.c | 4 ++-- arch/arm/plat-mxc/include/mach/iomux-mvf.h | 4 ++-- arch/arm/plat-mxc/include/mach/irqs.h | 7 ++++++ 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/arch/arm/configs/pcm052_defconfig b/arch/arm/configs/pcm052_defconfig index 2ba4cafb5815..bd13e16e0cea 100644 --- a/arch/arm/configs/pcm052_defconfig +++ b/arch/arm/configs/pcm052_defconfig @@ -660,7 +660,40 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_MG_DISK is not set # CONFIG_BLK_DEV_RBD is not set # CONFIG_SENSORS_LIS3LV02D is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c index dc583b4a69f5..08b071f1dcf7 100644 --- a/arch/arm/mach-mvf/board-pcm052.c +++ b/arch/arm/mach-mvf/board-pcm052.c @@ -436,7 +436,7 @@ static struct stmpe_ts_platform_data pba_ts_stm_pdata = { static struct stmpe_platform_data pba_stm_pdata = { .blocks = STMPE_BLOCK_GPIO | STMPE_BLOCK_TOUCHSCREEN, - .irq_base = NR_IRQS, + .irq_base = STMPE_IRQ_BASE, .irq_trigger = IRQF_TRIGGER_RISING, .irq_invert_polarity = true, .gpio = &pba_gpio_stm_data, @@ -457,7 +457,7 @@ static struct i2c_board_info pcm052_i2c2_board_info[] __initdata = { }, { I2C_BOARD_INFO("stmpe811", 0x41), - .irq = PCM052_TS_IRQ, + .irq = gpio_to_irq(PCM052_TS_IRQ), .platform_data = &pba_stm_pdata, }, }; diff --git a/arch/arm/plat-mxc/devices/platform-mvf-dcu.c b/arch/arm/plat-mxc/devices/platform-mvf-dcu.c index 0fe5099eca34..15f6f0dbe24e 100644 --- a/arch/arm/plat-mxc/devices/platform-mvf-dcu.c +++ b/arch/arm/plat-mxc/devices/platform-mvf-dcu.c @@ -28,10 +28,10 @@ int __init mvf_dcu_init(int id) ret = gpio_request_one(DCU_LCD_ENABLE_PIN, GPIOF_OUT_INIT_LOW, "DCU"); if (ret) - printk(KERN_ERR "DCU: failed to request GPIO 30\n"); + printk(KERN_ERR "DCU: failed to request GPIO 25\n"); msleep(2); - gpio_set_value(DCU_LCD_ENABLE_PIN, 1); + gpio_set_value(DCU_LCD_ENABLE_PIN, 0); writel(0x20000000, MVF_IO_ADDRESS(MVF_TCON0_BASE_ADDR)); return ret; diff --git a/arch/arm/plat-mxc/include/mach/iomux-mvf.h b/arch/arm/plat-mxc/include/mach/iomux-mvf.h index fbc0571f8b9f..a838e0bbead9 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mvf.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mvf.h @@ -356,8 +356,8 @@ typedef enum iomux_config { /* Touch Screen */ #define MVF600_PAD32_PTB10_TS_IRQ \ - IOMUX_PAD(0x0080, 0x0080, 0, 0x0000, 0, \ - MVF600_GPIO_GENERAL_CTRL | PAD_CTL_IBE_ENABLE) + IOMUX_PAD(0x0080, 0x0080, 0, 0x0000, 0, \ + PAD_CTL_SPEED_MED | PAD_CTL_IBE_ENABLE) /*QSPI*/ #define MVF600_PAD79_PTD0_QSPI0_A_SCK \ diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h index 9fce85784a32..4edd8d91c57d 100644 --- a/arch/arm/plat-mxc/include/mach/irqs.h +++ b/arch/arm/plat-mxc/include/mach/irqs.h @@ -74,7 +74,14 @@ #define MX5_IPU_IRQS 0 #endif +#ifdef CONFIG_MACH_PCM052 +#define STMPE_IRQ_BASE (MXC_IPU_IRQ_START) +#define STMPE_MAX_GPIOS 24 +#define STMPE_IRQ_END (STMPE_IRQ_BASE + STMPE_MAX_GPIOS) +#define NR_IRQS (STMPE_IRQ_END) +#else #define NR_IRQS (MXC_IPU_IRQ_START + MX3_IPU_IRQS + MX5_IPU_IRQS) +#endif extern int imx_irq_set_priority(unsigned char irq, unsigned char prio); -- cgit v1.2.3 From 960a5e572b76b51e1e6f184c2dae1394f0830bdc Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Wed, 23 Jan 2013 10:37:10 -0800 Subject: pcm052: sdhc: fix drive strength and use only hardware pull-ups Signed-off-by: Russell Robinson Jr --- arch/arm/plat-mxc/include/mach/iomux-mvf.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/plat-mxc/include/mach/iomux-mvf.h b/arch/arm/plat-mxc/include/mach/iomux-mvf.h index a838e0bbead9..05932e3af1d2 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mvf.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mvf.h @@ -40,9 +40,8 @@ typedef enum iomux_config { #define NON_MUX_I 0x3FF #define NON_PAD_I 0x7FF -#define MVF600_SDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ - PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH | \ - PAD_CTL_DSE_20ohm | PAD_CTL_OBE_IBE_ENABLE) +#define MVF600_SDHC_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_50ohm | PAD_CTL_OBE_IBE_ENABLE) #define MVF600_ENET_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ PAD_CTL_DSE_50ohm) -- cgit v1.2.3 From 10d675e891b7969fe0658db17ad0ecc88fd6eda5 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Mon, 4 Feb 2013 14:12:45 -0800 Subject: pcm052: usb: fix VBUS enable mux settings and assert GPIO to enable VBUS Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/board-pcm052.c | 15 ++++++++------- arch/arm/plat-mxc/include/mach/iomux-mvf.h | 13 ++++++++----- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c index 08b071f1dcf7..85706add0494 100644 --- a/arch/arm/mach-mvf/board-pcm052.c +++ b/arch/arm/mach-mvf/board-pcm052.c @@ -195,7 +195,7 @@ static iomux_v3_cfg_t pcm052_pads[] = { #ifdef PCM952_REV0 MVF600_PAD6_PTA16__USB0_VBUS_EN, #else - MVF600_PAD134_PTA7__USB0_VBUS_EN, + MVF600_PAD134_PTA7__USB_VBUS_EN, #endif MVF600_PAD7_PTA17__USB_OC_N, @@ -275,7 +275,7 @@ static struct switch_platform_data switch_data __initdata = { }; static int pcm052_spi_cs[] = { - 134, + 41, }; static const struct spi_mvf_master pcm052_spi_data __initconst = { @@ -479,13 +479,14 @@ static struct led_pwm_platform_data mvf_led_data __initdata = { .leds = &mvf_led, }; +#define USB_VBUS_ENABLE_PIN 134 static void __init pcm052_init_usb(void) { - imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR); - /*mvf_set_otghost_vbus_func(pcm052_usbotg_vbus);*/ -#ifdef CONFIG_USB_GADGET_ARC - mvf_usb_dr_init(); -#endif + gpio_request_one(USB_VBUS_ENABLE_PIN, GPIOF_OUT_INIT_LOW, "VBUS_EN"); + msleep(2); + gpio_set_value(USB_VBUS_ENABLE_PIN, 1); + +// mvf_usb_dr_init(); #ifdef CONFIG_USB_EHCI_ARC mvf_usb_dr2_init(); #endif diff --git a/arch/arm/plat-mxc/include/mach/iomux-mvf.h b/arch/arm/plat-mxc/include/mach/iomux-mvf.h index 05932e3af1d2..eb093e2c0f7f 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mvf.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mvf.h @@ -195,16 +195,19 @@ typedef enum iomux_config { MVF600_ENET_PAD_CTRL | PAD_CTL_OBE_ENABLE) /*USB0/1 VBUS, using the GPIO*/ -#define MVF600_PAD134_PTA7__USB0_VBUS_EN \ +#define MVF600_PAD134_PTA7__USB_VBUS_EN \ IOMUX_PAD(0x0218, 0x0218, 0, 0x0000, 0, \ - MVF600_GPIO_GENERAL_CTRL | PAD_CTL_OBE_ENABLE) + PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_25ohm | \ + PAD_CTL_SPEED_LOW | PAD_CTL_OBE_ENABLE) #define MVF600_PAD6_PTA16__USB0_VBUS_EN \ IOMUX_PAD(0x0018, 0x0018, 0, 0x0000, 0, \ - MVF600_GPIO_GENERAL_CTRL | PAD_CTL_OBE_ENABLE) - + PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_25ohm | \ + PAD_CTL_SPEED_LOW | PAD_CTL_OBE_ENABLE) #define MVF600_PAD7_PTA17__USB_OC_N \ IOMUX_PAD(0x001C, 0x001C, 2, 0x0000, 0, \ - PAD_CTL_DSE_20ohm | PAD_CTL_IBE_ENABLE) + PAD_CTL_HYS | PAD_CTL_IBE_ENABLE) /*ESAI0(share with FEC1)*/ #define MVF600_PAD54_PTC9__ESAI_SCKT \ -- cgit v1.2.3 From fd5b59f7d6fc1736c2b00f306dcfeb574fea4512 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Mon, 11 Feb 2013 15:33:19 -0800 Subject: mvf: usb: create modular defines for ehci and some hardware address changes. ehci changes are currently only used with phyCORE-Vybrid (pcm052) Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/clock.c | 2 ++ arch/arm/mach-mvf/devices-mvf.h | 26 ++++++++++++++++++++++ arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c | 12 ++++++++++ .../plat-mxc/devices/platform-fsl-usb2-wakeup.c | 12 ++++++++++ arch/arm/plat-mxc/devices/platform-mxc-ehci.c | 15 ++++++++++++- arch/arm/plat-mxc/include/mach/arc_otg.h | 2 +- arch/arm/plat-mxc/include/mach/mvf.h | 19 ++++++++++------ drivers/usb/core/hub.c | 19 ++++++++++++++++ 8 files changed, 98 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index c7279adba4d2..74ce8a9f290e 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -670,10 +670,12 @@ static int _clk_pll3_usb_otg_set_rate(struct clk *clk, unsigned long rate) else return -EINVAL; +#ifndef CONFIG_MACH_PCM052 reg = __raw_readl(PLL3_480_USB1_BASE_ADDR); reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK; reg |= div; __raw_writel(reg, PLL3_480_USB1_BASE_ADDR); +#endif return 0; } diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index c434834ba0b2..f4ec88b062ac 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -52,6 +52,15 @@ extern const struct imx_mxc_nand_data mvf_nand_data __initconst; #define mvf_add_nand(pdata) \ imx_add_mxc_nand(&mvf_nand_data, pdata) +#ifdef CONFIG_MACH_PCM052 +extern const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data[] __initconst; +#define mvf_add_fsl_usb2_udc(id, pdata) \ + imx_add_fsl_usb2_udc(&mvf_fsl_usb2_udc_data[id], pdata) + +extern const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data[] __initconst; +#define mvf_add_fsl_ehci_otg(id, pdata) \ + imx_add_fsl_ehci(&mvf_mxc_ehci_otg_data[id], pdata) +#else extern const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data __initconst; #define mvf_add_fsl_usb2_udc(pdata) \ imx_add_fsl_usb2_udc(&mvf_fsl_usb2_udc_data, pdata) @@ -59,10 +68,16 @@ extern const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data __initconst; extern const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data __initconst; #define mvf_add_fsl_ehci_otg(pdata) \ imx_add_fsl_ehci(&mvf_mxc_ehci_otg_data, pdata) +#endif extern const struct imx_mxc_ehci_data mvf_mxc_ehci_hs_data[] __initconst; +#ifdef CONFIG_MACH_PCM052 +#define mvf_add_fsl_ehci_hs(id, pdata) \ + imx_add_fsl_ehci(&mvf_mxc_ehci_hs_data[id], pdata) +#else #define mvf_add_fsl_ehci_hs(id, pdata) \ imx_add_fsl_ehci(&mvf_mxc_ehci_hs_data[id - 1], pdata) +#endif extern const struct imx_fsl_usb2_otg_data mvf_fsl_usb2_otg_data __initconst; #define mvf_add_fsl_usb2_otg(pdata) \ @@ -70,15 +85,26 @@ extern const struct imx_fsl_usb2_otg_data mvf_fsl_usb2_otg_data __initconst; extern const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst; +#ifdef CONFIG_MACH_PCM052 +#define mvf_add_fsl_usb2_ehci_otg_wakeup(id, pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[id], pdata) +#define mvf_add_fsl_usb2_udc_wakeup(id, pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[id], pdata) +#else #define mvf_add_fsl_usb2_ehci_otg_wakeup(pdata) \ imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[1], pdata) #define mvf_add_fsl_usb2_udc_wakeup(pdata) \ imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[0], pdata) +#endif extern const struct imx_fsl_usb2_wakeup_data mvf_fsl_hs_wakeup_data[] __initconst; +#ifdef CONFIG_MACH_PCM052 +#define mvf_add_fsl_usb2_hs_wakeup(id, pdata) \ + imx_add_fsl_usb2_wakeup(&mvf_fsl_hs_wakeup_data[id], pdata) #define mvf_add_fsl_usb2_hs_wakeup(id, pdata) \ imx_add_fsl_usb2_wakeup(&mvf_fsl_hs_wakeup_data[id - 1], pdata) +#endif extern const struct imx_imx_esai_data mvf_imx_esai_data[] __initconst; #define mvf_add_imx_esai(id, pdata) \ diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c index d50c5b0be550..5d7605421294 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c @@ -18,6 +18,12 @@ .irq = soc ## _INT_USB_OTG, \ } +#define mvf_fsl_usb2_udc_data_entry_single(arch, _id) \ + { \ + .iobase = arch ## _USBC ## _id ## _BASE_ADDR, \ + .irq = arch ## _INT_USB ## _id, \ + } + #ifdef CONFIG_SOC_IMX25 const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst = imx_fsl_usb2_udc_data_entry_single(MX25); @@ -44,9 +50,15 @@ const struct imx_fsl_usb2_udc_data imx6q_fsl_usb2_udc_data __initconst = #endif /* ifdef CONFIG_SOC_IMX6Q */ #ifdef CONFIG_ARCH_MVF +#ifdef CONFIG_MACH_PCM052 +const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data[] __initconst = { + mvf_fsl_usb2_udc_data_entry_single(MVF, 0), + mvf_fsl_usb2_udc_data_entry_single(MVF, 1), +#else const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data __initconst = { .iobase = MVF_USBC0_BASE_ADDR, .irq = MVF_INT_USBOTG0, +#endif }; #endif diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c index 957c96a7996e..80c44f48393d 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c @@ -17,6 +17,13 @@ .irq_core = soc ## _INT_USB_ ## hs, \ } +#define mvf_fsl_usb2_wakeup_data_entry_single(arch, _id) \ + { \ + .id = _id, \ + .irq_phy = arch ## _INT_USB ## _id, \ + .irq_core = arch ## _INT_USB ## _id, \ + } + #ifdef CONFIG_SOC_IMX6Q const struct imx_fsl_usb2_wakeup_data imx6q_fsl_otg_wakeup_data __initconst = imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 0, OTG); @@ -28,6 +35,10 @@ const struct imx_fsl_usb2_wakeup_data imx6q_fsl_hs_wakeup_data[] __initconst = { #endif /* ifdef CONFIG_SOC_IMX6Q */ #ifdef CONFIG_SOC_MVFA5 const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst = { +#ifdef CONFIG_MACH_PCM052 + mvf_fsl_usb2_wakeup_data_entry_single(MVF, 0), + mvf_fsl_usb2_wakeup_data_entry_single(MVF, 1), +#else { .id = 0, .irq_phy = MVF_INT_USBOTG0, @@ -38,6 +49,7 @@ const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst = { .irq_phy = MVF_INT_USB2, .irq_core = MVF_INT_USB2, } +#endif }; #endif diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c index f700d656c3b7..928f3b792e0f 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c @@ -16,6 +16,13 @@ .irq = soc ## _INT_USB_ ## hs, \ } +#define mvf_mxc_ehci_data_entry_single(arch, _id) \ + { \ + .id = _id, \ + .iobase = arch ## _USBC ## _id ## _BASE_ADDR, \ + .irq = arch ## _INT_USB ## _id, \ + } + #ifdef CONFIG_SOC_IMX25 const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data __initconst = imx_mxc_ehci_data_entry_single(MX25, 0, OTG); @@ -59,12 +66,18 @@ const struct imx_mxc_ehci_data imx6q_mxc_ehci_hs_data[] __initconst = { #endif /* ifdef CONFIG_SOC_IMX6Q */ #ifdef CONFIG_ARCH_MVF +#ifdef CONFIG_MACH_PCM052 +const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data[] __initconst = { + mvf_mxc_ehci_data_entry_single(MVF, 0), + mvf_mxc_ehci_data_entry_single(MVF, 1), +#else const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data __initconst = { .id = 0, .iobase = MVF_USBC1_BASE_ADDR, .irq = MVF_INT_USB2, -}; #endif +}; +#endif /* ifdef CONFIG_ARCH_MVF */ struct platform_device *__init imx_add_mxc_ehci( const struct imx_mxc_ehci_data *data, diff --git a/arch/arm/plat-mxc/include/mach/arc_otg.h b/arch/arm/plat-mxc/include/mach/arc_otg.h index 51945e0fa957..af06f51759e5 100755 --- a/arch/arm/plat-mxc/include/mach/arc_otg.h +++ b/arch/arm/plat-mxc/include/mach/arc_otg.h @@ -31,7 +31,7 @@ extern void __iomem *imx_otg_base; #define USB_OTGREGS_BASE MVF_IO_ADDRESS(0x40034000) #define USB_OTG2REGS_BASE MVF_IO_ADDRESS(0x400B4000) -#define USB_H1REGS_BASE MVF_IO_ADDRESS(0x400B4000) +#define USB_H1REGS_BASE MVF_IO_ADDRESS(0x40034000) /* dummy h2regs for MVF */ #define USB_H2REGS_BASE MVF_IO_ADDRESS(0x400B4000) #define USBC0_OTHERREGS_BASE MVF_IO_ADDRESS(0x40034800) diff --git a/arch/arm/plat-mxc/include/mach/mvf.h b/arch/arm/plat-mxc/include/mach/mvf.h index 838eef400e95..4a47636fa741 100644 --- a/arch/arm/plat-mxc/include/mach/mvf.h +++ b/arch/arm/plat-mxc/include/mach/mvf.h @@ -183,14 +183,14 @@ #define L2_BASE_ADDR MVF_L2C_BASE_ADDR -#define MVF_USBC0_CTRL_BASE_ADDR 0x40034800 -#define MVF_USBC1_CTRL_BASE_ADDR 0x400B4800 -#define MVF_USBC0_PHY_BASE_ADDR 0x40034818 -#define MVF_USBC1_PHY_BASE_ADDR 0x400B4818 +#define MVF_USBC0_CTRL_BASE_ADDR 0x40035800 +#define MVF_USBC1_CTRL_BASE_ADDR 0x400B5800 +#define MVF_USBC0_PHY_BASE_ADDR 0x40035818 +#define MVF_USBC1_PHY_BASE_ADDR 0x400B5818 #define MVF_USBC0_BASE_ADDR 0x40034000 #define MVF_USBC1_BASE_ADDR 0x400B4000 #define MVF_USBPHY0_BASE_ADDR 0x40050800 -#define MVF_USBPHY1_BASE_ADDR 0x40050B00 +#define MVF_USBPHY1_BASE_ADDR 0x40050C00 #define MVF_MSCM_INT_ROUTER_BASE (MVF_MSCM_BASE_ADDR + 0x800) @@ -553,8 +553,13 @@ #define MVF_INT_I2C1 104 #define MVF_INT_I2C2 105 #define MVF_INT_I2C3 106 -#define MVF_INT_USBOTG0 107 -#define MVF_INT_USB2 108 + +#ifdef CONFIG_MACH_PCM052 +#define MVF_INT_USB0 107 +#define MVF_INT_USB1 108 +#else +#endif + #define MVF_INT_ENET_MAC0 110 #define MVF_INT_ENET_MAC1 111 #define MVF_INT_1588_TIMER0 112 diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 694476ea22ac..f056707d0986 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -42,6 +42,11 @@ extern void fsl_platform_set_usb_phy_dis(struct fsl_usb2_platform_data *pdata, #ifdef CONFIG_ARCH_MVF #define MVF_USB_HOST_HACK #include + +extern void fsl_platform_set_usb0_phy_dis(struct fsl_usb2_platform_data *pdata, + bool enable); +extern void fsl_platform_set_usb1_phy_dis(struct fsl_usb2_platform_data *pdata, + bool enable); #endif /* if we are in debug mode, always announce new devices */ #ifdef DEBUG @@ -1669,7 +1674,14 @@ void usb_disconnect(struct usb_device **pdev) udev->devnum); #ifdef MVF_USB_HOST_HACK if (udev->speed == USB_SPEED_HIGH && udev->level == 1) +#ifdef CONFIG_MACH_PCM052 + { + fsl_platform_set_usb0_phy_dis(NULL, 0); + fsl_platform_set_usb1_phy_dis(NULL, 0); + } +#else fsl_platform_set_usb_phy_dis(NULL, 0); +#endif #endif usb_lock_device(udev); @@ -2917,7 +2929,14 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, } #ifdef MVF_USB_HOST_HACK if (udev->speed == USB_SPEED_HIGH && udev->level == 1) +#ifdef CONFIG_MACH_PCM052 + { + fsl_platform_set_usb0_phy_dis(NULL, 1); + fsl_platform_set_usb1_phy_dis(NULL, 1); + } +#else fsl_platform_set_usb_phy_dis(NULL, 1); +#endif #endif /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? * Because device hardware and firmware is sometimes buggy in -- cgit v1.2.3 From 16af5ee7d9556c47b332788e4107cbed5ee7ec10 Mon Sep 17 00:00:00 2001 From: Russell Robinson Jr Date: Mon, 11 Feb 2013 13:34:12 -0800 Subject: pcm052: usb: enable both USB0 and USB1 as ehci-host note: there are still intermittent detection errors with USB0 Signed-off-by: Russell Robinson Jr --- arch/arm/mach-mvf/board-pcm052.c | 2 +- arch/arm/mach-mvf/usb_dr.c | 228 +++++++++++++++++++++++---------------- arch/arm/mach-mvf/usb_dr2.c | 22 ++-- 3 files changed, 145 insertions(+), 107 deletions(-) diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c index 85706add0494..84bd65623ebb 100644 --- a/arch/arm/mach-mvf/board-pcm052.c +++ b/arch/arm/mach-mvf/board-pcm052.c @@ -486,8 +486,8 @@ static void __init pcm052_init_usb(void) msleep(2); gpio_set_value(USB_VBUS_ENABLE_PIN, 1); -// mvf_usb_dr_init(); #ifdef CONFIG_USB_EHCI_ARC + mvf_usb_dr_init(); mvf_usb_dr2_init(); #endif } diff --git a/arch/arm/mach-mvf/usb_dr.c b/arch/arm/mach-mvf/usb_dr.c index bbd29f3b45a9..34377c4c19b3 100644 --- a/arch/arm/mach-mvf/usb_dr.c +++ b/arch/arm/mach-mvf/usb_dr.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -37,10 +38,6 @@ static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); static void usbotg_wakeup_event_clear(void); -/* The usb_phy0_clk do not have enable/disable function at clock.c - * and PLL output for usb0's phy should be always enabled. - * usb_phy0_clk only stands for usb uses pll3 as its parent. - */ static struct clk *usb_phy0_clk; static u8 otg_used; @@ -65,24 +62,22 @@ static struct fsl_usb2_platform_data dr_utmi_config = { /* Platform data for wakeup operation */ static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = { - .name = "Gadget wakeup", + .name = "Host wakeup", .usb_clock_for_pm = usbotg_clock_gate, .usb_wakeup_exhandle = usbotg_wakeup_event_clear, }; static void usbotg_internal_phy_clock_gate(bool on) { - u32 reg; - void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); - reg = __raw_readl(phy_reg + HW_USBPHY_CTRL); if (on) - reg &= ~BM_USBPHY_CTRL_CLKGATE; + __raw_writel(BM_USBPHY_CTRL_CLKGATE, + phy_reg + HW_USBPHY_CTRL_CLR); else - reg |= BM_USBPHY_CTRL_CLKGATE; + __raw_writel(BM_USBPHY_CTRL_CLKGATE, + phy_reg + HW_USBPHY_CTRL_SET); - __raw_writel(reg, phy_reg + HW_USBPHY_CTRL); } static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) @@ -114,6 +109,13 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) /* Power up the PHY */ __raw_writel(0, phy_reg + HW_USBPHY_PWD); + if ((pdata->operating_mode == FSL_USB2_DR_HOST) || + (pdata->operating_mode == FSL_USB2_DR_OTG)) { + /* enable FS/LS device */ + __raw_writel( + BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3, + phy_reg + HW_USBPHY_CTRL_SET); + } return 0; } @@ -136,8 +138,8 @@ static int usbotg_init_ext(struct platform_device *pdev) usbotg_internal_phy_clock_gate(true); usb_phy_enable(pdev->dev.platform_data); /* - * after the phy reset,can not read the value for id/vbus at - * the register of otgsc ,cannot read at once ,need delay 3 ms + * after the phy reset,can't read the value for id/vbus at + * the register of otgsc at once ,need delay 3 ms */ mdelay(3); } @@ -159,21 +161,18 @@ static void usbotg_uninit_ext(struct platform_device *pdev) static void usbotg_clock_gate(bool on) { - pr_debug("%s: on is %d\n", __func__, on); + if (on) clk_enable(usb_phy0_clk); else clk_disable(usb_phy0_clk); + } -/* -void mvf_set_otghost_vbus_func(driver_vbus_func driver_vbus) -{ - dr_utmi_config.platform_driver_vbus = driver_vbus; -} -*/ + static void _dr_discharge_line(bool enable) { void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + if (enable) { __raw_writel(BF_USBPHY_DEBUG_ENHSTPULLDOWN(0x3), phy_reg + HW_USBPHY_DEBUG_SET); @@ -191,7 +190,6 @@ static void _dr_discharge_line(bool enable) /* Below two macros are used at otg mode to indicate usb mode*/ #define ENABLED_BY_HOST (0x1 << 0) #define ENABLED_BY_DEVICE (0x1 << 1) -static u32 low_power_enable_src; /* only useful at otg mode */ static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { @@ -233,12 +231,11 @@ static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, static void __phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable, int source) { - if (enable) { - low_power_enable_src |= source; + if (enable) enter_phy_lowpower_suspend(pdata, enable); - } else { + else { + pr_debug("phy lowpower disable\n"); enter_phy_lowpower_suspend(pdata, enable); - low_power_enable_src &= ~source; } } @@ -270,10 +267,9 @@ static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata, bool on, int source) { - /* otg host and device share the OWIE bit, only when host and device - * all enable the wakeup irq, we can enable the OWIE bit - */ - if (on) { + pr_debug("USB Host %s,on=%d\n", __func__, on); + mdelay(3); + if (on) { otg_wake_up_enable(pdata, on); } else { otg_wake_up_enable(pdata, on); @@ -302,125 +298,167 @@ static void usbotg_wakeup_event_clear(void) } /* End of Common operation for DR port */ + #ifdef CONFIG_USB_EHCI_ARC_OTG -#endif /* CONFIG_USB_EHCI_ARC_OTG */ +/* Beginning of host related operation for DR port */ +static void _host_platform_suspend(struct fsl_usb2_platform_data *pdata) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + u32 tmp; + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET); +} -#ifdef CONFIG_USB_GADGET_ARC -/* Beginning of device related operation for DR port */ -static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, +static void _host_platform_resume(struct fsl_usb2_platform_data *pdata) +{ + void __iomem *phy_reg = MVF_IO_ADDRESS(MVF_USBPHY0_BASE_ADDR); + u32 tmp; + + tmp = (BM_USBPHY_PWD_TXPWDFS + | BM_USBPHY_PWD_TXPWDIBIAS + | BM_USBPHY_PWD_TXPWDV2I + | BM_USBPHY_PWD_RXPWDENV + | BM_USBPHY_PWD_RXPWD1PT1 + | BM_USBPHY_PWD_RXPWDDIFF + | BM_USBPHY_PWD_RXPWDRX); + __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); +} + +static void _host_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { - __phy_lowpower_suspend(pdata, enable, ENABLED_BY_DEVICE); + __phy_lowpower_suspend(pdata, enable, ENABLED_BY_HOST); } -static void _device_wakeup_enable(struct fsl_usb2_platform_data *pdata, +static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, bool enable) { - __wakeup_irq_enable(pdata, enable, ENABLED_BY_DEVICE); - if (enable) { - pr_debug("device wakeup enable\n"); + __wakeup_irq_enable(pdata, enable, ENABLED_BY_HOST); + + if (enable) device_wakeup_enable(&pdata->pdev->dev); - } else { - pr_debug("device wakeup disable\n"); + else device_wakeup_disable(&pdata->pdev->dev); - } } static enum usb_wakeup_event -_is_device_wakeup(struct fsl_usb2_platform_data *pdata) +_is_host_wakeup(struct fsl_usb2_platform_data *pdata) { - int wakeup_req = USBC0_CTRL & UCTRL_OWIR; + u32 wakeup_req = USBC0_CTRL & UCTRL_OWIR; + u32 otgsc = UOG_OTGSC; - /* if ID=1, it is a device wakeup event */ - if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && - (UOG_USBSTS & USBSTS_URI)) { - printk(KERN_INFO "otg udc wakeup, host sends reset signal\n"); - return WAKEUP_EVENT_DPDM; - } - if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && \ - ((UOG_USBSTS & USBSTS_PCI) || - (UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME))) { - /* - * When the line state from J to K, the Port Change Detect bit - * in the USBSTS register is also set to '1'. - */ - printk(KERN_INFO "otg udc wakeup, host sends resume signal\n"); - return WAKEUP_EVENT_DPDM; + if (wakeup_req) { + pr_debug("the otgsc is 0x%x, usbsts is 0x%x," + " portsc is 0x%x, wakeup_irq is 0x%x\n", + UOG_OTGSC, UOG_USBSTS, UOG_PORTSC1, wakeup_req); } - if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && - (UOG_OTGSC & OTGSC_STS_A_VBUS_VALID) && - (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)) { - printk(KERN_INFO "otg udc vbus rising wakeup\n"); - return WAKEUP_EVENT_VBUS; + /* if ID change sts, it is a host wakeup event */ + if (wakeup_req && (otgsc & OTGSC_IS_USB_ID)) { + pr_debug("otg host ID wakeup\n"); + /* if host ID wakeup, we must clear the b session change sts */ + otgsc &= (~OTGSC_IS_USB_ID); + return WAKEUP_EVENT_ID; } - if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && - !(UOG_OTGSC & OTGSC_STS_A_VBUS_VALID)) { - printk(KERN_INFO "otg udc vbus falling wakeup\n"); - return WAKEUP_EVENT_VBUS; + if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) { + pr_debug("otg host Remote wakeup\n"); + return WAKEUP_EVENT_DPDM; } - - return WAKEUP_EVENT_DPDM; + return WAKEUP_EVENT_INVALID; } -static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata) +static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata) { - _device_phy_lowpower_suspend(pdata, false); - _device_wakeup_enable(pdata, false); + _host_phy_lowpower_suspend(pdata, false); + _host_wakeup_enable(pdata, false); } -/* end of device related operation for DR port */ -#endif /* CONFIG_USB_GADGET_ARC */ + +/* End of host related operation for DR port */ +#endif /* CONFIG_USB_EHCI_ARC_OTG */ + void __init mvf_usb_dr_init(void) { struct platform_device *pdev, *pdev_wakeup; u32 reg; -#ifdef CONFIG_USB_GADGET_ARC - dr_utmi_config.operating_mode = DR_UDC_MODE; - dr_utmi_config.wake_up_enable = _device_wakeup_enable; - dr_utmi_config.platform_suspend = NULL; - dr_utmi_config.platform_resume = NULL; - dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend; - dr_utmi_config.is_wakeup_event = _is_device_wakeup; + +#ifdef CONFIG_USB_EHCI_ARC_OTG + dr_utmi_config.operating_mode = DR_HOST_MODE; + dr_utmi_config.wake_up_enable = _host_wakeup_enable; + dr_utmi_config.platform_suspend = _host_platform_suspend; + dr_utmi_config.platform_resume = _host_platform_resume; + dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend; + dr_utmi_config.is_wakeup_event = _is_host_wakeup; dr_utmi_config.wakeup_pdata = &dr_wakeup_config; - dr_utmi_config.wakeup_handler = device_wakeup_handler; + dr_utmi_config.wakeup_handler = host_wakeup_handler; - pdev = mvf_add_fsl_usb2_udc(&dr_utmi_config); + pdev = mvf_add_fsl_ehci_otg(0, &dr_utmi_config); - dr_wakeup_config.usb_pdata[2] = pdev->dev.platform_data; + dr_wakeup_config.usb_pdata[0] = pdev->dev.platform_data; /* register wakeup device */ - pdev_wakeup = mvf_add_fsl_usb2_udc_wakeup(&dr_wakeup_config); + pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(0, &dr_wakeup_config); if (pdev != NULL) ((struct fsl_usb2_platform_data *) (pdev->dev.platform_data))->wakeup_pdata = (struct fsl_usb2_wakeup_platform_data *) (pdev_wakeup->dev.platform_data); - device_set_wakeup_capable(&pdev->dev, true); - __raw_writel(((0x01 << 30) | 0x2), ANADIG_USB1_MISC); - - __raw_writel(0x00000894, USBPHY1_CTRL); - udelay(10); + __raw_writel(0x0220C802, USBPHY1_CTRL); + udelay(20); __raw_writel(0x0, USBPHY1_PWD); - __raw_writel(0x1, USBPHY1_IP); - udelay(20); - __raw_writel(0x7, USBPHY1_IP); reg = __raw_readl(USBPHY1_DEBUG); - reg &= ~0x40000000; /* clear gate clock */ + reg &= ~0x40000000; /* clear clock gate */ __raw_writel(reg, USBPHY1_DEBUG); + reg = __raw_readl(ANADIG_USB1_MISC); + reg |= (0x01 << 30); /* Enable CLK_TO_UTMI */ + __raw_writel(reg, ANADIG_USB1_MISC); + __raw_writel(0x10000007, USBPHY1_TX); + /*__raw_writel(0x100F0F07, USBPHY1_TX);*/ + + /* Enable disconnect detect */ reg = __raw_readl(USBPHY1_CTRL); - reg |= ((0xD1 << 11) | 0x6); + reg &= ~0x040; /* clear OTG ID change IRQ */ + reg |= (0x1 << 14); /* Enable UTMI+ level2 */ + reg |= (0x1 << 9); + reg |= (0x1 << 15); /* Enable UTMI+ level3 */ + reg &= ~((0xD1 << 11) | 0x6); __raw_writel(reg, USBPHY1_CTRL); + __raw_writel(0x1 << 3, USBPHY1_CTRL + 0x8); + /* Disable VBUS and CHARGER detect */ reg = __raw_readl(ANADIG_USB1_VBUS_DETECT); reg |= 0xE8; __raw_writel(reg, ANADIG_USB1_VBUS_DETECT); __raw_writel(0x001c0000, ANADIG_USB1_CHRG_DETECT); + #endif +} + +/* USB HIGH_SPEED disconnect detect on/off */ +void fsl_platform_set_usb0_phy_dis(struct fsl_usb2_platform_data *pdata, + bool enable) +{ + u32 reg; + reg = __raw_readl(USBPHY1_CTRL); + + if (enable) + reg |= ((0xD1 << 11) | 0x6); + else + reg &= ~((0xD1 << 11) | 0x6); + + __raw_writel(reg, USBPHY1_CTRL); + + __raw_writel(0x1 << 3, USBPHY1_CTRL + 0x8); } diff --git a/arch/arm/mach-mvf/usb_dr2.c b/arch/arm/mach-mvf/usb_dr2.c index 67e3fcdbc921..c1d6ebf51791 100644 --- a/arch/arm/mach-mvf/usb_dr2.c +++ b/arch/arm/mach-mvf/usb_dr2.c @@ -32,8 +32,8 @@ #include "regs-anadig.h" #include "usb.h" -static int usbotg2_init_ext(struct platform_device *pdev); -static void usbotg2_uninit_ext(struct platform_device *pdev); +static int usbotg_init_ext(struct platform_device *pdev); +static void usbotg_uninit_ext(struct platform_device *pdev); static void usbotg_clock_gate(bool on); static void _dr_discharge_line(bool enable); static void usbotg_wakeup_event_clear(void); @@ -49,9 +49,9 @@ static u8 otg2_used; * - operating_mode plugged at run time */ static struct fsl_usb2_platform_data dr_utmi_config = { - .name = "DR", - .init = usbotg2_init_ext, - .exit = usbotg2_uninit_ext, + .name = "DR2", + .init = usbotg_init_ext, + .exit = usbotg_uninit_ext, .phy_mode = FSL_USB2_PHY_UTMI_WIDE, .power_budget = 500, /* 500 mA max power */ .usb_clock_for_pm = usbotg_clock_gate, @@ -120,7 +120,7 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) return 0; } /* Notes: configure USB clock*/ -static int usbotg2_init_ext(struct platform_device *pdev) +static int usbotg_init_ext(struct platform_device *pdev) { struct clk *usb_clk; u32 ret; @@ -148,7 +148,7 @@ static int usbotg2_init_ext(struct platform_device *pdev) return ret; } -static void usbotg2_uninit_ext(struct platform_device *pdev) +static void usbotg_uninit_ext(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; @@ -287,7 +287,7 @@ static void usbotg_wakeup_event_clear(void) int wakeup_req = USBC1_CTRL & UCTRL_OWIR; if (wakeup_req != 0) { - pr_debug("Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC); + pr_debug("Unknown wakeup.(OTGSC 0x%x)\n", UOG2_OTGSC); /* Disable OWIE to clear OWIR, wait 3 clock * cycles of standly clock(32KHz) */ @@ -398,12 +398,12 @@ void __init mvf_usb_dr2_init(void) dr_utmi_config.wakeup_pdata = &dr_wakeup_config; dr_utmi_config.wakeup_handler = host_wakeup_handler; - pdev = mvf_add_fsl_ehci_otg(&dr_utmi_config); + pdev = mvf_add_fsl_ehci_otg(1, &dr_utmi_config); dr_wakeup_config.usb_pdata[1] = pdev->dev.platform_data; /* register wakeup device */ - pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(&dr_wakeup_config); + pdev_wakeup = mvf_add_fsl_usb2_ehci_otg_wakeup(1, &dr_wakeup_config); if (pdev != NULL) ((struct fsl_usb2_platform_data *) (pdev->dev.platform_data))->wakeup_pdata = @@ -446,7 +446,7 @@ void __init mvf_usb_dr2_init(void) } /* USB HIGH_SPEED disconnect detect on/off */ -void fsl_platform_set_usb_phy_dis(struct fsl_usb2_platform_data *pdata, +void fsl_platform_set_usb1_phy_dis(struct fsl_usb2_platform_data *pdata, bool enable) { u32 reg; -- cgit v1.2.3