1/* 2 * linux/arch/arm/mach-w90x900/mfp.c 3 * 4 * Copyright (c) 2008 Nuvoton technology corporation 5 * 6 * Wan ZongShun <mcuos.com@gmail.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation;version 2 of the License. 11 */ 12 13#include <linux/module.h> 14#include <linux/kernel.h> 15#include <linux/device.h> 16#include <linux/list.h> 17#include <linux/errno.h> 18#include <linux/err.h> 19#include <linux/string.h> 20#include <linux/clk.h> 21#include <linux/mutex.h> 22#include <linux/io.h> 23 24#include <mach/hardware.h> 25 26#define REG_MFSEL (W90X900_VA_GCR + 0xC) 27 28#define GPSELF (0x01 << 1) 29#define GPSELC (0x03 << 2) 30#define GPSELD (0x0f << 4) 31 32#define GPSELEI0 (0x01 << 26) 33#define GPSELEI1 (0x01 << 27) 34 35#define GPIOG0TO1 (0x03 << 14) 36#define GPIOG2TO3 (0x03 << 16) 37#define GPIOG22TO23 (0x03 << 22) 38#define GPIOG18TO20 (0x07 << 18) 39 40#define ENSPI (0x0a << 14) 41#define ENI2C0 (0x01 << 14) 42#define ENI2C1 (0x01 << 16) 43#define ENAC97 (0x02 << 22) 44#define ENSD1 (0x02 << 18) 45#define ENSD0 (0x0a << 4) 46#define ENKPI (0x02 << 2) 47#define ENNAND (0x01 << 2) 48 49static DEFINE_MUTEX(mfp_mutex); 50 51void mfp_set_groupf(struct device *dev) 52{ 53 unsigned long mfpen; 54 const char *dev_id; 55 56 BUG_ON(!dev); 57 58 mutex_lock(&mfp_mutex); 59 60 dev_id = dev_name(dev); 61 62 mfpen = __raw_readl(REG_MFSEL); 63 64 if (strcmp(dev_id, "nuc900-emc") == 0) 65 mfpen |= GPSELF;/*enable mac*/ 66 else 67 mfpen &= ~GPSELF;/*GPIOF[9:0]*/ 68 69 __raw_writel(mfpen, REG_MFSEL); 70 71 mutex_unlock(&mfp_mutex); 72} 73EXPORT_SYMBOL(mfp_set_groupf); 74 75void mfp_set_groupc(struct device *dev) 76{ 77 unsigned long mfpen; 78 const char *dev_id; 79 80 BUG_ON(!dev); 81 82 mutex_lock(&mfp_mutex); 83 84 dev_id = dev_name(dev); 85 86 mfpen = __raw_readl(REG_MFSEL); 87 88 if (strcmp(dev_id, "nuc900-lcd") == 0) 89 mfpen |= GPSELC;/*enable lcd*/ 90 else if (strcmp(dev_id, "nuc900-kpi") == 0) { 91 mfpen &= (~GPSELC);/*enable kpi*/ 92 mfpen |= ENKPI; 93 } else if (strcmp(dev_id, "nuc900-nand") == 0) { 94 mfpen &= (~GPSELC);/*enable nand*/ 95 mfpen |= ENNAND; 96 } else 97 mfpen &= (~GPSELC);/*GPIOC[14:0]*/ 98 99 __raw_writel(mfpen, REG_MFSEL); 100 101 mutex_unlock(&mfp_mutex); 102} 103EXPORT_SYMBOL(mfp_set_groupc); 104 105void mfp_set_groupi(struct device *dev) 106{ 107 unsigned long mfpen; 108 const char *dev_id; 109 110 BUG_ON(!dev); 111 112 mutex_lock(&mfp_mutex); 113 114 dev_id = dev_name(dev); 115 116 mfpen = __raw_readl(REG_MFSEL); 117 118 mfpen &= ~GPSELEI1;/*default gpio16*/ 119 120 if (strcmp(dev_id, "nuc900-wdog") == 0) 121 mfpen |= GPSELEI1;/*enable wdog*/ 122 else if (strcmp(dev_id, "nuc900-atapi") == 0) 123 mfpen |= GPSELEI0;/*enable atapi*/ 124 else if (strcmp(dev_id, "nuc900-keypad") == 0) 125 mfpen &= ~GPSELEI0;/*enable keypad*/ 126 127 __raw_writel(mfpen, REG_MFSEL); 128 129 mutex_unlock(&mfp_mutex); 130} 131EXPORT_SYMBOL(mfp_set_groupi); 132 133void mfp_set_groupg(struct device *dev, const char *subname) 134{ 135 unsigned long mfpen; 136 const char *dev_id; 137 138 BUG_ON((!dev) && (!subname)); 139 140 mutex_lock(&mfp_mutex); 141 142 if (subname != NULL) 143 dev_id = subname; 144 else 145 dev_id = dev_name(dev); 146 147 mfpen = __raw_readl(REG_MFSEL); 148 149 if (strcmp(dev_id, "nuc900-spi") == 0) { 150 mfpen &= ~(GPIOG0TO1 | GPIOG2TO3); 151 mfpen |= ENSPI;/*enable spi*/ 152 } else if (strcmp(dev_id, "nuc900-i2c0") == 0) { 153 mfpen &= ~(GPIOG0TO1); 154 mfpen |= ENI2C0;/*enable i2c0*/ 155 } else if (strcmp(dev_id, "nuc900-i2c1") == 0) { 156 mfpen &= ~(GPIOG2TO3); 157 mfpen |= ENI2C1;/*enable i2c1*/ 158 } else if (strcmp(dev_id, "nuc900-ac97") == 0) { 159 mfpen &= ~(GPIOG22TO23); 160 mfpen |= ENAC97;/*enable AC97*/ 161 } else if (strcmp(dev_id, "nuc900-mmc-port1") == 0) { 162 mfpen &= ~(GPIOG18TO20); 163 mfpen |= (ENSD1 | 0x01);/*enable sd1*/ 164 } else { 165 mfpen &= ~(GPIOG0TO1 | GPIOG2TO3);/*GPIOG[3:0]*/ 166 } 167 168 __raw_writel(mfpen, REG_MFSEL); 169 170 mutex_unlock(&mfp_mutex); 171} 172EXPORT_SYMBOL(mfp_set_groupg); 173 174void mfp_set_groupd(struct device *dev, const char *subname) 175{ 176 unsigned long mfpen; 177 const char *dev_id; 178 179 BUG_ON((!dev) && (!subname)); 180 181 mutex_lock(&mfp_mutex); 182 183 if (subname != NULL) 184 dev_id = subname; 185 else 186 dev_id = dev_name(dev); 187 188 mfpen = __raw_readl(REG_MFSEL); 189 190 if (strcmp(dev_id, "nuc900-mmc-port0") == 0) { 191 mfpen &= ~GPSELD;/*enable sd0*/ 192 mfpen |= ENSD0; 193 } else 194 mfpen &= (~GPSELD); 195 196 __raw_writel(mfpen, REG_MFSEL); 197 198 mutex_unlock(&mfp_mutex); 199} 200EXPORT_SYMBOL(mfp_set_groupd); 201