All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cyril Bur <cyrilbur@gmail.com>
To: Greg KH <gregkh@linuxfoundation.org>
Cc: jk@ozlabs.org, benh@kernel.crashing.org, andrew@aj.id.au,
	 openbmc@lists.ozlabs.org, joel@jms.id.au
Subject: Re: [PATCH v2] drivers/misc: Add ASpeed LPC control driver
Date: Mon, 16 Jan 2017 09:43:35 +1100	[thread overview]
Message-ID: <1484520215.13393.1.camel@gmail.com> (raw)
In-Reply-To: <20170113103625.GA15142@kroah.com>

On Fri, 2017-01-13 at 11:36 +0100, Greg KH wrote:
> On Fri, Jan 13, 2017 at 06:47:13PM +1100, Cyril Bur wrote:
> > +config ASPEED_LPC_CTRL
> > +	depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
> > +	bool "Build a driver to control the BMC to HOST LPC bus"
> > +	default "y"
> 
> Unless a kernel option prevents a machine from booting, it should never
> be 'default y'.  This is a misc driver, it should never be 'default y'.
> 

Hi Greg,

Yes, I think I was convinced otherwise. I'll change.

> 
> > --- /dev/null
> > +++ b/drivers/misc/aspeed-lpc-ctrl.c
> > @@ -0,0 +1,264 @@
> > +/*
> > + * Copyright 2017 IBM Corporation
> > + *
> > + * 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.
> 
> I have to ask, do you really mean "any later version"?
> 

I appreciate that you checked - I can confirm that I do mean "any later
version"

> > + */
> > +
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/miscdevice.h>
> > +#include <linux/mm.h>
> > +#include <linux/module.h>
> > +#include <linux/of_address.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/poll.h>
> > +#include <linux/regmap.h>
> > +
> > +#include <linux/aspeed-lpc-ctrl.h>
> > +
> > +#define DEVICE_NAME	"aspeed-lpc-ctrl"
> > +
> > +#define HICR7 0x8
> > +#define HICR8 0xc
> > +
> > +struct aspeed_lpc_ctrl {
> > +	struct miscdevice	miscdev;
> > +	struct regmap		*regmap;
> > +	phys_addr_t		mem_base;
> > +	resource_size_t		mem_size;
> > +	__u32		pnor_size;
> > +	__u32		pnor_base;
> > +};
> > +
> > +static struct aspeed_lpc_ctrl *file_aspeed_lpc_ctrl(struct file *file)
> > +{
> > +	return container_of(file->private_data, struct aspeed_lpc_ctrl,
> > +			miscdev);
> > +}
> > +
> > +static int aspeed_lpc_ctrl_mmap(struct file *file, struct vm_area_struct *vma)
> > +{
> > +	struct aspeed_lpc_ctrl *lpc_ctrl = file_aspeed_lpc_ctrl(file);
> > +	unsigned long vsize = vma->vm_end - vma->vm_start;
> > +	pgprot_t prot = vma->vm_page_prot;
> > +
> > +	if (vma->vm_pgoff + vsize > lpc_ctrl->mem_base + lpc_ctrl->mem_size)
> > +		return -EINVAL;
> > +
> > +	/* AHB access are not cache coherent */
> > +	if (file->f_flags & O_DSYNC)
> > +		prot = pgprot_noncached(prot);
> > +
> > +	if (remap_pfn_range(vma, vma->vm_start,
> > +		(lpc_ctrl->mem_base >> PAGE_SHIFT) + vma->vm_pgoff,
> > +		vsize, prot))
> > +		return -EAGAIN;
> > +
> > +	return 0;
> > +}
> > +
> > +static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd,
> > +		unsigned long param)
> > +{
> > +	long rc;
> > +	struct aspeed_lpc_ctrl_mapping map;
> > +	struct aspeed_lpc_ctrl *lpc_ctrl = file_aspeed_lpc_ctrl(file);
> > +	void __user *p = (void __user *)param;
> > +	u32 addr;
> > +	u32 size;
> > +
> > +	if (copy_from_user(&map, p, sizeof(map)))
> > +		return -EFAULT;
> > +
> > +	switch (cmd) {
> > +	case ASPEED_LPC_CTRL_IOCTL_GET_SIZE:
> > +		/* The flash windows don't report their size */
> > +		if (map.window_type != ASPEED_LPC_CTRL_WINDOW_MEMORY)
> > +			return -EINVAL;
> > +
> > +		/* Support more than one window id in the future */
> > +		if (map.window_id != 0)
> > +			return -EINVAL;
> > +
> > +		map.size = lpc_ctrl->mem_size;
> > +
> > +		return copy_to_user(p, &map, sizeof(map)) ? -EFAULT : 0;
> > +	case ASPEED_LPC_CTRL_IOCTL_MAP:
> > +
> > +		/*
> > +		 * The top half of HICR7 is the MSB of the BMC address of the
> > +		 * mapping.
> > +		 * The bottom half of HICR7 is the MSB of the HOST LPC
> > +		 * firmware space address of the mapping.
> > +		 *
> > +		 * The 1 bits in the top of half of HICR8 represent the bits
> > +		 * (in the requested address) that should be ignored and
> > +		 * replaced with those from the top half of HICR7.
> > +		 * The 1 bits in the bottom half of HICR8 represent the bits
> > +		 * (in the requested address) that should be kept and pass
> > +		 * into the BMC address space.
> > +		 */
> > +
> > +		/*
> > +		 * It doesn't make sense to talk about a size or offset with
> > +		 * low 16 bits set. Both HICR7 and HICR8 talk about the top 16
> > +		 * bits of addresses and sizes.
> > +		 */
> > +
> > +		if ((map.size & 0x0000ffff) || (map.offset & 0x0000ffff))
> > +			return -EINVAL;
> > +
> > +		/*
> > +		 * Because of the way the masks work in HICR8 offset has to
> > +		 * be a multiple of size
> > +		 */
> > +		if (map.offset & (map.size - 1))
> > +			return -EINVAL;
> > +
> > +		if (map.window_type == ASPEED_LPC_CTRL_WINDOW_FLASH) {
> > +			addr = lpc_ctrl->pnor_base;
> > +			size = lpc_ctrl->pnor_size;
> > +		} else if (map.window_type == ASPEED_LPC_CTRL_WINDOW_MEMORY) {
> > +			addr = lpc_ctrl->mem_base;
> > +			size = lpc_ctrl->mem_size;
> > +		} else {
> > +			return -EINVAL;
> > +		}
> > +
> > +		/* Overflow first! */
> > +		if (map.offset + map.size < map.offset ||
> > +			map.offset + map.size > size)
> > +			return -EINVAL;
> > +
> > +		if (map.size == 0 || map.size > size)
> > +			return -EINVAL;
> > +
> > +		addr += map.offset;
> > +
> > +		/*
> > +		 * hostaddr is safe regardless of values. This simply changes
> > +		 * the address the host has to request on its side of the LPC
> > +		 * bus. This cannot impact the hosts own memory space by
> > +		 * surprise as LPC specific accessors are required. The only
> > +		 * strange thing that could be done is setting the lower 16
> > +		 * bits but the shift takes care of that.
> > +		 */
> > +
> > +		rc = regmap_write(lpc_ctrl->regmap, HICR7,
> > +				(addr | (map.addr >> 16)));
> > +		if (rc)
> > +			return rc;
> > +
> > +		return regmap_write(lpc_ctrl->regmap, HICR8,
> > +			(~(map.size - 1)) | ((map.size >> 16) - 1));
> > +	}
> > +
> > +	return -EINVAL;
> > +}
> > +
> > +static const struct file_operations aspeed_lpc_ctrl_fops = {
> > +	.owner		= THIS_MODULE,
> > +	.mmap		= aspeed_lpc_ctrl_mmap,
> > +	.unlocked_ioctl	= aspeed_lpc_ctrl_ioctl,
> > +};
> > +
> > +static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
> > +{
> > +	struct aspeed_lpc_ctrl *lpc_ctrl;
> > +	struct device *dev;
> > +	struct device_node *node;
> > +	struct resource resm;
> > +	int rc;
> > +
> > +	dev = &pdev->dev;
> > +
> > +	lpc_ctrl = devm_kzalloc(dev, sizeof(*lpc_ctrl), GFP_KERNEL);
> > +	if (!lpc_ctrl)
> > +		return -ENOMEM;
> > +
> > +	node = of_parse_phandle(dev->of_node, "flash", 0);
> > +	if (!node) {
> > +		dev_err(dev, "Didn't find host pnor flash node\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	rc = of_property_read_u32_index(node, "reg", 3,
> > +			&lpc_ctrl->pnor_size);
> > +	if (rc)
> > +		return rc;
> > +	rc = of_property_read_u32_index(node, "reg", 2,
> > +			&lpc_ctrl->pnor_base);
> > +	if (rc)
> > +		return rc;
> > +
> > +	dev_set_drvdata(&pdev->dev, lpc_ctrl);
> > +
> > +	node = of_parse_phandle(dev->of_node, "memory-region", 0);
> > +	if (!node) {
> > +		dev_err(dev, "Didn't find reserved memory\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	rc = of_address_to_resource(node, 0, &resm);
> > +	of_node_put(node);
> > +	if (rc) {
> > +		dev_err(dev, "Could address to resource\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	lpc_ctrl->mem_size = resource_size(&resm);
> > +	lpc_ctrl->mem_base = resm.start;
> > +
> > +	lpc_ctrl->regmap = syscon_node_to_regmap(
> > +			pdev->dev.parent->of_node);
> > +	if (IS_ERR(lpc_ctrl->regmap)) {
> > +		dev_err(dev, "Couldn't get regmap\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	lpc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR;
> > +	lpc_ctrl->miscdev.name = DEVICE_NAME;
> > +	lpc_ctrl->miscdev.fops = &aspeed_lpc_ctrl_fops;
> > +	lpc_ctrl->miscdev.parent = dev;
> > +	rc = misc_register(&lpc_ctrl->miscdev);
> > +	if (rc)
> > +		dev_err(dev, "Unable to register device\n");
> > +	else
> > +		dev_info(dev, "Loaded at 0x%08x (0x%08x)\n",
> > +			lpc_ctrl->mem_base, lpc_ctrl->mem_size);
> > +
> > +	return rc;
> > +}
> > +
> > +static int aspeed_lpc_ctrl_remove(struct platform_device *pdev)
> > +{
> > +	struct aspeed_lpc_ctrl *lpc_ctrl = dev_get_drvdata(&pdev->dev);
> > +
> > +	misc_deregister(&lpc_ctrl->miscdev);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id aspeed_lpc_ctrl_match[] = {
> > +	{ .compatible = "aspeed,ast2400-lpc-ctrl" },
> > +	{ .compatible = "aspeed,ast2500-lpc-ctrl" },
> > +	{ },
> > +};
> > +
> > +static struct platform_driver aspeed_lpc_ctrl_driver = {
> > +	.driver = {
> > +		.name		= DEVICE_NAME,
> > +		.of_match_table = aspeed_lpc_ctrl_match,
> > +	},
> > +	.probe = aspeed_lpc_ctrl_probe,
> > +	.remove = aspeed_lpc_ctrl_remove,
> > +};
> > +
> > +module_platform_driver(aspeed_lpc_ctrl_driver);
> > +
> > +MODULE_DEVICE_TABLE(of, aspeed_lpc_ctrl_match);
> > +MODULE_LICENSE("GPL");
> > +MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>");
> > +MODULE_DESCRIPTION("Linux device interface to control LPC bus");
> > diff --git a/include/uapi/linux/aspeed-lpc-ctrl.h b/include/uapi/linux/aspeed-lpc-ctrl.h
> > new file mode 100644
> > index 000000000000..220220b6c83a
> > --- /dev/null
> > +++ b/include/uapi/linux/aspeed-lpc-ctrl.h
> > @@ -0,0 +1,35 @@
> > +/*
> > + * Copyright 2017 IBM Corp.
> > + *
> > + * 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.
> > + */
> > +
> > +#ifndef _UAPI_LINUX_ASPEED_LPC_CTRL_H
> > +#define _UAPI_LINUX_ASPEED_LPC_CTRL_H
> > +
> > +#include <linux/ioctl.h>
> > +
> > +/* Window types */
> > +#define ASPEED_LPC_CTRL_WINDOW_FLASH	1
> > +#define ASPEED_LPC_CTRL_WINDOW_MEMORY	2
> > +
> > +struct aspeed_lpc_ctrl_mapping {
> > +	__u8	window_type;
> > +	__u8	window_id;
> > +	__u32	addr;
> > +	__u32	offset;
> > +	__u32	size;
> 
> That's some crazy alignment, do you really mean to put a 32bit value
> aligned like that?  Will it work properly on your systems?
> 

Well, in my probably unrealistic and rushed testing it did work - but
then this was all with one compiler on one machine so I'm not
surprised. I'll put the u8s at the end.

Thanks,

Cyril


> thanks,
> 
> greg k-h

  reply	other threads:[~2017-01-15 22:44 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-13  7:47 [PATCH v2] drivers/misc: Add ASpeed LPC control driver Cyril Bur
2017-01-13 10:36 ` Greg KH
2017-01-15 22:43   ` Cyril Bur [this message]
2017-01-16  4:45     ` Benjamin Herrenschmidt
2017-01-16 10:45       ` Greg KH
2017-01-16 13:34         ` Benjamin Herrenschmidt
2017-01-18 22:47           ` Cyril Bur

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1484520215.13393.1.camel@gmail.com \
    --to=cyrilbur@gmail.com \
    --cc=andrew@aj.id.au \
    --cc=benh@kernel.crashing.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jk@ozlabs.org \
    --cc=joel@jms.id.au \
    --cc=openbmc@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.