static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	dma_addr_t ptr;
	snd_pcm_uframes_t offset;

	if (cpu_is_omap1510()) {
		offset = prtd->period_index * runtime->period_size;
	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		ptr = omap_get_dma_dst_pos(prtd->dma_ch);
		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	} else {
		ptr = omap_get_dma_src_pos(prtd->dma_ch);
		offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
	}

	if (offset >= runtime->buffer_size)
		offset = 0;

	return offset;
}
Ejemplo n.º 2
0
Archivo: io.c Proyecto: kzlin129/tt-gpl
static void __init _omap_map_io(void)
{
	initialized = 1;

	/* We have to initialize the IO space mapping before we can run
	 * cpu_is_omapxxx() macros. */
	iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
	omap_check_revision();

#ifdef CONFIG_ARCH_OMAP730
	if (cpu_is_omap730()) {
		iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
	}
#endif
#ifdef CONFIG_ARCH_OMAP1510
	if (cpu_is_omap1510()) {
		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
	}
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
	if (cpu_is_omap1610() || cpu_is_omap1710()) {
		iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
	}
	if (cpu_is_omap5912()) {
		iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
	}
#endif

	/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
	 * on a Posted Write in the TIPB Bridge".
	 */
	omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL);
	omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL);

	/* Must init clocks early to assure that timer interrupt works
	 */
	clk_init();
}
Ejemplo n.º 3
0
/*
 *  Main dma routine, requests dma according where you are in main alsa buffer
 */
static void audio_process_dma(struct audio_stream *s)
{
	struct snd_pcm_substream *substream = s->stream;
	struct snd_pcm_runtime *runtime;
	unsigned int dma_size;
	unsigned int offset;
	int ret;
	
	ADEBUG();
	runtime = substream->runtime;
	if (s->active) {
		dma_size = frames_to_bytes(runtime, runtime->period_size);
		offset = dma_size * s->period;
		snd_assert(dma_size <= DMA_BUF_SIZE,);
		/*
		 * On omap1510 based devices, we need to call the stop_dma
		 * before calling the start_dma or we will not receive the
		 * irq from DMA after the first transfered/played buffer.
		 * (invocation of callback_omap_alsa_sound_dma() method).
		 */
		if (cpu_is_omap1510()) {
			omap_stop_alsa_sound_dma(s);
		}
		ret = omap_start_alsa_sound_dma(s,
				(dma_addr_t)runtime->dma_area + offset,
				dma_size);
		if (ret) {
			printk(KERN_ERR
			       "audio_process_dma: cannot queue DMA buffer (%i)\n",
			       ret);
			return;
		}

		s->period++;
		s->period %= runtime->periods;
		s->periods++;
		s->offset = offset;
	}
Ejemplo n.º 4
0
static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
{
	struct snd_pcm_substream *substream = data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	unsigned long flags;

	if ((cpu_is_omap1510())) {
		/*
		 * OMAP1510 doesn't fully support DMA progress counter
		 * and there is no software emulation implemented yet,
		 * so have to maintain our own progress counters
		 * that can be used by omap_pcm_pointer() instead.
		 */
		spin_lock_irqsave(&prtd->lock, flags);
		if ((stat == OMAP_DMA_LAST_IRQ) &&
				(prtd->period_index == runtime->periods - 1)) {
			/* we are in sync, do nothing */
			spin_unlock_irqrestore(&prtd->lock, flags);
			return;
		}
		if (prtd->period_index >= 0) {
			if (stat & OMAP_DMA_BLOCK_IRQ) {
				/* end of buffer reached, loop back */
				prtd->period_index = 0;
			} else if (stat & OMAP_DMA_LAST_IRQ) {
				/* update the counter for the last period */
				prtd->period_index = runtime->periods - 1;
			} else if (++prtd->period_index >= runtime->periods) {
				/* end of buffer missed? loop back */
				prtd->period_index = 0;
			}
		}
		spin_unlock_irqrestore(&prtd->lock, flags);
	}

	snd_pcm_period_elapsed(substream);
}
Ejemplo n.º 5
0
static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
{
	struct snd_pcm_substream *substream = data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	unsigned long flags;

	if (cpu_is_omap1510()) {
		/*
		 * OMAP1510 doesn't support DMA chaining so have to restart
		 * the transfer after all periods are transferred
		 */
		spin_lock_irqsave(&prtd->lock, flags);
		if (prtd->period_index >= 0) {
			if (++prtd->period_index == runtime->periods) {
				prtd->period_index = 0;
				omap_start_dma(prtd->dma_ch);
			}
		}
		spin_unlock_irqrestore(&prtd->lock, flags);
	}

	snd_pcm_period_elapsed(substream);
}
Ejemplo n.º 6
0
static int omap_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	struct omap_pcm_dma_data *dma_data = prtd->dma_data;
	struct omap_dma_channel_params dma_params;
	int bytes;

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if (!prtd->dma_data)
		return 0;

	memset(&dma_params, 0, sizeof(dma_params));
	dma_params.data_type			= dma_data->data_type;
	dma_params.trigger			= dma_data->dma_req;
	dma_params.sync_mode			= dma_data->sync_mode;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		dma_params.src_amode		= OMAP_DMA_AMODE_POST_INC;
		dma_params.dst_amode		= OMAP_DMA_AMODE_CONSTANT;
		dma_params.src_or_dst_synch	= OMAP_DMA_DST_SYNC;
		dma_params.src_start		= runtime->dma_addr;
		dma_params.dst_start		= dma_data->port_addr;
		dma_params.dst_port		= OMAP_DMA_PORT_MPUI;
		dma_params.dst_fi		= dma_data->packet_size;
	} else {
		dma_params.src_amode		= OMAP_DMA_AMODE_CONSTANT;
		dma_params.dst_amode		= OMAP_DMA_AMODE_POST_INC;
		dma_params.src_or_dst_synch	= OMAP_DMA_SRC_SYNC;
		dma_params.src_start		= dma_data->port_addr;
		dma_params.dst_start		= runtime->dma_addr;
		dma_params.src_port		= OMAP_DMA_PORT_MPUI;
		dma_params.src_fi		= dma_data->packet_size;
	}
	/*
	 * Set DMA transfer frame size equal to ALSA period size and frame
	 * count as no. of ALSA periods. Then with DMA frame interrupt enabled,
	 * we can transfer the whole ALSA buffer with single DMA transfer but
	 * still can get an interrupt at each period bounary
	 */
	bytes = snd_pcm_lib_period_bytes(substream);
	dma_params.elem_count	= bytes >> dma_data->data_type;
	dma_params.frame_count	= runtime->periods;
	omap_set_dma_params(prtd->dma_ch, &dma_params);

	if ((cpu_is_omap1510()))
		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
			      OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
	else if (!substream->runtime->no_period_wakeup)
		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
	else {
		/*
		 * No period wakeup:
		 * we need to disable BLOCK_IRQ, which is enabled by the omap
		 * dma core at request dma time.
		 */
		omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ);
	}

	if (!(cpu_class_is_omap1())) {
		omap_set_dma_src_burst_mode(prtd->dma_ch,
						OMAP_DMA_DATA_BURST_16);
		omap_set_dma_dest_burst_mode(prtd->dma_ch,
						OMAP_DMA_DATA_BURST_16);
	}

	return 0;
}
Ejemplo n.º 7
0
/*
 * Note that on Innovator-1510 UART2 pins conflict with USB2.
 * By default UART2 does not work on Innovator-1510 if you have
 * USB OHCI enabled. To use UART2, you must disable USB2 first.
 */
