1 /**
2  * Register map access API - ENCX24J600 support
3  *
4  * Copyright 2015 Gridpoint
5  *
6  * Author: Jon Ringle <jringle@gridpoint.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 version 2 as
10  * published by the Free Software Foundation.
11  */
12 
13 #include <linux/delay.h>
14 #include <linux/errno.h>
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/netdevice.h>
18 #include <linux/regmap.h>
19 #include <linux/spi/spi.h>
20 
21 #include "encx24j600_hw.h"
22 
23 static inline bool is_bits_set(int value, int mask)
24 {
25 	return (value & mask) == mask;
26 }
27 
28 static int encx24j600_switch_bank(struct encx24j600_context *ctx,
29 				  int bank)
30 {
31 	int ret = 0;
32 	int bank_opcode = BANK_SELECT(bank);
33 
34 	ret = spi_write(ctx->spi, &bank_opcode, 1);
35 	if (ret == 0)
36 		ctx->bank = bank;
37 
38 	return ret;
39 }
40 
41 static int encx24j600_cmdn(struct encx24j600_context *ctx, u8 opcode,
42 			   const void *buf, size_t len)
43 {
44 	struct spi_message m;
45 	struct spi_transfer t[2] = { { .tx_buf = &opcode, .len = 1, },
46 				     { .tx_buf = buf, .len = len }, };
47 	spi_message_init(&m);
48 	spi_message_add_tail(&t[0], &m);
49 	spi_message_add_tail(&t[1], &m);
50 
51 	return spi_sync(ctx->spi, &m);
52 }
53 
54 static void regmap_lock_mutex(void *context)
55 {
56 	struct encx24j600_context *ctx = context;
57 
58 	mutex_lock(&ctx->mutex);
59 }
60 
61 static void regmap_unlock_mutex(void *context)
62 {
63 	struct encx24j600_context *ctx = context;
64 
65 	mutex_unlock(&ctx->mutex);
66 }
67 
68 static int regmap_encx24j600_sfr_read(void *context, u8 reg, u8 *val,
69 				      size_t len)
70 {
71 	struct encx24j600_context *ctx = context;
72 	u8 banked_reg = reg & ADDR_MASK;
73 	u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT);
74 	u8 cmd = RCRU;
75 	int ret = 0;
76 	int i = 0;
77 	u8 tx_buf[2];
78 
79 	if (reg < 0x80) {
80 		cmd = RCRCODE | banked_reg;
81 		if ((banked_reg < 0x16) && (ctx->bank != bank))
82 			ret = encx24j600_switch_bank(ctx, bank);
83 		if (unlikely(ret))
84 			return ret;
85 	} else {
86 		/* Translate registers that are more effecient using
87 		 * 3-byte SPI commands
88 		 */
89 		switch (reg) {
90 		case EGPRDPT:
91 			cmd = RGPRDPT; break;
92 		case EGPWRPT:
93 			cmd = RGPWRPT; break;
94 		case ERXRDPT:
95 			cmd = RRXRDPT; break;
96 		case ERXWRPT:
97 			cmd = RRXWRPT; break;
98 		case EUDARDPT:
99 			cmd = RUDARDPT; break;
100 		case EUDAWRPT:
101 			cmd = RUDAWRPT; break;
102 		case EGPDATA:
103 		case ERXDATA:
104 		case EUDADATA:
105 		default:
106 			return -EINVAL;
107 		}
108 	}
109 
110 	tx_buf[i++] = cmd;
111 	if (cmd == RCRU)
112 		tx_buf[i++] = reg;
113 
114 	ret = spi_write_then_read(ctx->spi, tx_buf, i, val, len);
115 
116 	return ret;
117 }
118 
119 static int regmap_encx24j600_sfr_update(struct encx24j600_context *ctx,
120 					u8 reg, u8 *val, size_t len,
121 					u8 unbanked_cmd, u8 banked_code)
122 {
123 	u8 banked_reg = reg & ADDR_MASK;
124 	u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT);
125 	u8 cmd = unbanked_cmd;
126 	struct spi_message m;
127 	struct spi_transfer t[3] = { { .tx_buf = &cmd, .len = sizeof(cmd), },
128 				     { .tx_buf = &reg, .len = sizeof(reg), },
129 				     { .tx_buf = val, .len = len }, };
130 
131 	if (reg < 0x80) {
132 		int ret = 0;
133 
134 		cmd = banked_code | banked_reg;
135 		if ((banked_reg < 0x16) && (ctx->bank != bank))
136 			ret = encx24j600_switch_bank(ctx, bank);
137 		if (unlikely(ret))
138 			return ret;
139 	} else {
140 		/* Translate registers that are more effecient using
141 		 * 3-byte SPI commands
142 		 */
143 		switch (reg) {
144 		case EGPRDPT:
145 			cmd = WGPRDPT; break;
146 		case EGPWRPT:
147 			cmd = WGPWRPT; break;
148 		case ERXRDPT:
149 			cmd = WRXRDPT; break;
150 		case ERXWRPT:
151 			cmd = WRXWRPT; break;
152 		case EUDARDPT:
153 			cmd = WUDARDPT; break;
154 		case EUDAWRPT:
155 			cmd = WUDAWRPT; break;
156 		case EGPDATA:
157 		case ERXDATA:
158 		case EUDADATA:
159 		default:
160 			return -EINVAL;
161 		}
162 	}
163 
164 	spi_message_init(&m);
165 	spi_message_add_tail(&t[0], &m);
166 
167 	if (cmd == unbanked_cmd) {
168 		t[1].tx_buf = &reg;
169 		spi_message_add_tail(&t[1], &m);
170 	}
171 
172 	spi_message_add_tail(&t[2], &m);
173 	return spi_sync(ctx->spi, &m);
174 }
175 
176 static int regmap_encx24j600_sfr_write(void *context, u8 reg, u8 *val,
177 				       size_t len)
178 {
179 	struct encx24j600_context *ctx = context;
180 
181 	return regmap_encx24j600_sfr_update(ctx, reg, val, len, WCRU, WCRCODE);
182 }
183 
184 static int regmap_encx24j600_sfr_set_bits(struct encx24j600_context *ctx,
185 					  u8 reg, u8 val)
186 {
187 	return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFSU, BFSCODE);
188 }
189 
190 static int regmap_encx24j600_sfr_clr_bits(struct encx24j600_context *ctx,
191 					  u8 reg, u8 val)
192 {
193 	return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFCU, BFCCODE);
194 }
195 
196 static int regmap_encx24j600_reg_update_bits(void *context, unsigned int reg,
197 					     unsigned int mask,
198 					     unsigned int val)
199 {
200 	struct encx24j600_context *ctx = context;
201 
202 	int ret = 0;
203 	unsigned int set_mask = mask & val;
204 	unsigned int clr_mask = mask & ~val;
205 
206 	if ((reg >= 0x40 && reg < 0x6c) || reg >= 0x80)
207 		return -EINVAL;
208 
209 	if (set_mask & 0xff)
210 		ret = regmap_encx24j600_sfr_set_bits(ctx, reg, set_mask);
211 
212 	set_mask = (set_mask & 0xff00) >> 8;
213 
214 	if ((set_mask & 0xff) && (ret == 0))
215 		ret = regmap_encx24j600_sfr_set_bits(ctx, reg + 1, set_mask);
216 
217 	if ((clr_mask & 0xff) && (ret == 0))
218 		ret = regmap_encx24j600_sfr_clr_bits(ctx, reg, clr_mask);
219 
220 	clr_mask = (clr_mask & 0xff00) >> 8;
221 
222 	if ((clr_mask & 0xff) && (ret == 0))
223 		ret = regmap_encx24j600_sfr_clr_bits(ctx, reg + 1, clr_mask);
224 
225 	return ret;
226 }
227 
228 int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data,
229 				size_t count)
230 {
231 	struct encx24j600_context *ctx = context;
232 
233 	if (reg < 0xc0)
234 		return encx24j600_cmdn(ctx, reg, data, count);
235 
236 	/* SPI 1-byte command. Ignore data */
237 	return spi_write(ctx->spi, &reg, 1);
238 }
239 EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_write);
240 
241 int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count)
242 {
243 	struct encx24j600_context *ctx = context;
244 
245 	if (reg == RBSEL && count > 1)
246 		count = 1;
247 
248 	return spi_write_then_read(ctx->spi, &reg, sizeof(reg), data, count);
249 }
250 EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_read);
251 
252 static int regmap_encx24j600_write(void *context, const void *data,
253 				   size_t len)
254 {
255 	u8 *dout = (u8 *)data;
256 	u8 reg = dout[0];
257 	++dout;
258 	--len;
259 
260 	if (reg > 0xa0)
261 		return regmap_encx24j600_spi_write(context, reg, dout, len);
262 
263 	if (len > 2)
264 		return -EINVAL;
265 
266 	return regmap_encx24j600_sfr_write(context, reg, dout, len);
267 }
268 
269 static int regmap_encx24j600_read(void *context,
270 				  const void *reg_buf, size_t reg_size,
271 				  void *val, size_t val_size)
272 {
273 	u8 reg = *(const u8 *)reg_buf;
274 
275 	if (reg_size != 1) {
276 		pr_err("%s: reg=%02x reg_size=%zu\n", __func__, reg, reg_size);
277 		return -EINVAL;
278 	}
279 
280 	if (reg > 0xa0)
281 		return regmap_encx24j600_spi_read(context, reg, val, val_size);
282 
283 	if (val_size > 2) {
284 		pr_err("%s: reg=%02x val_size=%zu\n", __func__, reg, val_size);
285 		return -EINVAL;
286 	}
287 
288 	return regmap_encx24j600_sfr_read(context, reg, val, val_size);
289 }
290 
291 static bool encx24j600_regmap_readable(struct device *dev, unsigned int reg)
292 {
293 	if ((reg < 0x36) ||
294 	    ((reg >= 0x40) && (reg < 0x4c)) ||
295 	    ((reg >= 0x52) && (reg < 0x56)) ||
296 	    ((reg >= 0x60) && (reg < 0x66)) ||
297 	    ((reg >= 0x68) && (reg < 0x80)) ||
298 	    ((reg >= 0x86) && (reg < 0x92)) ||
299 	    (reg == 0xc8))
300 		return true;
301 	else
302 		return false;
303 }
304 
305 static bool encx24j600_regmap_writeable(struct device *dev, unsigned int reg)
306 {
307 	if ((reg < 0x12) ||
308 	    ((reg >= 0x14) && (reg < 0x1a)) ||
309 	    ((reg >= 0x1c) && (reg < 0x36)) ||
310 	    ((reg >= 0x40) && (reg < 0x4c)) ||
311 	    ((reg >= 0x52) && (reg < 0x56)) ||
312 	    ((reg >= 0x60) && (reg < 0x68)) ||
313 	    ((reg >= 0x6c) && (reg < 0x80)) ||
314 	    ((reg >= 0x86) && (reg < 0x92)) ||
315 	    ((reg >= 0xc0) && (reg < 0xc8)) ||
316 	    ((reg >= 0xca) && (reg < 0xf0)))
317 		return true;
318 	else
319 		return false;
320 }
321 
322 static bool encx24j600_regmap_volatile(struct device *dev, unsigned int reg)
323 {
324 	switch (reg) {
325 	case ERXHEAD:
326 	case EDMACS:
327 	case ETXSTAT:
328 	case ETXWIRE:
329 	case ECON1:	/* Can be modified via single byte cmds */
330 	case ECON2:	/* Can be modified via single byte cmds */
331 	case ESTAT:
332 	case EIR:	/* Can be modified via single byte cmds */
333 	case MIRD:
334 	case MISTAT:
335 		return true;
336 	default:
337 		break;
338 	}
339 
340 	return false;
341 }
342 
343 static bool encx24j600_regmap_precious(struct device *dev, unsigned int reg)
344 {
345 	/* single byte cmds are precious */
346 	if (((reg >= 0xc0) && (reg < 0xc8)) ||
347 	    ((reg >= 0xca) && (reg < 0xf0)))
348 		return true;
349 	else
350 		return false;
351 }
352 
353 static int regmap_encx24j600_phy_reg_read(void *context, unsigned int reg,
354 					  unsigned int *val)
355 {
356 	struct encx24j600_context *ctx = context;
357 	int ret;
358 	unsigned int mistat;
359 
360 	reg = MIREGADR_VAL | (reg & PHREG_MASK);
361 	ret = regmap_write(ctx->regmap, MIREGADR, reg);
362 	if (unlikely(ret))
363 		goto err_out;
364 
365 	ret = regmap_write(ctx->regmap, MICMD, MIIRD);
366 	if (unlikely(ret))
367 		goto err_out;
368 
369 	usleep_range(26, 100);
370 	while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) &&
371 	       (mistat & BUSY))
372 		cpu_relax();
373 
374 	if (unlikely(ret))
375 		goto err_out;
376 
377 	ret = regmap_write(ctx->regmap, MICMD, 0);
378 	if (unlikely(ret))
379 		goto err_out;
380 
381 	ret = regmap_read(ctx->regmap, MIRD, val);
382 
383 err_out:
384 	if (ret)
385 		pr_err("%s: error %d reading reg %02x\n", __func__, ret,
386 		       reg & PHREG_MASK);
387 
388 	return ret;
389 }
390 
391 static int regmap_encx24j600_phy_reg_write(void *context, unsigned int reg,
392 					   unsigned int val)
393 {
394 	struct encx24j600_context *ctx = context;
395 	int ret;
396 	unsigned int mistat;
397 
398 	reg = MIREGADR_VAL | (reg & PHREG_MASK);
399 	ret = regmap_write(ctx->regmap, MIREGADR, reg);
400 	if (unlikely(ret))
401 		goto err_out;
402 
403 	ret = regmap_write(ctx->regmap, MIWR, val);
404 	if (unlikely(ret))
405 		goto err_out;
406 
407 	usleep_range(26, 100);
408 	while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) &&
409 	       (mistat & BUSY))
410 		cpu_relax();
411 
412 err_out:
413 	if (ret)
414 		pr_err("%s: error %d writing reg %02x=%04x\n", __func__, ret,
415 		       reg & PHREG_MASK, val);
416 
417 	return ret;
418 }
419 
420 static bool encx24j600_phymap_readable(struct device *dev, unsigned int reg)
421 {
422 	switch (reg) {
423 	case PHCON1:
424 	case PHSTAT1:
425 	case PHANA:
426 	case PHANLPA:
427 	case PHANE:
428 	case PHCON2:
429 	case PHSTAT2:
430 	case PHSTAT3:
431 		return true;
432 	default:
433 		return false;
434 	}
435 }
436 
437 static bool encx24j600_phymap_writeable(struct device *dev, unsigned int reg)
438 {
439 	switch (reg) {
440 	case PHCON1:
441 	case PHCON2:
442 	case PHANA:
443 		return true;
444 	case PHSTAT1:
445 	case PHSTAT2:
446 	case PHSTAT3:
447 	case PHANLPA:
448 	case PHANE:
449 	default:
450 		return false;
451 	}
452 }
453 
454 static bool encx24j600_phymap_volatile(struct device *dev, unsigned int reg)
455 {
456 	switch (reg) {
457 	case PHSTAT1:
458 	case PHSTAT2:
459 	case PHSTAT3:
460 	case PHANLPA:
461 	case PHANE:
462 	case PHCON2:
463 		return true;
464 	default:
465 		return false;
466 	}
467 }
468 
469 static struct regmap_config regcfg = {
470 	.name = "reg",
471 	.reg_bits = 8,
472 	.val_bits = 16,
473 	.max_register = 0xee,
474 	.reg_stride = 2,
475 	.cache_type = REGCACHE_RBTREE,
476 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
477 	.readable_reg = encx24j600_regmap_readable,
478 	.writeable_reg = encx24j600_regmap_writeable,
479 	.volatile_reg = encx24j600_regmap_volatile,
480 	.precious_reg = encx24j600_regmap_precious,
481 	.lock = regmap_lock_mutex,
482 	.unlock = regmap_unlock_mutex,
483 };
484 
485 static struct regmap_bus regmap_encx24j600 = {
486 	.write = regmap_encx24j600_write,
487 	.read = regmap_encx24j600_read,
488 	.reg_update_bits = regmap_encx24j600_reg_update_bits,
489 };
490 
491 static struct regmap_config phycfg = {
492 	.name = "phy",
493 	.reg_bits = 8,
494 	.val_bits = 16,
495 	.max_register = 0x1f,
496 	.cache_type = REGCACHE_RBTREE,
497 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
498 	.readable_reg = encx24j600_phymap_readable,
499 	.writeable_reg = encx24j600_phymap_writeable,
500 	.volatile_reg = encx24j600_phymap_volatile,
501 };
502 
503 static struct regmap_bus phymap_encx24j600 = {
504 	.reg_write = regmap_encx24j600_phy_reg_write,
505 	.reg_read = regmap_encx24j600_phy_reg_read,
506 };
507 
508 void devm_regmap_init_encx24j600(struct device *dev,
509 				 struct encx24j600_context *ctx)
510 {
511 	mutex_init(&ctx->mutex);
512 	regcfg.lock_arg = ctx;
513 	ctx->regmap = devm_regmap_init(dev, &regmap_encx24j600, ctx, &regcfg);
514 	ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg);
515 }
516 EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600);
517 
518 MODULE_LICENSE("GPL");
519