From 18c9a541ccaf09e8f4cfb98ad797e4df55f8112c Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 25 Aug 2011 13:53:10 -0700 Subject: OMAP4: HWMOD: Add support for McASP This change adds: - HWMOD data structures for McASP peripheral - Function for initialising McASP HWMOD - New sysconfig type for OMAP4 that is used by the McASP - New McASP header file with configuration structure to be passed to the McASP driver Change-Id: I0a96d6032eb4e6a21716c9dc71b84c9f15d99d3d Signed-off-by: Simon Wilson --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 101 +++++++++++++++++++++++++++ arch/arm/mach-omap2/omap_hwmod_common_data.c | 9 +++ arch/arm/plat-omap/devices.c | 38 ++++++++++ arch/arm/plat-omap/include/plat/mcasp.h | 52 ++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 8 +++ 5 files changed, 208 insertions(+) create mode 100644 arch/arm/plat-omap/include/plat/mcasp.h diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index b52857dee20..e10b22fd011 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -3634,6 +3634,104 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), }; +/* + * 'mcasp' class + * multi channel audio serial port controller + */ + +static struct omap_hwmod_class_sysconfig omap44xx_mcasp_sysc = { + .sysc_offs = 0x0004, + .sysc_flags = SYSC_HAS_SIDLEMODE, + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type3, +}; + +static struct omap_hwmod_class omap44xx_mcasp_hwmod_class = { + .name = "omap-mcasp-dai", + .sysc = &omap44xx_mcasp_sysc, +}; + +/* mcasp */ +static struct omap_hwmod omap44xx_mcasp_hwmod; +static struct omap_hwmod_irq_info omap44xx_mcasp_irqs[] = { + { .name = "tx", .irq = 109 + OMAP44XX_IRQ_GIC_START }, + { .name = "rx", .irq = 0 }, +}; + +static struct omap_hwmod_dma_info omap44xx_mcasp_sdma_reqs[] = { + { .name = "tx", .dma_req = 7 + OMAP44XX_DMA_REQ_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_mcasp_addrs[] = { + { + .pa_start = 0x49028000, + .pa_end = 0x49028000 + SZ_4K - 1, /* McASP CFG Port */ + .flags = ADDR_TYPE_RT + }, + { + .pa_start = 0x4902A000, + .pa_end = 0x4902A000 + SZ_4K - 1, /* McASP Data Port */ + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_abe -> mcasp */ +static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcasp = { + .master = &omap44xx_l4_abe_hwmod, + .slave = &omap44xx_mcasp_hwmod, + .clk = "ocp_abe_iclk", + .addr = omap44xx_mcasp_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_mcasp_addrs), + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space omap44xx_mcasp_dma_addrs[] = { + { + .pa_start = 0x49028000, + .pa_end = 0x49028000 + SZ_4K - 1, /* McASP CFG Port */ + .flags = ADDR_TYPE_RT + }, + { + .pa_start = 0x4902A000, + .pa_end = 0x4902A000 + SZ_4K - 1, /* McASP Data Port */ + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_abe -> mcasp (dma) */ +static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcasp_dma = { + .master = &omap44xx_l4_abe_hwmod, + .slave = &omap44xx_mcasp_hwmod, + .clk = "ocp_abe_iclk", + .addr = omap44xx_mcasp_dma_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_mcasp_dma_addrs), + .user = OCP_USER_SDMA, +}; + +/* mcasp1 slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_mcasp_slaves[] = { + &omap44xx_l4_abe__mcasp, + &omap44xx_l4_abe__mcasp_dma, +}; + +static struct omap_hwmod omap44xx_mcasp_hwmod = { + .name = "omap-mcasp-dai", + .class = &omap44xx_mcasp_hwmod_class, + .mpu_irqs = omap44xx_mcasp_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mcasp_irqs), + .sdma_reqs = omap44xx_mcasp_sdma_reqs, + .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_mcasp_sdma_reqs), + .main_clk = "mcasp_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM1_ABE_MCASP_CLKCTRL, + }, + }, + .slaves = omap44xx_mcasp_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_mcasp_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP44XX), +}; + /* * 'mcbsp' class * multi channel buffered serial port controller @@ -6037,6 +6135,9 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* mailbox class */ &omap44xx_mailbox_hwmod, + /* mcasp class */ + &omap44xx_mcasp_hwmod, + /* mcbsp class */ &omap44xx_mcbsp1_hwmod, &omap44xx_mcbsp2_hwmod, diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c index 08a134243ec..03127711e36 100644 --- a/arch/arm/mach-omap2/omap_hwmod_common_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c @@ -49,6 +49,15 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = { .srst_shift = SYSC_TYPE2_SOFTRESET_SHIFT, }; +/** + * struct omap_hwmod_sysc_type3 - TYPE3 sysconfig scheme. + * + * To be used by hwmod structure to specify the sysconfig offsets if the + * device ip is compliant only implements the sidle feature. + */ +struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3 = { + .sidle_shift = SYSC_TYPE3_SIDLEMODE_SHIFT, +}; /* * omap_hwmod class data diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index d8add7e7b2e..3841887eaab 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +77,43 @@ void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, { } #endif + +/*-------------------------------------------------------------------------*/ + +#if defined(CONFIG_SND_OMAP_SOC_MCASP) || \ + defined(CONFIG_SND_OMAP_SOC_MCASP_MODULE) + +static struct omap_device_pm_latency omap_mcasp_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +void omap_init_mcasp(struct omap_mcasp_platform_data *pdata) +{ + struct omap_hwmod *oh; + struct omap_device *od; + + oh = omap_hwmod_lookup("omap-mcasp-dai"); + if (!oh) { + printk(KERN_ERR "Could not look up mcasp hw_mod\n"); + return; + } + + od = omap_device_build("omap-mcasp-dai", -1, oh, pdata, + sizeof(struct omap_mcasp_platform_data), + omap_mcasp_latency, + ARRAY_SIZE(omap_mcasp_latency), 0); + + if (od <= 0) + printk(KERN_ERR "Could not build omap_device for omap-mcasp-dai\n"); +} +#else +inline void omap_init_mcasp(struct omap_mcasp_platform_data *pdata) {} +#endif + /*-------------------------------------------------------------------------*/ #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ diff --git a/arch/arm/plat-omap/include/plat/mcasp.h b/arch/arm/plat-omap/include/plat/mcasp.h new file mode 100644 index 00000000000..aead0a051d8 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/mcasp.h @@ -0,0 +1,52 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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 St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __OMAP_PLAT_MCASP_H__ +#define __OMAP_PLAT_MCASP_H__ + +#include + +/* The SPDIF bit clock is derived from the McASP functional clock. + * The McASP has two programmable clock dividers (aclkxdiv and + * ahclkxdiv) that are configured via the registers MCASP_ACLKXCTL + * and MCASP_AHCLKXCTL. For SPDIF the bit clock frequency should be + * 128 * sample rate freq. Therefore... + * + * McASP functional clock = aclkxdiv * ahclkxdiv * 128 * sample rate + * + * For each sample rate supported the user must define the aclkxdiv + * and ahclkxdiv values that are passed to the McASP driver via the + * following structure. The McASP functional clock frequency can be + * configured also, and this is pass to the McASP driver via the + * omap_mcasp_platform_data structure below. + */ +struct omap_mcasp_configs { + unsigned int sampling_rate; + u16 aclkxdiv; + u16 ahclkxdiv; +}; + +struct omap_mcasp_platform_data { + unsigned long mcasp_fclk_rate; + struct omap_mcasp_configs *mcasp_configs; + unsigned int num_configs; +}; + +void omap_init_mcasp(struct omap_mcasp_platform_data *pdata); + +#endif diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index d99b953380d..42dacc6cc3c 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -40,6 +40,7 @@ struct omap_device; extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1; extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2; +extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3; /* * OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant @@ -69,6 +70,13 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2; #define SYSC_TYPE2_MIDLEMODE_SHIFT 4 #define SYSC_TYPE2_MIDLEMODE_MASK (0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT) +/* + * OCP SYSCONFIG bit shifts/masks TYPE3. These are for IPs compliant + * that only implement the sidle feature. + */ +#define SYSC_TYPE3_SIDLEMODE_SHIFT 0 +#define SYSC_TYPE3_SIDLEMODE_MASK (0x3 << SYSC_TYPE3_SIDLEMODE_SHIFT) + /* OCP SYSSTATUS bit shifts/masks */ #define SYSS_RESETDONE_SHIFT 0 #define SYSS_RESETDONE_MASK (1 << SYSS_RESETDONE_SHIFT) -- cgit v1.2.3