void __init omap_serial_init(void)
{
	int i;
	const struct omap_uart_config *info;

	if (cpu_is_omap730()) {
		serial_platform_data[0].regshift = 0;
		serial_platform_data[1].regshift = 0;
		serial_platform_data[0].irq = INT_730_UART_MODEM_1;
		serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2;
	}

	if (cpu_is_omap1510()) {
		serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
		serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
		serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
	}

	info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
	if (info == NULL)
		return;

	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
		unsigned char reg;

		if (!((1 << i) & info->enabled_uarts)) {
			serial_platform_data[i].membase = NULL;
			serial_platform_data[i].mapbase = 0;
			continue;
		}

		switch (i) {
		case 0:
			uart1_ck = clk_get(NULL, "uart1_ck");
			if (IS_ERR(uart1_ck))
				printk("Could not get uart1_ck\n");
			else {
				clk_use(uart1_ck);
				if (cpu_is_omap1510())
					clk_set_rate(uart1_ck, 12000000);
			}
			if (cpu_is_omap1510()) {
				omap_cfg_reg(UART1_TX);
				omap_cfg_reg(UART1_RTS);
				if (machine_is_omap_innovator()) {
					reg = fpga_read(OMAP1510_FPGA_POWER);
					reg |= OMAP1510_FPGA_PCR_COM1_EN;
					fpga_write(reg, OMAP1510_FPGA_POWER);
					udelay(10);
				}
			}
			break;
		case 1:
			uart2_ck = clk_get(NULL, "uart2_ck");
			if (IS_ERR(uart2_ck))
				printk("Could not get uart2_ck\n");
			else {
				clk_use(uart2_ck);
				if (cpu_is_omap1510())
					clk_set_rate(uart2_ck, 12000000);
				else
					clk_set_rate(uart2_ck, 48000000);
			}
			if (cpu_is_omap1510()) {
				omap_cfg_reg(UART2_TX);
				omap_cfg_reg(UART2_RTS);
				if (machine_is_omap_innovator()) {
					reg = fpga_read(OMAP1510_FPGA_POWER);
					reg |= OMAP1510_FPGA_PCR_COM2_EN;
					fpga_write(reg, OMAP1510_FPGA_POWER);
					udelay(10);
				}
			}
			break;
		case 2:
			uart3_ck = clk_get(NULL, "uart3_ck");
			if (IS_ERR(uart3_ck))
				printk("Could not get uart3_ck\n");
			else {
				clk_use(uart3_ck);
				if (cpu_is_omap1510())
					clk_set_rate(uart3_ck, 12000000);
			}
			if (cpu_is_omap1510()) {
				omap_cfg_reg(UART3_TX);
				omap_cfg_reg(UART3_RX);
			}
			break;
		}
		omap_serial_reset(&serial_platform_data[i]);
	}
}
Ejemplo n.º 8
0
int __init omap1_clk_init(void)
{
	struct omap_clk *c;
	int crystal_type = 0; /* Default 12 MHz */
	u32 reg;

#ifdef CONFIG_DEBUG_LL
	/*
	 * Resets some clocks that may be left on from bootloader,
	 * but leaves serial clocks on.
	 */
	omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
#endif

	/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
	reg = omap_readw(SOFT_REQ_REG) & (1 << 4);
	omap_writew(reg, SOFT_REQ_REG);
	if (!cpu_is_omap15xx())
		omap_writew(0, SOFT_REQ_REG2);

	/* By default all idlect1 clocks are allowed to idle */
	arm_idlect1_mask = ~0;

	for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
		clk_preinit(c->lk.clk);

	cpu_mask = 0;
	if (cpu_is_omap1710())
		cpu_mask |= CK_1710;
	if (cpu_is_omap16xx())
		cpu_mask |= CK_16XX;
	if (cpu_is_omap1510())
		cpu_mask |= CK_1510;
	if (cpu_is_omap7xx())
		cpu_mask |= CK_7XX;
	if (cpu_is_omap310())
		cpu_mask |= CK_310;

	for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
		if (c->cpu & cpu_mask) {
			clkdev_add(&c->lk);
			clk_register(c->lk.clk);
		}

	/* Pointers to these clocks are needed by code in clock.c */
	api_ck_p = clk_get(NULL, "api_ck");
	ck_dpll1_p = clk_get(NULL, "ck_dpll1");
	ck_ref_p = clk_get(NULL, "ck_ref");

	if (cpu_is_omap7xx())
		ck_ref.rate = 13000000;
	if (cpu_is_omap16xx() && crystal_type == 2)
		ck_ref.rate = 19200000;

	pr_info("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n",
		omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
		omap_readw(ARM_CKCTL));

	/* We want to be in syncronous scalable mode */
	omap_writew(0x1000, ARM_SYSST);


	/*
	 * Initially use the values set by bootloader. Determine PLL rate and
	 * recalculate dependent clocks as if kernel had changed PLL or
	 * divisors. See also omap1_clk_late_init() that can reprogram dpll1
	 * after the SRAM is initialized.
	 */
	{
		unsigned pll_ctl_val = omap_readw(DPLL_CTL);

		ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */
		if (pll_ctl_val & 0x10) {
			/* PLL enabled, apply multiplier and divisor */
			if (pll_ctl_val & 0xf80)
				ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7;
			ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1;
		} else {
			/* PLL disabled, apply bypass divisor */
			switch (pll_ctl_val & 0xc) {
			case 0:
				break;
			case 0x4:
				ck_dpll1.rate /= 2;
				break;
			default:
				ck_dpll1.rate /= 4;
				break;
			}
		}
	}
Ejemplo n.º 9
0
/***************************************************************************************
 *
 * Sync up the buffers before we shutdown, else under-run errors will happen
 *
 **************************************************************************************/
int audio_sync(struct file *file)
{
	audio_state_t *state = file->private_data;
	audio_stream_t *s = state->output_stream;
	audio_buf_t *b;
	u_int shiftval = 0;
	unsigned long flags;

	DECLARE_WAITQUEUE(wait, current);

	FN_IN;

	if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped) {
		FN_OUT(1);
		return 0;
	}

	/*
	 * Send current buffer if it contains data.  Be sure to send
	 * a full sample count.
	 */
	b = &s->buffers[s->usr_head];
	if (b->offset &= ~3) {
		/* Wait for a buffer to become free */
		if (wait_for_completion_interruptible(&s->wfc))
			return 0;
		/*
		 * HACK ALERT !
		 * To avoid increased complexity in the rest of the code
		 * where full fragment sizes are assumed, we cheat a little
		 * with the start pointer here and don't forget to restore
		 * it later.
		 */
		
		/* As this is a last frag we need only one dma channel
		 * to complete. So it's need to unlink dma channels
		 * to avoid empty dma work.
		 */
		if (!cpu_is_omap1510() && AUDIO_QUEUE_EMPTY(s))
			omap_sound_dma_unlink_lch(s);

		shiftval = s->fragsize - b->offset;
		b->offset = shiftval;
		b->dma_addr -= shiftval;
		b->data -= shiftval;
		local_irq_save(flags);
		s->bytecount -= shiftval;
		if (++s->usr_head >= s->nbfrags)
			s->usr_head = 0;

		s->pending_frags++;
		audio_process_dma(s);
		local_irq_restore(flags);
	}

	/* Let's wait for all buffers to complete */
	set_current_state(TASK_INTERRUPTIBLE);
	add_wait_queue(&s->wq, &wait);
	while ((s->pending_frags || (s->wfc.done < s->nbfrags))
	       && !signal_pending(current)) {
		schedule();
		set_current_state(TASK_INTERRUPTIBLE);
	}
	set_current_state(TASK_RUNNING);
	remove_wait_queue(&s->wq, &wait);

	/* undo the pointer hack above */
	if (shiftval) {
		local_irq_save(flags);
		b->dma_addr += shiftval;
		b->data += shiftval;
		/* ensure sane DMA code behavior if not yet processed */
		if (b->offset != 0)
			b->offset = s->fragsize;
		local_irq_restore(flags);
	}

	FN_OUT(0);
	return 0;
}
Ejemplo n.º 10
0
/**
 * usb_hcd_omap_probe - initialize OMAP-based HCDs
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller, and
 * then invokes the start() method for the HCD associated with it
 * through the hotplug entry's driver_data.
 */
