diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/ks8851.c | 228 | ||||
| -rw-r--r-- | drivers/net/ks8851.h | 14 |
2 files changed, 241 insertions, 1 deletions
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 623171f37d99..3dba57b72ef8 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c | |||
| @@ -1034,6 +1034,234 @@ static const struct net_device_ops ks8851_netdev_ops = { | |||
| 1034 | .ndo_validate_addr = eth_validate_addr, | 1034 | .ndo_validate_addr = eth_validate_addr, |
| 1035 | }; | 1035 | }; |
| 1036 | 1036 | ||
| 1037 | /* Companion eeprom access */ | ||
| 1038 | |||
| 1039 | enum { /* EEPROM programming states */ | ||
| 1040 | EEPROM_CONTROL, | ||
| 1041 | EEPROM_ADDRESS, | ||
| 1042 | EEPROM_DATA, | ||
| 1043 | EEPROM_COMPLETE | ||
| 1044 | }; | ||
| 1045 | |||
| 1046 | /** | ||
| 1047 | * ks8851_eeprom_read - read a 16bits word in ks8851 companion EEPROM | ||
| 1048 | * @dev: The network device the PHY is on. | ||
| 1049 | * @addr: EEPROM address to read | ||
| 1050 | * | ||
| 1051 | * eeprom_size: used to define the data coding length. Can be changed | ||
| 1052 | * through debug-fs. | ||
| 1053 | * | ||
| 1054 | * Programs a read on the EEPROM using ks8851 EEPROM SW access feature. | ||
| 1055 | * Warning: The READ feature is not supported on ks8851 revision 0. | ||
| 1056 | * | ||
| 1057 | * Rough programming model: | ||
| 1058 | * - on period start: set clock high and read value on bus | ||
| 1059 | * - on period / 2: set clock low and program value on bus | ||
| 1060 | * - start on period / 2 | ||
| 1061 | */ | ||
| 1062 | unsigned int ks8851_eeprom_read(struct net_device *dev, unsigned int addr) | ||
| 1063 | { | ||
| 1064 | struct ks8851_net *ks = netdev_priv(dev); | ||
| 1065 | int eepcr; | ||
| 1066 | int ctrl = EEPROM_OP_READ; | ||
| 1067 | int state = EEPROM_CONTROL; | ||
| 1068 | int bit_count = EEPROM_OP_LEN - 1; | ||
| 1069 | unsigned int data = 0; | ||
| 1070 | int dummy; | ||
| 1071 | unsigned int addr_len; | ||
| 1072 | |||
| 1073 | addr_len = (ks->eeprom_size == 128) ? 6 : 8; | ||
| 1074 | |||
| 1075 | /* start transaction: chip select high, authorize write */ | ||
| 1076 | mutex_lock(&ks->lock); | ||
| 1077 | eepcr = EEPCR_EESA | EEPCR_EESRWA; | ||
| 1078 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1079 | eepcr |= EEPCR_EECS; | ||
| 1080 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1081 | mutex_unlock(&ks->lock); | ||
| 1082 | |||
| 1083 | while (state != EEPROM_COMPLETE) { | ||
| 1084 | /* falling clock period starts... */ | ||
| 1085 | /* set EED_IO pin for control and address */ | ||
| 1086 | eepcr &= ~EEPCR_EEDO; | ||
| 1087 | switch (state) { | ||
| 1088 | case EEPROM_CONTROL: | ||
| 1089 | eepcr |= ((ctrl >> bit_count) & 1) << 2; | ||
| 1090 | if (bit_count-- <= 0) { | ||
| 1091 | bit_count = addr_len - 1; | ||
| 1092 | state = EEPROM_ADDRESS; | ||
| 1093 | } | ||
| 1094 | break; | ||
| 1095 | case EEPROM_ADDRESS: | ||
| 1096 | eepcr |= ((addr >> bit_count) & 1) << 2; | ||
| 1097 | bit_count--; | ||
| 1098 | break; | ||
| 1099 | case EEPROM_DATA: | ||
| 1100 | /* Change to receive mode */ | ||
| 1101 | eepcr &= ~EEPCR_EESRWA; | ||
| 1102 | break; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | /* lower clock */ | ||
| 1106 | eepcr &= ~EEPCR_EESCK; | ||
| 1107 | |||
| 1108 | mutex_lock(&ks->lock); | ||
| 1109 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1110 | mutex_unlock(&ks->lock); | ||
| 1111 | |||
| 1112 | /* waitread period / 2 */ | ||
| 1113 | udelay(EEPROM_SK_PERIOD / 2); | ||
| 1114 | |||
| 1115 | /* rising clock period starts... */ | ||
| 1116 | |||
| 1117 | /* raise clock */ | ||
| 1118 | mutex_lock(&ks->lock); | ||
| 1119 | eepcr |= EEPCR_EESCK; | ||
| 1120 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1121 | mutex_unlock(&ks->lock); | ||
| 1122 | |||
| 1123 | /* Manage read */ | ||
| 1124 | switch (state) { | ||
| 1125 | case EEPROM_ADDRESS: | ||
| 1126 | if (bit_count < 0) { | ||
| 1127 | bit_count = EEPROM_DATA_LEN - 1; | ||
| 1128 | state = EEPROM_DATA; | ||
| 1129 | } | ||
| 1130 | break; | ||
| 1131 | case EEPROM_DATA: | ||
| 1132 | mutex_lock(&ks->lock); | ||
| 1133 | dummy = ks8851_rdreg16(ks, KS_EEPCR); | ||
| 1134 | mutex_unlock(&ks->lock); | ||
| 1135 | data |= ((dummy >> EEPCR_EESB_OFFSET) & 1) << bit_count; | ||
| 1136 | if (bit_count-- <= 0) | ||
| 1137 | state = EEPROM_COMPLETE; | ||
| 1138 | break; | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | /* wait period / 2 */ | ||
| 1142 | udelay(EEPROM_SK_PERIOD / 2); | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | /* close transaction */ | ||
| 1146 | mutex_lock(&ks->lock); | ||
| 1147 | eepcr &= ~EEPCR_EECS; | ||
| 1148 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1149 | eepcr = 0; | ||
| 1150 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1151 | mutex_unlock(&ks->lock); | ||
| 1152 | |||
| 1153 | return data; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | /** | ||
| 1157 | * ks8851_eeprom_write - write a 16bits word in ks8851 companion EEPROM | ||
| 1158 | * @dev: The network device the PHY is on. | ||
| 1159 | * @op: operand (can be WRITE, EWEN, EWDS) | ||
| 1160 | * @addr: EEPROM address to write | ||
| 1161 | * @data: data to write | ||
| 1162 | * | ||
| 1163 | * eeprom_size: used to define the data coding length. Can be changed | ||
| 1164 | * through debug-fs. | ||
| 1165 | * | ||
| 1166 | * Programs a write on the EEPROM using ks8851 EEPROM SW access feature. | ||
| 1167 | * | ||
| 1168 | * Note that a write enable is required before writing data. | ||
| 1169 | * | ||
| 1170 | * Rough programming model: | ||
| 1171 | * - on period start: set clock high | ||
| 1172 | * - on period / 2: set clock low and program value on bus | ||
| 1173 | * - start on period / 2 | ||
| 1174 | */ | ||
| 1175 | void ks8851_eeprom_write(struct net_device *dev, unsigned int op, | ||
| 1176 | unsigned int addr, unsigned int data) | ||
| 1177 | { | ||
| 1178 | struct ks8851_net *ks = netdev_priv(dev); | ||
| 1179 | int eepcr; | ||
| 1180 | int state = EEPROM_CONTROL; | ||
| 1181 | int bit_count = EEPROM_OP_LEN - 1; | ||
| 1182 | unsigned int addr_len; | ||
| 1183 | |||
| 1184 | addr_len = (ks->eeprom_size == 128) ? 6 : 8; | ||
| 1185 | |||
| 1186 | switch (op) { | ||
| 1187 | case EEPROM_OP_EWEN: | ||
| 1188 | addr = 0x30; | ||
| 1189 | break; | ||
| 1190 | case EEPROM_OP_EWDS: | ||
| 1191 | addr = 0; | ||
| 1192 | break; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | /* start transaction: chip select high, authorize write */ | ||
| 1196 | mutex_lock(&ks->lock); | ||
| 1197 | eepcr = EEPCR_EESA | EEPCR_EESRWA; | ||
| 1198 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1199 | eepcr |= EEPCR_EECS; | ||
| 1200 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1201 | mutex_unlock(&ks->lock); | ||
| 1202 | |||
| 1203 | while (state != EEPROM_COMPLETE) { | ||
| 1204 | /* falling clock period starts... */ | ||
| 1205 | /* set EED_IO pin for control and address */ | ||
| 1206 | eepcr &= ~EEPCR_EEDO; | ||
| 1207 | switch (state) { | ||
| 1208 | case EEPROM_CONTROL: | ||
| 1209 | eepcr |= ((op >> bit_count) & 1) << 2; | ||
| 1210 | if (bit_count-- <= 0) { | ||
| 1211 | bit_count = addr_len - 1; | ||
| 1212 | state = EEPROM_ADDRESS; | ||
| 1213 | } | ||
| 1214 | break; | ||
| 1215 | case EEPROM_ADDRESS: | ||
| 1216 | eepcr |= ((addr >> bit_count) & 1) << 2; | ||
| 1217 | if (bit_count-- <= 0) { | ||
| 1218 | if (op == EEPROM_OP_WRITE) { | ||
| 1219 | bit_count = EEPROM_DATA_LEN - 1; | ||
| 1220 | state = EEPROM_DATA; | ||
| 1221 | } else { | ||
| 1222 | state = EEPROM_COMPLETE; | ||
| 1223 | } | ||
| 1224 | } | ||
| 1225 | break; | ||
| 1226 | case EEPROM_DATA: | ||
| 1227 | eepcr |= ((data >> bit_count) & 1) << 2; | ||
| 1228 | if (bit_count-- <= 0) | ||
| 1229 | state = EEPROM_COMPLETE; | ||
| 1230 | break; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | /* lower clock */ | ||
| 1234 | eepcr &= ~EEPCR_EESCK; | ||
| 1235 | |||
| 1236 | mutex_lock(&ks->lock); | ||
| 1237 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1238 | mutex_unlock(&ks->lock); | ||
| 1239 | |||
| 1240 | /* wait period / 2 */ | ||
| 1241 | udelay(EEPROM_SK_PERIOD / 2); | ||
| 1242 | |||
| 1243 | /* rising clock period starts... */ | ||
| 1244 | |||
| 1245 | /* raise clock */ | ||
| 1246 | eepcr |= EEPCR_EESCK; | ||
| 1247 | mutex_lock(&ks->lock); | ||
| 1248 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1249 | mutex_unlock(&ks->lock); | ||
| 1250 | |||
| 1251 | /* wait period / 2 */ | ||
| 1252 | udelay(EEPROM_SK_PERIOD / 2); | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | /* close transaction */ | ||
| 1256 | mutex_lock(&ks->lock); | ||
| 1257 | eepcr &= ~EEPCR_EECS; | ||
| 1258 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1259 | eepcr = 0; | ||
| 1260 | ks8851_wrreg16(ks, KS_EEPCR, eepcr); | ||
| 1261 | mutex_unlock(&ks->lock); | ||
| 1262 | |||
| 1263 | } | ||
| 1264 | |||
| 1037 | /* ethtool support */ | 1265 | /* ethtool support */ |
| 1038 | 1266 | ||
| 1039 | static void ks8851_get_drvinfo(struct net_device *dev, | 1267 | static void ks8851_get_drvinfo(struct net_device *dev, |
diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h index f52c312cc356..537fb06e5932 100644 --- a/drivers/net/ks8851.h +++ b/drivers/net/ks8851.h | |||
| @@ -25,12 +25,24 @@ | |||
| 25 | #define OBCR_ODS_16mA (1 << 6) | 25 | #define OBCR_ODS_16mA (1 << 6) |
| 26 | 26 | ||
| 27 | #define KS_EEPCR 0x22 | 27 | #define KS_EEPCR 0x22 |
| 28 | #define EEPCR_EESRWA (1 << 5) | ||
| 28 | #define EEPCR_EESA (1 << 4) | 29 | #define EEPCR_EESA (1 << 4) |
| 29 | #define EEPCR_EESB (1 << 3) | 30 | #define EEPCR_EESB_OFFSET 3 |
| 31 | #define EEPCR_EESB (1 << EEPCR_EESB_OFFSET) | ||
| 30 | #define EEPCR_EEDO (1 << 2) | 32 | #define EEPCR_EEDO (1 << 2) |
| 31 | #define EEPCR_EESCK (1 << 1) | 33 | #define EEPCR_EESCK (1 << 1) |
| 32 | #define EEPCR_EECS (1 << 0) | 34 | #define EEPCR_EECS (1 << 0) |
| 33 | 35 | ||
| 36 | #define EEPROM_OP_LEN 3 /* bits:*/ | ||
| 37 | #define EEPROM_OP_READ 0x06 | ||
| 38 | #define EEPROM_OP_EWEN 0x04 | ||
| 39 | #define EEPROM_OP_WRITE 0x05 | ||
| 40 | #define EEPROM_OP_EWDS 0x14 | ||
| 41 | |||
| 42 | #define EEPROM_DATA_LEN 16 /* 16 bits EEPROM */ | ||
| 43 | #define EEPROM_WRITE_TIME 4 /* wrt ack time in ms */ | ||
| 44 | #define EEPROM_SK_PERIOD 400 /* in us */ | ||
| 45 | |||
| 34 | #define KS_MBIR 0x24 | 46 | #define KS_MBIR 0x24 |
| 35 | #define MBIR_TXMBF (1 << 12) | 47 | #define MBIR_TXMBF (1 << 12) |
| 36 | #define MBIR_TXMBFA (1 << 11) | 48 | #define MBIR_TXMBFA (1 << 11) |
