0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/init.h>
0014 #include <linux/types.h>
0015 #include <asm/io.h>
0016 #include <asm/txx9/smsc_fdc37m81x.h>
0017
0018
0019 #define SMSC_FDC37M81X_CONFIG_INDEX 0x00
0020 #define SMSC_FDC37M81X_CONFIG_DATA 0x01
0021 #define SMSC_FDC37M81X_CONF 0x02
0022 #define SMSC_FDC37M81X_INDEX 0x03
0023 #define SMSC_FDC37M81X_DNUM 0x07
0024 #define SMSC_FDC37M81X_DID 0x20
0025 #define SMSC_FDC37M81X_DREV 0x21
0026 #define SMSC_FDC37M81X_PCNT 0x22
0027 #define SMSC_FDC37M81X_PMGT 0x23
0028 #define SMSC_FDC37M81X_OSC 0x24
0029 #define SMSC_FDC37M81X_CONFPA0 0x26
0030 #define SMSC_FDC37M81X_CONFPA1 0x27
0031 #define SMSC_FDC37M81X_TEST4 0x2B
0032 #define SMSC_FDC37M81X_TEST5 0x2C
0033 #define SMSC_FDC37M81X_TEST1 0x2D
0034 #define SMSC_FDC37M81X_TEST2 0x2E
0035 #define SMSC_FDC37M81X_TEST3 0x2F
0036
0037
0038 #define SMSC_FDC37M81X_FDD 0x00
0039 #define SMSC_FDC37M81X_SERIAL1 0x04
0040 #define SMSC_FDC37M81X_SERIAL2 0x05
0041 #define SMSC_FDC37M81X_KBD 0x07
0042
0043
0044 #define SMSC_FDC37M81X_ACTIVE 0x30
0045 #define SMSC_FDC37M81X_BASEADDR0 0x60
0046 #define SMSC_FDC37M81X_BASEADDR1 0x61
0047 #define SMSC_FDC37M81X_INT 0x70
0048 #define SMSC_FDC37M81X_INT2 0x72
0049 #define SMSC_FDC37M81X_MODE 0xF0
0050
0051
0052 #define SMSC_FDC37M81X_CONFIG_ENTER 0x55
0053 #define SMSC_FDC37M81X_CONFIG_EXIT 0xaa
0054 #define SMSC_FDC37M81X_CHIP_ID 0x4d
0055
0056 static unsigned long g_smsc_fdc37m81x_base;
0057
0058 static inline unsigned char smsc_fdc37m81x_rd(unsigned char index)
0059 {
0060 outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX);
0061
0062 return inb(g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA);
0063 }
0064
0065 static inline void smsc_dc37m81x_wr(unsigned char index, unsigned char data)
0066 {
0067 outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX);
0068 outb(data, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA);
0069 }
0070
0071 void smsc_fdc37m81x_config_beg(void)
0072 {
0073 if (g_smsc_fdc37m81x_base) {
0074 outb(SMSC_FDC37M81X_CONFIG_ENTER,
0075 g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX);
0076 }
0077 }
0078
0079 void smsc_fdc37m81x_config_end(void)
0080 {
0081 if (g_smsc_fdc37m81x_base)
0082 outb(SMSC_FDC37M81X_CONFIG_EXIT,
0083 g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX);
0084 }
0085
0086 u8 smsc_fdc37m81x_config_get(u8 reg)
0087 {
0088 u8 val = 0;
0089
0090 if (g_smsc_fdc37m81x_base)
0091 val = smsc_fdc37m81x_rd(reg);
0092
0093 return val;
0094 }
0095
0096 void smsc_fdc37m81x_config_set(u8 reg, u8 val)
0097 {
0098 if (g_smsc_fdc37m81x_base)
0099 smsc_dc37m81x_wr(reg, val);
0100 }
0101
0102 unsigned long __init smsc_fdc37m81x_init(unsigned long port)
0103 {
0104 const int field = sizeof(unsigned long) * 2;
0105 u8 chip_id;
0106
0107 if (g_smsc_fdc37m81x_base)
0108 pr_warn("%s: stepping on old base=0x%0*lx\n", __func__, field,
0109 g_smsc_fdc37m81x_base);
0110
0111 g_smsc_fdc37m81x_base = port;
0112
0113 smsc_fdc37m81x_config_beg();
0114
0115 chip_id = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DID);
0116 if (chip_id == SMSC_FDC37M81X_CHIP_ID)
0117 smsc_fdc37m81x_config_end();
0118 else {
0119 pr_warn("%s: unknown chip id 0x%02x\n", __func__, chip_id);
0120 g_smsc_fdc37m81x_base = 0;
0121 }
0122
0123 return g_smsc_fdc37m81x_base;
0124 }
0125
0126 #ifdef DEBUG
0127 static void smsc_fdc37m81x_config_dump_one(const char *key, u8 dev, u8 reg)
0128 {
0129 pr_info("%s: dev=0x%02x reg=0x%02x val=0x%02x\n", key, dev, reg,
0130 smsc_fdc37m81x_rd(reg));
0131 }
0132
0133 void smsc_fdc37m81x_config_dump(void)
0134 {
0135 u8 orig;
0136 const char *fname = __func__;
0137
0138 smsc_fdc37m81x_config_beg();
0139
0140 orig = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DNUM);
0141
0142 pr_info("%s: common\n", fname);
0143 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
0144 SMSC_FDC37M81X_DNUM);
0145 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
0146 SMSC_FDC37M81X_DID);
0147 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
0148 SMSC_FDC37M81X_DREV);
0149 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
0150 SMSC_FDC37M81X_PCNT);
0151 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
0152 SMSC_FDC37M81X_PMGT);
0153
0154 pr_info("%s: keyboard\n", fname);
0155 smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, SMSC_FDC37M81X_KBD);
0156 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD,
0157 SMSC_FDC37M81X_ACTIVE);
0158 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD,
0159 SMSC_FDC37M81X_INT);
0160 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD,
0161 SMSC_FDC37M81X_INT2);
0162 smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD,
0163 SMSC_FDC37M81X_LDCR_F0);
0164
0165 smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, orig);
0166
0167 smsc_fdc37m81x_config_end();
0168 }
0169 #endif