static int usb_hcd_omap_probe (const struct hc_driver *driver,
			  struct platform_device *pdev)
{
	int retval, irq;
	struct usb_hcd *hcd = 0;
	struct ohci_hcd *ohci;

	if (pdev->num_resources != 2) {
		printk(KERN_ERR "hcd probe: invalid num_resources: %i\n",
		       pdev->num_resources);
		return -ENODEV;
	}

	if (pdev->resource[0].flags != IORESOURCE_MEM
			|| pdev->resource[1].flags != IORESOURCE_IRQ) {
		printk(KERN_ERR "hcd probe: invalid resource type\n");
		return -ENODEV;
	}

	usb_host_ck = clk_get(0, "usb_hhc_ck");
	if (IS_ERR(usb_host_ck))
		return PTR_ERR(usb_host_ck);

	if (!cpu_is_omap1510())
		usb_dc_ck = clk_get(0, "usb_dc_ck");
	else
		usb_dc_ck = clk_get(0, "lb_ck");

	if (IS_ERR(usb_dc_ck)) {
		clk_put(usb_host_ck);
		return PTR_ERR(usb_dc_ck);
	}


	hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
	if (!hcd) {
		retval = -ENOMEM;
		goto err0;
	}
	hcd->rsrc_start = pdev->resource[0].start;
	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;

	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
		dev_dbg(&pdev->dev, "request_mem_region failed\n");
		retval = -EBUSY;
		goto err1;
	}

	hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start);

	ohci = hcd_to_ohci(hcd);
	ohci_hcd_init(ohci);

	host_initialized = 0;
	host_enabled = 1;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		retval = -ENXIO;
		goto err2;
	}
	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
	if (retval)
		goto err2;

	host_initialized = 1;

	if (!host_enabled)
		omap_ohci_clock_power(0);

	return 0;
