encx24j600-regmap.c 12 KB

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