encx24j600-regmap.c 11 KB

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