err2:
	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
	usb_put_hcd(hcd);
err0:
	clk_put(usb_dc_ck);
	clk_put(usb_host_ck);
	return retval;
}
Ejemplo n.º 11
0
static int ohci_omap_init(struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
	struct omap_usb_config	*config = hcd->self.controller->platform_data;
	int			need_transceiver = (config->otg != 0);
	int			ret;

	dev_dbg(hcd->self.controller, "starting USB Controller\n");

	if (config->otg) {
		ohci_to_hcd(ohci)->self.otg_port = config->otg;
		/* default/minimum OTG power budget:  8 mA */
		ohci_to_hcd(ohci)->power_budget = 8;
	}

	/* boards can use OTG transceivers in non-OTG modes */
	need_transceiver = need_transceiver
			|| machine_is_omap_h2() || machine_is_omap_h3();

	if (cpu_is_omap16xx())
		ocpi_enable();

#ifdef	CONFIG_ARCH_OMAP_OTG
	if (need_transceiver) {
		ohci->transceiver = otg_get_transceiver();
		if (ohci->transceiver) {
			int	status = otg_set_host(ohci->transceiver,
						&ohci_to_hcd(ohci)->self);
			dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
					ohci->transceiver->label, status);
			if (status) {
				if (ohci->transceiver)
					put_device(ohci->transceiver->dev);
				return status;
			}
		} else {
			dev_err(hcd->self.controller, "can't find transceiver\n");
			return -ENODEV;
		}
	}
#endif

	omap_ohci_clock_power(1);

	if (cpu_is_omap1510()) {
		omap_1510_local_bus_power(1);
		omap_1510_local_bus_init();
	}

	if ((ret = ohci_init(ohci)) < 0)
		return ret;

	/* board-specific power switching and overcurrent support */
	if (machine_is_omap_osk() || machine_is_omap_innovator()) {
		u32	rh = roothub_a (ohci);

		/* power switching (ganged by default) */
		rh &= ~RH_A_NPS;

		/* TPS2045 switch for internal transceiver (port 1) */
		if (machine_is_omap_osk()) {
			ohci_to_hcd(ohci)->power_budget = 250;

			rh &= ~RH_A_NOCP;

			/* gpio9 for overcurrent detction */
			omap_cfg_reg(W8_1610_GPIO9);
			omap_request_gpio(9);
			omap_set_gpio_direction(9, 1 /* IN */);

			/* for paranoia's sake:  disable USB.PUEN */
			omap_cfg_reg(W4_USB_HIGHZ);
		}
		ohci_writel(ohci, rh, &ohci->regs->roothub.a);
		distrust_firmware = 0;
	} else if (machine_is_nokia770()) {
		/* We require a self-powered hub, which should have
		 * plenty of power. */
		ohci_to_hcd(ohci)->power_budget = 0;
	}

	/* FIXME khubd hub requests should manage power switching */
	omap_ohci_transceiver_power(1);

	/* board init will have already handled HMC and mux setup.
	 * any external transceiver should already be initialized
	 * too, so all configured ports use the right signaling now.
	 */

	return 0;
}
Ejemplo n.º 12
0
/*
 * Sets the Omap MUX and PULL_DWN registers based on the table
 */
