2 * linux/arch/arm/mach-omap2/mcbsp.c
4 * Copyright (C) 2008 Instituto Nokia de Tecnologia
5 * Contact: Eduardo Valentin <eduardo.valentin@indt.org.br>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Multichannel mode not supported.
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/clk.h>
16 #include <linux/err.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
21 #include <mach/irqs.h>
24 #include <plat/mcbsp.h>
25 #include <plat/omap_device.h>
26 #include <linux/pm_runtime.h>
30 /* McBSP internal signal muxing functions */
32 void omap2_mcbsp1_mux_clkr_src(u8 mux
)
36 v
= omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0
);
37 if (mux
== CLKR_SRC_CLKR
)
38 v
&= ~OMAP2_MCBSP1_CLKR_MASK
;
39 else if (mux
== CLKR_SRC_CLKX
)
40 v
|= OMAP2_MCBSP1_CLKR_MASK
;
41 omap_ctrl_writel(v
, OMAP2_CONTROL_DEVCONF0
);
43 EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src
);
45 void omap2_mcbsp1_mux_fsr_src(u8 mux
)
49 v
= omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0
);
50 if (mux
== FSR_SRC_FSR
)
51 v
&= ~OMAP2_MCBSP1_FSR_MASK
;
52 else if (mux
== FSR_SRC_FSX
)
53 v
|= OMAP2_MCBSP1_FSR_MASK
;
54 omap_ctrl_writel(v
, OMAP2_CONTROL_DEVCONF0
);
56 EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src
);
58 /* McBSP CLKS source switching function */
60 int omap2_mcbsp_set_clks_src(u8 id
, u8 fck_src_id
)
62 struct omap_mcbsp
*mcbsp
;
67 if (!omap_mcbsp_check_valid_id(id
)) {
68 pr_err("%s: Invalid id (%d)\n", __func__
, id
+ 1);
71 mcbsp
= id_to_mcbsp_ptr(id
);
73 if (fck_src_id
== MCBSP_CLKS_PAD_SRC
)
74 fck_src_name
= mcbsp
->pdata
->clks_pad_src
;
75 else if (fck_src_id
== MCBSP_CLKS_PRCM_SRC
)
76 fck_src_name
= mcbsp
->pdata
->clks_prcm_src
;
80 fck_src
= clk_get(mcbsp
->dev
, fck_src_name
);
81 if (IS_ERR_OR_NULL(fck_src
)) {
82 pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
87 pm_runtime_put_sync(mcbsp
->dev
);
89 r
= clk_set_parent(mcbsp
->fclk
, fck_src
);
90 if (IS_ERR_VALUE(r
)) {
91 pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
92 "clks", fck_src_name
);
97 pm_runtime_get_sync(mcbsp
->dev
);
103 EXPORT_SYMBOL(omap2_mcbsp_set_clks_src
);
105 struct omap_device_pm_latency omap2_mcbsp_latency
[] = {
107 .deactivate_func
= omap_device_idle_hwmods
,
108 .activate_func
= omap_device_enable_hwmods
,
109 .flags
= OMAP_DEVICE_LATENCY_AUTO_ADJUST
,
113 static int omap_init_mcbsp(struct omap_hwmod
*oh
, void *unused
)
116 char *name
= "omap-mcbsp";
117 struct omap_hwmod
*oh_device
[2];
118 struct omap_mcbsp_platform_data
*pdata
= NULL
;
119 struct omap_device
*od
;
121 sscanf(oh
->name
, "mcbsp%d", &id
);
123 pdata
= kzalloc(sizeof(struct omap_mcbsp_platform_data
), GFP_KERNEL
);
125 pr_err("%s: No memory for mcbsp\n", __func__
);
129 pdata
->mcbsp_config_type
= oh
->class->rev
;
131 if (oh
->class->rev
== MCBSP_CONFIG_TYPE3
) {
132 strcpy(pdata
->clks_pad_src
, "pad_fck");
133 strcpy(pdata
->clks_prcm_src
, "prcm_fck");
136 /* The FIFO has 1024 + 256 locations */
137 pdata
->buffer_size
= 0x500;
139 /* The FIFO has 128 locations */
140 pdata
->buffer_size
= 0x80;
141 } else if (oh
->class->rev
== MCBSP_CONFIG_TYPE4
) {
142 strcpy(pdata
->clks_pad_src
, "pad_clks_ck");
143 sprintf(pdata
->clks_prcm_src
, "mcbsp%d_sync_mux_ck", id
);
145 /* The FIFO has 128 locations for all instances */
146 pdata
->buffer_size
= 0x80;
152 oh_device
[1] = omap_hwmod_lookup((
153 (struct omap_mcbsp_dev_attr
*)(oh
->dev_attr
))->sidetone
);
156 od
= omap_device_build_ss(name
, id
, oh_device
, count
, pdata
,
157 sizeof(*pdata
), omap2_mcbsp_latency
,
158 ARRAY_SIZE(omap2_mcbsp_latency
), false);
161 pr_err("%s: Can't build omap_device for %s:%s.\n", __func__
,
169 static int __init
omap2_mcbsp_init(void)
171 omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp
, NULL
);
173 mcbsp_ptr
= kzalloc(omap_mcbsp_count
* sizeof(struct omap_mcbsp
*),
178 return omap_mcbsp_init();
180 arch_initcall(omap2_mcbsp_init
);