Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5526b3f7 authored by Kevin Hilman's avatar Kevin Hilman
Browse files

davinci: update pin-multiplexing support



Update MUX support to be more general and useful across multiple
SoCs in the DaVinci family.

Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 617b925f
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -18,6 +18,32 @@ config MACH_DAVINCI_EVM
	  Configure this option to specify the whether the board used
	  for development is a DaVinci EVM


config DAVINCI_MUX
	bool "DAVINCI multiplexing support"
	depends on ARCH_DAVINCI
	default y
	help
	  Pin multiplexing support for DAVINCI boards. If your bootloader
	  sets the multiplexing correctly, say N. Otherwise, or if unsure,
	  say Y.

config DAVINCI_MUX_DEBUG
        bool "Multiplexing debug output"
        depends on DAVINCI_MUX
        help
          Makes the multiplexing functions print out a lot of debug info.
          This is useful if you want to find out the correct values of the
          multiplexing registers.

config DAVINCI_MUX_WARNINGS
        bool "Warn about pins the bootloader didn't set up"
        depends on DAVINCI_MUX
        help
          Choose Y here to warn whenever driver initialization logic needs
          to change the pin multiplexing setup.  When there are no warnings
          printed, it's safe to deselect DAVINCI_MUX for your product.

config DAVINCI_RESET_CLOCKS
	bool "Reset unused clocks during boot"
	depends on ARCH_DAVINCI
+3 −1
Original line number Diff line number Diff line
@@ -5,7 +5,9 @@

# Common objects
obj-y 			:= time.o irq.o clock.o serial.o io.o id.o psc.o \
			   gpio.o mux.o devices.o dma.o usb.o
			   gpio.o devices.o dma.o usb.o

obj-$(CONFIG_DAVINCI_MUX)		+= mux.o

# Board specific
obj-$(CONFIG_MACH_DAVINCI_EVM)  += board-evm.o
+5 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@
#include <mach/hardware.h>
#include <mach/i2c.h>
#include <mach/irqs.h>
#include <mach/cputype.h>
#include <mach/mux.h>

#define DAVINCI_I2C_BASE	     0x01C21000

@@ -45,6 +47,9 @@ static struct platform_device davinci_i2c_device = {

void __init davinci_init_i2c(struct davinci_i2c_platform_data *pdata)
{
	if (cpu_is_davinci_dm644x())
		davinci_cfg_reg(DM644X_I2C);

	davinci_i2c_device.dev.platform_data = pdata;
	(void) platform_device_register(&davinci_i2c_device);
}
+174 −46
Original line number Diff line number Diff line
/*
 * DaVinci pin multiplexing defines
 * Table of the DAVINCI register configurations for the PINMUX combinations
 *
 * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
 *
 * Based on linux/include/asm-arm/arch-omap/mux.h:
 * Copyright (C) 2003 - 2005 Nokia Corporation
 *
 * Written by Tony Lindgren
 *
 * 2007 (c) MontaVista Software, Inc. This file is licensed under
 * the terms of the GNU General Public License version 2. This program
 * is licensed "as is" without any warranty of any kind, whether express
 * or implied.
 *
 * Copyright (C) 2008 Texas Instruments.
 */
#ifndef __ASM_ARCH_MUX_H
#define __ASM_ARCH_MUX_H

#define DAVINCI_MUX_AEAW0	0
#define DAVINCI_MUX_AEAW1	1
#define DAVINCI_MUX_AEAW2	2
#define DAVINCI_MUX_AEAW3	3
#define DAVINCI_MUX_AEAW4	4
#define DAVINCI_MUX_AECS4	10
#define DAVINCI_MUX_AECS5	11
#define DAVINCI_MUX_VLYNQWD0	12
#define DAVINCI_MUX_VLYNQWD1	13
#define DAVINCI_MUX_VLSCREN	14
#define DAVINCI_MUX_VLYNQEN	15
#define DAVINCI_MUX_HDIREN	16
#define DAVINCI_MUX_ATAEN	17
#define DAVINCI_MUX_RGB666	22
#define DAVINCI_MUX_RGB888	23
#define DAVINCI_MUX_LOEEN	24
#define DAVINCI_MUX_LFLDEN	25
#define DAVINCI_MUX_CWEN	26
#define DAVINCI_MUX_CFLDEN	27
#define DAVINCI_MUX_HPIEN	29
#define DAVINCI_MUX_1394EN	30
#define DAVINCI_MUX_EMACEN	31

#define DAVINCI_MUX_LEVEL2	32
#define DAVINCI_MUX_UART0	(DAVINCI_MUX_LEVEL2 + 0)
#define DAVINCI_MUX_UART1	(DAVINCI_MUX_LEVEL2 + 1)
#define DAVINCI_MUX_UART2	(DAVINCI_MUX_LEVEL2 + 2)
#define DAVINCI_MUX_U2FLO	(DAVINCI_MUX_LEVEL2 + 3)
#define DAVINCI_MUX_PWM0	(DAVINCI_MUX_LEVEL2 + 4)
#define DAVINCI_MUX_PWM1	(DAVINCI_MUX_LEVEL2 + 5)
#define DAVINCI_MUX_PWM2	(DAVINCI_MUX_LEVEL2 + 6)
#define DAVINCI_MUX_I2C		(DAVINCI_MUX_LEVEL2 + 7)
#define DAVINCI_MUX_SPI		(DAVINCI_MUX_LEVEL2 + 8)
#define DAVINCI_MUX_MSTK	(DAVINCI_MUX_LEVEL2 + 9)
#define DAVINCI_MUX_ASP		(DAVINCI_MUX_LEVEL2 + 10)
#define DAVINCI_MUX_CLK0	(DAVINCI_MUX_LEVEL2 + 16)
#define DAVINCI_MUX_CLK1	(DAVINCI_MUX_LEVEL2 + 17)
#define DAVINCI_MUX_TIMIN	(DAVINCI_MUX_LEVEL2 + 18)

extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable);

