Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * arch/arm/plat-orion/mpp.c
0003  *
0004  * MPP functions for Marvell orion SoCs
0005  *
0006  * This file is licensed under the terms of the GNU General Public
0007  * License version 2.  This program is licensed "as is" without any
0008  * warranty of any kind, whether express or implied.
0009  */
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/init.h>
0013 #include <linux/mbus.h>
0014 #include <linux/io.h>
0015 #include <linux/gpio.h>
0016 #include <plat/orion-gpio.h>
0017 #include <plat/mpp.h>
0018 
0019 /* Address of the ith MPP control register */
0020 static __init void __iomem *mpp_ctrl_addr(unsigned int i,
0021                       void __iomem *dev_bus)
0022 {
0023     return dev_bus + (i) * 4;
0024 }
0025 
0026 
0027 void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
0028                unsigned int mpp_max, void __iomem *dev_bus)
0029 {
0030     unsigned int mpp_nr_regs = (1 + mpp_max/8);
0031     u32 mpp_ctrl[8];
0032     int i;
0033 
0034     printk(KERN_DEBUG "initial MPP regs:");
0035     if (mpp_nr_regs > ARRAY_SIZE(mpp_ctrl)) {
0036         printk(KERN_ERR "orion_mpp_conf: invalid mpp_max\n");
0037         return;
0038     }
0039 
0040     for (i = 0; i < mpp_nr_regs; i++) {
0041         mpp_ctrl[i] = readl(mpp_ctrl_addr(i, dev_bus));
0042         printk(" %08x", mpp_ctrl[i]);
0043     }
0044     printk("\n");
0045 
0046     for ( ; *mpp_list; mpp_list++) {
0047         unsigned int num = MPP_NUM(*mpp_list);
0048         unsigned int sel = MPP_SEL(*mpp_list);
0049         int shift, gpio_mode;
0050 
0051         if (num > mpp_max) {
0052             printk(KERN_ERR "orion_mpp_conf: invalid MPP "
0053                     "number (%u)\n", num);
0054             continue;
0055         }
0056         if (variant_mask && !(*mpp_list & variant_mask)) {
0057             printk(KERN_WARNING
0058                    "orion_mpp_conf: requested MPP%u config "
0059                    "unavailable on this hardware\n", num);
0060             continue;
0061         }
0062 
0063         shift = (num & 7) << 2;
0064         mpp_ctrl[num / 8] &= ~(0xf << shift);
0065         mpp_ctrl[num / 8] |= sel << shift;
0066 
0067         gpio_mode = 0;
0068         if (*mpp_list & MPP_INPUT_MASK)
0069             gpio_mode |= GPIO_INPUT_OK;
0070         if (*mpp_list & MPP_OUTPUT_MASK)
0071             gpio_mode |= GPIO_OUTPUT_OK;
0072 
0073         orion_gpio_set_valid(num, gpio_mode);
0074     }
0075 
0076     printk(KERN_DEBUG "  final MPP regs:");
0077     for (i = 0; i < mpp_nr_regs; i++) {
0078         writel(mpp_ctrl[i], mpp_ctrl_addr(i, dev_bus));
0079         printk(" %08x", mpp_ctrl[i]);
0080     }
0081     printk("\n");
0082 }