From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
To: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>,
Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>
Cc: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
Subject: Re: [PATCH] i2c: add bcm2835 driver
Date: Fri, 08 Feb 2013 21:48:46 +0000 [thread overview]
Message-ID: <20130208214846.35F2D3E2C27@localhost> (raw)
In-Reply-To: <1357191978-11038-1-git-send-email-swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
On Wed, 2 Jan 2013 22:46:18 -0700, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
> This implements a very basic I2C host driver for the BCM2835 SoC. Missing
> features so far are:
>
> * Clock rate adjustment.
> * 10-bit addressing.
> * DMA.
>
> Signed-off-by: Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
> ---
> .../devicetree/bindings/i2c/brcm,bcm2835-i2c.txt | 20 ++
> drivers/i2c/busses/Kconfig | 12 +
> drivers/i2c/busses/Makefile | 1 +
> drivers/i2c/busses/i2c-bcm2835.c | 331 ++++++++++++++++++++
> 4 files changed, 364 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
> create mode 100644 drivers/i2c/busses/i2c-bcm2835.c
>
> diff --git a/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt b/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
> new file mode 100644
> index 0000000..e9de375
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
> @@ -0,0 +1,20 @@
> +Broadcom BCM2835 I2C controller
> +
> +Required properties:
> +- compatible : Should be "brcm,bcm2835-i2c".
> +- reg: Should contain register location and length.
> +- interrupts: Should contain interrupt.
> +- clocks : The clock feeding the I2C controller.
> +
> +Recommended properties:
> +- clock-frequency : desired I2C bus clock frequency in Hz.
> +
> +Example:
> +
> +i2c@20205000 {
> + compatible = "brcm,bcm2835-i2c";
> + reg = <0x7e205000 0x1000>;
> + interrupts = <2 21>;
> + clocks = <&clk_i2c>;
> + clock-frequency = <100000>;
> +};
Looks good.
> +static int __devinit bcm2835_i2c_probe(struct platform_device *pdev)
> +{
> + struct bcm2835_i2c_dev *i2c_dev;
> + struct resource *mem, *requested, *irq;
> + int ret;
> + struct i2c_adapter *adap;
> +
> + i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
> + if (!i2c_dev) {
> + dev_err(&pdev->dev, "Cannot allocate i2c_dev\n");
> + return -ENOMEM;
> + }
> + platform_set_drvdata(pdev, i2c_dev);
> + i2c_dev->dev = &pdev->dev;
> + init_completion(&i2c_dev->completion);
> +
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!mem) {
> + dev_err(&pdev->dev, "No mem resource\n");
> + return -ENODEV;
> + }
> +
> + requested = devm_request_mem_region(&pdev->dev, mem->start,
> + resource_size(mem),
> + dev_name(&pdev->dev));
> + if (!requested) {
> + dev_err(&pdev->dev, "Could not claim register region\n");
> + return -EBUSY;
> + }
> +
> + i2c_dev->regs = devm_ioremap(&pdev->dev, mem->start,
> + resource_size(mem));
> + if (!i2c_dev->regs) {
> + dev_err(&pdev->dev, "Could not map registers\n");
> + return -ENOMEM;
> + }
> +
> + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (!irq) {
> + dev_err(&pdev->dev, "No IRQ resource\n");
> + return -ENODEV;
> + }
> +
> + ret = devm_request_irq(&pdev->dev, irq->start, bcm2835_i2c_isr,
> + IRQF_SHARED, dev_name(&pdev->dev), i2c_dev);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not request IRQ\n");
> + return -ENODEV;
> + }
> +
> + adap = &i2c_dev->adapter;
> + i2c_set_adapdata(adap, i2c_dev);
> + adap->owner = THIS_MODULE;
> + adap->class = I2C_CLASS_HWMON;
> + strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name));
> + adap->algo = &bcm2835_i2c_algo;
> + adap->dev.parent = &pdev->dev;
> + adap->nr = -1;
> +
> + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
> +
> + ret = i2c_add_numbered_adapter(adap);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not add adapter\n");
> + return ret;
> + }
> +
> + return 0;
The driver core will print a message if things fail here. The above 6
lines can be replaced with simply:
return i2c_add_numbered_adapter(adap);
> +}
> +
> +static int bcm2835_i2c_remove(struct platform_device *pdev)
> +{
> + struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
> +
> + i2c_del_adapter(&i2c_dev->adapter);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id bcm2835_i2c_of_match[] = {
> + { .compatible = "brcm,bcm2835-i2c" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match);
> +
> +static struct platform_driver bcm2835_i2c_driver = {
> + .probe = bcm2835_i2c_probe,
> + .remove = bcm2835_i2c_remove,
> + .driver = {
> + .name = "i2c-bcm2835",
> + .owner = THIS_MODULE,
> + .of_match_table = bcm2835_i2c_of_match,
> + },
> +};
> +
> +static int __init bcm2835_i2c_init_driver(void)
> +{
> + return platform_driver_register(&bcm2835_i2c_driver);
> +}
> +module_init(bcm2835_i2c_init_driver);
> +
> +static void __exit bcm2835_i2c_exit_driver(void)
> +{
> + platform_driver_unregister(&bcm2835_i2c_driver);
> +}
> +module_exit(bcm2835_i2c_exit_driver);
Nit: module_platform_driver()
Otherwise looks pretty tight.
Reviewed-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
g.
WARNING: multiple messages have this Message-ID (diff)
From: grant.likely@secretlab.ca (Grant Likely)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] i2c: add bcm2835 driver
Date: Fri, 08 Feb 2013 21:48:46 +0000 [thread overview]
Message-ID: <20130208214846.35F2D3E2C27@localhost> (raw)
In-Reply-To: <1357191978-11038-1-git-send-email-swarren@wwwdotorg.org>
On Wed, 2 Jan 2013 22:46:18 -0700, Stephen Warren <swarren@wwwdotorg.org> wrote:
> This implements a very basic I2C host driver for the BCM2835 SoC. Missing
> features so far are:
>
> * Clock rate adjustment.
> * 10-bit addressing.
> * DMA.
>
> Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
> ---
> .../devicetree/bindings/i2c/brcm,bcm2835-i2c.txt | 20 ++
> drivers/i2c/busses/Kconfig | 12 +
> drivers/i2c/busses/Makefile | 1 +
> drivers/i2c/busses/i2c-bcm2835.c | 331 ++++++++++++++++++++
> 4 files changed, 364 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
> create mode 100644 drivers/i2c/busses/i2c-bcm2835.c
>
> diff --git a/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt b/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
> new file mode 100644
> index 0000000..e9de375
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/brcm,bcm2835-i2c.txt
> @@ -0,0 +1,20 @@
> +Broadcom BCM2835 I2C controller
> +
> +Required properties:
> +- compatible : Should be "brcm,bcm2835-i2c".
> +- reg: Should contain register location and length.
> +- interrupts: Should contain interrupt.
> +- clocks : The clock feeding the I2C controller.
> +
> +Recommended properties:
> +- clock-frequency : desired I2C bus clock frequency in Hz.
> +
> +Example:
> +
> +i2c at 20205000 {
> + compatible = "brcm,bcm2835-i2c";
> + reg = <0x7e205000 0x1000>;
> + interrupts = <2 21>;
> + clocks = <&clk_i2c>;
> + clock-frequency = <100000>;
> +};
Looks good.
> +static int __devinit bcm2835_i2c_probe(struct platform_device *pdev)
> +{
> + struct bcm2835_i2c_dev *i2c_dev;
> + struct resource *mem, *requested, *irq;
> + int ret;
> + struct i2c_adapter *adap;
> +
> + i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
> + if (!i2c_dev) {
> + dev_err(&pdev->dev, "Cannot allocate i2c_dev\n");
> + return -ENOMEM;
> + }
> + platform_set_drvdata(pdev, i2c_dev);
> + i2c_dev->dev = &pdev->dev;
> + init_completion(&i2c_dev->completion);
> +
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!mem) {
> + dev_err(&pdev->dev, "No mem resource\n");
> + return -ENODEV;
> + }
> +
> + requested = devm_request_mem_region(&pdev->dev, mem->start,
> + resource_size(mem),
> + dev_name(&pdev->dev));
> + if (!requested) {
> + dev_err(&pdev->dev, "Could not claim register region\n");
> + return -EBUSY;
> + }
> +
> + i2c_dev->regs = devm_ioremap(&pdev->dev, mem->start,
> + resource_size(mem));
> + if (!i2c_dev->regs) {
> + dev_err(&pdev->dev, "Could not map registers\n");
> + return -ENOMEM;
> + }
> +
> + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (!irq) {
> + dev_err(&pdev->dev, "No IRQ resource\n");
> + return -ENODEV;
> + }
> +
> + ret = devm_request_irq(&pdev->dev, irq->start, bcm2835_i2c_isr,
> + IRQF_SHARED, dev_name(&pdev->dev), i2c_dev);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not request IRQ\n");
> + return -ENODEV;
> + }
> +
> + adap = &i2c_dev->adapter;
> + i2c_set_adapdata(adap, i2c_dev);
> + adap->owner = THIS_MODULE;
> + adap->class = I2C_CLASS_HWMON;
> + strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name));
> + adap->algo = &bcm2835_i2c_algo;
> + adap->dev.parent = &pdev->dev;
> + adap->nr = -1;
> +
> + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
> +
> + ret = i2c_add_numbered_adapter(adap);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not add adapter\n");
> + return ret;
> + }
> +
> + return 0;
The driver core will print a message if things fail here. The above 6
lines can be replaced with simply:
return i2c_add_numbered_adapter(adap);
> +}
> +
> +static int bcm2835_i2c_remove(struct platform_device *pdev)
> +{
> + struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
> +
> + i2c_del_adapter(&i2c_dev->adapter);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id bcm2835_i2c_of_match[] = {
> + { .compatible = "brcm,bcm2835-i2c" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, bcm2835_i2c_of_match);
> +
> +static struct platform_driver bcm2835_i2c_driver = {
> + .probe = bcm2835_i2c_probe,
> + .remove = bcm2835_i2c_remove,
> + .driver = {
> + .name = "i2c-bcm2835",
> + .owner = THIS_MODULE,
> + .of_match_table = bcm2835_i2c_of_match,
> + },
> +};
> +
> +static int __init bcm2835_i2c_init_driver(void)
> +{
> + return platform_driver_register(&bcm2835_i2c_driver);
> +}
> +module_init(bcm2835_i2c_init_driver);
> +
> +static void __exit bcm2835_i2c_exit_driver(void)
> +{
> + platform_driver_unregister(&bcm2835_i2c_driver);
> +}
> +module_exit(bcm2835_i2c_exit_driver);
Nit: module_platform_driver()
Otherwise looks pretty tight.
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
g.
next prev parent reply other threads:[~2013-02-08 21:48 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-03 5:46 [PATCH] i2c: add bcm2835 driver Stephen Warren
2013-01-03 5:46 ` Stephen Warren
[not found] ` <1357191978-11038-1-git-send-email-swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-02-08 21:48 ` Grant Likely [this message]
2013-02-08 21:48 ` Grant Likely
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=20130208214846.35F2D3E2C27@localhost \
--to=grant.likely-s3s/wqlpoipyb63q8fvjnq@public.gmane.org \
--cc=ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org \
--cc=devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org \
--cc=swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org \
--cc=w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.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.