#endif /* __ASM_ARCH_MUX_H */

#ifndef __INC_MACH_MUX_H
#define __INC_MACH_MUX_H

/* System module registers */
#define PINMUX0			0x00
#define PINMUX1			0x04
/* dm355 only */
#define PINMUX2			0x08
#define PINMUX3			0x0c
#define PINMUX4			0x10
#define INTMUX			0x18
#define EVTMUX			0x1c

struct mux_config {
	const char *name;
	const char *mux_reg_name;
	const unsigned char mux_reg;
	const unsigned char mask_offset;
	const unsigned char mask;
	const unsigned char mode;
	bool debug;
};

enum davinci_dm644x_index {
	/* ATA and HDDIR functions */
	DM644X_HDIREN,
	DM644X_ATAEN,
	DM644X_ATAEN_DISABLE,

	/* HPI functions */
	DM644X_HPIEN_DISABLE,

	/* AEAW functions */
	DM644X_AEAW,

	/* Memory Stick */
	DM644X_MSTK,

	/* I2C */
	DM644X_I2C,

	/* ASP function */
	DM644X_MCBSP,

	/* UART1 */
	DM644X_UART1,

	/* UART2 */
	DM644X_UART2,

	/* PWM0 */
	DM644X_PWM0,

	/* PWM1 */
	DM644X_PWM1,

	/* PWM2 */
	DM644X_PWM2,

	/* VLYNQ function */
	DM644X_VLYNQEN,
	DM644X_VLSCREN,
	DM644X_VLYNQWD,

	/* EMAC and MDIO function */
	DM644X_EMACEN,

	/* GPIO3V[0:16] pins */
	DM644X_GPIO3V,

	/* GPIO pins */
	DM644X_GPIO0,
	DM644X_GPIO3,
	DM644X_GPIO43_44,
	DM644X_GPIO46_47,

	/* VPBE */
	DM644X_RGB666,

	/* LCD */
	DM644X_LOEEN,
	DM644X_LFLDEN,
};

enum davinci_dm646x_index {
	/* ATA function */
	DM646X_ATAEN,

	/* AUDIO Clock */
	DM646X_AUDCK1,
	DM646X_AUDCK0,

	/* CRGEN Control */
	DM646X_CRGMUX,

	/* VPIF Control */
	DM646X_STSOMUX_DISABLE,
	DM646X_STSIMUX_DISABLE,
	DM646X_PTSOMUX_DISABLE,
	DM646X_PTSIMUX_DISABLE,

	/* TSIF Control */
	DM646X_STSOMUX,
	DM646X_STSIMUX,
	DM646X_PTSOMUX_PARALLEL,
	DM646X_PTSIMUX_PARALLEL,
	DM646X_PTSOMUX_SERIAL,
	DM646X_PTSIMUX_SERIAL,
};

enum davinci_dm355_index {
	/* MMC/SD 0 */
	DM355_MMCSD0,

	/* MMC/SD 1 */
	DM355_SD1_CLK,
	DM355_SD1_CMD,
	DM355_SD1_DATA3,
	DM355_SD1_DATA2,
	DM355_SD1_DATA1,
	DM355_SD1_DATA0,

	/* I2C */
	DM355_I2C_SDA,
	DM355_I2C_SCL,

