diff options
Diffstat (limited to 'arch/arm/mach-u300/padmux.c')
| -rw-r--r-- | arch/arm/mach-u300/padmux.c | 367 | 
1 files changed, 0 insertions, 367 deletions
diff --git a/arch/arm/mach-u300/padmux.c b/arch/arm/mach-u300/padmux.c deleted file mode 100644 index 4c93c6cefd3..00000000000 --- a/arch/arm/mach-u300/padmux.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * - * arch/arm/mach-u300/padmux.c - * - * - * Copyright (C) 2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * U300 PADMUX functions - * Author: Martin Persson <martin.persson@stericsson.com> - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/errno.h> -#include <linux/io.h> -#include <linux/mutex.h> -#include <linux/string.h> -#include <linux/bug.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <mach/u300-regs.h> -#include <mach/syscon.h> -#include "padmux.h" - -static DEFINE_MUTEX(pmx_mutex); - -const u32 pmx_registers[] = { -	(U300_SYSCON_VBASE + U300_SYSCON_PMC1LR), -	(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR), -	(U300_SYSCON_VBASE + U300_SYSCON_PMC2R), -	(U300_SYSCON_VBASE + U300_SYSCON_PMC3R), -	(U300_SYSCON_VBASE + U300_SYSCON_PMC4R) -}; - -/* High level functionality */ - -/* Lazy dog: - * onmask = { - *   {"PMC1LR" mask, "PMC1LR" value}, - *   {"PMC1HR" mask, "PMC1HR" value}, - *   {"PMC2R"  mask, "PMC2R"  value}, - *   {"PMC3R"  mask, "PMC3R"  value}, - *   {"PMC4R"  mask, "PMC4R"  value} - * } - */ -static struct pmx mmc_setting = { -	.setting = U300_APP_PMX_MMC_SETTING, -	.default_on = false, -	.activated = false, -	.name = "MMC", -	.onmask = { -		   {U300_SYSCON_PMC1LR_MMCSD_MASK, -		    U300_SYSCON_PMC1LR_MMCSD_MMCSD}, -		   {0, 0}, -		   {0, 0}, -		   {0, 0}, -		   {U300_SYSCON_PMC4R_APP_MISC_12_MASK, -		    U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO} -		   }, -}; - -static struct pmx spi_setting = { -	.setting = U300_APP_PMX_SPI_SETTING, -	.default_on = false, -	.activated = false, -	.name = "SPI", -	.onmask = {{0, 0}, -		   {U300_SYSCON_PMC1HR_APP_SPI_2_MASK | -		    U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK | -		    U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK, -		    U300_SYSCON_PMC1HR_APP_SPI_2_SPI | -		    U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI | -		    U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI}, -		   {0, 0}, -		   {0, 0}, -		   {0, 0} -		   }, -}; - -/* Available padmux settings */ -static struct pmx *pmx_settings[] = { -	&mmc_setting, -	&spi_setting, -}; - -static void update_registers(struct pmx *pmx, bool activate) -{ -	u16 regval, val, mask; -	int i; - -	for (i = 0; i < ARRAY_SIZE(pmx_registers); i++) { -		if (activate) -			val = pmx->onmask[i].val; -		else -			val = 0; - -		mask = pmx->onmask[i].mask; -		if (mask != 0) { -			regval = readw(pmx_registers[i]); -			regval &= ~mask; -			regval |= val; -			writew(regval, pmx_registers[i]); -		} -	} -} - -struct pmx *pmx_get(struct device *dev, enum pmx_settings setting) -{ -	int i; -	struct pmx *pmx = ERR_PTR(-ENOENT); - -	if (dev == NULL) -		return ERR_PTR(-EINVAL); - -	mutex_lock(&pmx_mutex); -	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - -		if (setting == pmx_settings[i]->setting) { - -			if (pmx_settings[i]->dev != NULL) { -				WARN(1, "padmux: required setting " -				     "in use by another consumer\n"); -			} else { -				pmx = pmx_settings[i]; -				pmx->dev = dev; -				dev_dbg(dev, "padmux: setting nr %d is now " -					"bound to %s and ready to use\n", -					setting, dev_name(dev)); -				break; -			} -		} -	} -	mutex_unlock(&pmx_mutex); - -	return pmx; -} -EXPORT_SYMBOL(pmx_get); - -int pmx_put(struct device *dev, struct pmx *pmx) -{ -	int i; -	int ret = -ENOENT; - -	if (pmx == NULL || dev == NULL) -		return -EINVAL; - -	mutex_lock(&pmx_mutex); -	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - -		if (pmx->setting == pmx_settings[i]->setting) { - -			if (dev != pmx->dev) { -				WARN(1, "padmux: cannot release handle as " -					"it is bound to another consumer\n"); -				ret = -EINVAL; -				break; -			} else { -				pmx_settings[i]->dev = NULL; -				ret = 0; -				break; -			} -		} -	} -	mutex_unlock(&pmx_mutex); - -	return ret; -} -EXPORT_SYMBOL(pmx_put); - -int pmx_activate(struct device *dev, struct pmx *pmx) -{ -	int i, j, ret; -	ret = 0; - -	if (pmx == NULL || dev == NULL) -		return -EINVAL; - -	mutex_lock(&pmx_mutex); - -	/* Make sure the required bits are not used */ -	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - -		if (pmx_settings[i]->dev == NULL || pmx_settings[i] == pmx) -			continue; - -		for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) { - -			if (pmx_settings[i]->onmask[j].mask & pmx-> -				onmask[j].mask) { -				/* More than one entry on the same bits */ -				WARN(1, "padmux: cannot activate " -					"setting. Bit conflict with " -					"an active setting\n"); - -				ret = -EUSERS; -				goto exit; -			} -		} -	} -	update_registers(pmx, true); -	pmx->activated = true; -	dev_dbg(dev, "padmux: setting nr %d is activated\n", -		pmx->setting); - -exit: -	mutex_unlock(&pmx_mutex); -	return ret; -} -EXPORT_SYMBOL(pmx_activate); - -int pmx_deactivate(struct device *dev, struct pmx *pmx) -{ -	int i; -	int ret = -ENOENT; - -	if (pmx == NULL || dev == NULL) -		return -EINVAL; - -	mutex_lock(&pmx_mutex); -	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - -		if (pmx_settings[i]->dev == NULL) -			continue; - -		if (pmx->setting == pmx_settings[i]->setting) { - -			if (dev != pmx->dev) { -				WARN(1, "padmux: cannot deactivate " -				     "pmx setting as it was activated " -				     "by another consumer\n"); - -				ret = -EBUSY; -				continue; -			} else { -				update_registers(pmx, false); -				pmx_settings[i]->dev = NULL; -				pmx->activated = false; -				ret = 0; -				dev_dbg(dev, "padmux: setting nr %d is deactivated", -					pmx->setting); -				break; -			} -		} -	} -	mutex_unlock(&pmx_mutex); - -	return ret; -} -EXPORT_SYMBOL(pmx_deactivate); - -/* - * For internal use only. If it is to be exported, - * it should be reentrant. Notice that pmx_activate - * (i.e. runtime settings) always override default settings. - */ -static int pmx_set_default(void) -{ -	/* Used to identify several entries on the same bits */ -	u16 modbits[ARRAY_SIZE(pmx_registers)]; - -	int i, j; - -	memset(modbits, 0, ARRAY_SIZE(pmx_registers) * sizeof(u16)); - -	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - -		if (!pmx_settings[i]->default_on) -			continue; - -		for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) { - -			/* Make sure there is only one entry on the same bits */ -			if (modbits[j] & pmx_settings[i]->onmask[j].mask) { -				BUG(); -				return -EUSERS; -			} -			modbits[j] |= pmx_settings[i]->onmask[j].mask; -		} -		update_registers(pmx_settings[i], true); -	} -	return 0; -} - -#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG)) -static int pmx_show(struct seq_file *s, void *data) -{ -	int i; -	seq_printf(s, "-------------------------------------------------\n"); -	seq_printf(s, "SETTING     BOUND TO DEVICE               STATE\n"); -	seq_printf(s, "-------------------------------------------------\n"); -	mutex_lock(&pmx_mutex); -	for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { -		/* Format pmx and device name nicely */ -		char cdp[33]; -		int chars; - -		chars = snprintf(&cdp[0], 17, "%s", pmx_settings[i]->name); -		while (chars < 16) { -			cdp[chars] = ' '; -			chars++; -		} -		chars = snprintf(&cdp[16], 17, "%s", pmx_settings[i]->dev ? -				dev_name(pmx_settings[i]->dev) : "N/A"); -		while (chars < 16) { -			cdp[chars+16] = ' '; -			chars++; -		} -		cdp[32] = '\0'; - -		seq_printf(s, -			"%s\t%s\n", -			&cdp[0], -			pmx_settings[i]->activated ? -			"ACTIVATED" : "DEACTIVATED" -			); - -	} -	mutex_unlock(&pmx_mutex); -	return 0; -} - -static int pmx_open(struct inode *inode, struct file *file) -{ -	return single_open(file, pmx_show, NULL); -} - -static const struct file_operations pmx_operations = { -	.owner		= THIS_MODULE, -	.open		= pmx_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= single_release, -}; - -static int __init init_pmx_read_debugfs(void) -{ -	/* Expose a simple debugfs interface to view pmx settings */ -	(void) debugfs_create_file("padmux", S_IFREG | S_IRUGO, -				   NULL, NULL, -				   &pmx_operations); -	return 0; -} - -/* - * This needs to come in after the core_initcall(), - * because debugfs is not available until - * the subsystems come up. - */ -module_init(init_pmx_read_debugfs); -#endif - -static int __init pmx_init(void) -{ -	int ret; - -	ret = pmx_set_default(); - -	if (IS_ERR_VALUE(ret)) -		pr_crit("padmux: default settings could not be set\n"); - -	return 0; -} - -/* Should be initialized before consumers */ -core_initcall(pmx_init);  | 