int __init_or_module omap_cfg_reg(const unsigned long index)
{
	static DEFINE_RAW_SPINLOCK(mux_spin_lock);

	unsigned long flags;
	struct pin_config *cfg;
	unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
		pull_orig = 0, pull = 0;
	unsigned int mask, warn = 0;

	if (!pin_table)
		BUG();

	if (index >= pin_table_sz) {
		printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
		       index, pin_table_sz);
		dump_stack();
		return -ENODEV;
	}

	cfg = (struct pin_config *)&pin_table[index];
	if (cpu_is_omap24xx()) {
		u8 reg = 0;

		reg |= cfg->mask & 0x7;
		if (cfg->pull_val)
			reg |= OMAP24XX_PULL_ENA;
		if(cfg->pu_pd_val)
			reg |= OMAP24XX_PULL_UP;
#if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
		{
			u8 orig = omap_readb(OMAP24XX_L4_BASE + cfg->mux_reg);
			u8 debug = 0;

#ifdef	CONFIG_OMAP_MUX_DEBUG
			debug = cfg->debug;
#endif
			warn = (orig != reg);
			if (debug || warn)
				printk("MUX: setup %s (0x%08x): 0x%02x -> 0x%02x\n",
				       cfg->name,
				       OMAP24XX_L4_BASE + cfg->mux_reg,
				       orig, reg);
		}
#endif
		omap_writeb(reg, OMAP24XX_L4_BASE + cfg->mux_reg);

		return 0;
	}

	/* Check the mux register in question */
	if (cfg->mux_reg) {
		unsigned	tmp1, tmp2;

		spin_lock_irqsave(&mux_spin_lock, flags);
		reg_orig = omap_readl(cfg->mux_reg);

		/* The mux registers always seem to be 3 bits long */
		mask = (0x7 << cfg->mask_offset);
		tmp1 = reg_orig & mask;
		reg = reg_orig & ~mask;

		tmp2 = (cfg->mask << cfg->mask_offset);
		reg |= tmp2;

		if (tmp1 != tmp2)
			warn = 1;

		omap_writel(reg, cfg->mux_reg);
		spin_unlock_irqrestore(&mux_spin_lock, flags);
	}

	/* Check for pull up or pull down selection on 1610 */
	if (!cpu_is_omap1510()) {
		if (cfg->pu_pd_reg && cfg->pull_val) {
			spin_lock_irqsave(&mux_spin_lock, flags);
			pu_pd_orig = omap_readl(cfg->pu_pd_reg);
			mask = 1 << cfg->pull_bit;

			if (cfg->pu_pd_val) {
				if (!(pu_pd_orig & mask))
					warn = 1;
				/* Use pull up */
				pu_pd = pu_pd_orig | mask;
			} else {
				if (pu_pd_orig & mask)
					warn = 1;
				/* Use pull down */
				pu_pd = pu_pd_orig & ~mask;
			}
			omap_writel(pu_pd, cfg->pu_pd_reg);
			spin_unlock_irqrestore(&mux_spin_lock, flags);
		}
	}

	/* Check for an associated pull down register */
	if (cfg->pull_reg) {
		spin_lock_irqsave(&mux_spin_lock, flags);
		pull_orig = omap_readl(cfg->pull_reg);
		mask = 1 << cfg->pull_bit;

		if (cfg->pull_val) {
			if (pull_orig & mask)
				warn = 1;
			/* Low bit = pull enabled */
			pull = pull_orig & ~mask;
		} else {
			if (!(pull_orig & mask))
				warn = 1;
			/* High bit = pull disabled */
			pull = pull_orig | mask;
		}

		omap_writel(pull, cfg->pull_reg);
		spin_unlock_irqrestore(&mux_spin_lock, flags);
	}

	if (warn) {
#ifdef CONFIG_OMAP_MUX_WARNINGS
		printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
#endif
	}

#ifdef CONFIG_OMAP_MUX_DEBUG
	if (cfg->debug || warn) {
		printk("MUX: Setting register %s\n", cfg->name);
		printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
		       cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);

		if (!cpu_is_omap1510()) {
			if (cfg->pu_pd_reg && cfg->pull_val) {
				printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
				       cfg->pu_pd_name, cfg->pu_pd_reg,
				       pu_pd_orig, pu_pd);
			}
		}

		if (cfg->pull_reg)
			printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
			       cfg->pull_name, cfg->pull_reg, pull_orig, pull);
	}
#endif

#ifdef CONFIG_OMAP_MUX_ERRORS
	return warn ? -ETXTBSY : 0;
#else
	return 0;
#endif
}
Ejemplo n.º 13
0
/*
 * Sets the Omap MUX and PULL_DWN registers based on the table
 */
