xref: /linux/arch/arm/mach-omap2/mcbsp.c (revision b76c8b19b082c3fc84725de0d3ba5ee1f571c0ae)
178673bc8SEduardo Valentin /*
278673bc8SEduardo Valentin  * linux/arch/arm/mach-omap2/mcbsp.c
378673bc8SEduardo Valentin  *
478673bc8SEduardo Valentin  * Copyright (C) 2008 Instituto Nokia de Tecnologia
578673bc8SEduardo Valentin  * Contact: Eduardo Valentin <eduardo.valentin@indt.org.br>
678673bc8SEduardo Valentin  *
778673bc8SEduardo Valentin  * This program is free software; you can redistribute it and/or modify
878673bc8SEduardo Valentin  * it under the terms of the GNU General Public License version 2 as
978673bc8SEduardo Valentin  * published by the Free Software Foundation.
1078673bc8SEduardo Valentin  *
1178673bc8SEduardo Valentin  * Multichannel mode not supported.
1278673bc8SEduardo Valentin  */
1378673bc8SEduardo Valentin #include <linux/module.h>
1478673bc8SEduardo Valentin #include <linux/init.h>
1578673bc8SEduardo Valentin #include <linux/clk.h>
1678673bc8SEduardo Valentin #include <linux/err.h>
1778673bc8SEduardo Valentin #include <linux/io.h>
18e586e955SPeter Ujfalusi #include <linux/of.h>
1978673bc8SEduardo Valentin #include <linux/platform_device.h>
205a0e3ad6STejun Heo #include <linux/slab.h>
212203747cSArnd Bergmann #include <linux/platform_data/asoc-ti-mcbsp.h>
2225c7d49eSTony Lindgren #include <linux/pm_runtime.h>
2378673bc8SEduardo Valentin 
2445c3eb7dSTony Lindgren #include <linux/omap-dma.h>
2525c7d49eSTony Lindgren 
26*b76c8b19STony Lindgren #include "soc.h"
2725c7d49eSTony Lindgren #include "omap_device.h"
284814ced5SPaul Walmsley 
291743d14fSJarkko Nikula /*
301743d14fSJarkko Nikula  * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
311743d14fSJarkko Nikula  * Sidetone needs non-gated ICLK and sidetone autoidle is broken.
321743d14fSJarkko Nikula  */
33d9a16f9aSPaul Walmsley #include "cm3xxx.h"
341743d14fSJarkko Nikula #include "cm-regbits-34xx.h"
351743d14fSJarkko Nikula 
361743d14fSJarkko Nikula static int omap3_enable_st_clock(unsigned int id, bool enable)
371743d14fSJarkko Nikula {
381743d14fSJarkko Nikula 	unsigned int w;
391743d14fSJarkko Nikula 
401743d14fSJarkko Nikula 	/*
411743d14fSJarkko Nikula 	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
421743d14fSJarkko Nikula 	 * are enabled or sidetones start sounding ugly.
431743d14fSJarkko Nikula 	 */
441743d14fSJarkko Nikula 	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
451743d14fSJarkko Nikula 	if (enable)
461743d14fSJarkko Nikula 		w &= ~(1 << (id - 2));
471743d14fSJarkko Nikula 	else
481743d14fSJarkko Nikula 		w |= 1 << (id - 2);
491743d14fSJarkko Nikula 	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
501743d14fSJarkko Nikula 
511743d14fSJarkko Nikula 	return 0;
521743d14fSJarkko Nikula }
531743d14fSJarkko Nikula 
549cf793f9SKevin Hilman static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
5578673bc8SEduardo Valentin {
5664bcbd33SKishon Vijay Abraham I 	int id, count = 1;
5764bcbd33SKishon Vijay Abraham I 	char *name = "omap-mcbsp";
5864bcbd33SKishon Vijay Abraham I 	struct omap_hwmod *oh_device[2];
5964bcbd33SKishon Vijay Abraham I 	struct omap_mcbsp_platform_data *pdata = NULL;
603528c58eSKevin Hilman 	struct platform_device *pdev;
6178673bc8SEduardo Valentin 
6264bcbd33SKishon Vijay Abraham I 	sscanf(oh->name, "mcbsp%d", &id);
6364bcbd33SKishon Vijay Abraham I 
6464bcbd33SKishon Vijay Abraham I 	pdata = kzalloc(sizeof(struct omap_mcbsp_platform_data), GFP_KERNEL);
6564bcbd33SKishon Vijay Abraham I 	if (!pdata) {
6664bcbd33SKishon Vijay Abraham I 		pr_err("%s: No memory for mcbsp\n", __func__);
6764bcbd33SKishon Vijay Abraham I 		return -ENOMEM;
6864bcbd33SKishon Vijay Abraham I 	}
6964bcbd33SKishon Vijay Abraham I 
70cdc71514SJarkko Nikula 	pdata->reg_step = 4;
7188408230SJarkko Nikula 	if (oh->class->rev < MCBSP_CONFIG_TYPE2) {
72cdc71514SJarkko Nikula 		pdata->reg_size = 2;
7388408230SJarkko Nikula 	} else {
74cdc71514SJarkko Nikula 		pdata->reg_size = 4;
7588408230SJarkko Nikula 		pdata->has_ccr = true;
7688408230SJarkko Nikula 	}
7740c0764bSPeter Ujfalusi 
78cafebc4aSPeter Ujfalusi 	if (oh->class->rev == MCBSP_CONFIG_TYPE2) {
79cafebc4aSPeter Ujfalusi 		/* The FIFO has 128 locations */
80cafebc4aSPeter Ujfalusi 		pdata->buffer_size = 0x80;
81cafebc4aSPeter Ujfalusi 	} else if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
8264bcbd33SKishon Vijay Abraham I 		if (id == 2)
8364bcbd33SKishon Vijay Abraham I 			/* The FIFO has 1024 + 256 locations */
8464bcbd33SKishon Vijay Abraham I 			pdata->buffer_size = 0x500;
8564bcbd33SKishon Vijay Abraham I 		else
8664bcbd33SKishon Vijay Abraham I 			/* The FIFO has 128 locations */
8764bcbd33SKishon Vijay Abraham I 			pdata->buffer_size = 0x80;
88da76250eSPeter Ujfalusi 	} else if (oh->class->rev == MCBSP_CONFIG_TYPE4) {
89da76250eSPeter Ujfalusi 		/* The FIFO has 128 locations for all instances */
90da76250eSPeter Ujfalusi 		pdata->buffer_size = 0x80;
9164bcbd33SKishon Vijay Abraham I 	}
9264bcbd33SKishon Vijay Abraham I 
931a645884SJarkko Nikula 	if (oh->class->rev >= MCBSP_CONFIG_TYPE3)
941a645884SJarkko Nikula 		pdata->has_wakeup = true;
951a645884SJarkko Nikula 
9664bcbd33SKishon Vijay Abraham I 	oh_device[0] = oh;
9764bcbd33SKishon Vijay Abraham I 
9864bcbd33SKishon Vijay Abraham I 	if (oh->dev_attr) {
9964bcbd33SKishon Vijay Abraham I 		oh_device[1] = omap_hwmod_lookup((
10064bcbd33SKishon Vijay Abraham I 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
1011743d14fSJarkko Nikula 		pdata->enable_st_clock = omap3_enable_st_clock;
10264bcbd33SKishon Vijay Abraham I 		count++;
10364bcbd33SKishon Vijay Abraham I 	}
1043528c58eSKevin Hilman 	pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
105f718e2c0SBenoit Cousson 				sizeof(*pdata), NULL, 0, false);
10664bcbd33SKishon Vijay Abraham I 	kfree(pdata);
1073528c58eSKevin Hilman 	if (IS_ERR(pdev))  {
10825985edcSLucas De Marchi 		pr_err("%s: Can't build omap_device for %s:%s.\n", __func__,
10964bcbd33SKishon Vijay Abraham I 					name, oh->name);
1103528c58eSKevin Hilman 		return PTR_ERR(pdev);
11164bcbd33SKishon Vijay Abraham I 	}
11264bcbd33SKishon Vijay Abraham I 	return 0;
11364bcbd33SKishon Vijay Abraham I }
114a5b92cc3SSyed Rafiuddin 
115b4b58f58SChandra Shekhar static int __init omap2_mcbsp_init(void)
11678673bc8SEduardo Valentin {
117e586e955SPeter Ujfalusi 	if (!of_have_populated_dt())
11864bcbd33SKishon Vijay Abraham I 		omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
119b4b58f58SChandra Shekhar 
1200210dc4eSPeter Ujfalusi 	return 0;
12178673bc8SEduardo Valentin }
122*b76c8b19STony Lindgren omap_arch_initcall(omap2_mcbsp_init);
123