forked from Minki/linux
soc: amlogic: updates for v5.5
Highlights - socinfo: more SoC IDs - firmware: misc secure-monitor cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEe4dGDhaSf6n1v/EMWTcYmtP7xmUFAl3FFpMACgkQWTcYmtP7 xmXH/A//UdI1sQ5B4jX4SNa7ijbUo2/7X9VycQG3rOixWgMnTnRoovQcQrHjKIF9 ocAxxayHkFs5xDyJ2bGiif7vSqEBitfg1MTHYJBPQi/2kgReSxP/tgaym0Ku57kU GVP1/KfEDwNpOvUXr6LFGTpz55tju19X+TvEdlMTP4+wDIFrXJa19LeNZnfBDYZX OGipDqwEbYBu19h2QtX+lBFX00nd+XPIMee0aNeFmMybcyK/+Woi/3PuA4QzrZru Sj7rF5SdGMepJTB/o2L2S0SqZwhsnw7oWWVlyeuIlkrF0i6Tbh6E832ig913Fr0r y33A8+vdLTkq2SILlTiz3OXM3TaqYyKOZx3kL2SxhUd5QklksnVl+sjTv2S/1DSd HQD9Iy+oQSKKJ1ho7V1ReQ2NRvuhq8AsOIXZlBMgGhx6lddahK1UiyYQ0FSI1o+t ZPI+KjEaBxW/vjBSusws7uworuZJxBX5Xd10xv4XHc5q3wCpho+xod8YjUGVOYs+ jZyRX3idJwJvtJio7WkrafmOYPjsT18MPS7+GWt+Vq6Kq92r7UER1sz04a1YTWS1 3DTwJ9q2LNorL9Xi7O+bOo/B5tsIUuJ2Qnt6vv781rKkxVE+I49obknB9WB/hXXD 42vyWm5i+ZnbUTQoOwmdPX30+lM/ZBJDKw8c9A2/0ERV4t9MEJU= =6HZt -----END PGP SIGNATURE----- Merge tag 'amlogic-drivers' of https://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic into arm/drivers soc: amlogic: updates for v5.5 Highlights - socinfo: more SoC IDs - firmware: misc secure-monitor cleanups * tag 'amlogic-drivers' of https://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic: soc: amlogic: meson-gx-socinfo: Fix S905D3 ID for VIM3L soc: amlogic: meson-gx-socinfo: Add S905X3 ID for VIM3L soc: amlogic: meson-gx-socinfo: Add A1 and A113L IDs firmware: meson_sm: use %*ph to print small buffer firmware: meson_sm: Rework driver as a proper platform driver nvmem: meson-efuse: bindings: Add secure-monitor phandle firmware: meson_sm: Mark chip struct as static const Link: https://lore.kernel.org/r/7hftivs11f.fsf@baylibre.com Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
13a6c8efb3
@ -4,6 +4,7 @@ Required properties:
|
||||
- compatible: should be "amlogic,meson-gxbb-efuse"
|
||||
- clocks: phandle to the efuse peripheral clock provided by the
|
||||
clock controller.
|
||||
- secure-monitor: phandle to the secure-monitor node
|
||||
|
||||
= Data cells =
|
||||
Are child nodes of eFuse, bindings of which as described in
|
||||
@ -16,6 +17,7 @@ Example:
|
||||
clocks = <&clkc CLKID_EFUSE>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
secure-monitor = <&sm>;
|
||||
|
||||
sn: sn@14 {
|
||||
reg = <0x14 0x10>;
|
||||
@ -30,6 +32,10 @@ Example:
|
||||
};
|
||||
};
|
||||
|
||||
sm: secure-monitor {
|
||||
compatible = "amlogic,meson-gxbb-sm";
|
||||
};
|
||||
|
||||
= Data consumers =
|
||||
Are device nodes which consume nvmem data cells.
|
||||
|
||||
|
@ -35,7 +35,7 @@ struct meson_sm_chip {
|
||||
struct meson_sm_cmd cmd[];
|
||||
};
|
||||
|
||||
struct meson_sm_chip gxbb_chip = {
|
||||
static const struct meson_sm_chip gxbb_chip = {
|
||||
.shmem_size = SZ_4K,
|
||||
.cmd_shmem_in_base = 0x82000020,
|
||||
.cmd_shmem_out_base = 0x82000021,
|
||||
@ -54,8 +54,6 @@ struct meson_sm_firmware {
|
||||
void __iomem *sm_shmem_out_base;
|
||||
};
|
||||
|
||||
static struct meson_sm_firmware fw;
|
||||
|
||||
static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip,
|
||||
unsigned int cmd_index)
|
||||
{
|
||||
@ -90,6 +88,7 @@ static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size)
|
||||
/**
|
||||
* meson_sm_call - generic SMC32 call to the secure-monitor
|
||||
*
|
||||
* @fw: Pointer to secure-monitor firmware
|
||||
* @cmd_index: Index of the SMC32 function ID
|
||||
* @ret: Returned value
|
||||
* @arg0: SMC32 Argument 0
|
||||
@ -100,15 +99,15 @@ static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size)
|
||||
*
|
||||
* Return: 0 on success, a negative value on error
|
||||
*/
|
||||
int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0,
|
||||
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
|
||||
int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
|
||||
u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
|
||||
{
|
||||
u32 cmd, lret;
|
||||
|
||||
if (!fw.chip)
|
||||
if (!fw->chip)
|
||||
return -ENOENT;
|
||||
|
||||
cmd = meson_sm_get_cmd(fw.chip, cmd_index);
|
||||
cmd = meson_sm_get_cmd(fw->chip, cmd_index);
|
||||
if (!cmd)
|
||||
return -EINVAL;
|
||||
|
||||
@ -124,6 +123,7 @@ EXPORT_SYMBOL(meson_sm_call);
|
||||
/**
|
||||
* meson_sm_call_read - retrieve data from secure-monitor
|
||||
*
|
||||
* @fw: Pointer to secure-monitor firmware
|
||||
* @buffer: Buffer to store the retrieved data
|
||||
* @bsize: Size of the buffer
|
||||
* @cmd_index: Index of the SMC32 function ID
|
||||
@ -137,22 +137,23 @@ EXPORT_SYMBOL(meson_sm_call);
|
||||
* When 0 is returned there is no guarantee about the amount of
|
||||
* data read and bsize bytes are copied in buffer.
|
||||
*/
|
||||
int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
|
||||
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
|
||||
int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
|
||||
unsigned int bsize, unsigned int cmd_index, u32 arg0,
|
||||
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
|
||||
{
|
||||
u32 size;
|
||||
int ret;
|
||||
|
||||
if (!fw.chip)
|
||||
if (!fw->chip)
|
||||
return -ENOENT;
|
||||
|
||||
if (!fw.chip->cmd_shmem_out_base)
|
||||
if (!fw->chip->cmd_shmem_out_base)
|
||||
return -EINVAL;
|
||||
|
||||
if (bsize > fw.chip->shmem_size)
|
||||
if (bsize > fw->chip->shmem_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
|
||||
if (meson_sm_call(fw, cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (size > bsize)
|
||||
@ -164,7 +165,7 @@ int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
|
||||
size = bsize;
|
||||
|
||||
if (buffer)
|
||||
memcpy(buffer, fw.sm_shmem_out_base, size);
|
||||
memcpy(buffer, fw->sm_shmem_out_base, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -173,6 +174,7 @@ EXPORT_SYMBOL(meson_sm_call_read);
|
||||
/**
|
||||
* meson_sm_call_write - send data to secure-monitor
|
||||
*
|
||||
* @fw: Pointer to secure-monitor firmware
|
||||
* @buffer: Buffer containing data to send
|
||||
* @size: Size of the data to send
|
||||
* @cmd_index: Index of the SMC32 function ID
|
||||
@ -184,23 +186,24 @@ EXPORT_SYMBOL(meson_sm_call_read);
|
||||
*
|
||||
* Return: size of sent data on success, a negative value on error
|
||||
*/
|
||||
int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index,
|
||||
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
|
||||
int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
|
||||
unsigned int size, unsigned int cmd_index, u32 arg0,
|
||||
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
|
||||
{
|
||||
u32 written;
|
||||
|
||||
if (!fw.chip)
|
||||
if (!fw->chip)
|
||||
return -ENOENT;
|
||||
|
||||
if (size > fw.chip->shmem_size)
|
||||
if (size > fw->chip->shmem_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (!fw.chip->cmd_shmem_in_base)
|
||||
if (!fw->chip->cmd_shmem_in_base)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(fw.sm_shmem_in_base, buffer, size);
|
||||
memcpy(fw->sm_shmem_in_base, buffer, size);
|
||||
|
||||
if (meson_sm_call(cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
|
||||
if (meson_sm_call(fw, cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!written)
|
||||
@ -210,6 +213,24 @@ int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index,
|
||||
}
|
||||
EXPORT_SYMBOL(meson_sm_call_write);
|
||||
|
||||
/**
|
||||
* meson_sm_get - get pointer to meson_sm_firmware structure.
|
||||
*
|
||||
* @sm_node: Pointer to the secure-monitor Device Tree node.
|
||||
*
|
||||
* Return: NULL is the secure-monitor device is not ready.
|
||||
*/
|
||||
struct meson_sm_firmware *meson_sm_get(struct device_node *sm_node)
|
||||
{
|
||||
struct platform_device *pdev = of_find_device_by_node(sm_node);
|
||||
|
||||
if (!pdev)
|
||||
return NULL;
|
||||
|
||||
return platform_get_drvdata(pdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(meson_sm_get);
|
||||
|
||||
#define SM_CHIP_ID_LENGTH 119
|
||||
#define SM_CHIP_ID_OFFSET 4
|
||||
#define SM_CHIP_ID_SIZE 12
|
||||
@ -217,33 +238,25 @@ EXPORT_SYMBOL(meson_sm_call_write);
|
||||
static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct meson_sm_firmware *fw;
|
||||
uint8_t *id_buf;
|
||||
int ret;
|
||||
|
||||
fw = platform_get_drvdata(pdev);
|
||||
|
||||
id_buf = kmalloc(SM_CHIP_ID_LENGTH, GFP_KERNEL);
|
||||
if (!id_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = meson_sm_call_read(id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID,
|
||||
ret = meson_sm_call_read(fw, id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID,
|
||||
0, 0, 0, 0, 0);
|
||||
if (ret < 0) {
|
||||
kfree(id_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||
id_buf[SM_CHIP_ID_OFFSET + 0],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 1],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 2],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 3],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 4],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 5],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 6],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 7],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 8],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 9],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 10],
|
||||
id_buf[SM_CHIP_ID_OFFSET + 11]);
|
||||
ret = sprintf(buf, "%12phN\n", &id_buf[SM_CHIP_ID_OFFSET]);
|
||||
|
||||
kfree(id_buf);
|
||||
|
||||
@ -268,25 +281,34 @@ static const struct of_device_id meson_sm_ids[] = {
|
||||
|
||||
static int __init meson_sm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct meson_sm_chip *chip;
|
||||
struct meson_sm_firmware *fw;
|
||||
|
||||
chip = of_match_device(meson_sm_ids, &pdev->dev)->data;
|
||||
fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL);
|
||||
if (!fw)
|
||||
return -ENOMEM;
|
||||
|
||||
chip = of_match_device(meson_sm_ids, dev)->data;
|
||||
|
||||
if (chip->cmd_shmem_in_base) {
|
||||
fw.sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
|
||||
chip->shmem_size);
|
||||
if (WARN_ON(!fw.sm_shmem_in_base))
|
||||
fw->sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
|
||||
chip->shmem_size);
|
||||
if (WARN_ON(!fw->sm_shmem_in_base))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (chip->cmd_shmem_out_base) {
|
||||
fw.sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
|
||||
chip->shmem_size);
|
||||
if (WARN_ON(!fw.sm_shmem_out_base))
|
||||
fw->sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
|
||||
chip->shmem_size);
|
||||
if (WARN_ON(!fw->sm_shmem_out_base))
|
||||
goto out_in_base;
|
||||
}
|
||||
|
||||
fw.chip = chip;
|
||||
fw->chip = chip;
|
||||
|
||||
platform_set_drvdata(pdev, fw);
|
||||
|
||||
pr_info("secure-monitor enabled\n");
|
||||
|
||||
if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group))
|
||||
@ -295,7 +317,7 @@ static int __init meson_sm_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
out_in_base:
|
||||
iounmap(fw.sm_shmem_in_base);
|
||||
iounmap(fw->sm_shmem_in_base);
|
||||
out:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -17,14 +17,18 @@
|
||||
static int meson_efuse_read(void *context, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
return meson_sm_call_read((u8 *)val, bytes, SM_EFUSE_READ, offset,
|
||||
struct meson_sm_firmware *fw = context;
|
||||
|
||||
return meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset,
|
||||
bytes, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int meson_efuse_write(void *context, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
return meson_sm_call_write((u8 *)val, bytes, SM_EFUSE_WRITE, offset,
|
||||
struct meson_sm_firmware *fw = context;
|
||||
|
||||
return meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset,
|
||||
bytes, 0, 0, 0);
|
||||
}
|
||||
|
||||
@ -37,12 +41,25 @@ MODULE_DEVICE_TABLE(of, meson_efuse_match);
|
||||
static int meson_efuse_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct meson_sm_firmware *fw;
|
||||
struct device_node *sm_np;
|
||||
struct nvmem_device *nvmem;
|
||||
struct nvmem_config *econfig;
|
||||
struct clk *clk;
|
||||
unsigned int size;
|
||||
int ret;
|
||||
|
||||
sm_np = of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0);
|
||||
if (!sm_np) {
|
||||
dev_err(&pdev->dev, "no secure-monitor node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
fw = meson_sm_get(sm_np);
|
||||
of_node_put(sm_np);
|
||||
if (!fw)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
ret = PTR_ERR(clk);
|
||||
@ -65,7 +82,7 @@ static int meson_efuse_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) {
|
||||
if (meson_sm_call(fw, SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) {
|
||||
dev_err(dev, "failed to get max user");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -81,6 +98,7 @@ static int meson_efuse_probe(struct platform_device *pdev)
|
||||
econfig->reg_read = meson_efuse_read;
|
||||
econfig->reg_write = meson_efuse_write;
|
||||
econfig->size = size;
|
||||
econfig->priv = fw;
|
||||
|
||||
nvmem = devm_nvmem_register(&pdev->dev, econfig);
|
||||
|
||||
|
@ -40,6 +40,7 @@ static const struct meson_gx_soc_id {
|
||||
{ "G12A", 0x28 },
|
||||
{ "G12B", 0x29 },
|
||||
{ "SM1", 0x2b },
|
||||
{ "A1", 0x2c },
|
||||
};
|
||||
|
||||
static const struct meson_gx_package_id {
|
||||
@ -68,6 +69,8 @@ static const struct meson_gx_package_id {
|
||||
{ "S922X", 0x29, 0x40, 0xf0 },
|
||||
{ "A311D", 0x29, 0x10, 0xf0 },
|
||||
{ "S905X3", 0x2b, 0x5, 0xf },
|
||||
{ "S905D3", 0x2b, 0xb0, 0xf0 },
|
||||
{ "A113L", 0x2c, 0x0, 0xf8 },
|
||||
};
|
||||
|
||||
static inline unsigned int socinfo_to_major(u32 socinfo)
|
||||
|
@ -16,11 +16,14 @@ enum {
|
||||
|
||||
struct meson_sm_firmware;
|
||||
|
||||
int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1,
|
||||
u32 arg2, u32 arg3, u32 arg4);
|
||||
int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index,
|
||||
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
|
||||
u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
|
||||
u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
|
||||
unsigned int b_size, unsigned int cmd_index, u32 arg0,
|
||||
u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
|
||||
unsigned int bsize, unsigned int cmd_index, u32 arg0,
|
||||
u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
struct meson_sm_firmware *meson_sm_get(struct device_node *firmware_node);
|
||||
|
||||
#endif /* _MESON_SM_FW_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user