int __init_or_module
omap_cfg_reg(const reg_cfg_t reg_cfg)
{
	static DEFINE_SPINLOCK(mux_spin_lock);

	unsigned long flags;
	reg_cfg_set *cfg;
	unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
		pull_orig = 0, pull = 0;
	unsigned int mask, warn = 0;

	if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
		printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
		return -EINVAL;
	}

	cfg = &reg_cfg_table[reg_cfg];

	/*
	 * We do a pretty long section here with lock on, but pin muxing
	 * should only happen on driver init for each driver, so it's not time
	 * critical.
	 */
	spin_lock_irqsave(&mux_spin_lock, flags);

	/* Check the mux register in question */
	if (cfg->mux_reg) {
		unsigned	tmp1, tmp2;

		reg_orig = omap_readl(cfg->mux_reg);

		/* The mux registers always seem to be 3 bits long */
		mask = (0x7 << cfg->mask_offset);
		tmp1 = reg_orig & mask;
		reg = reg_orig & ~mask;

		tmp2 = (cfg->mask << cfg->mask_offset);
		reg |= tmp2;

		if (tmp1 != tmp2)
			warn = 1;

		omap_writel(reg, cfg->mux_reg);
	}

	/* Check for pull up or pull down selection on 1610 */
	if (!cpu_is_omap1510()) {
		if (cfg->pu_pd_reg && cfg->pull_val) {
			pu_pd_orig = omap_readl(cfg->pu_pd_reg);
			mask = 1 << cfg->pull_bit;

			if (cfg->pu_pd_val) {
				if (!(pu_pd_orig & mask))
					warn = 1;
				/* Use pull up */
				pu_pd = pu_pd_orig | mask;
			} else {
				if (pu_pd_orig & mask)
					warn = 1;
				/* Use pull down */
				pu_pd = pu_pd_orig & ~mask;
			}
			omap_writel(pu_pd, cfg->pu_pd_reg);
		}
	}

	/* Check for an associated pull down register */
	if (cfg->pull_reg) {
		pull_orig = omap_readl(cfg->pull_reg);
		mask = 1 << cfg->pull_bit;

		if (cfg->pull_val) {
			if (pull_orig & mask)
				warn = 1;
			/* Low bit = pull enabled */
			pull = pull_orig & ~mask;
		} else {
			if (!(pull_orig & mask))
				warn = 1;
			/* High bit = pull disabled */
			pull = pull_orig | mask;
		}

		omap_writel(pull, cfg->pull_reg);
	}

	if (warn) {
#ifdef CONFIG_OMAP_MUX_WARNINGS
		printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
#endif
	}

#ifdef CONFIG_OMAP_MUX_DEBUG
	if (cfg->debug || warn) {
		printk("MUX: Setting register %s\n", cfg->name);
		printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
		       cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);

		if (!cpu_is_omap1510()) {
			if (cfg->pu_pd_reg && cfg->pull_val) {
				printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
				       cfg->pu_pd_name, cfg->pu_pd_reg,
				       pu_pd_orig, pu_pd);
			}
		}

		if (cfg->pull_reg)
			printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
			       cfg->pull_name, cfg->pull_reg, pull_orig, pull);
	}
#endif

	spin_unlock_irqrestore(&mux_spin_lock, flags);

#ifdef CONFIG_OMAP_MUX_ERRORS
	return warn ? -ETXTBSY : 0;
#else
	return 0;
