diff options
author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2020-12-08 00:45:20 +0300 |
---|---|---|
committer | Jason M. Bills <jason.m.bills@linux.intel.com> | 2020-12-10 01:15:05 +0300 |
commit | 82dbc15a05125a812c140a3c8cff81c366482229 (patch) | |
tree | 9c8f1ad262a2e281f20340cf8646aca6f8596044 /meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch | |
parent | 8d6ae7f2a817751fad151168fa10ce28ee0869d8 (diff) | |
download | openbmc-82dbc15a05125a812c140a3c8cff81c366482229.tar.xz |
Update to internal 0.26
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch | 491 |
1 files changed, 0 insertions, 491 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch deleted file mode 100644 index c5add2dd5..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch +++ /dev/null @@ -1,491 +0,0 @@ -From 42326dfecd45c52918272cf6b65e6eb5b8499c46 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> -Date: Wed, 10 Jul 2019 16:19:33 -0700 -Subject: [PATCH] misc: aspeed: add lpc mbox driver - -This commit adds back the lpc mbox driver which was removed from -the openbmc linux dev-5.2 tree. - -This driver should be rewritten later. - -Signed-off-by: Cyril Bur <cyrilbur@gmail.com>" -Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> -Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com> ---- - arch/arm/boot/dts/aspeed-g4.dtsi | 9 + - arch/arm/boot/dts/aspeed-g5.dtsi | 9 + - arch/arm/boot/dts/aspeed-g6.dtsi | 1 + - drivers/soc/aspeed/Kconfig | 7 + - drivers/soc/aspeed/Makefile | 1 + - drivers/soc/aspeed/aspeed-lpc-mbox.c | 377 +++++++++++++++++++++++++++ - 6 files changed, 404 insertions(+) - create mode 100644 drivers/soc/aspeed/aspeed-lpc-mbox.c - -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index e9fd66ab3099..f3edda4ae477 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -393,6 +393,15 @@ - sio_regs: regs { - compatible = "aspeed,bmc-misc"; - }; -+ -+ mbox: mbox@180 { -+ compatible = "aspeed,ast2400-mbox"; -+ reg = <0x180 0x5c>; -+ interrupts = <46>; -+ #mbox-cells = <1>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; - }; - }; - -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index b4ae3827ed1d..b69110b9eab9 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -522,6 +522,15 @@ - sio_regs: regs { - compatible = "aspeed,bmc-misc"; - }; -+ -+ mbox: mbox@180 { -+ compatible = "aspeed,ast2500-mbox"; -+ reg = <0x180 0x5c>; -+ interrupts = <46>; -+ #mbox-cells = <1>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; - }; - }; - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 825e64ce317a..183869eaf79a 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -594,6 +594,7 @@ - reg = <0x180 0x5c>; - interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>; - #mbox-cells = <1>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - }; - }; - }; -diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig -index a4b3cac87ce2..464a55c7eb39 100644 ---- a/drivers/soc/aspeed/Kconfig -+++ b/drivers/soc/aspeed/Kconfig -@@ -21,6 +21,13 @@ config ASPEED_LPC_CTRL - ioctl()s, the driver also provides a read/write interface to a BMC ram - region where the host LPC read/write region can be buffered. - -+config ASPEED_LPC_MBOX -+ tristate "Aspeed LPC Mailbox Controller" -+ depends on SOC_ASPEED && REGMAP && MFD_SYSCON -+ ---help--- -+ Expose the ASPEED LPC MBOX registers found on Aspeed SOCs (AST2400 -+ and AST2500) to userspace. -+ - config ASPEED_LPC_SNOOP - tristate "Aspeed ast2500 HOST LPC snoop support" - depends on SOC_ASPEED && REGMAP && MFD_SYSCON -diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile -index 217d876fec25..26924c111af3 100644 ---- a/drivers/soc/aspeed/Makefile -+++ b/drivers/soc/aspeed/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0-only - obj-$(CONFIG_ASPEED_BMC_MISC) += aspeed-bmc-misc.o - obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o -+obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o - obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o - obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o - obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o -diff --git a/drivers/soc/aspeed/aspeed-lpc-mbox.c b/drivers/soc/aspeed/aspeed-lpc-mbox.c -new file mode 100644 -index 000000000000..583feecc4f18 ---- /dev/null -+++ b/drivers/soc/aspeed/aspeed-lpc-mbox.c -@@ -0,0 +1,377 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+// Copyright 2017 IBM Corporation -+// TODO: Rewrite this driver -+ -+#include <linux/clk.h> -+#include <linux/interrupt.h> -+#include <linux/mfd/syscon.h> -+#include <linux/miscdevice.h> -+#include <linux/module.h> -+#include <linux/of_irq.h> -+#include <linux/platform_device.h> -+#include <linux/poll.h> -+#include <linux/regmap.h> -+#include <linux/slab.h> -+ -+#define DEVICE_NAME "aspeed-mbox" -+ -+#define MBX_USE_INTERRUPT 0 -+ -+#define ASPEED_MBOX_NUM_REGS 16 -+ -+#define ASPEED_MBOX_DATA_0 0x00 -+#define ASPEED_MBOX_STATUS_0 0x40 -+#define ASPEED_MBOX_STATUS_1 0x44 -+#define ASPEED_MBOX_BMC_CTRL 0x48 -+#define ASPEED_MBOX_CTRL_RECV BIT(7) -+#define ASPEED_MBOX_CTRL_MASK BIT(1) -+#define ASPEED_MBOX_CTRL_SEND BIT(0) -+#define ASPEED_MBOX_HOST_CTRL 0x4c -+#define ASPEED_MBOX_INTERRUPT_0 0x50 -+#define ASPEED_MBOX_INTERRUPT_1 0x54 -+ -+struct aspeed_mbox { -+ struct miscdevice miscdev; -+ struct regmap *regmap; -+ struct clk *clk; -+ unsigned int base; -+ int irq; -+ wait_queue_head_t queue; -+ struct mutex mutex; -+}; -+ -+static atomic_t aspeed_mbox_open_count = ATOMIC_INIT(0); -+ -+static u8 aspeed_mbox_inb(struct aspeed_mbox *mbox, int reg) -+{ -+ /* -+ * The mbox registers are actually only one byte but are addressed -+ * four bytes apart. The other three bytes are marked 'reserved', -+ * they *should* be zero but lets not rely on it. -+ * I am going to rely on the fact we can casually read/write to them... -+ */ -+ unsigned int val = 0xff; /* If regmap throws an error return 0xff */ -+ int rc = regmap_read(mbox->regmap, mbox->base + reg, &val); -+ -+ if (rc) -+ dev_err(mbox->miscdev.parent, "regmap_read() failed with " -+ "%d (reg: 0x%08x)\n", rc, reg); -+ -+ return val & 0xff; -+} -+ -+static void aspeed_mbox_outb(struct aspeed_mbox *mbox, u8 data, int reg) -+{ -+ int rc = regmap_write(mbox->regmap, mbox->base + reg, data); -+ -+ if (rc) -+ dev_err(mbox->miscdev.parent, "regmap_write() failed with " -+ "%d (data: %u reg: 0x%08x)\n", rc, data, reg); -+} -+ -+static struct aspeed_mbox *file_mbox(struct file *file) -+{ -+ return container_of(file->private_data, struct aspeed_mbox, miscdev); -+} -+ -+static int aspeed_mbox_open(struct inode *inode, struct file *file) -+{ -+#if MBX_USE_INTERRUPT -+ struct aspeed_mbox *mbox = file_mbox(file); -+#endif -+ -+ if (atomic_inc_return(&aspeed_mbox_open_count) == 1) { -+#if MBX_USE_INTERRUPT -+ /* -+ * Clear the interrupt status bit if it was left on and unmask -+ * interrupts. -+ * ASPEED_MBOX_CTRL_RECV bit is W1C, this also unmasks in 1 step -+ */ -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+#endif -+ return 0; -+ } -+ -+ atomic_dec(&aspeed_mbox_open_count); -+ return -EBUSY; -+} -+ -+static ssize_t aspeed_mbox_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct aspeed_mbox *mbox = file_mbox(file); -+ char __user *p = buf; -+ ssize_t ret; -+ int i; -+ -+ if (!access_ok(buf, count)) -+ return -EFAULT; -+ -+ if (count + *ppos > ASPEED_MBOX_NUM_REGS) -+ return -EINVAL; -+ -+#if MBX_USE_INTERRUPT -+ if (file->f_flags & O_NONBLOCK) { -+ if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & -+ ASPEED_MBOX_CTRL_RECV)) -+ return -EAGAIN; -+ } else if (wait_event_interruptible(mbox->queue, -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & -+ ASPEED_MBOX_CTRL_RECV)) { -+ return -ERESTARTSYS; -+ } -+#endif -+ -+ mutex_lock(&mbox->mutex); -+ -+ for (i = *ppos; count > 0 && i < ASPEED_MBOX_NUM_REGS; i++) { -+ uint8_t reg = aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4)); -+ -+ ret = __put_user(reg, p); -+ if (ret) -+ goto out_unlock; -+ -+ p++; -+ count--; -+ } -+ -+#if MBX_USE_INTERRUPT -+ /* ASPEED_MBOX_CTRL_RECV bit is write to clear, this also unmasks in 1 step */ -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+#endif -+ ret = p - buf; -+ -+out_unlock: -+ mutex_unlock(&mbox->mutex); -+ return ret; -+} -+ -+static ssize_t aspeed_mbox_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct aspeed_mbox *mbox = file_mbox(file); -+ const char __user *p = buf; -+ ssize_t ret; -+ char c; -+ int i; -+ -+ if (!access_ok(buf, count)) -+ return -EFAULT; -+ -+ if (count + *ppos > ASPEED_MBOX_NUM_REGS) -+ return -EINVAL; -+ -+ mutex_lock(&mbox->mutex); -+ -+ for (i = *ppos; count > 0 && i < ASPEED_MBOX_NUM_REGS; i++) { -+ ret = __get_user(c, p); -+ if (ret) -+ goto out_unlock; -+ -+ aspeed_mbox_outb(mbox, c, ASPEED_MBOX_DATA_0 + (i * 4)); -+ p++; -+ count--; -+ } -+ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0); -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1); -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV | ASPEED_MBOX_CTRL_MASK | ASPEED_MBOX_CTRL_SEND, ASPEED_MBOX_BMC_CTRL); -+ ret = p - buf; -+ -+out_unlock: -+ mutex_unlock(&mbox->mutex); -+ return ret; -+} -+ -+static unsigned int aspeed_mbox_poll(struct file *file, poll_table *wait) -+{ -+ struct aspeed_mbox *mbox = file_mbox(file); -+ unsigned int mask = 0; -+ -+ poll_wait(file, &mbox->queue, wait); -+ -+#if MBX_USE_INTERRUPT -+ if (aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV) -+#endif -+ mask |= POLLIN; -+ -+ return mask; -+} -+ -+static int aspeed_mbox_release(struct inode *inode, struct file *file) -+{ -+ atomic_dec(&aspeed_mbox_open_count); -+ return 0; -+} -+ -+static const struct file_operations aspeed_mbox_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_seek_end_llseek, -+ .read = aspeed_mbox_read, -+ .write = aspeed_mbox_write, -+ .open = aspeed_mbox_open, -+ .release = aspeed_mbox_release, -+ .poll = aspeed_mbox_poll, -+}; -+ -+static irqreturn_t aspeed_mbox_irq(int irq, void *arg) -+{ -+ struct aspeed_mbox *mbox = arg; -+#if MBX_USE_INTERRUPT -+ int i; -+ -+// if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV)) -+// return IRQ_NONE; -+ -+ printk(KERN_ERR "BMC_CTRL: 0x%02x\n", -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL)); -+ printk(KERN_ERR "STATUS_0: 0x%02x\n", -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_0)); -+ printk(KERN_ERR "STATUS_1: 0x%02x\n", -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_1)); -+ for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) { -+ printk(KERN_ERR "DATA_%d: 0x%02x\n", i, -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4))); -+ } -+#endif -+ -+ /* Clear interrupt status */ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0); -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1); -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+ -+ wake_up(&mbox->queue); -+ return IRQ_HANDLED; -+} -+ -+static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox, -+ struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ int rc; -+ -+ mbox->irq = platform_get_irq(pdev, 0); -+ if (!mbox->irq) -+ return -ENODEV; -+ -+ rc = devm_request_irq(dev, mbox->irq, aspeed_mbox_irq, -+ IRQF_SHARED, DEVICE_NAME, mbox); -+ if (rc < 0) { -+ dev_err(dev, "Unable to request IRQ %d\n", mbox->irq); -+ return rc; -+ } -+ -+ /* Disable all register based interrupts. */ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_INTERRUPT_0); /* regs 0 - 7 */ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_INTERRUPT_1); /* regs 8 - 15 */ -+ -+ /* These registers are write one to clear. Clear them. */ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0); -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1); -+ -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+ return 0; -+} -+ -+static int aspeed_mbox_probe(struct platform_device *pdev) -+{ -+ struct aspeed_mbox *mbox; -+ struct device *dev; -+ int rc; -+ -+ dev = &pdev->dev; -+ -+ mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); -+ if (!mbox) -+ return -ENOMEM; -+ -+ dev_set_drvdata(&pdev->dev, mbox); -+ -+ rc = of_property_read_u32(dev->of_node, "reg", &mbox->base); -+ if (rc) { -+ dev_err(dev, "Couldn't read reg device-tree property\n"); -+ return rc; -+ } -+ -+ mbox->regmap = syscon_node_to_regmap( -+ pdev->dev.parent->of_node); -+ if (IS_ERR(mbox->regmap)) { -+ dev_err(dev, "Couldn't get regmap\n"); -+ return -ENODEV; -+ } -+ -+ mutex_init(&mbox->mutex); -+ init_waitqueue_head(&mbox->queue); -+ -+ mbox->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(mbox->clk)) { -+ rc = PTR_ERR(mbox->clk); -+ if (rc != -EPROBE_DEFER) -+ dev_err(dev, "couldn't get clock\n"); -+ return rc; -+ } -+ rc = clk_prepare_enable(mbox->clk); -+ if (rc) { -+ dev_err(dev, "couldn't enable clock\n"); -+ return rc; -+ } -+ -+ mbox->miscdev.minor = MISC_DYNAMIC_MINOR; -+ mbox->miscdev.name = DEVICE_NAME; -+ mbox->miscdev.fops = &aspeed_mbox_fops; -+ mbox->miscdev.parent = dev; -+ rc = misc_register(&mbox->miscdev); -+ if (rc) { -+ dev_err(dev, "Unable to register device\n"); -+ goto err; -+ } -+ -+ rc = aspeed_mbox_config_irq(mbox, pdev); -+ if (rc) { -+ dev_err(dev, "Failed to configure IRQ\n"); -+ misc_deregister(&mbox->miscdev); -+ goto err; -+ } -+ -+ dev_info(&pdev->dev, "LPC mbox registered, irq %d\n", mbox->irq); -+ -+ return 0; -+ -+err: -+ clk_disable_unprepare(mbox->clk); -+ -+ return rc; -+} -+ -+static int aspeed_mbox_remove(struct platform_device *pdev) -+{ -+ struct aspeed_mbox *mbox = dev_get_drvdata(&pdev->dev); -+ -+ misc_deregister(&mbox->miscdev); -+ clk_disable_unprepare(mbox->clk); -+ -+ return 0; -+} -+ -+static const struct of_device_id aspeed_mbox_match[] = { -+ { .compatible = "aspeed,ast2400-mbox" }, -+ { .compatible = "aspeed,ast2500-mbox" }, -+ { .compatible = "aspeed,ast2600-mbox" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, aspeed_mbox_match); -+ -+static struct platform_driver aspeed_mbox_driver = { -+ .driver = { -+ .name = DEVICE_NAME, -+ .of_match_table = aspeed_mbox_match, -+ }, -+ .probe = aspeed_mbox_probe, -+ .remove = aspeed_mbox_remove, -+}; -+ -+module_platform_driver(aspeed_mbox_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>"); -+MODULE_DESCRIPTION("Aspeed mailbox device driver"); --- -2.17.1 - |