Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Utility to set the DAVINCI MUX register from a table in mux.h
0004  *
0005  * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
0006  *
0007  * Based on linux/arch/arm/plat-omap/mux.c:
0008  * Copyright (C) 2003 - 2005 Nokia Corporation
0009  *
0010  * Written by Tony Lindgren
0011  *
0012  * 2007 (c) MontaVista Software, Inc.
0013  *
0014  * Copyright (C) 2008 Texas Instruments.
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  * Sets the DAVINCI MUX register based on the table
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     /* Update the mux register in question */
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 }