0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018
0019 #include <linux/io.h>
0020 #include <linux/module.h>
0021 #include <linux/spinlock.h>
0022
0023 #include "mux.h"
0024 #include "common.h"
0025
0026 static void __iomem *pinmux_base;
0027
0028
0029
0030
0031 int davinci_cfg_reg(const unsigned long index)
0032 {
0033 static DEFINE_SPINLOCK(mux_spin_lock);
0034 struct davinci_soc_info *soc_info = &davinci_soc_info;
0035 unsigned long flags;
0036 const struct mux_config *cfg;
0037 unsigned int reg_orig = 0, reg = 0;
0038 unsigned int mask, warn = 0;
0039
0040 if (WARN_ON(!soc_info->pinmux_pins))
0041 return -ENODEV;
0042
0043 if (!pinmux_base) {
0044 pinmux_base = ioremap(soc_info->pinmux_base, SZ_4K);
0045 if (WARN_ON(!pinmux_base))
0046 return -ENOMEM;
0047 }
0048
0049 if (index >= soc_info->pinmux_pins_num) {
0050 pr_err("Invalid pin mux index: %lu (%lu)\n",
0051 index, soc_info->pinmux_pins_num);
0052 dump_stack();
0053 return -ENODEV;
0054 }
0055
0056 cfg = &soc_info->pinmux_pins[index];
0057
0058 if (cfg->name == NULL) {
0059 pr_err("No entry for the specified index\n");
0060 return -ENODEV;
0061 }
0062
0063
0064 if (cfg->mask) {
0065 unsigned tmp1, tmp2;
0066
0067 spin_lock_irqsave(&mux_spin_lock, flags);
0068 reg_orig = __raw_readl(pinmux_base + cfg->mux_reg);
0069
0070 mask = (cfg->mask << cfg->mask_offset);
0071 tmp1 = reg_orig & mask;
0072 reg = reg_orig & ~mask;
0073
0074 tmp2 = (cfg->mode << cfg->mask_offset);
0075 reg |= tmp2;
0076
0077 if (tmp1 != tmp2)
0078 warn = 1;
0079
0080 __raw_writel(reg, pinmux_base + cfg->mux_reg);
0081 spin_unlock_irqrestore(&mux_spin_lock, flags);
0082 }
0083
0084 if (warn) {
0085 #ifdef CONFIG_DAVINCI_MUX_WARNINGS
0086 pr_warn("initialized %s\n", cfg->name);
0087 #endif
0088 }
0089
0090 #ifdef CONFIG_DAVINCI_MUX_DEBUG
0091 if (cfg->debug || warn) {
0092 pr_warn("Setting register %s\n", cfg->name);
0093 pr_warn(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
0094 cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
0095 }
0096 #endif
0097
0098 return 0;
0099 }
0100 EXPORT_SYMBOL(davinci_cfg_reg);
0101
0102 int davinci_cfg_reg_list(const short pins[])
0103 {
0104 int i, error = -EINVAL;
0105
0106 if (pins)
0107 for (i = 0; pins[i] >= 0; i++) {
0108 error = davinci_cfg_reg(pins[i]);
0109 if (error)
0110 break;
0111 }
0112
0113 return error;
0114 }