jz4780_efuse.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * JZ4780 EFUSE driver
  4. *
  5. * Copyright (c) 2014 Imagination Technologies
  6. * Author: Alex Smith <alex.smith@imgtec.com>
  7. */
  8. #include <common.h>
  9. #include <asm/io.h>
  10. #include <asm/unaligned.h>
  11. #include <errno.h>
  12. #include <linux/bitops.h>
  13. #include <mach/jz4780.h>
  14. #include <wait_bit.h>
  15. #define EFUSE_EFUCTRL 0xd0
  16. #define EFUSE_EFUCFG 0xd4
  17. #define EFUSE_EFUSTATE 0xd8
  18. #define EFUSE_EFUDATA(n) (0xdc + ((n) * 4))
  19. #define EFUSE_EFUCTRL_RD_EN BIT(0)
  20. #define EFUSE_EFUCTRL_LEN_BIT 16
  21. #define EFUSE_EFUCTRL_LEN_MASK 0x1f
  22. #define EFUSE_EFUCTRL_ADDR_BIT 21
  23. #define EFUSE_EFUCTRL_ADDR_MASK 0x1ff
  24. #define EFUSE_EFUCTRL_CS BIT(30)
  25. #define EFUSE_EFUCFG_RD_STROBE_BIT 16
  26. #define EFUSE_EFUCFG_RD_STROBE_MASK 0xf
  27. #define EFUSE_EFUCFG_RD_ADJ_BIT 20
  28. #define EFUSE_EFUCFG_RD_ADJ_MASK 0xf
  29. #define EFUSE_EFUSTATE_RD_DONE BIT(0)
  30. static void jz4780_efuse_read_chunk(size_t addr, size_t count, u8 *buf)
  31. {
  32. void __iomem *regs = (void __iomem *)NEMC_BASE;
  33. size_t i;
  34. u32 val;
  35. int ret;
  36. val = EFUSE_EFUCTRL_RD_EN |
  37. ((count - 1) << EFUSE_EFUCTRL_LEN_BIT) |
  38. (addr << EFUSE_EFUCTRL_ADDR_BIT) |
  39. ((addr > 0x200) ? EFUSE_EFUCTRL_CS : 0);
  40. writel(val, regs + EFUSE_EFUCTRL);
  41. ret = wait_for_bit_le32(regs + EFUSE_EFUSTATE,
  42. EFUSE_EFUSTATE_RD_DONE, true, 10000, false);
  43. if (ret)
  44. return;
  45. if ((count % 4) == 0) {
  46. for (i = 0; i < count / 4; i++) {
  47. val = readl(regs + EFUSE_EFUDATA(i));
  48. put_unaligned(val, (u32 *)(buf + (i * 4)));
  49. }
  50. } else {
  51. val = readl(regs + EFUSE_EFUDATA(0));
  52. if (count > 2)
  53. buf[2] = (val >> 16) & 0xff;
  54. if (count > 1)
  55. buf[1] = (val >> 8) & 0xff;
  56. buf[0] = val & 0xff;
  57. }
  58. }
  59. static inline int jz4780_efuse_chunk_size(size_t count)
  60. {
  61. if (count >= 32)
  62. return 32;
  63. else if ((count / 4) > 0)
  64. return (count / 4) * 4;
  65. else
  66. return count % 4;
  67. }
  68. void jz4780_efuse_read(size_t addr, size_t count, u8 *buf)
  69. {
  70. size_t chunk;
  71. while (count > 0) {
  72. chunk = jz4780_efuse_chunk_size(count);
  73. jz4780_efuse_read_chunk(addr, chunk, buf);
  74. addr += chunk;
  75. buf += chunk;
  76. count -= chunk;
  77. }
  78. }
  79. void jz4780_efuse_init(u32 ahb2_rate)
  80. {
  81. void __iomem *regs = (void __iomem *)NEMC_BASE;
  82. u32 rd_adj, rd_strobe, tmp;
  83. rd_adj = (((6500 * (ahb2_rate / 1000000)) / 1000000) + 0xf) / 2;
  84. tmp = (((35000 * (ahb2_rate / 1000000)) / 1000000) - 4) - rd_adj;
  85. rd_strobe = ((tmp + 0xf) / 2 < 7) ? 7 : (tmp + 0xf) / 2;
  86. tmp = (rd_adj << EFUSE_EFUCFG_RD_ADJ_BIT) |
  87. (rd_strobe << EFUSE_EFUCFG_RD_STROBE_BIT);
  88. writel(tmp, regs + EFUSE_EFUCFG);
  89. }