#endif
}
Ejemplo n.º 14
0
int __init omap1_clk_init(void)
{
	struct omap_clk *c;
	const struct omap_clock_config *info;
	int crystal_type = 0; /* Default 12 MHz */
	u32 reg, cpu_mask;

#ifdef CONFIG_DEBUG_LL
	/*
	 * Resets some clocks that may be left on from bootloader,
	 * but leaves serial clocks on.
	 */
	omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
#endif

	/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
	reg = omap_readw(SOFT_REQ_REG) & (1 << 4);
	omap_writew(reg, SOFT_REQ_REG);
	if (!cpu_is_omap15xx())
		omap_writew(0, SOFT_REQ_REG2);

	clk_init(&omap1_clk_functions);

	/* By default all idlect1 clocks are allowed to idle */
	arm_idlect1_mask = ~0;

	for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
		clk_preinit(c->lk.clk);

	cpu_mask = 0;
	if (cpu_is_omap16xx())
		cpu_mask |= CK_16XX;
	if (cpu_is_omap1510())
		cpu_mask |= CK_1510;
	if (cpu_is_omap7xx())
		cpu_mask |= CK_7XX;
	if (cpu_is_omap310())
		cpu_mask |= CK_310;

	for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
		if (c->cpu & cpu_mask) {
			clkdev_add(&c->lk);
			clk_register(c->lk.clk);
		}

	/* Pointers to these clocks are needed by code in clock.c */
	api_ck_p = clk_get(NULL, "api_ck");
	ck_dpll1_p = clk_get(NULL, "ck_dpll1");
	ck_ref_p = clk_get(NULL, "ck_ref");

	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
	if (info != NULL) {
		if (!cpu_is_omap15xx())
			crystal_type = info->system_clock_type;
	}

#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
	ck_ref.rate = 13000000;
#elif defined(CONFIG_ARCH_OMAP16XX)
	if (crystal_type == 2)
		ck_ref.rate = 19200000;
#endif

	pr_info("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: "
		"0x%04x\n", omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
		omap_readw(ARM_CKCTL));

	/* We want to be in syncronous scalable mode */
	omap_writew(0x1000, ARM_SYSST);

#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
	/* Use values set by bootloader. Determine PLL rate and recalculate
	 * dependent clocks as if kernel had changed PLL or divisors.
	 */
	{
		unsigned pll_ctl_val = omap_readw(DPLL_CTL);

		ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */
		if (pll_ctl_val & 0x10) {
			/* PLL enabled, apply multiplier and divisor */
			if (pll_ctl_val & 0xf80)
				ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7;
			ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1;
		} else {
			/* PLL disabled, apply bypass divisor */
			switch (pll_ctl_val & 0xc) {
			case 0:
				break;
			case 0x4:
				ck_dpll1.rate /= 2;
				break;
			default:
				ck_dpll1.rate /= 4;
				break;
			}
		}
	}
Ejemplo n.º 15
0
static int omap_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	struct omap_pcm_dma_data *dma_data = prtd->dma_data;
	struct omap_dma_channel_params dma_params;

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if (!prtd->dma_data)
		return 0;

	memset(&dma_params, 0, sizeof(dma_params));
	/*
	 * Note: Regardless of interface data formats supported by OMAP McBSP
	 * or EAC blocks, internal representation is always fixed 16-bit/sample
	 */
	dma_params.data_type			= OMAP_DMA_DATA_TYPE_S16;
	dma_params.trigger			= dma_data->dma_req;
	dma_params.sync_mode			= dma_data->sync_mode;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		dma_params.src_amode		= OMAP_DMA_AMODE_POST_INC;
		dma_params.dst_amode		= OMAP_DMA_AMODE_CONSTANT;
		dma_params.src_or_dst_synch	= OMAP_DMA_DST_SYNC;
		dma_params.src_start		= runtime->dma_addr;
		dma_params.dst_start		= dma_data->port_addr;
		dma_params.dst_port		= OMAP_DMA_PORT_MPUI;
	} else {
		dma_params.src_amode		= OMAP_DMA_AMODE_CONSTANT;
		dma_params.dst_amode		= OMAP_DMA_AMODE_POST_INC;
		dma_params.src_or_dst_synch	= OMAP_DMA_SRC_SYNC;
		dma_params.src_start		= dma_data->port_addr;
		dma_params.dst_start		= runtime->dma_addr;
		dma_params.src_port		= OMAP_DMA_PORT_MPUI;
	}
	/*
	 * Set DMA transfer frame size equal to ALSA period size and frame
	 * count as no. of ALSA periods. Then with DMA frame interrupt enabled,
	 * we can transfer the whole ALSA buffer with single DMA transfer but
	 * still can get an interrupt at each period bounary
	 */
	dma_params.elem_count	= snd_pcm_lib_period_bytes(substream) / 2;
	dma_params.frame_count	= runtime->periods;
	omap_set_dma_params(prtd->dma_ch, &dma_params);

	if ((cpu_is_omap1510()) &&
			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
			      OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
	else
		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);

	if (!(cpu_class_is_omap1())) {
		omap_set_dma_src_burst_mode(prtd->dma_ch,
						OMAP_DMA_DATA_BURST_16);
		omap_set_dma_dest_burst_mode(prtd->dma_ch,
						OMAP_DMA_DATA_BURST_16);
	}

	return 0;
}
Ejemplo n.º 16
0
static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
{
	struct omap_usb_config	*config = pdev->dev.platform_data;
	int			need_transceiver = (config->otg != 0);

	dev_dbg(&pdev->dev, "starting USB Controller\n");

	if (config->otg) {
		ohci->hcd.self.otg_port = config->otg;
		/* default/minimum OTG power budget:  8 mA */
		ohci->power_budget = 8;
	}

	/* boards can use OTG transceivers in non-OTG modes */
	need_transceiver = need_transceiver
			|| machine_is_omap_h2() || machine_is_omap_h3();

	if (cpu_is_omap16xx())
		ocpi_enable();

#ifdef	CONFIG_ARCH_OMAP_OTG
	if (need_transceiver) {
		ohci->transceiver = otg_get_transceiver();
		if (ohci->transceiver) {
			int	status = otg_set_host(ohci->transceiver,
						&ohci->hcd.self);
			dev_dbg(&pdev->dev, "init %s transceiver, status %d\n",
					ohci->transceiver->label, status);
			if (status) {
				if (ohci->transceiver)
					put_device(ohci->transceiver->dev);
				return status;
			}
		} else {
			dev_err(&pdev->dev, "can't find transceiver\n");
			return -ENODEV;
		}
	}
#endif

	if (machine_is_omap_osk()) {
		omap_request_gpio(9);
		omap_set_gpio_direction(9, 1);
		omap_set_gpio_dataout(9, 1);
	}

	omap_ohci_clock_power(1);

	omap_ohci_transceiver_power(1);

	if (cpu_is_omap1510()) {
		omap_1510_local_bus_power(1);
		omap_1510_local_bus_init();
	}

	/* board init will have already handled HMC and mux setup.
	 * any external transceiver should already be initialized
	 * too, so all configured ports use the right signaling now.
	 */

	return 0;
}
Ejemplo n.º 17
0
void __init omap_init_irq(void)
{
	int i, j;

#ifdef CONFIG_ARCH_OMAP730
	if (cpu_is_omap730()) {
		irq_banks = omap730_irq_banks;
		irq_bank_count = ARRAY_SIZE(omap730_irq_banks);
	}
#endif
#ifdef CONFIG_ARCH_OMAP15XX
	if (cpu_is_omap1510()) {
		irq_banks = omap1510_irq_banks;
		irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
	}
	if (cpu_is_omap310()) {
		irq_banks = omap310_irq_banks;
		irq_bank_count = ARRAY_SIZE(omap310_irq_banks);
	}
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
	if (cpu_is_omap16xx()) {
		irq_banks = omap1610_irq_banks;
		irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
	}
#endif
	printk("Total of %i interrupts in %i interrupt banks\n",
	       irq_bank_count * 32, irq_bank_count);

	/* Mask and clear all interrupts */
	for (i = 0; i < irq_bank_count; i++) {
		irq_bank_writel(~0x0, i, IRQ_MIR_REG_OFFSET);
		irq_bank_writel(0x0, i, IRQ_ITR_REG_OFFSET);
	}

	/* Clear any pending interrupts */
	irq_bank_writel(0x03, 0, IRQ_CONTROL_REG_OFFSET);
	irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET);

	/* Enable interrupts in global mask */
	if (cpu_is_omap730()) {
		irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET);
	}

	/* Install the interrupt handlers for each bank */
	for (i = 0; i < irq_bank_count; i++) {
		for (j = i * 32; j < (i + 1) * 32; j++) {
			int irq_trigger;

			irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j);
			omap_irq_set_cfg(j, 0, 0, irq_trigger);

			set_irq_chip(j, &omap_irq_chip);
			set_irq_handler(j, handle_level_irq);
			set_irq_flags(j, IRQF_VALID);
		}
	}

	/* Unmask level 2 handler */

	if (cpu_is_omap730())
		omap_unmask_irq(INT_730_IH2_IRQ);
	else if (cpu_is_omap15xx())
		omap_unmask_irq(INT_1510_IH2_IRQ);
	else if (cpu_is_omap16xx())
		omap_unmask_irq(INT_1610_IH2_IRQ);
}
Ejemplo n.º 18
0
int __init
init_ck(void)
{
    const struct omap_clock_info *info;
    int crystal_type = 0; /* Default 12 MHz */

    __ck_make_lookup_table();
    info = omap_get_per_info(OMAP_TAG_CLOCK, struct omap_clock_info);
    if (info != NULL) {
        if (!cpu_is_omap1510())
            crystal_type = info->system_clock_type;
    }

    /* We want to be in syncronous scalable mode */
    omap_writew(0x1000, ARM_SYSST);
#if defined(CONFIG_OMAP_ARM_30MHZ)
    omap_writew(0x1555, ARM_CKCTL);
    omap_writew(0x2290, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_60MHZ)
    omap_writew(0x1005, ARM_CKCTL);
    omap_writew(0x2290, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_96MHZ)
    omap_writew(0x1005, ARM_CKCTL);
    omap_writew(0x2410, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_120MHZ)
    omap_writew(0x110a, ARM_CKCTL);
    omap_writew(0x2510, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_168MHZ)
    omap_writew(0x110f, ARM_CKCTL);
    omap_writew(0x2710, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
    omap_writew(0x250E, ARM_CKCTL);
    omap_writew(0x2710, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912))
    omap_writew(0x150f, ARM_CKCTL);
    if (crystal_type == 2) {
        source_clock = 13;	/* MHz */
        omap_writew(0x2510, DPLL_CTL);
    } else
        omap_writew(0x2810, DPLL_CTL);
#elif defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730)
    omap_writew(0x250E, ARM_CKCTL);
    omap_writew(0x2790, DPLL_CTL);
#else
#error "OMAP MHZ not set, please run make xconfig"
#endif

#ifdef CONFIG_MACH_OMAP_PERSEUS2
    /* Select slicer output as OMAP input clock */
    omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
#endif

    /* Turn off some other junk the bootloader might have turned on */

    /* Turn off DSP, ARM_INTHCK, ARM_TIMXO */
    omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);

    /* Put DSP/MPUI into reset until needed */
    omap_writew(0, ARM_RSTCT1);
    omap_writew(1, ARM_RSTCT2);
    omap_writew(0x400, ARM_IDLECT1);

    /*
     * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
     * of the ARM_IDLECT2 register must be set to zero. The power-on
     * default value of this bit is one.
     */
    omap_writew(0x0000, ARM_IDLECT2);	/* Turn LCD clock off also */

    /*
     * Only enable those clocks we will need, let the drivers
     * enable other clocks as necessary
     */
    ck_enable(OMAP_MPUPER_CK);
    ck_enable(OMAP_ARM_GPIO_CK);
    ck_enable(OMAP_MPUXOR_CK);
    //ck_set_rate(OMAP_MPUTIM_CK, OMAP_CLKIN);
    ck_enable(OMAP_MPUTIM_CK);
    start_mputimer1(0xffffffff);

    return 0;
}