bl40: g12a/sm1: add m4 bringup path [1/3]
authorShunzhou Jiang <shunzhou.jiang@amlogic.com>
Tue, 20 Aug 2019 12:09:13 +0000 (20:09 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Thu, 12 Sep 2019 08:22:02 +0000 (01:22 -0700)
PD#SWPL-12964

Problem:
bring up m4

Solution:
add kernel driver

Verify:
U209+S905D3

Change-Id: Iaa57f24c919af013581b8e3faffb0b57f5af10ed
Signed-off-by: Shunzhou Jiang <shunzhou.jiang@amlogic.com>
14 files changed:
MAINTAINERS
arch/arm/boot/dts/amlogic/mesong12a.dtsi
arch/arm/boot/dts/amlogic/mesonsm1.dtsi
arch/arm/configs/meson64_a32_defconfig
arch/arm64/boot/dts/amlogic/mesong12a.dtsi
arch/arm64/boot/dts/amlogic/mesonsm1.dtsi
arch/arm64/configs/meson64_defconfig
drivers/amlogic/Kconfig
drivers/amlogic/Makefile
drivers/amlogic/firmware/Kconfig [new file with mode: 0644]
drivers/amlogic/firmware/Makefile [new file with mode: 0644]
drivers/amlogic/firmware/bl40_module.c [new file with mode: 0644]
drivers/amlogic/mailbox/scpi_protocol.c
include/linux/amlogic/scpi_protocol.h

index 1708ee9..9fc6c2a 100644 (file)
@@ -15147,3 +15147,9 @@ F:      include/dt-bindings/display/meson-drm-ids.h
 AMLOGIC LCD EXTERN DRIVER
 M:      Shaochan Liu <shaochan.liu@amlogic.com>
 F:      drivers/amlogic/media/vout/lcd/lcd_extern/i2c_CS602.c
+
+AMLOGIC SM1/G12A BL40 BOOTUP DRIVER
+M: shunzhou jiang <shunzhou.jiang@amlogic.com>
+F: drivers/amlogic/firmware/bl40_module.c
+F: drivers/amlogic/firmware/Makefile
+F: drivers/amlogic/firmware/Kconfig
index 47b5d2f..806e3b8 100644 (file)
                #thermal-sensor-cells = <1>;
        };
 
+       bl40: bl40 {
+               compatible = "amlogic, bl40-bootup";
+               status = "okay";
+       };
+
        soc {
                compatible = "simple-bus";
                #address-cells = <1>;
index 16ba4a2..341060f 100644 (file)
                      <0xff63c100 0x10>;
        };
 
+       bl40: bl40 {
+               compatible = "amlogic, bl40-bootup";
+               status = "okay";
+       };
+
        soc {
                compatible = "simple-bus";
                #address-cells = <1>;
index 9f925b7..15b533d 100644 (file)
@@ -386,6 +386,7 @@ CONFIG_AMLOGIC_BATTERY_DUMMY=y
 CONFIG_AMLOGIC_CHARGER_DUMMY=y
 CONFIG_AMLOGIC_HIFI4DSP=y
 CONFIG_AMLOGIC_PIXEL_PROBE=y
+CONFIG_AMLOGIC_FIRMWARE=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
index 0bf23d3..b657453 100644 (file)
                #thermal-sensor-cells = <1>;
        };
 
+       bl40: bl40 {
+               compatible = "amlogic, bl40-bootup";
+               status = "okay";
+       };
+
        soc {
                compatible = "simple-bus";
                #address-cells = <2>;
index ac87f8a..fb1ccb6 100644 (file)
                      <0x0 0xff63c100 0x0 0x10>;
        };
 
