.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Amlogic Meson GX eFuse Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2016 Endless Computers, Inc. |
---|
5 | 6 | * Author: Carlo Caione <carlo@endlessm.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify it |
---|
8 | | - * under the terms of version 2 of the GNU General Public License as |
---|
9 | | - * published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
12 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
13 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
14 | | - * more details. |
---|
15 | 7 | */ |
---|
16 | 8 | |
---|
| 9 | +#include <linux/clk.h> |
---|
17 | 10 | #include <linux/module.h> |
---|
18 | 11 | #include <linux/nvmem-provider.h> |
---|
19 | 12 | #include <linux/of.h> |
---|
.. | .. |
---|
24 | 17 | static int meson_efuse_read(void *context, unsigned int offset, |
---|
25 | 18 | void *val, size_t bytes) |
---|
26 | 19 | { |
---|
27 | | - return meson_sm_call_read((u8 *)val, bytes, SM_EFUSE_READ, offset, |
---|
| 20 | + struct meson_sm_firmware *fw = context; |
---|
| 21 | + |
---|
| 22 | + return meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset, |
---|
28 | 23 | bytes, 0, 0, 0); |
---|
29 | 24 | } |
---|
30 | 25 | |
---|
31 | 26 | static int meson_efuse_write(void *context, unsigned int offset, |
---|
32 | 27 | void *val, size_t bytes) |
---|
33 | 28 | { |
---|
34 | | - return meson_sm_call_write((u8 *)val, bytes, SM_EFUSE_WRITE, offset, |
---|
| 29 | + struct meson_sm_firmware *fw = context; |
---|
| 30 | + |
---|
| 31 | + return meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset, |
---|
35 | 32 | bytes, 0, 0, 0); |
---|
36 | 33 | } |
---|
37 | 34 | |
---|
.. | .. |
---|
44 | 41 | static int meson_efuse_probe(struct platform_device *pdev) |
---|
45 | 42 | { |
---|
46 | 43 | struct device *dev = &pdev->dev; |
---|
| 44 | + struct meson_sm_firmware *fw; |
---|
| 45 | + struct device_node *sm_np; |
---|
47 | 46 | struct nvmem_device *nvmem; |
---|
48 | 47 | struct nvmem_config *econfig; |
---|
| 48 | + struct clk *clk; |
---|
49 | 49 | unsigned int size; |
---|
| 50 | + int ret; |
---|
50 | 51 | |
---|
51 | | - if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) |
---|
| 52 | + sm_np = of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0); |
---|
| 53 | + if (!sm_np) { |
---|
| 54 | + dev_err(&pdev->dev, "no secure-monitor node\n"); |
---|
| 55 | + return -ENODEV; |
---|
| 56 | + } |
---|
| 57 | + |
---|
| 58 | + fw = meson_sm_get(sm_np); |
---|
| 59 | + of_node_put(sm_np); |
---|
| 60 | + if (!fw) |
---|
| 61 | + return -EPROBE_DEFER; |
---|
| 62 | + |
---|
| 63 | + clk = devm_clk_get(dev, NULL); |
---|
| 64 | + if (IS_ERR(clk)) { |
---|
| 65 | + ret = PTR_ERR(clk); |
---|
| 66 | + if (ret != -EPROBE_DEFER) |
---|
| 67 | + dev_err(dev, "failed to get efuse gate"); |
---|
| 68 | + return ret; |
---|
| 69 | + } |
---|
| 70 | + |
---|
| 71 | + ret = clk_prepare_enable(clk); |
---|
| 72 | + if (ret) { |
---|
| 73 | + dev_err(dev, "failed to enable gate"); |
---|
| 74 | + return ret; |
---|
| 75 | + } |
---|
| 76 | + |
---|
| 77 | + ret = devm_add_action_or_reset(dev, |
---|
| 78 | + (void(*)(void *))clk_disable_unprepare, |
---|
| 79 | + clk); |
---|
| 80 | + if (ret) { |
---|
| 81 | + dev_err(dev, "failed to add disable callback"); |
---|
| 82 | + return ret; |
---|
| 83 | + } |
---|
| 84 | + |
---|
| 85 | + if (meson_sm_call(fw, SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) { |
---|
| 86 | + dev_err(dev, "failed to get max user"); |
---|
52 | 87 | return -EINVAL; |
---|
| 88 | + } |
---|
53 | 89 | |
---|
54 | 90 | econfig = devm_kzalloc(dev, sizeof(*econfig), GFP_KERNEL); |
---|
55 | 91 | if (!econfig) |
---|
.. | .. |
---|
62 | 98 | econfig->reg_read = meson_efuse_read; |
---|
63 | 99 | econfig->reg_write = meson_efuse_write; |
---|
64 | 100 | econfig->size = size; |
---|
| 101 | + econfig->priv = fw; |
---|
65 | 102 | |
---|
66 | 103 | nvmem = devm_nvmem_register(&pdev->dev, econfig); |
---|
67 | 104 | |
---|