	/* ASP0 function */
	DM355_MCBSP0_BDX,
	DM355_MCBSP0_X,
	DM355_MCBSP0_BFSX,
	DM355_MCBSP0_BDR,
	DM355_MCBSP0_R,
	DM355_MCBSP0_BFSR,

	/* SPI0 */
	DM355_SPI0_SDI,
	DM355_SPI0_SDENA0,
	DM355_SPI0_SDENA1,

	/* IRQ muxing */
	DM355_INT_EDMA_CC,
	DM355_INT_EDMA_TC0_ERR,
	DM355_INT_EDMA_TC1_ERR,

	/* EDMA event muxing */
	DM355_EVT8_ASP1_TX,
	DM355_EVT9_ASP1_RX,
	DM355_EVT26_MMC0_RX,
};

#ifdef CONFIG_DAVINCI_MUX
/* setup pin muxing */
extern void davinci_mux_init(void);
extern int davinci_mux_register(const struct mux_config *pins,
				unsigned long size);
extern int davinci_cfg_reg(unsigned long reg_cfg);
#else
/* boot loader does it all (no warnings from CONFIG_DAVINCI_MUX_WARNINGS) */
static inline void davinci_mux_init(void) {}
static inline int davinci_mux_register(const struct mux_config *pins,
				       unsigned long size) { return 0; }
static inline int davinci_cfg_reg(unsigned long reg_cfg) { return 0; }
#endif

#endif /* __INC_MACH_MUX_H */
+80 −19
Original line number Diff line number Diff line
/*
 * DaVinci pin multiplexing configurations
 * Utility to set the DAVINCI MUX register from a table in mux.h
 *
 * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
 *
 * Based on linux/arch/arm/plat-omap/mux.c:
 * Copyright (C) 2003 - 2005 Nokia Corporation
 *
 * Written by Tony Lindgren
 *
 * 2007 (c) MontaVista Software, Inc. This file is licensed under
 * the terms of the GNU General Public License version 2. This program
 * is licensed "as is" without any warranty of any kind, whether express
 * or implied.
 *
 * Copyright (C) 2008 Texas Instruments.
 */
#include <linux/io.h>
#include <linux/module.h>
#include <linux/spinlock.h>

#include <mach/hardware.h>

#include <mach/mux.h>

/* System control register offsets */
#define PINMUX0         0x00
#define PINMUX1         0x04
static const struct mux_config *mux_table;
static unsigned long pin_table_sz;

int __init davinci_mux_register(const struct mux_config *pins,
				unsigned long size)
{
	mux_table = pins;
	pin_table_sz = size;

static DEFINE_SPINLOCK(mux_lock);
	return 0;
}

void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
/*
 * Sets the DAVINCI MUX register based on the table
 */
int __init_or_module davinci_cfg_reg(const unsigned long index)
{
	static DEFINE_SPINLOCK(mux_spin_lock);
	void __iomem *base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE);
	u32 pinmux, muxreg = PINMUX0;
	unsigned long flags;
	const struct mux_config *cfg;
	unsigned int reg_orig = 0, reg = 0;
	unsigned int mask, warn = 0;

	if (!mux_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 = &mux_table[index];

	if (cfg->name == NULL) {
		printk(KERN_ERR "No entry for the specified index\n");
		return -ENODEV;
	}

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

		spin_lock_irqsave(&mux_spin_lock, flags);
		reg_orig = __raw_readl(base + cfg->mux_reg);

		mask = (cfg->mask << cfg->mask_offset);
		tmp1 = reg_orig & mask;
		reg = reg_orig & ~mask;

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

		if (tmp1 != tmp2)
			warn = 1;

		__raw_writel(reg, base + cfg->mux_reg);
		spin_unlock_irqrestore(&mux_spin_lock, flags);
	}

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

	if (mux >= DAVINCI_MUX_LEVEL2) {
		muxreg = PINMUX1;
		mux -= DAVINCI_MUX_LEVEL2;
#ifdef CONFIG_DAVINCI_MUX_DEBUG
	if (cfg->debug || warn) {
		printk(KERN_WARNING "MUX: Setting register %s\n", cfg->name);
		printk(KERN_WARNING "	   %s (0x%08x) = 0x%08x -> 0x%08x\n",
		       cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
	}
#endif

	spin_lock(&mux_lock);
	pinmux = __raw_readl(base + muxreg);
	if (enable)
		pinmux |= (1 << mux);
	else
		pinmux &= ~(1 << mux);
	__raw_writel(pinmux, base + muxreg);
	spin_unlock(&mux_lock);
	return 0;
}
EXPORT_SYMBOL(davinci_cfg_reg);
Loading