fuse-tegra20.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms and conditions of the GNU General Public License,
  6. * version 2, as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. * more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. * Based on drivers/misc/eeprom/sunxi_sid.c
  17. */
  18. #include <linux/device.h>
  19. #include <linux/clk.h>
  20. #include <linux/completion.h>
  21. #include <linux/dmaengine.h>
  22. #include <linux/dma-mapping.h>
  23. #include <linux/err.h>
  24. #include <linux/io.h>
  25. #include <linux/kernel.h>
  26. #include <linux/kobject.h>
  27. #include <linux/of_device.h>
  28. #include <linux/platform_device.h>
  29. #include <linux/random.h>
  30. #include <soc/tegra/fuse.h>
  31. #include "fuse.h"
  32. #define FUSE_BEGIN 0x100
  33. #define FUSE_SIZE 0x1f8
  34. #define FUSE_UID_LOW 0x08
  35. #define FUSE_UID_HIGH 0x0c
  36. static phys_addr_t fuse_phys;
  37. static struct clk *fuse_clk;
  38. static void __iomem __initdata *fuse_base;
  39. static DEFINE_MUTEX(apb_dma_lock);
  40. static DECLARE_COMPLETION(apb_dma_wait);
  41. static struct dma_chan *apb_dma_chan;
  42. static struct dma_slave_config dma_sconfig;
  43. static u32 *apb_buffer;
  44. static dma_addr_t apb_buffer_phys;
  45. static void apb_dma_complete(void *args)
  46. {
  47. complete(&apb_dma_wait);
  48. }
  49. static u32 tegra20_fuse_readl(const unsigned int offset)
  50. {
  51. int ret;
  52. u32 val = 0;
  53. struct dma_async_tx_descriptor *dma_desc;
  54. mutex_lock(&apb_dma_lock);
  55. dma_sconfig.src_addr = fuse_phys + FUSE_BEGIN + offset;
  56. ret = dmaengine_slave_config(apb_dma_chan, &dma_sconfig);
  57. if (ret)
  58. goto out;
  59. dma_desc = dmaengine_prep_slave_single(apb_dma_chan, apb_buffer_phys,
  60. sizeof(u32), DMA_DEV_TO_MEM,
  61. DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
  62. if (!dma_desc)
  63. goto out;
  64. dma_desc->callback = apb_dma_complete;
  65. dma_desc->callback_param = NULL;
  66. reinit_completion(&apb_dma_wait);
  67. clk_prepare_enable(fuse_clk);
  68. dmaengine_submit(dma_desc);
  69. dma_async_issue_pending(apb_dma_chan);
  70. ret = wait_for_completion_timeout(&apb_dma_wait, msecs_to_jiffies(50));
  71. if (WARN(ret == 0, "apb read dma timed out"))
  72. dmaengine_terminate_all(apb_dma_chan);
  73. else
  74. val = *apb_buffer;
  75. clk_disable_unprepare(fuse_clk);
  76. out:
  77. mutex_unlock(&apb_dma_lock);
  78. return val;
  79. }
  80. static const struct of_device_id tegra20_fuse_of_match[] = {
  81. { .compatible = "nvidia,tegra20-efuse" },
  82. {},
  83. };
  84. static int apb_dma_init(void)
  85. {
  86. dma_cap_mask_t mask;
  87. dma_cap_zero(mask);
  88. dma_cap_set(DMA_SLAVE, mask);
  89. apb_dma_chan = dma_request_channel(mask, NULL, NULL);
  90. if (!apb_dma_chan)
  91. return -EPROBE_DEFER;
  92. apb_buffer = dma_alloc_coherent(NULL, sizeof(u32), &apb_buffer_phys,
  93. GFP_KERNEL);
  94. if (!apb_buffer) {
  95. dma_release_channel(apb_dma_chan);
  96. return -ENOMEM;
  97. }
  98. dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
  99. dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
  100. dma_sconfig.src_maxburst = 1;
  101. dma_sconfig.dst_maxburst = 1;
  102. return 0;
  103. }
  104. static int tegra20_fuse_probe(struct platform_device *pdev)
  105. {
  106. struct resource *res;
  107. int err;
  108. fuse_clk = devm_clk_get(&pdev->dev, NULL);
  109. if (IS_ERR(fuse_clk)) {
  110. dev_err(&pdev->dev, "missing clock");
  111. return PTR_ERR(fuse_clk);
  112. }
  113. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  114. if (!res)
  115. return -EINVAL;
  116. fuse_phys = res->start;
  117. err = apb_dma_init();
  118. if (err)
  119. return err;
  120. if (tegra_fuse_create_sysfs(&pdev->dev, FUSE_SIZE, tegra20_fuse_readl))
  121. return -ENODEV;
  122. dev_dbg(&pdev->dev, "loaded\n");
  123. return 0;
  124. }
  125. static struct platform_driver tegra20_fuse_driver = {
  126. .probe = tegra20_fuse_probe,
  127. .driver = {
  128. .name = "tegra20_fuse",
  129. .owner = THIS_MODULE,
  130. .of_match_table = tegra20_fuse_of_match,
  131. }
  132. };
  133. static int __init tegra20_fuse_init(void)
  134. {
  135. return platform_driver_register(&tegra20_fuse_driver);
  136. }
  137. postcore_initcall(tegra20_fuse_init);
  138. /* Early boot code. This code is called before the devices are created */
  139. u32 __init tegra20_fuse_early(const unsigned int offset)
  140. {
  141. return readl_relaxed(fuse_base + FUSE_BEGIN + offset);
  142. }
  143. bool __init tegra20_spare_fuse_early(int spare_bit)
  144. {
  145. u32 offset = spare_bit * 4;
  146. bool value;
  147. value = tegra20_fuse_early(offset + 0x100);
  148. return value;
  149. }
  150. static void __init tegra20_fuse_add_randomness(void)
  151. {
  152. u32 randomness[7];
  153. randomness[0] = tegra_sku_info.sku_id;
  154. randomness[1] = tegra_read_straps();
  155. randomness[2] = tegra_read_chipid();
  156. randomness[3] = tegra_sku_info.cpu_process_id << 16;
  157. randomness[3] |= tegra_sku_info.core_process_id;
  158. randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
  159. randomness[4] |= tegra_sku_info.soc_speedo_id;
  160. randomness[5] = tegra20_fuse_early(FUSE_UID_LOW);
  161. randomness[6] = tegra20_fuse_early(FUSE_UID_HIGH);
  162. add_device_randomness(randomness, sizeof(randomness));
  163. }
  164. void __init tegra20_init_fuse_early(void)
  165. {
  166. fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE);
  167. tegra_init_revision();
  168. tegra20_init_speedo_data(&tegra_sku_info);
  169. tegra20_fuse_add_randomness();
  170. iounmap(fuse_base);
  171. }