+       bl40: bl40 {
+               compatible = "amlogic, bl40-bootup";
+               status = "okay";
+       };
+
        soc {
                compatible = "simple-bus";
                #address-cells = <2>;
index 79a0cc2..7d4ff94 100644 (file)
@@ -382,6 +382,7 @@ CONFIG_AMLOGIC_CHARGER_DUMMY=y
 CONFIG_DOLBY_FW=y
 CONFIG_AMLOGIC_HIFI4DSP=y
 CONFIG_AMLOGIC_PIXEL_PROBE=y
+CONFIG_AMLOGIC_FIRMWARE=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
index 32493b0..93ee0eb 100644 (file)
@@ -144,5 +144,7 @@ source "drivers/amlogic/hifi4dsp/Kconfig"
 
 source "drivers/amlogic/pixel_probe/Kconfig"
 
+source "drivers/amlogic/firmware/Kconfig"
+
 endmenu
 endif
index 885097b..5ed5331 100644 (file)
@@ -141,3 +141,5 @@ obj-$(CONFIG_DOLBY_FW) += dolby_fw/
 obj-$(CONFIG_AMLOGIC_IRCUT) += ircut/
 
 obj-$(CONFIG_AMLOGIC_PIXEL_PROBE) += pixel_probe/
+
+obj-$(CONFIG_AMLOGIC_FIRMWARE) += firmware/
diff --git a/drivers/amlogic/firmware/Kconfig b/drivers/amlogic/firmware/Kconfig
new file mode 100644 (file)
index 0000000..89d6645
--- /dev/null
@@ -0,0 +1,11 @@
+# firmware configuration
+#
+menu "AMLOGIC firmware boot"
+
+config AMLOGIC_FIRMWARE
+       bool "firmware bootup support"
+       default n
+       help
+               support the amlogic firmware bootup;
+
+endmenu
diff --git a/drivers/amlogic/firmware/Makefile b/drivers/amlogic/firmware/Makefile
new file mode 100644 (file)
index 0000000..e33ea26
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_AMLOGIC_FIRMWARE)    += bl40_module.o
diff --git a/drivers/amlogic/firmware/bl40_module.c b/drivers/amlogic/firmware/bl40_module.c
new file mode 100644 (file)
index 0000000..e7436a6
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * drivers/amlogic/firmware/bl40_module.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#define pr_fmt(fmt) "bl40: " fmt
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/reset.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <asm/cacheflush.h>
+#include <linux/firmware.h>
+#include <linux/arm-smccc.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/amlogic/scpi_protocol.h>
+
+#define AMLOGIC_BL40_BOOTUP    0x8200004E
+struct bl40_info {
+       char name[30];
+};
+
+struct device *device;
+#define BL40_IOC_MAGIC  'H'
+#define BL40_FIRMWARE_LOAD     _IOWR(BL40_IOC_MAGIC, 1, struct bl40_info)
+
+static long bl40_miscdev_ioctl(struct file *fp, unsigned int cmd,
+                              unsigned long arg)
+{
+       int ret = 0;
+       const struct firmware *firmware;
+       void __user *argp = (void __user *)arg;
+       struct bl40_info bl40_info;
+       unsigned long phy_addr;
+       void *virt_addr = NULL;
+       struct arm_smccc_res res = {0};
+       size_t size;
+
+       switch (cmd) {
+       case BL40_FIRMWARE_LOAD:
+               ret = copy_from_user((void *)&bl40_info,
+                                    argp, sizeof(bl40_info));
+               if (ret < 0)
+                       return ret;
+               ret = request_firmware(&firmware, bl40_info.name, device);
+               if (ret < 0) {
+                       pr_err("req firmware fail %d\n", ret);
+                       return ret;
+               }
+
+               size = firmware->size;
+               virt_addr = devm_kzalloc(device, size, GFP_KERNEL);
+               if (!virt_addr) {
+                       release_firmware(firmware);
+                       pr_err("memory request fail\n");
+                       return -ENOMEM;
+               }
+               memcpy(virt_addr, firmware->data, size);
+               release_firmware(firmware);
+               dma_map_single(device, virt_addr, size, DMA_FROM_DEVICE);
+               phy_addr = virt_to_phys(virt_addr);
+
+               /* unlock bl40 */
+               scpi_unlock_bl40();
+               arm_smccc_smc(AMLOGIC_BL40_BOOTUP, phy_addr,
+                             size, 0, 0, 0, 0, 0, &res);
+               pr_info("free memory\n");
+               devm_kfree(device, virt_addr);
+               ret = res.a0;
+       break;
+       default:
+               pr_info("Not have this cmd\n");
+       break;
+       };
+       pr_info("bl40 ioctl\n");
+       return ret;
+}
+
+static const struct file_operations bl40_miscdev_fops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .unlocked_ioctl = bl40_miscdev_ioctl,
+       .compat_ioctl = bl40_miscdev_ioctl,
+};
+
+static struct miscdevice bl40_miscdev = {
+       .minor  = MISC_DYNAMIC_MINOR,
+       .name   = "bl40",
+       .fops   = &bl40_miscdev_fops,
+};
+
+static int bl40_platform_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       device = &pdev->dev;
+       platform_set_drvdata(pdev, NULL);
+       ret = misc_register(&bl40_miscdev);
+       pr_info("bl40 probe\n");
+       return ret;
+}
+
+static int bl40_platform_remove(struct platform_device *pdev)
+{
+       misc_deregister(&bl40_miscdev);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static const struct of_device_id bl40_device_id[] = {
+       {
+               .compatible = "amlogic, bl40-bootup",
+       },
+       {}
+};
+
+static struct platform_driver bl40_platform_driver = {
+       .driver = {
+               .name  = "bl40",
+               .owner = THIS_MODULE,
+               .of_match_table = bl40_device_id,
+       },
+       .probe  = bl40_platform_probe,
+       .remove = bl40_platform_remove,
+};
+module_platform_driver(bl40_platform_driver);
+
+MODULE_AUTHOR("Amlogic Bl40");
+MODULE_DESCRIPTION("BL40 Boot Module Driver");
+MODULE_LICENSE("GPL v2");
index 7718892..7158f3f 100644 (file)
@@ -671,3 +671,21 @@ int scpi_get_cpuinfo(enum scpi_get_pfm_type type, u32 *freq, u32 *vol)
        return ret;
 }
 EXPORT_SYMBOL_GPL(scpi_get_cpuinfo);
+
+int scpi_unlock_bl40(void)
+{
+       struct scpi_data_buf sdata;
+       struct mhu_data_buf mdata;
+       u8 temp = 0;
+
+       struct __packed {
+               u32 status;
+       } buf;
+
+       SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_NONE,
+                       SCPI_CMD_BL4_WAIT_UNLOCK, temp, buf);
+       if (scpi_execute_cmd(&sdata))
+               return -1;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(scpi_unlock_bl40);
index 06c829d..b433f59 100644 (file)
@@ -73,6 +73,7 @@ enum scpi_std_cmd {
 
        SCPI_CMD_GET_CEC1               = 0xB4,
        SCPI_CMD_GET_CEC2               = 0xB5,
+       SCPI_CMD_BL4_WAIT_UNLOCK        = 0xD6,
        SCPI_CMD_COUNT
 };
 
@@ -112,4 +113,5 @@ int scpi_get_cec_val(enum scpi_std_cmd index, u32 *p_cec);
 u8  scpi_get_ethernet_calc(void);
 int scpi_get_cpuinfo(enum scpi_get_pfm_type type, u32 *freq, u32 *vol);
 int scpi_init_dsp_cfg0(u32 id, u32 addr, u32 cfg0);
+int scpi_unlock_bl40(void);
 #endif /*_SCPI_PROTOCOL_H_*/