From 5412b149136e49f05dd860a8a464471a80099383 Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Tue, 20 Aug 2019 20:09:13 +0800 Subject: [PATCH] bl40: g12a/sm1: add m4 bringup path [1/3] PD#SWPL-12964 Problem: bring up m4 Solution: add kernel driver Verify: U209+S905D3 Change-Id: Iaa57f24c919af013581b8e3faffb0b57f5af10ed Signed-off-by: Shunzhou Jiang --- MAINTAINERS | 6 ++ arch/arm/boot/dts/amlogic/mesong12a.dtsi | 5 + arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 5 + arch/arm/configs/meson64_a32_defconfig | 1 + arch/arm64/boot/dts/amlogic/mesong12a.dtsi | 5 + arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 5 + arch/arm64/configs/meson64_defconfig | 1 + drivers/amlogic/Kconfig | 2 + drivers/amlogic/Makefile | 2 + drivers/amlogic/firmware/Kconfig | 11 ++ drivers/amlogic/firmware/Makefile | 2 + drivers/amlogic/firmware/bl40_module.c | 159 +++++++++++++++++++++++++++++ drivers/amlogic/mailbox/scpi_protocol.c | 18 ++++ include/linux/amlogic/scpi_protocol.h | 2 + 14 files changed, 224 insertions(+) create mode 100644 drivers/amlogic/firmware/Kconfig create mode 100644 drivers/amlogic/firmware/Makefile create mode 100644 drivers/amlogic/firmware/bl40_module.c diff --git a/MAINTAINERS b/MAINTAINERS index 1708ee9..9fc6c2a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15147,3 +15147,9 @@ F: include/dt-bindings/display/meson-drm-ids.h AMLOGIC LCD EXTERN DRIVER M: Shaochan Liu F: drivers/amlogic/media/vout/lcd/lcd_extern/i2c_CS602.c + +AMLOGIC SM1/G12A BL40 BOOTUP DRIVER +M: shunzhou jiang +F: drivers/amlogic/firmware/bl40_module.c +F: drivers/amlogic/firmware/Makefile +F: drivers/amlogic/firmware/Kconfig diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index 47b5d2f..806e3b8 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -503,6 +503,11 @@ #thermal-sensor-cells = <1>; }; + bl40: bl40 { + compatible = "amlogic, bl40-bootup"; + status = "okay"; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 16ba4a2..341060f 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -501,6 +501,11 @@ <0xff63c100 0x10>; }; + bl40: bl40 { + compatible = "amlogic, bl40-bootup"; + status = "okay"; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 9f925b7..15b533d 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -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 diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 0bf23d3..b657453 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -503,6 +503,11 @@ #thermal-sensor-cells = <1>; }; + bl40: bl40 { + compatible = "amlogic, bl40-bootup"; + status = "okay"; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index ac87f8a..fb1ccb6 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -501,6 +501,11 @@ <0x0 0xff63c100 0x0 0x10>; }; + bl40: bl40 { + compatible = "amlogic, bl40-bootup"; + status = "okay"; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 79a0cc2..7d4ff94 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -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 diff --git a/drivers/amlogic/Kconfig b/drivers/amlogic/Kconfig index 32493b0..93ee0eb 100644 --- a/drivers/amlogic/Kconfig +++ b/drivers/amlogic/Kconfig @@ -144,5 +144,7 @@ source "drivers/amlogic/hifi4dsp/Kconfig" source "drivers/amlogic/pixel_probe/Kconfig" +source "drivers/amlogic/firmware/Kconfig" + endmenu endif diff --git a/drivers/amlogic/Makefile b/drivers/amlogic/Makefile index 885097b..5ed5331 100644 --- a/drivers/amlogic/Makefile +++ b/drivers/amlogic/Makefile @@ -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 index 0000000..89d6645 --- /dev/null +++ b/drivers/amlogic/firmware/Kconfig @@ -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 index 0000000..e33ea26 --- /dev/null +++ b/drivers/amlogic/firmware/Makefile @@ -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 index 0000000..e7436a6 --- /dev/null +++ b/drivers/amlogic/firmware/bl40_module.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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"); diff --git a/drivers/amlogic/mailbox/scpi_protocol.c b/drivers/amlogic/mailbox/scpi_protocol.c index 7718892..7158f3f 100644 --- a/drivers/amlogic/mailbox/scpi_protocol.c +++ b/drivers/amlogic/mailbox/scpi_protocol.c @@ -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); diff --git a/include/linux/amlogic/scpi_protocol.h b/include/linux/amlogic/scpi_protocol.h index 06c829d..b433f59 100644 --- a/include/linux/amlogic/scpi_protocol.h +++ b/include/linux/amlogic/scpi_protocol.h @@ -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_*/ -- 2.7.4