From swarren at wwwdotorg.org  Thu Jan  3 00:34:49 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed,  2 Jan 2013 22:34:49 -0700
Subject: [PATCH] mmc: add BCM2835 driver
Message-ID: <1357191289-10455-1-git-send-email-swarren@wwwdotorg.org>

Add a very simple driver for the BCM2835 SoC, which is used in the
Raspberry Pi board.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 .../devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt |   18 ++
 drivers/mmc/host/Kconfig                           |   11 +
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/sdhci-bcm2835.c                   |  227 ++++++++++++++++++++
 4 files changed, 257 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt
 create mode 100644 drivers/mmc/host/sdhci-bcm2835.c

diff --git a/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt
new file mode 100644
index 0000000..59476fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/brcm,bcm2835-sdhci.txt
@@ -0,0 +1,18 @@
+Broadcom BCM2835 SDHCI controller
+
+This file documents differences between the core properties described
+by mmc.txt and the properties that represent the BCM2835 controller.
+
+Required properties:
+- compatible : Should be "brcm,bcm2835-sdhci".
+- clocks : The clock feeding the SDHCI controller.
+
+Example:
+
+sdhci: sdhci {
+	compatible = "brcm,bcm2835-sdhci";
+	reg = <0x7e300000 0x100>;
+	interrupts = <2 30>;
+	clocks = <&clk_mmc>;
+	bus-width = <4>;
+};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index cc8a8fa..7684f7f 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -238,6 +238,17 @@ config MMC_SDHCI_S3C_DMA
 
 	  YMMV.
 
+config MMC_SDHCI_BCM2835
+	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
+	depends on ARCH_BCM2835
+	depends on MMC_SDHCI_PLTFM
+	select MMC_SDHCI_IO_ACCESSORS
+	help
+	  This selects the BCM2835 SD/MMC controller. If you have a BCM2835
+	  platform with SD or MMC devices, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_OMAP
 	tristate "TI OMAP Multimedia Card Interface support"
 	depends on ARCH_OMAP
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index e4e218c..d5ea0722 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_MMC_SDHCI_DOVE)		+= sdhci-dove.o
 obj-$(CONFIG_MMC_SDHCI_TEGRA)		+= sdhci-tegra.o
 obj-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o
 obj-$(CONFIG_MMC_SDHCI_OF_HLWD)		+= sdhci-of-hlwd.o
+obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= sdhci-bcm2835.o
 
 ifeq ($(CONFIG_CB710_DEBUG),y)
 	CFLAGS-cb710-mmc	+= -DDEBUG
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c
new file mode 100644
index 0000000..453825f
--- /dev/null
+++ b/drivers/mmc/host/sdhci-bcm2835.c
@@ -0,0 +1,227 @@
+/*
+ * BCM2835 SDHCI
+ * Copyright (C) 2012 Stephen Warren
+ * Based on U-Boot's MMC driver for the BCM2835 by Oleksandr Tymoshenko & me
+ * Portions of the code there were obviously based on the Linux kernel at:
+ * git://github.com/raspberrypi/linux.git rpi-3.6.y
+ * commit f5b930b "Main bcm2708 linux port" signed-off-by Dom Cobley.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/mmc/host.h>
+#include "sdhci-pltfm.h"
+
+/*
+ * 400KHz is max freq for card ID etc. Use that as min card clock. We need to
+ * know the min to enable static calculation of max BCM2835_SDHCI_WRITE_DELAY.
+ */
+#define MIN_FREQ 400000
+
+/*
+ * The Arasan has a bugette whereby it may lose the content of successive
+ * writes to registers that are within two SD-card clock cycles of each other
+ * (a clock domain crossing problem). It seems, however, that the data
+ * register does not have this problem, which is just as well - otherwise we'd
+ * have to nobble the DMA engine too.
+ *
+ * This should probably be dynamically calculated based on the actual card
+ * frequency. However, this is the longest we'll have to wait, and doesn't
+ * seem to slow access down too much, so the added complexity doesn't seem
+ * worth it for now.
+ *
+ * 1/MIN_FREQ is (max) time per tick of eMMC clock.
+ * 2/MIN_FREQ is time for two ticks.
+ * Multiply by 1000000 to get uS per two ticks.
+ * *1000000 for uSecs.
+ * +1 for hack rounding.
+ */
+#define BCM2835_SDHCI_WRITE_DELAY	(((2 * 1000000) / MIN_FREQ) + 1)
+
+struct bcm2835_sdhci {
+	struct clk *clk;
+	u32 shadow;
+};
+
+static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
+{
+	writel(val, host->ioaddr + reg);
+
+	udelay(BCM2835_SDHCI_WRITE_DELAY);
+}
+
+static inline u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg)
+{
+	u32 val = readl(host->ioaddr + reg);
+
+	if (reg == SDHCI_CAPABILITIES)
+		val |= SDHCI_CAN_VDD_330;
+
+	return val;
+}
+
+static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct bcm2835_sdhci *bcm2835_host = pltfm_host->priv;
+	u32 oldval = (reg == SDHCI_COMMAND) ? bcm2835_host->shadow :
+		bcm2835_sdhci_readl(host, reg & ~3);
+	u32 word_num = (reg >> 1) & 1;
+	u32 word_shift = word_num * 16;
+	u32 mask = 0xffff << word_shift;
+	u32 newval = (oldval & ~mask) | (val << word_shift);
+
+	if (reg == SDHCI_TRANSFER_MODE)
+		bcm2835_host->shadow = newval;
+	else
+		bcm2835_sdhci_writel(host, newval, reg & ~3);
+}
+
+static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg)
+{
+	u32 val = bcm2835_sdhci_readl(host, (reg & ~3));
+	u32 word_num = (reg >> 1) & 1;
+	u32 word_shift = word_num * 16;
+	u32 word = (val >> word_shift) & 0xffff;
+
+	return word;
+}
+
+static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+	u32 oldval = bcm2835_sdhci_readl(host, reg & ~3);
+	u32 byte_num = reg & 3;
+	u32 byte_shift = byte_num * 8;
+	u32 mask = 0xff << byte_shift;
+	u32 newval = (oldval & ~mask) | (val << byte_shift);
+
+	bcm2835_sdhci_writel(host, newval, reg & ~3);
+}
+
+static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
+{
+	u32 val = bcm2835_sdhci_readl(host, (reg & ~3));
+	u32 byte_num = reg & 3;
+	u32 byte_shift = byte_num * 8;
+	u32 byte = (val >> byte_shift) & 0xff;
+
+	return byte;
+}
+
+static unsigned int bcm2835_sdhci_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct bcm2835_sdhci *bcm2835_host = pltfm_host->priv;
+
+	return clk_get_rate(bcm2835_host->clk);
+}
+
+unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
+{
+	return MIN_FREQ;
+}
+
+unsigned int bcm2835_sdhci_get_timeout_clock(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct bcm2835_sdhci *bcm2835_host = pltfm_host->priv;
+
+	return clk_get_rate(bcm2835_host->clk);
+}
+
+static struct sdhci_ops bcm2835_sdhci_ops = {
+	.write_l = bcm2835_sdhci_writel,
+	.write_w = bcm2835_sdhci_writew,
+	.write_b = bcm2835_sdhci_writeb,
+	.read_l = bcm2835_sdhci_readl,
+	.read_w = bcm2835_sdhci_readw,
+	.read_b = bcm2835_sdhci_readb,
+	.get_max_clock = bcm2835_sdhci_get_max_clock,
+	.get_min_clock = bcm2835_sdhci_get_min_clock,
+	.get_timeout_clock = bcm2835_sdhci_get_timeout_clock,
+};
+
+static struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
+	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION,
+	.ops = &bcm2835_sdhci_ops,
+};
+
+static int bcm2835_sdhci_probe(struct platform_device *pdev)
+{
+	struct sdhci_host *host;
+	struct bcm2835_sdhci *bcm2835_host;
+	struct sdhci_pltfm_host *pltfm_host;
+	int ret;
+
+	host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata);
+	if (IS_ERR(host))
+		return PTR_ERR(host);
+
+	bcm2835_host = devm_kzalloc(&pdev->dev, sizeof(*bcm2835_host),
+					GFP_KERNEL);
+	if (!bcm2835_host) {
+		dev_err(mmc_dev(host->mmc),
+			"failed to allocate bcm2835_sdhci\n");
+		return -ENOMEM;
+	}
+
+	pltfm_host = sdhci_priv(host);
+	pltfm_host->priv = bcm2835_host;
+
+	bcm2835_host->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(bcm2835_host->clk)) {
+		ret = PTR_ERR(bcm2835_host->clk);
+		goto err;
+	}
+
+	return sdhci_add_host(host);
+
+err:
+	sdhci_pltfm_free(pdev);
+	return ret;
+}
+
+static int bcm2835_sdhci_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+	sdhci_remove_host(host, dead);
+	sdhci_pltfm_free(pdev);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_sdhci_of_match[] = {
+	{ .compatible = "brcm,bcm2835-sdhci" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, bcm2835_sdhci_of_match);
+
+static struct platform_driver bcm2835_sdhci_driver = {
+	.driver = {
+		.name = "sdhci-bcm2835",
+		.owner = THIS_MODULE,
+		.of_match_table = bcm2835_sdhci_of_match,
+		.pm = SDHCI_PLTFM_PMOPS,
+	},
+	.probe = bcm2835_sdhci_probe,
+	.remove = bcm2835_sdhci_remove,
+};
+module_platform_driver(bcm2835_sdhci_driver);
+
+MODULE_DESCRIPTION("BCM2835 SDHCI driver");
+MODULE_AUTHOR("Stephen Warren");
+MODULE_LICENSE("GPL v2");
-- 
1.7.10.4



From swarren at wwwdotorg.org  Thu Jan  3 00:46:18 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed,  2 Jan 2013 22:46:18 -0700
Subject: [PATCH] i2c: add bcm2835 driver
Message-ID: <1357191978-11038-1-git-send-email-swarren@wwwdotorg.org>

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 at 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>;
+};
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index bdca511..5aab774 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -319,6 +319,18 @@ config I2C_AU1550
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-au1550.
 
+config I2C_BCM2835
+	tristate "Broadcom BCM2835 I2C controller"
+	depends on ARCH_BCM2835
+	help
+	  If you say yes to this option, support will be included for the
+	  BCM2835 I2C controller.
+
+	  If you don't know what to do here, say N.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-bcm2835.
+
 config I2C_BLACKFIN_TWI
 	tristate "Blackfin TWI I2C support"
 	depends on BLACKFIN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 6181f3f..a52a891 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
 # Embedded system I2C/SMBus host controller drivers
 obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
+obj-$(CONFIG_I2C_BCM2835)	+= i2c-bcm2835.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CBUS_GPIO)	+= i2c-cbus-gpio.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
new file mode 100644
index 0000000..c212471
--- /dev/null
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -0,0 +1,331 @@
+/*
+ * BCM2835 master mode driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define BCM2835_I2C_C		0x0
+#define BCM2835_I2C_S		0x4
+#define BCM2835_I2C_DLEN	0x8
+#define BCM2835_I2C_A		0xc
+#define BCM2835_I2C_FIFO	0x10
+#define BCM2835_I2C_DIV		0x14
+#define BCM2835_I2C_DEL		0x18
+#define BCM2835_I2C_CLKT	0x1c
+
+#define BCM2835_I2C_C_READ	BIT(0)
+#define BCM2835_I2C_C_CLEAR	BIT(4) /* bits 4 and 5 both clear */
+#define BCM2835_I2C_C_ST	BIT(7)
+#define BCM2835_I2C_C_INTD	BIT(8)
+#define BCM2835_I2C_C_INTT	BIT(9)
+#define BCM2835_I2C_C_INTR	BIT(10)
+#define BCM2835_I2C_C_I2CEN	BIT(15)
+
+#define BCM2835_I2C_S_TA	BIT(0)
+#define BCM2835_I2C_S_DONE	BIT(1)
+#define BCM2835_I2C_S_TXW	BIT(2)
+#define BCM2835_I2C_S_RXR	BIT(3)
+#define BCM2835_I2C_S_TXD	BIT(4)
+#define BCM2835_I2C_S_RXD	BIT(5)
+#define BCM2835_I2C_S_TXE	BIT(6)
+#define BCM2835_I2C_S_RXF	BIT(7)
+#define BCM2835_I2C_S_ERR	BIT(8)
+#define BCM2835_I2C_S_CLKT	BIT(9)
+#define BCM2835_I2C_S_LEN	BIT(10) /* Fake bit for SW error reporting */
+
+#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000))
+
+struct bcm2835_i2c_dev {
+	struct device *dev;
+	void __iomem *regs;
+	struct i2c_adapter adapter;
+	struct completion completion;
+	u32 msg_err;
+	u8 *msg_buf;
+	size_t msg_buf_remaining;
+};
+
+static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev,
+				      u32 reg, u32 val)
+{
+	writel(val, i2c_dev->regs + reg);
+}
+
+static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg)
+{
+	return readl(i2c_dev->regs + reg);
+}
+
+static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 val;
+
+	for (;;) {
+		if (!i2c_dev->msg_buf_remaining)
+			return;
+		val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		if (!(val & BCM2835_I2C_S_TXD))
+			break;
+		bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_FIFO,
+				   *i2c_dev->msg_buf);
+		i2c_dev->msg_buf++;
+		i2c_dev->msg_buf_remaining--;
+	}
+}
+
+static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 val;
+
+	for (;;) {
+		if (!i2c_dev->msg_buf_remaining)
+			return;
+		val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		if (!(val & BCM2835_I2C_S_RXD))
+			break;
+		*i2c_dev->msg_buf = bcm2835_i2c_readl(i2c_dev,
+						      BCM2835_I2C_FIFO);
+		i2c_dev->msg_buf++;
+		i2c_dev->msg_buf_remaining--;
+	}
+}
+
+static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+{
+	struct bcm2835_i2c_dev *i2c_dev = data;
+	u32 val, err;
+
+	val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
+
+	err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
+	if (err) {
+		i2c_dev->msg_err = err;
+		complete(&i2c_dev->completion);
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_RXD) {
+		bcm2835_drain_rxfifo(i2c_dev);
+		if (!(val & BCM2835_I2C_S_DONE))
+			return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_DONE) {
+		if (i2c_dev->msg_buf_remaining)
+			i2c_dev->msg_err = BCM2835_I2C_S_LEN;
+		else
+			i2c_dev->msg_err = 0;
+		complete(&i2c_dev->completion);
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_TXD) {
+		bcm2835_fill_txfifo(i2c_dev);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+				struct i2c_msg *msg)
+{
+	u32 c;
+	int ret;
+
+	i2c_dev->msg_buf = msg->buf;
+	i2c_dev->msg_buf_remaining = msg->len;
+	INIT_COMPLETION(i2c_dev->completion);
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+
+	if (msg->flags & I2C_M_RD) {
+		c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
+	} else {
+		c = BCM2835_I2C_C_INTT;
+		bcm2835_fill_txfifo(i2c_dev);
+	}
+	c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN;
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
+
+	ret = wait_for_completion_timeout(&i2c_dev->completion,
+					  BCM2835_I2C_TIMEOUT);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+	if (WARN_ON(ret == 0)) {
+		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	if (likely(!i2c_dev->msg_err))
+		return 0;
+
+	if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) &&
+	    (msg->flags & I2C_M_IGNORE_NAK))
+		return 0;
+
+	dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
+
+	if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
+		return -EREMOTEIO;
+	else
+		return -EIO;
+}
+
+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+			    int num)
+{
+	struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < num; i++) {
+		ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]);
+		if (ret)
+			break;
+	}
+
+	return ret ?: i;
+}
+
+static u32 bcm2835_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm bcm2835_i2c_algo = {
+	.master_xfer	= bcm2835_i2c_xfer,
+	.functionality	= bcm2835_i2c_func,
+};
+
+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;
+}
+
+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);
+
+MODULE_AUTHOR("Stephen Warren <swarren at wwwdotorg.org>");
+MODULE_DESCRIPTION("BCM2835 I2C bus adapter");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:i2c-bcm2835");
-- 
1.7.10.4



From swarren at wwwdotorg.org  Thu Jan  3 00:55:16 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed,  2 Jan 2013 22:55:16 -0700
Subject: [PATCH 1/6] clk: bcm2835: probe for fixed-clock in device tree
Message-ID: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>

This will allow fixed-clocks to be registered in device tree, which in
turn will allow clock clients to look up their clocks in device tree.
The first driver to use this feature will be the bcm2835 SDHCI/MMC
driver. In the long run, it is likely these fixed clocks will be
replaced with an actual clock implementation which speaks to the
VideoCore processor, but this change should be transparent to clock
consumers.

Cc: Mike Turquette <mturquette at linaro.org>
Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 drivers/clk/clk-bcm2835.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c
index e69991a..792bc57 100644
--- a/drivers/clk/clk-bcm2835.c
+++ b/drivers/clk/clk-bcm2835.c
@@ -20,6 +20,13 @@
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/bcm2835.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+
+static const __initconst struct of_device_id clk_match[] = {
+	{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+	{ }
+};
 
 /*
  * These are fixed clocks. They're probably not all root clocks and it may
@@ -56,4 +63,6 @@ void __init bcm2835_init_clocks(void)
 	ret = clk_register_clkdev(clk, NULL, "20215000.uart");
 	if (ret)
 		pr_err("uart1_pclk alias not registered\n");
+
+	of_clk_init(clk_match);
 }
-- 
1.7.10.4



From swarren at wwwdotorg.org  Thu Jan  3 00:55:17 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed,  2 Jan 2013 22:55:17 -0700
Subject: [PATCH 2/6] ARM: bcm2835: add a pm_power_off implementation
In-Reply-To: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
References: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1357192521-13025-2-git-send-email-swarren@wwwdotorg.org>

From: Dom Cobley <popcornmix at gmail.com>

Add a pm_power_off function that resets the SoC, and indicates to
bootcode.bin not to boot. Should allow a lower power 'off' state, even
if it's not really off.

This is commit 48efdd2 "Add a pm_power_off function that resets us, ..."
downstream.

Signed-off-by: Dom Cobley <popcornmix at gmail.com>
[swarren: Various non-semantic rework for upstreaming]
Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 arch/arm/mach-bcm2835/bcm2835.c |   28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
index f0d739f..c867d0e 100644
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -26,11 +26,13 @@
 #include <mach/bcm2835_soc.h>
 
 #define PM_RSTC				0x1c
+#define PM_RSTS				0x20
 #define PM_WDOG				0x24
 
 #define PM_PASSWORD			0x5a000000
 #define PM_RSTC_WRCFG_MASK		0x00000030
 #define PM_RSTC_WRCFG_FULL_RESET	0x00000020
+#define PM_RSTS_HADWRH_SET		0x00000040
 
 static void __iomem *wdt_regs;
 
@@ -67,6 +69,29 @@ static void bcm2835_restart(char mode, const char *cmd)
 	mdelay(1);
 }
 
+/*
+ * We can't really power off, but if we do the normal reset scheme, and
+ * indicate to bootcode.bin not to reboot, then most of the chip will be
+ * powered off.
+ */
+static void bcm2835_power_off(void)
+{
+	u32 val;
+
+	/*
+	 * We set the watchdog hard reset bit here to distinguish this reset
+	 * from the normal (full) reset. bootcode.bin will not reboot after a
+	 * hard reset.
+	 */
+	val = readl_relaxed(wdt_regs + PM_RSTS);
+	val &= ~PM_RSTC_WRCFG_MASK;
+	val |= PM_PASSWORD | PM_RSTS_HADWRH_SET;
+	writel_relaxed(val, wdt_regs + PM_RSTS);
+
+	/* Continue with normal reset mechanism */
+	bcm2835_restart(0, "");
+}
+
 static struct map_desc io_map __initdata = {
 	.virtual = BCM2835_PERIPH_VIRT,
 	.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
@@ -84,6 +109,9 @@ static void __init bcm2835_init(void)
 	int ret;
 
 	bcm2835_setup_restart();
+	if (wdt_regs)
+		pm_power_off = bcm2835_power_off;
+
 	bcm2835_init_clocks();
 
 	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
-- 
1.7.10.4



From swarren at wwwdotorg.org  Thu Jan  3 00:55:18 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed,  2 Jan 2013 22:55:18 -0700
Subject: [PATCH 3/6] ARM: bcm2835 rpi: remove hard-coded memreserve from DT
In-Reply-To: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
References: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1357192521-13025-3-git-send-email-swarren@wwwdotorg.org>

The Raspberry Pi has either 256MB or 512MB of RAM. However, a portion is
reserved for use by the VideoCore co-processor. The RPi DT contained a
/memreserve/ statement to reserve that RAM. However, the exact amount of
RAM used by the VideoCore is dynamic at boot-time; a firmware config
file specifies the amount. As such, we can't hard-code the size in the
DT. Remove the /memreserve/ statement. The bootloader is expected to
adjust the /memory properties to reflect the RAM size the ARM CPU can
use. Upstream U-Boot certainly does this, although I'm not sure that the
basic firmware does if it boots the kernel directly; users may need to
manually adjust their DT if not using U-Boot.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 arch/arm/boot/dts/bcm2835-rpi-b.dts |    1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index 9b72054..6ff26f9 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -1,5 +1,4 @@
 /dts-v1/;
-/memreserve/ 0x0c000000 0x04000000;
 /include/ "bcm2835.dtsi"
 
 / {
-- 
1.7.10.4



From swarren at wwwdotorg.org  Thu Jan  3 00:55:19 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed,  2 Jan 2013 22:55:19 -0700
Subject: [PATCH 4/6] ARM: bcm2835: add SDHCI node to DT
In-Reply-To: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
References: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1357192521-13025-4-git-send-email-swarren@wwwdotorg.org>

Add the SDHCI device node to the SoC DT file. Add a dummy fixed-clock
to satisfy the SDHCI driver's clock lookup; eventually this should be
replaced by a real clock implementation. Add board specific properties
to the Raspberry Pi board file.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 arch/arm/boot/dts/bcm2835-rpi-b.dts |    5 +++++
 arch/arm/boot/dts/bcm2835.dtsi      |   14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index 6ff26f9..0544ef8 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -24,3 +24,8 @@
 		brcm,function = <7>; /* alt3 */
 	};
 };
+
+&sdhci {
+	status = "okay";
+	bus-width = <4>;
+};
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index 8917550..1d7e4f5 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -63,5 +63,19 @@
 			interrupt-controller;
 			#interrupt-cells = <2>;
 		};
+
+		sdhci: sdhci {
+			compatible = "brcm,bcm2835-sdhci";
+			reg = <0x7e300000 0x100>;
+			interrupts = <2 30>;
+			clocks = <&clk_mmc>;
+			status = "disabled";
+		};
+	};
+
+	clk_mmc: clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
 	};
 };
-- 
1.7.10.4



From swarren at wwwdotorg.org  Thu Jan  3 00:55:20 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed,  2 Jan 2013 22:55:20 -0700
Subject: [PATCH 5/6] ARM: bcm2835: add I2C controllers to DT
In-Reply-To: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
References: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1357192521-13025-5-git-send-email-swarren@wwwdotorg.org>

The BCM2835 has 3 identical I2C controllers. Instantiate them all in the
SoC .dtsi file, and enable the relevant two in the Raspberry Pi board
.dts file.

Note that on the Raspberry Pi Model B revision 1, I2C0 is connected to
the general-purpose expansion header, and I2C1 is connected to the camera
connector. Revision 2 of the board swaps these assignments:-(

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 arch/arm/boot/dts/bcm2835-rpi-b.dts |   10 ++++++++++
 arch/arm/boot/dts/bcm2835.dtsi      |   22 ++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index 0544ef8..aafda17 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -25,6 +25,16 @@
 	};
 };
 
+&i2c0 {
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
 &sdhci {
 	status = "okay";
 	bus-width = <4>;
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index 1d7e4f5..c69a591 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -64,6 +64,22 @@
 			#interrupt-cells = <2>;
 		};
 
+		i2c0: i2c at 20205000 {
+			compatible = "brcm,bcm2835-i2c";
+			reg = <0x7e205000 0x1000>;
+			interrupts = <2 21>;
+			clocks = <&clk_i2c>;
+			status = "disabled";
+		};
+
+		i2c1: i2c at 20804000 {
+			compatible = "brcm,bcm2835-i2c";
+			reg = <0x7e804000 0x1000>;
+			interrupts = <2 21>;
+			clocks = <&clk_i2c>;
+			status = "disabled";
+		};
+
 		sdhci: sdhci {
 			compatible = "brcm,bcm2835-sdhci";
 			reg = <0x7e300000 0x100>;
@@ -73,6 +89,12 @@
 		};
 	};
 
+	clk_i2c: clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <150000000>;
+	};
+
 	clk_mmc: clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
-- 
1.7.10.4



From swarren at wwwdotorg.org  Thu Jan  3 00:55:21 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed,  2 Jan 2013 22:55:21 -0700
Subject: [PATCH 6/6] ARM: bcm2835: defconfig updates
In-Reply-To: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
References: <1357192521-13025-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1357192521-13025-6-git-send-email-swarren@wwwdotorg.org>

Now that we have an SDHCI driver, enable the block layer, and common
filesystems; MSDOS/VFAT for the SoC-required firmware partition, ext2/3/4
for a root partition.

Add tmpfs, NFS, file locking, file notify, networking, and NLS to support
distro expectations.

Enable GPIO_SYSFS to allow GPIO twiddling from user-space; likely a
common activity on this hardware.

Enable I2C.

Remove bogus CONFIG_DEFAULT_MMAP_MIN_ADDR so that applications running as
non-root actually work; without this, execve() immediately triggers
SIGKILL. This setting was sourced from some downstream defconfig early
during upstream Raspberry Pi support development.

Other non-semantic diffs due to rebuilding defconfig using the latest
Kconfig defaults etc.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 arch/arm/configs/bcm2835_defconfig |   43 +++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 74e27f0..af472e4 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -1,11 +1,10 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
@@ -30,13 +29,10 @@ CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_JUMP_LABEL=y
-# CONFIG_BLOCK is not set
 CONFIG_ARCH_BCM2835=y
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
-CONFIG_COMPACTION=y
 CONFIG_KSM=y
-CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
 CONFIG_CLEANCACHE=y
 CONFIG_SECCOMP=y
 CONFIG_CC_STACKPROTECTOR=y
@@ -45,6 +41,11 @@ CONFIG_CRASH_DUMP=y
 CONFIG_VFP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_NETWORK_SECMARK=y
+# CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
@@ -53,20 +54,42 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
-# CONFIG_UNIX98_PTYS is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_TTY_PRINTK=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_BCM2835=y
+CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2835=y
 # CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_FILE_LOCKING is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_FANOTIFY=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFSD=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
 CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-- 
1.7.10.4



From swarren at wwwdotorg.org  Thu Jan  3 22:55:27 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Thu,  3 Jan 2013 20:55:27 -0700
Subject: [PATCH] ARM: bcm2835: make use of CLKSRC_OF
Message-ID: <1357271727-2065-1-git-send-email-swarren@wwwdotorg.org>

Using CLKSRC_OF enables deletion of the SoC-specific header
bcm2835_timer.h, replacing the custom function bcm2835_timer_init() with
the standardized automatic clocksource_of_init().

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
This is based on my arm-timer-rework branch, for which I'll send a pull
request to arm-soc tomorrow.

 arch/arm/Kconfig                    |    1 +
 arch/arm/mach-bcm2835/bcm2835.c     |    4 ++--
 drivers/clocksource/bcm2835_timer.c |    5 +++--
 include/linux/bcm2835_timer.h       |   22 ----------------------
 4 files changed, 6 insertions(+), 26 deletions(-)
 delete mode 100644 include/linux/bcm2835_timer.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 91f8d78..2d274df 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -345,6 +345,7 @@ config ARCH_BCM2835
 	select ARM_ERRATA_411920
 	select ARM_TIMER_SP804
 	select CLKDEV_LOOKUP
+	select CLKSRC_OF
 	select COMMON_CLK
 	select CPU_V6
 	select GENERIC_CLOCKEVENTS
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
index 1a446a1..6f57859 100644
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -17,8 +17,8 @@
 #include <linux/irqchip/bcm2835.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
-#include <linux/bcm2835_timer.h>
 #include <linux/clk/bcm2835.h>
+#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -132,7 +132,7 @@ DT_MACHINE_START(BCM2835, "BCM2835")
 	.init_irq = bcm2835_init_irq,
 	.handle_irq = bcm2835_handle_irq,
 	.init_machine = bcm2835_init,
-	.init_time = bcm2835_timer_init,
+	.init_time = clocksource_of_init,
 	.restart = bcm2835_restart,
 	.dt_compat = bcm2835_compat
 MACHINE_END
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
index 7f796d8f..50c68fe 100644
--- a/drivers/clocksource/bcm2835_timer.c
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -16,7 +16,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/bcm2835_timer.h>
 #include <linux/bitops.h>
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
@@ -101,7 +100,7 @@ static struct of_device_id bcm2835_time_match[] __initconst = {
 	{}
 };
 
-void __init bcm2835_timer_init(void)
+static void __init bcm2835_timer_init(void)
 {
 	struct device_node *node;
 	void __iomem *base;
@@ -155,3 +154,5 @@ void __init bcm2835_timer_init(void)
 
 	pr_info("bcm2835: system timer (irq = %d)\n", irq);
 }
+CLOCKSOURCE_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",
+			bcm2835_timer_init);
diff --git a/include/linux/bcm2835_timer.h b/include/linux/bcm2835_timer.h
deleted file mode 100644
index ca17aa8..0000000
--- a/include/linux/bcm2835_timer.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2012 Simon Arlott
- *
- * 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.
- */
-
-#ifndef __BCM2835_TIMER_H
-#define __BCM2835_TIMER_H
-
-#include <asm/mach/time.h>
-
-extern void bcm2835_timer_init(void);
-
-#endif
-- 
1.7.10.4



From spartacus06 at gmail.com  Tue Jan  8 19:19:04 2013
From: spartacus06 at gmail.com (Seth Jennings)
Date: Tue, 8 Jan 2013 18:19:04 -0600
Subject: DWC2 OTG HS driver submitted
Message-ID: <CAG-w=x7GNc=OieY=Ykz60zuoUJBBVUQEUG9jLbbCsSDOYkOrOg@mail.gmail.com>

Just FYI, Paul Zimmerman posted an early driver (PCI only) for the
DWC2 OTG HS USB controller on the RPi.  I haven't tried yet, but it
would interesting to add platform/DT code to this and try it out on
the RPi.

http://thread.gmane.org/gmane.linux.usb.general/77041

Seth


From swarren at wwwdotorg.org  Wed Jan  9 11:49:15 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed, 09 Jan 2013 09:49:15 -0700
Subject: DWC2 OTG HS driver submitted
In-Reply-To: <CAG-w=x7GNc=OieY=Ykz60zuoUJBBVUQEUG9jLbbCsSDOYkOrOg@mail.gmail.com>
References: <CAG-w=x7GNc=OieY=Ykz60zuoUJBBVUQEUG9jLbbCsSDOYkOrOg@mail.gmail.com>
Message-ID: <50ED9F8B.4010501@wwwdotorg.org>

On 01/08/2013 05:19 PM, Seth Jennings wrote:
> Just FYI, Paul Zimmerman posted an early driver (PCI only) for the
> DWC2 OTG HS USB controller on the RPi.  I haven't tried yet, but it
> would interesting to add platform/DT code to this and try it out on
> the RPi.
> 
> http://thread.gmane.org/gmane.linux.usb.general/77041

FYI, I did hack together a platform driver wrapper, but it doesn't yet
work due to hanging during initialization, and I didn't have time to
look into why at all. This may be due to many factors e.g. I haven't
fully validated all the IP configuration parameters vs. the peripherals
PDF - I just did a very quick pass, and haven't even looked into the
BCM2835's extra registers mentioned in the PDF, nor tested after
explicitly powering on the IP block, although I guess it's on by default
etc. etc. At least the device ID register matches the HW, so there's a
chance it can be made to work!

git://github.com/swarren/linux-rpi.git rpi_usb


From cjb at laptop.org  Mon Jan 14 14:33:00 2013
From: cjb at laptop.org (Chris Ball)
Date: Mon, 14 Jan 2013 14:33:00 -0500
Subject: [PATCH] mmc: add BCM2835 driver
In-Reply-To: <1357191289-10455-1-git-send-email-swarren@wwwdotorg.org>
 (Stephen Warren's message of "Wed, 2 Jan 2013 22:34:49 -0700")
References: <1357191289-10455-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <871udntv9v.fsf@laptop.org>

Hi Stephen,

On Thu, Jan 03 2013, Stephen Warren wrote:
> Add a very simple driver for the BCM2835 SoC, which is used in the
> Raspberry Pi board.
>
> Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>

Looks good, thanks -- pushed to mmc-next for 3.9.

- Chris.
-- 
Chris Ball   <cjb at laptop.org>   <http://printf.net/>
One Laptop Per Child


From swarren at wwwdotorg.org  Mon Jan 14 23:25:06 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Mon, 14 Jan 2013 21:25:06 -0700
Subject: [PATCH V2] i2c: add bcm2835 driver
Message-ID: <1358223906-6566-1-git-send-email-swarren@wwwdotorg.org>

This implements a very basic I2C host driver for the BCM2835 SoC. Missing
features so far are:

* 10-bit addressing.
* DMA.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v2:
* Implemented clock divider configuration based on desired bus rate.
* Make use of module_platform_driver().
* Removed use of devinit.
---
 .../devicetree/bindings/i2c/brcm,bcm2835-i2c.txt   |   20 ++
 drivers/i2c/busses/Kconfig                         |   12 +
 drivers/i2c/busses/Makefile                        |    1 +
 drivers/i2c/busses/i2c-bcm2835.c                   |  346 ++++++++++++++++++++
 4 files changed, 379 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>;
+};
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index bdca511..5aab774 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -319,6 +319,18 @@ config I2C_AU1550
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-au1550.
 
+config I2C_BCM2835
+	tristate "Broadcom BCM2835 I2C controller"
+	depends on ARCH_BCM2835
+	help
+	  If you say yes to this option, support will be included for the
+	  BCM2835 I2C controller.
+
+	  If you don't know what to do here, say N.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-bcm2835.
+
 config I2C_BLACKFIN_TWI
 	tristate "Blackfin TWI I2C support"
 	depends on BLACKFIN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 6181f3f..a52a891 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
 # Embedded system I2C/SMBus host controller drivers
 obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
+obj-$(CONFIG_I2C_BCM2835)	+= i2c-bcm2835.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CBUS_GPIO)	+= i2c-cbus-gpio.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
new file mode 100644
index 0000000..22a29de
--- /dev/null
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -0,0 +1,346 @@
+/*
+ * BCM2835 master mode driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define BCM2835_I2C_C		0x0
+#define BCM2835_I2C_S		0x4
+#define BCM2835_I2C_DLEN	0x8
+#define BCM2835_I2C_A		0xc
+#define BCM2835_I2C_FIFO	0x10
+#define BCM2835_I2C_DIV		0x14
+#define BCM2835_I2C_DEL		0x18
+#define BCM2835_I2C_CLKT	0x1c
+
+#define BCM2835_I2C_C_READ	BIT(0)
+#define BCM2835_I2C_C_CLEAR	BIT(4) /* bits 4 and 5 both clear */
+#define BCM2835_I2C_C_ST	BIT(7)
+#define BCM2835_I2C_C_INTD	BIT(8)
+#define BCM2835_I2C_C_INTT	BIT(9)
+#define BCM2835_I2C_C_INTR	BIT(10)
+#define BCM2835_I2C_C_I2CEN	BIT(15)
+
+#define BCM2835_I2C_S_TA	BIT(0)
+#define BCM2835_I2C_S_DONE	BIT(1)
+#define BCM2835_I2C_S_TXW	BIT(2)
+#define BCM2835_I2C_S_RXR	BIT(3)
+#define BCM2835_I2C_S_TXD	BIT(4)
+#define BCM2835_I2C_S_RXD	BIT(5)
+#define BCM2835_I2C_S_TXE	BIT(6)
+#define BCM2835_I2C_S_RXF	BIT(7)
+#define BCM2835_I2C_S_ERR	BIT(8)
+#define BCM2835_I2C_S_CLKT	BIT(9)
+#define BCM2835_I2C_S_LEN	BIT(10) /* Fake bit for SW error reporting */
+
+#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000))
+
+struct bcm2835_i2c_dev {
+	struct device *dev;
+	void __iomem *regs;
+	struct clk *clk;
+	struct i2c_adapter adapter;
+	struct completion completion;
+	u32 msg_err;
+	u8 *msg_buf;
+	size_t msg_buf_remaining;
+};
+
+static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev,
+				      u32 reg, u32 val)
+{
+	writel(val, i2c_dev->regs + reg);
+}
+
+static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg)
+{
+	return readl(i2c_dev->regs + reg);
+}
+
+static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 val;
+
+	for (;;) {
+		if (!i2c_dev->msg_buf_remaining)
+			return;
+		val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		if (!(val & BCM2835_I2C_S_TXD))
+			break;
+		bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_FIFO,
+				   *i2c_dev->msg_buf);
+		i2c_dev->msg_buf++;
+		i2c_dev->msg_buf_remaining--;
+	}
+}
+
+static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 val;
+
+	for (;;) {
+		if (!i2c_dev->msg_buf_remaining)
+			return;
+		val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		if (!(val & BCM2835_I2C_S_RXD))
+			break;
+		*i2c_dev->msg_buf = bcm2835_i2c_readl(i2c_dev,
+						      BCM2835_I2C_FIFO);
+		i2c_dev->msg_buf++;
+		i2c_dev->msg_buf_remaining--;
+	}
+}
+
+static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+{
+	struct bcm2835_i2c_dev *i2c_dev = data;
+	u32 val, err;
+
+	val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
+
+	err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
+	if (err) {
+		i2c_dev->msg_err = err;
+		complete(&i2c_dev->completion);
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_RXD) {
+		bcm2835_drain_rxfifo(i2c_dev);
+		if (!(val & BCM2835_I2C_S_DONE))
+			return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_DONE) {
+		if (i2c_dev->msg_buf_remaining)
+			i2c_dev->msg_err = BCM2835_I2C_S_LEN;
+		else
+			i2c_dev->msg_err = 0;
+		complete(&i2c_dev->completion);
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_TXD) {
+		bcm2835_fill_txfifo(i2c_dev);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+				struct i2c_msg *msg)
+{
+	u32 c;
+	int ret;
+
+	i2c_dev->msg_buf = msg->buf;
+	i2c_dev->msg_buf_remaining = msg->len;
+	INIT_COMPLETION(i2c_dev->completion);
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+
+	if (msg->flags & I2C_M_RD) {
+		c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
+	} else {
+		c = BCM2835_I2C_C_INTT;
+		bcm2835_fill_txfifo(i2c_dev);
+	}
+	c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN;
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
+
+	ret = wait_for_completion_timeout(&i2c_dev->completion,
+					  BCM2835_I2C_TIMEOUT);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+	if (WARN_ON(ret == 0)) {
+		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	if (likely(!i2c_dev->msg_err))
+		return 0;
+
+	if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) &&
+	    (msg->flags & I2C_M_IGNORE_NAK))
+		return 0;
+
+	dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
+
+	if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
+		return -EREMOTEIO;
+	else
+		return -EIO;
+}
+
+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+			    int num)
+{
+	struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < num; i++) {
+		ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]);
+		if (ret)
+			break;
+	}
+
+	return ret ?: i;
+}
+
+static u32 bcm2835_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm bcm2835_i2c_algo = {
+	.master_xfer	= bcm2835_i2c_xfer,
+	.functionality	= bcm2835_i2c_func,
+};
+
+static int bcm2835_i2c_probe(struct platform_device *pdev)
+{
+	struct bcm2835_i2c_dev *i2c_dev;
+	struct resource *mem, *requested, *irq;
+	u32 bus_clk_rate, divider;
+	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;
+	}
+
+	i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(i2c_dev->clk)) {
+		dev_err(&pdev->dev, "Could not get clock\n");
+		return PTR_ERR(i2c_dev->clk);
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+				   &bus_clk_rate);
+	if (ret < 0) {
+		dev_warn(&pdev->dev,
+			 "Could not read clock-frequency property\n");
+		bus_clk_rate = 100000;
+	}
+
+	divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate);
+	/*
+	 * Per the datasheet, the register is always interpreted as an even
+	 * number, by rounding down. In other words, the LSB is ignored. So,
+	 * if the LSB is set, increment the divider to avoid any issue.
+	 */
+	if (divider & 1)
+		divider++;
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
+
+	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;
+}
+
+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,
+	},
+};
+module_platform_driver(bcm2835_i2c_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren at wwwdotorg.org>");
+MODULE_DESCRIPTION("BCM2835 I2C bus adapter");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:i2c-bcm2835");
-- 
1.7.10.4



From swarren at wwwdotorg.org  Mon Jan 14 23:26:50 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Mon, 14 Jan 2013 21:26:50 -0700
Subject: [PATCH] ARM: bcm2835: fix clock node aliasing in device tree
Message-ID: <1358224010-6619-1-git-send-email-swarren@wwwdotorg.org>

Both clock nodes in the current device tree are named "clock" and hence
end up being the same node. Rename the nodes to different names to avoid
this. In fact, fixed-clock uses the node name as the clock name, so name
the nodes after the clock they represent. Move the clocks into a
"clocks" sub-node to group them and avoid any possible naming conflicts
with other nodes also named after the device type.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 arch/arm/boot/dts/bcm2835.dtsi |   26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index c69a591..4bf2a87 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -89,15 +89,23 @@
 		};
 	};
 
-	clk_i2c: clock {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <150000000>;
-	};
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
 
-	clk_mmc: clock {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <100000000>;
+		clk_mmc: mmc {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <100000000>;
+		};
+
+		clk_i2c: i2c {
+			compatible = "fixed-clock";
+			reg = <1>;
+			#clock-cells = <0>;
+			clock-frequency = <150000000>;
+		};
 	};
 };
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 15 21:26:54 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 15 Jan 2013 19:26:54 -0700
Subject: [PATCH V5 REPOST 2/7] ARM: rpi_b: use bcm2835 mbox driver to get
 memory size
In-Reply-To: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
References: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1358303219-17503-2-git-send-email-swarren@wwwdotorg.org>

The firmware running on the bcm2835 SoC's VideoCore CPU determines how
much of the system RAM is available for use by the ARM CPU. Previously,
U-Boot assumed that only 128MB was available, since this was the
smallest value configured by any public firmware. However, we can now
query the actual value at run-time from the firmware using the mbox
property protocol.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v5: No change; merged patch series.
v4: No change; rebased.
v3: No change.
v2: Updated to use macros etc. added in v2 of mbox driver patch.
---
 board/raspberrypi/rpi_b/rpi_b.c |   21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/board/raspberrypi/rpi_b/rpi_b.c b/board/raspberrypi/rpi_b/rpi_b.c
index 688b0aa..3c654a1 100644
--- a/board/raspberrypi/rpi_b/rpi_b.c
+++ b/board/raspberrypi/rpi_b/rpi_b.c
@@ -15,13 +15,32 @@
  */
 
 #include <common.h>
+#include <asm/arch/mbox.h>
 #include <asm/global_data.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct msg_get_arm_mem {
+	struct bcm2835_mbox_hdr hdr;
+	struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
+	u32 end_tag;
+};
+
 int dram_init(void)
 {
-	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+	ALLOC_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1, 16);
+	int ret;
+
+	BCM2835_MBOX_INIT_HDR(msg);
+	BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY);
+
+	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
+	if (ret) {
+		printf("bcm2835: Could not query ARM memory size\n");
+		return -1;
+	}
+
+	gd->ram_size = msg->get_arm_mem.body.resp.mem_size;
 
 	return 0;
 }
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 15 21:26:56 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 15 Jan 2013 19:26:56 -0700
Subject: [PATCH V5 REPOST 4/7] ARM: rpi_b: disable rpi_b dcache explicitly
In-Reply-To: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
References: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1358303219-17503-4-git-send-email-swarren@wwwdotorg.org>

There appears to be no implementation of flush_dcache_range() for
ARM1176, so explicitly disable dcache support to avoid references to
that function from the LCD core in the next patch. This was presumably
not noticed before simply because no drivers for the rpi_b were
attempting DMA.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v5: No change; merged patch series.
v4: New patch.
---
 include/configs/rpi_b.h |    1 +
 1 file changed, 1 insertion(+)

diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index cf62e45..5db31f5 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -23,6 +23,7 @@
 #define CONFIG_ARM1176
 #define CONFIG_BCM2835
 #define CONFIG_ARCH_CPU_INIT
+#define CONFIG_SYS_DCACHE_OFF
 /*
  * 2835 is a SKU in a series for which the 2708 is the first or primary SoC,
  * so 2708 has historically been used rather than a dedicated 2835 ID.
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 15 21:26:53 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 15 Jan 2013 19:26:53 -0700
Subject: [PATCH V5 REPOST 1/7] ARM: bcm2835: add mailbox driver
Message-ID: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>

The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU")
and the ARM CPU. The ARM CPU is often thought of as the main CPU.
However, the VideoCore actually controls the initial SoC boot, and hides
much of the hardware behind a protocol. This protocol is transported
using the SoC's mailbox hardware module.

Here, we add a very simplistic driver for the mailbox module, and define
a few structures for the property messages.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
For some reason, none of these patches got picked up for v2013.01.

The video driver depends on new ARM/bcm2835 APIs added earlier, so it's
easiest to just merge it through the ARM tree. The patches have been ack'd
by Anatolij.

I believe the MMC driver itself doesn't depend on anything earlier, but
patch 7 which touches ARM/bcm2835 code and enables the MMC driver does depend
on the MMC driver, so it's probably easiest to just merge everything through
the ARM tree.

This series is based on v2013.01.

v5: No change; merged patch series.
v4: No change; rebased.
v3: Re-license to GPL-v2 or later.
v2:
* Added documentation to mbox.h.
* Implemented macros to set up headers and tags.
* Implemented error-checking of response bits in bcm2835_mbox_call_prop().
* Reworked tag structs based on experience writing LCD driver.
* Added a lot more video-related tag structs.
* Added debug spew and error messages to mbox.c; useful when debugging LCD.
* Removed __packed attributes from message structs.
* Removed stale FIXME comments.
---
 arch/arm/cpu/arm1176/bcm2835/Makefile    |    2 +-
 arch/arm/cpu/arm1176/bcm2835/mbox.c      |  164 ++++++++++++
 arch/arm/include/asm/arch-bcm2835/mbox.h |  407 ++++++++++++++++++++++++++++++
 3 files changed, 572 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/cpu/arm1176/bcm2835/mbox.c
 create mode 100644 arch/arm/include/asm/arch-bcm2835/mbox.h

diff --git a/arch/arm/cpu/arm1176/bcm2835/Makefile b/arch/arm/cpu/arm1176/bcm2835/Makefile
index 95da6a8..135de42 100644
--- a/arch/arm/cpu/arm1176/bcm2835/Makefile
+++ b/arch/arm/cpu/arm1176/bcm2835/Makefile
@@ -17,7 +17,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(SOC).o
 
 SOBJS	:= lowlevel_init.o
-COBJS	:= init.o reset.o timer.o
+COBJS	:= init.o reset.o timer.o mbox.o
 
 SRCS	:= $(SOBJS:.o=.c) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/arch/arm/cpu/arm1176/bcm2835/mbox.c b/arch/arm/cpu/arm1176/bcm2835/mbox.c
new file mode 100644
index 0000000..fd65e33
--- /dev/null
+++ b/arch/arm/cpu/arm1176/bcm2835/mbox.c
@@ -0,0 +1,164 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/mbox.h>
+
+#define TIMEOUT (100 * 1000) /* 100mS in uS */
+
+int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv)
+{
+	struct bcm2835_mbox_regs *regs =
+		(struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR;
+	ulong endtime = get_timer(0) + TIMEOUT;
+	u32 val;
+
+	debug("time: %lu timeout: %lu\n", get_timer(0), endtime);
+
+	if (send & BCM2835_CHAN_MASK) {
+		printf("mbox: Illegal mbox data 0x%08x\n", send);
+		return -1;
+	}
+
+	/* Drain any stale responses */
+
+	for (;;) {
+		val = readl(&regs->status);
+		if (val & BCM2835_MBOX_STATUS_RD_EMPTY)
+			break;
+		if (get_timer(0) >= endtime) {
+			printf("mbox: Timeout draining stale responses\n");
+			return -1;
+		}
+		val = readl(&regs->read);
+	}
+
+	/* Wait for space to send */
+
+	for (;;) {
+		val = readl(&regs->status);
+		if (!(val & BCM2835_MBOX_STATUS_WR_FULL))
+			break;
+		if (get_timer(0) >= endtime) {
+			printf("mbox: Timeout waiting for send space\n");
+			return -1;
+		}
+	}
+
+	/* Send the request */
+
+	val = BCM2835_MBOX_PACK(chan, send);
+	debug("mbox: TX raw: 0x%08x\n", val);
+	writel(val, &regs->write);
+
+	/* Wait for the response */
+
+	for (;;) {
+		val = readl(&regs->status);
+		if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY))
+			break;
+		if (get_timer(0) >= endtime) {
+			printf("mbox: Timeout waiting for response\n");
+			return -1;
+		}
+	}
+
+	/* Read the response */
+
+	val = readl(&regs->read);
+	debug("mbox: RX raw: 0x%08x\n", val);
+
+	/* Validate the response */
+
+	if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) {
+		printf("mbox: Response channel mismatch\n");
+		return -1;
+	}
+
+	*recv = BCM2835_MBOX_UNPACK_DATA(val);
+
+	return 0;
+}
+
+#ifdef DEBUG
+void dump_buf(struct bcm2835_mbox_hdr *buffer)
+{
+	u32 *p;
+	u32 words;
+	int i;
+
+	p = (u32 *)buffer;
+	words = buffer->buf_size / 4;
+	for (i = 0; i < words; i++)
+		printf("    0x%04x: 0x%08x\n", i * 4, p[i]);
+}
+#endif
+
+int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
+{
+	int ret;
+	u32 rbuffer;
+	struct bcm2835_mbox_tag_hdr *tag;
+	int tag_index;
+
+#ifdef DEBUG
+	printf("mbox: TX buffer\n");
+	dump_buf(buffer);
+#endif
+
+	ret = bcm2835_mbox_call_raw(chan, (u32)buffer, &rbuffer);
+	if (ret)
+		return ret;
+	if (rbuffer != (u32)buffer) {
+		printf("mbox: Response buffer mismatch\n");
+		return -1;
+	}
+
+#ifdef DEBUG
+	printf("mbox: RX buffer\n");
+	dump_buf(buffer);
+#endif
+
+	/* Validate overall response status */
+
+	if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) {
+		printf("mbox: Header response code invalid\n");
+		return -1;
+	}
+
+	/* Validate each tag's response status */
+
+	tag = (void *)(buffer + 1);
+	tag_index = 0;
+	while (tag->tag) {
+		if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) {
+			printf("mbox: Tag %d missing val_len response bit\n",
+				tag_index);
+			return -1;
+		}
+		/*
+		 * Clear the reponse bit so clients can just look right at the
+		 * length field without extra processing
+		 */
+		tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
+		tag = (void *)(((u8 *)tag) + sizeof(*tag) + tag->val_buf_size);
+		tag_index++;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h b/arch/arm/include/asm/arch-bcm2835/mbox.h
new file mode 100644
index 0000000..4752091
--- /dev/null
+++ b/arch/arm/include/asm/arch-bcm2835/mbox.h
@@ -0,0 +1,407 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ */
+
+#ifndef _BCM2835_MBOX_H
+#define _BCM2835_MBOX_H
+
+#include <linux/compiler.h>
+
+/*
+ * The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU")
+ * and the ARM CPU. The ARM CPU is often thought of as the main CPU.
+ * However, the VideoCore actually controls the initial SoC boot, and hides
+ * much of the hardware behind a protocol. This protocol is transported
+ * using the SoC's mailbox hardware module.
+ *
+ * The mailbox hardware supports passing 32-bit values back and forth.
+ * Presumably by software convention of the firmware, the bottom 4 bits of the
+ * value are used to indicate a logical channel, and the upper 28 bits are the
+ * actual payload. Various channels exist using these simple raw messages. See
+ * https://github.com/raspberrypi/firmware/wiki/Mailboxes for a list. As an
+ * example, the messages on the power management channel are a bitmask of
+ * devices whose power should be enabled.
+ *
+ * The property mailbox channel passes messages that contain the (16-byte
+ * aligned) ARM physical address of a memory buffer. This buffer is passed to
+ * the VC for processing, is modified in-place by the VC, and the address then
+ * passed back to the ARM CPU as the response mailbox message to indicate
+ * request completion. The buffers have a generic and extensible format; each
+ * buffer contains a standard header, a list of "tags", and a terminating zero
+ * entry. Each tag contains an ID indicating its type, and length fields for
+ * generic parsing. With some limitations, an arbitrary set of tags may be
+ * combined together into a single message buffer. This file defines structs
+ * representing the header and many individual tag layouts and IDs.
+ */
+
+/* Raw mailbox HW */
+
+#define BCM2835_MBOX_PHYSADDR	0x2000b880
+
+struct bcm2835_mbox_regs {
+	u32 read;
+	u32 rsvd0[5];
+	u32 status;
+	u32 config;
+	u32 write;
+};
+
+#define BCM2835_MBOX_STATUS_WR_FULL	0x80000000
+#define BCM2835_MBOX_STATUS_RD_EMPTY	0x40000000
+
+/* Lower 4-bits are channel ID */
+#define BCM2835_CHAN_MASK		0xf
+#define BCM2835_MBOX_PACK(chan, data)	(((data) & (~BCM2835_CHAN_MASK)) | \
+					 (chan & BCM2835_CHAN_MASK))
+#define BCM2835_MBOX_UNPACK_CHAN(val)	((val) & BCM2835_CHAN_MASK)
+#define BCM2835_MBOX_UNPACK_DATA(val)	((val) & (~BCM2835_CHAN_MASK))
+
+/* Property mailbox buffer structures */
+
+#define BCM2835_MBOX_PROP_CHAN		8
+
+/* All message buffers must start with this header */
+struct bcm2835_mbox_hdr {
+	u32 buf_size;
+	u32 code;
+};
+
+#define BCM2835_MBOX_REQ_CODE		0
+#define BCM2835_MBOX_RESP_CODE_SUCCESS	0x80000000
+
+#define BCM2835_MBOX_INIT_HDR(_m_) { \
+		memset((_m_), 0, sizeof(*(_m_))); \
+		(_m_)->hdr.buf_size = sizeof(*(_m_)); \
+		(_m_)->hdr.code = 0; \
+		(_m_)->end_tag = 0; \
+	}
+
+/*
+ * A message buffer contains a list of tags. Each tag must also start with
+ * a standardized header.
+ */
+struct bcm2835_mbox_tag_hdr {
+	u32 tag;
+	u32 val_buf_size;
+	u32 val_len;
+};
+
+#define BCM2835_MBOX_INIT_TAG(_t_, _id_) { \
+		(_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \
+		(_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \
+		(_t_)->tag_hdr.val_len = sizeof((_t_)->body.req); \
+	}
+
+#define BCM2835_MBOX_INIT_TAG_NO_REQ(_t_, _id_) { \
+		(_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \
+		(_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \
+		(_t_)->tag_hdr.val_len = 0; \
+	}
+
+/* When responding, the VC sets this bit in val_len to indicate a response */
+#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE	0x80000000
+
+/*
+ * Below we define the ID and struct for many possible tags. This header only
+ * defines individual tag structs, not entire message structs, since in
+ * general an arbitrary set of tags may be combined into a single message.
+ * Clients of the mbox API are expected to define their own overall message
+ * structures by combining the header, a set of tags, and a terminating
+ * entry. For example,
+ *
+ * struct msg {
+ *     struct bcm2835_mbox_hdr hdr;
+ *     struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
+ *     ... perhaps other tags here ...
+ *     u32 end_tag;
+ * };
+ */
+
+#define BCM2835_MBOX_TAG_GET_ARM_MEMORY		0x00010005
+
+struct bcm2835_mbox_tag_get_arm_mem {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+		} req;
+		struct {
+			u32 mem_base;
+			u32 mem_size;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER	0x00040001
+
+struct bcm2835_mbox_tag_allocate_buffer {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			u32 alignment;
+		} req;
+		struct {
+			u32 fb_address;
+			u32 fb_size;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_RELEASE_BUFFER		0x00048001
+
+struct bcm2835_mbox_tag_release_buffer {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+		} req;
+		struct {
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_BLANK_SCREEN		0x00040002
+
+struct bcm2835_mbox_tag_blank_screen {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			/* bit 0 means on, other bots reserved */
+			u32 state;
+		} req;
+		struct {
+			u32 state;
+		} resp;
+	} body;
+};
+
+/* Physical means output signal */
+#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H	0x00040003
+#define BCM2835_MBOX_TAG_TEST_PHYSICAL_W_H	0x00044003
+#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H	0x00048003
+
+struct bcm2835_mbox_tag_physical_w_h {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 width;
+			u32 height;
+		} req;
+		struct {
+			u32 width;
+			u32 height;
+		} resp;
+	} body;
+};
+
+/* Virtual means display buffer */
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H	0x00040004
+#define BCM2835_MBOX_TAG_TEST_VIRTUAL_W_H	0x00044004
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H	0x00048004
+
+struct bcm2835_mbox_tag_virtual_w_h {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 width;
+			u32 height;
+		} req;
+		struct {
+			u32 width;
+			u32 height;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_DEPTH		0x00040005
+#define BCM2835_MBOX_TAG_TEST_DEPTH		0x00044005
+#define BCM2835_MBOX_TAG_SET_DEPTH		0x00048005
+
+struct bcm2835_mbox_tag_depth {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 bpp;
+		} req;
+		struct {
+			u32 bpp;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PIXEL_ORDER	0x00040006
+#define BCM2835_MBOX_TAG_TEST_PIXEL_ORDER	0x00044005
+#define BCM2835_MBOX_TAG_SET_PIXEL_ORDER	0x00048006
+
+#define BCM2835_MBOX_PIXEL_ORDER_BGR		0
+#define BCM2835_MBOX_PIXEL_ORDER_RGB		1
+
+struct bcm2835_mbox_tag_pixel_order {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 order;
+		} req;
+		struct {
+			u32 order;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_ALPHA_MODE		0x00040007
+#define BCM2835_MBOX_TAG_TEST_ALPHA_MODE	0x00044007
+#define BCM2835_MBOX_TAG_SET_ALPHA_MODE		0x00048007
+
+#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE	0
+#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT	1
+#define BCM2835_MBOX_ALPHA_MODE_IGNORED		2
+
+struct bcm2835_mbox_tag_alpha_mode {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 alpha;
+		} req;
+		struct {
+			u32 alpha;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PITCH		0x00040008
+
+struct bcm2835_mbox_tag_pitch {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+		} req;
+		struct {
+			u32 pitch;
+		} resp;
+	} body;
+};
+
+/* Offset of display window within buffer */
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET	0x00040009
+#define BCM2835_MBOX_TAG_TEST_VIRTUAL_OFFSET	0x00044009
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET	0x00048009
+
+struct bcm2835_mbox_tag_virtual_offset {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 x;
+			u32 y;
+		} req;
+		struct {
+			u32 x;
+			u32 y;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_OVERSCAN		0x0004000a
+#define BCM2835_MBOX_TAG_TEST_OVERSCAN		0x0004400a
+#define BCM2835_MBOX_TAG_SET_OVERSCAN		0x0004800a
+
+struct bcm2835_mbox_tag_overscan {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 top;
+			u32 bottom;
+			u32 left;
+			u32 right;
+		} req;
+		struct {
+			u32 top;
+			u32 bottom;
+			u32 left;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PALETTE		0x0004000b
+
+struct bcm2835_mbox_tag_get_palette {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+		} req;
+		struct {
+			u32 data[1024];
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_TEST_PALETTE		0x0004400b
+
+struct bcm2835_mbox_tag_test_palette {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			u32 offset;
+			u32 num_entries;
+			u32 data[256];
+		} req;
+		struct {
+			u32 is_invalid;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_SET_PALETTE		0x0004800b
+
+struct bcm2835_mbox_tag_set_palette {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			u32 offset;
+			u32 num_entries;
+			u32 data[256];
+		} req;
+		struct {
+			u32 is_invalid;
+		} resp;
+	} body;
+};
+
+/*
+ * Pass a raw u32 message to the VC, and receive a raw u32 back.
+ *
+ * Returns 0 for success, any other value for error.
+ */
+int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv);
+
+/*
+ * Pass a complete property-style buffer to the VC, and wait until it has
+ * been processed.
+ *
+ * This function expects a pointer to the mbox_hdr structure in an attempt
+ * to ensure some degree of type safety. However, some number of tags and
+ * a termination value are expected to immediately follow the header in
+ * memory, as required by the property protocol.
+ *
+ * Returns 0 for success, any other value for error.
+ */
+int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer);
+
+#endif
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 15 21:26:55 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 15 Jan 2013 19:26:55 -0700
Subject: [PATCH V5 REPOST 3/7] lcd: calculate line_length after lcd_ctrl_init()
In-Reply-To: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
References: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1358303219-17503-3-git-send-email-swarren@wwwdotorg.org>

When an LCD driver is actually driving a regular external display, e.g.
an HDMI monitor, the display resolution might not be known until the
display controller has initialized, i.e. during lcd_ctrl_init(). However,
lcd.c calculates lcd_line_length before calling this function, thus
relying on a hard-coded resolution in struct panel_info.

Instead, defer this calculation until after lcd_ctrl_init() has had the
chance to dynamically determine the resolution. This needs to happen
before lcd_clear(), since the value is used there.

grep indicates that no code outside lcd.c uses this lcd_line_length; in
particular, no lcd_ctrl_init() implementations read it.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
Acked-by: Anatolij Gustschin <agust at denx.de>
--
v5: No change; merged patch series.
v4: Adjusted to addition of lcd_get_size() function. Rebased.
v3: No change.
---
 common/lcd.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/lcd.c b/common/lcd.c
index 66d4f94..9fa4e5c 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -384,8 +384,6 @@ int drv_lcd_init (void)
 
 	lcd_base = (void *)(gd->fb_base);
 
-	lcd_get_size(&lcd_line_length);
-
 	lcd_init(lcd_base);		/* LCD initialization */
 
 	/* Device initialization */
@@ -468,6 +466,8 @@ static int lcd_init(void *lcdbase)
 	debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
 
 	lcd_ctrl_init(lcdbase);
+	lcd_get_size(&lcd_line_length);
+	lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
 	lcd_is_enabled = 1;
 	lcd_clear();
 	lcd_enable ();
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 15 21:26:57 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 15 Jan 2013 19:26:57 -0700
Subject: [PATCH V5 REPOST 5/7] video: add a driver for the bcm2835
In-Reply-To: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
References: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1358303219-17503-5-git-send-email-swarren@wwwdotorg.org>

The firmware running on the bcm2835 SoC's VideoCore CPU manages the
display controller. Add a simple "LCD" driver that communicates with the
firmware using the property mailbox protocol. This configures the
display and frame-buffer to match whatever physical resolution the
firmware chosen when booting, which is typically the native resolution
of the attached display device, presumably unless otherwise specified
in config.txt on the boot media.

Enable this driver in the Raspberry Pi board configuration.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
Acked-by: Anatolij Gustschin <agust at denx.de>
---
v5: No change; merged patch series.
v4: No change; rebased.
v3: Re-license to GPL-v2 or later. Fix typo in commit description.
v2: New patch.
---
 drivers/video/Makefile  |    1 +
 drivers/video/bcm2835.c |  127 +++++++++++++++++++++++++++++++++++++++++++++++
 include/configs/rpi_b.h |   16 ++++++
 3 files changed, 144 insertions(+)
 create mode 100644 drivers/video/bcm2835.c

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 170a358..e8cecca 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_S6E63D6) += s6e63d6.o
 COBJS-$(CONFIG_LD9040) += ld9040.o
 COBJS-$(CONFIG_SED156X) += sed156x.o
 COBJS-$(CONFIG_VIDEO_AMBA) += amba.o
+COBJS-$(CONFIG_VIDEO_BCM2835) += bcm2835.o
 COBJS-$(CONFIG_VIDEO_COREBOOT) += coreboot_fb.o
 COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o
 COBJS-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
new file mode 100644
index 0000000..1e9a84a
--- /dev/null
+++ b/drivers/video/bcm2835.c
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <lcd.h>
+#include <asm/arch/mbox.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Global variables that lcd.c expects to exist */
+int lcd_line_length;
+int lcd_color_fg;
+int lcd_color_bg;
+void *lcd_base;
+void *lcd_console_address;
+short console_col;
+short console_row;
+vidinfo_t panel_info;
+char lcd_cursor_enabled;
+ushort lcd_cursor_width;
+ushort lcd_cursor_height;
+
+struct msg_query {
+	struct bcm2835_mbox_hdr hdr;
+	struct bcm2835_mbox_tag_physical_w_h physical_w_h;
+	u32 end_tag;
+};
+
+struct msg_setup {
+	struct bcm2835_mbox_hdr hdr;
+	struct bcm2835_mbox_tag_physical_w_h physical_w_h;
+	struct bcm2835_mbox_tag_virtual_w_h virtual_w_h;
+	struct bcm2835_mbox_tag_depth depth;
+	struct bcm2835_mbox_tag_pixel_order pixel_order;
+	struct bcm2835_mbox_tag_alpha_mode alpha_mode;
+	struct bcm2835_mbox_tag_virtual_offset virtual_offset;
+	struct bcm2835_mbox_tag_overscan overscan;
+	struct bcm2835_mbox_tag_allocate_buffer allocate_buffer;
+	u32 end_tag;
+};
+
+void lcd_ctrl_init(void *lcdbase)
+{
+	ALLOC_ALIGN_BUFFER(struct msg_query, msg_query, 1, 16);
+	ALLOC_ALIGN_BUFFER(struct msg_setup, msg_setup, 1, 16);
+	int ret;
+	u32 w, h;
+
+	debug("bcm2835: Query resolution...\n");
+
+	BCM2835_MBOX_INIT_HDR(msg_query);
+	BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h,
+					GET_PHYSICAL_W_H);
+	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr);
+	if (ret) {
+		printf("bcm2835: Could not query display resolution\n");
+		/* FIXME: How to disable the LCD to prevent errors? hang()? */
+		return;
+	}
+
+	w = msg_query->physical_w_h.body.resp.width;
+	h = msg_query->physical_w_h.body.resp.height;
+
+	debug("bcm2835: Setting up display for %d x %d\n", w, h);
+
+	BCM2835_MBOX_INIT_HDR(msg_setup);
+	BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H);
+	msg_setup->physical_w_h.body.req.width = w;
+	msg_setup->physical_w_h.body.req.height = h;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H);
+	msg_setup->virtual_w_h.body.req.width = w;
+	msg_setup->virtual_w_h.body.req.height = h;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH);
+	msg_setup->depth.body.req.bpp = 16;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER);
+	msg_setup->pixel_order.body.req.order = BCM2835_MBOX_PIXEL_ORDER_BGR;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE);
+	msg_setup->alpha_mode.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET);
+	msg_setup->virtual_offset.body.req.x = 0;
+	msg_setup->virtual_offset.body.req.y = 0;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN);
+	msg_setup->overscan.body.req.top = 0;
+	msg_setup->overscan.body.req.bottom = 0;
+	msg_setup->overscan.body.req.left = 0;
+	msg_setup->overscan.body.req.right = 0;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER);
+	msg_setup->allocate_buffer.body.req.alignment = 0x100;
+
+	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr);
+	if (ret) {
+		printf("bcm2835: Could not configure display\n");
+		/* FIXME: How to disable the LCD to prevent errors? hang()? */
+		return;
+	}
+
+	w = msg_setup->physical_w_h.body.resp.width;
+	h = msg_setup->physical_w_h.body.resp.height;
+
+	debug("bcm2835: Final resolution is %d x %d\n", w, h);
+
+	panel_info.vl_col = w;
+	panel_info.vl_row = h;
+	panel_info.vl_bpix = LCD_COLOR16;
+
+	gd->fb_base = msg_setup->allocate_buffer.body.resp.fb_address;
+	lcd_base = (void *)gd->fb_base;
+}
+
+void lcd_enable(void)
+{
+}
diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index 5db31f5..e485a06 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -58,6 +58,17 @@
 /* Devices */
 /* GPIO */
 #define CONFIG_BCM2835_GPIO
+/* LCD */
+#define CONFIG_LCD
+#define LCD_BPP				LCD_COLOR16
+/*
+ * Prevent allocation of RAM for FB; the real FB address is queried
+ * dynamically from the VideoCore co-processor, and comes from RAM
+ * not owned by the ARM CPU.
+ */
+#define CONFIG_FB_ADDR			0
+#define CONFIG_VIDEO_BCM2835
+#define CONFIG_SYS_WHITE_ON_BLACK
 
 /* Console UART */
 #define CONFIG_PL011_SERIAL
@@ -75,6 +86,11 @@
 #define CONFIG_ENV_SIZE			SZ_16K
 #define CONFIG_ENV_IS_NOWHERE
 #define CONFIG_SYS_LOAD_ADDR		0x1000000
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
+					"stderr=serial,lcd\0" \
+					"stdout=serial,lcd\0"
 
 /* Shell */
 #define CONFIG_SYS_HUSH_PARSER
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 15 21:26:58 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 15 Jan 2013 19:26:58 -0700
Subject: [PATCH V5 REPOST 6/7] mmc: add bcm2835 driver
In-Reply-To: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
References: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1358303219-17503-6-git-send-email-swarren@wwwdotorg.org>

This adds a simple driver for the BCM2835's SD controller.

Workarounds are implemented for:
* Register writes can't be too close to each-other in time, or they will
  be lost.
* Register accesses must all be 32-bit, so implement custom accessors.

This code was extracted from:
git://github.com/gonzoua/u-boot-pi.git master
which was created by Oleksandr Tymoshenko.

Portions of the code there were obviously based on the Linux kernel at:
git://github.com/raspberrypi/linux.git rpi-3.6.y
commit f5b930b "Main bcm2708 linux port" signed-off-by Dom Cobley.

swarren changed the following for upstream:
* Removed hack udelay()s in bcm2835_sdhci_raw_writel(); setting
  SDHCI_QUIRK_WAIT_SEND_CMD appears to solve the issues.
* Remove register logging from read*/write* functions.
* Sort out confusion with min/max_freq values passed to add_sdhci().
* Use more descriptive variable names and calculations in IO accessors.
* Simplified and commented twoticks_delay calculation.
* checkpatch fixes.

Cc: Andy Fleming <afleming at gmail.com>
Signed-off-by: Oleksandr Tymoshenko <gonzo at bluezbox.com>
Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
Andy, could you please ack this so Albert can take it through the ARM tree;
patch 7/7 depends is an ARM patch and depends on this. Thanks.

v5: Invent struct bcm2835_sdhci_host to avoid static/global variables.
v4:
* Merged with video patch series due to dependencies in rpi_b.h.
* Rebased onto latest u-boot-arm/master; no real changes.
v3: No such version was posted.
v2:
* Use more descriptive variable names and calculations in IO accessors.
* Add Oleksandr's S-o-b.
* Rewrite commit description to note that the Linux code this was derived
  from was S-o-b Dom Cobley.
---
 arch/arm/include/asm/arch-bcm2835/sdhci.h |   24 ++++
 drivers/mmc/Makefile                      |    1 +
 drivers/mmc/bcm2835_sdhci.c               |  189 +++++++++++++++++++++++++++++
 3 files changed, 214 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-bcm2835/sdhci.h
 create mode 100644 drivers/mmc/bcm2835_sdhci.c

diff --git a/arch/arm/include/asm/arch-bcm2835/sdhci.h b/arch/arm/include/asm/arch-bcm2835/sdhci.h
new file mode 100644
index 0000000..a4f867b
--- /dev/null
+++ b/arch/arm/include/asm/arch-bcm2835/sdhci.h
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _BCM2835_SDHCI_H_
+#define _BCM2835_SDHCI_H_
+
+#define BCM2835_SDHCI_BASE 0x20300000
+
+int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq);
+
+#endif
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 65791aa..1d6faa2 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -43,6 +43,7 @@ COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o
 COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
 COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
 COBJS-$(CONFIG_SDHCI) += sdhci.o
+COBJS-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o
 COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
 COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
new file mode 100644
index 0000000..b0afc3c
--- /dev/null
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -0,0 +1,189 @@
+/*
+ * This code was extracted from:
+ * git://github.com/gonzoua/u-boot-pi.git master
+ * and hence presumably (C) 2012 Oleksandr Tymoshenko
+ *
+ * Tweaks for U-Boot upstreaming
+ * (C) 2012 Stephen Warren
+ *
+ * Portions (e.g. read/write macros, concepts for back-to-back register write
+ * timing workarounds) obviously extracted from the Linux kernel at:
+ * https://github.com/raspberrypi/linux.git rpi-3.6.y
+ *
+ * The Linux kernel code has the following (c) and license, which is hence
+ * propagated to Oleksandr's tree and here:
+ *
+ * Support for SDHCI device on 2835
+ * Based on sdhci-bcm2708.c (c) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * SDHCI platform device - Arasan SD controller in BCM2708
+ *
+ * Inspired by sdhci-pci.c, by Pierre Ossman
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <sdhci.h>
+
+/* 400KHz is max freq for card ID etc. Use that as min */
+#define MIN_FREQ 400000
+
+struct bcm2835_sdhci_host {
+	struct sdhci_host host;
+	uint twoticks_delay;
+	ulong last_write;
+};
+
+static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host)
+{
+	return (struct bcm2835_sdhci_host *)host;
+}
+
+static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val,
+						int reg)
+{
+	struct bcm2835_sdhci_host *bcm_host = to_bcm(host);
+
+	/*
+	 * The Arasan has a bugette whereby it may lose the content of
+	 * successive writes to registers that are within two SD-card clock
+	 * cycles of each other (a clock domain crossing problem).
+	 * It seems, however, that the data register does not have this problem.
+	 * (Which is just as well - otherwise we'd have to nobble the DMA engine
+	 * too)
+	 */
+	while (get_timer(bcm_host->last_write) < bcm_host->twoticks_delay)
+		;
+
+	writel(val, host->ioaddr + reg);
+	bcm_host->last_write = get_timer(0);
+}
+
+static inline u32 bcm2835_sdhci_raw_readl(struct sdhci_host *host, int reg)
+{
+	return readl(host->ioaddr + reg);
+}
+
+static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
+{
+	bcm2835_sdhci_raw_writel(host, val, reg);
+}
+
+static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
+{
+	static u32 shadow;
+	u32 oldval = (reg == SDHCI_COMMAND) ? shadow :
+		bcm2835_sdhci_raw_readl(host, reg & ~3);
+	u32 word_num = (reg >> 1) & 1;
+	u32 word_shift = word_num * 16;
+	u32 mask = 0xffff << word_shift;
+	u32 newval = (oldval & ~mask) | (val << word_shift);
+
+	if (reg == SDHCI_TRANSFER_MODE)
+		shadow = newval;
+	else
+		bcm2835_sdhci_raw_writel(host, newval, reg & ~3);
+}
+
+static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+	u32 oldval = bcm2835_sdhci_raw_readl(host, reg & ~3);
+	u32 byte_num = reg & 3;
+	u32 byte_shift = byte_num * 8;
+	u32 mask = 0xff << byte_shift;
+	u32 newval = (oldval & ~mask) | (val << byte_shift);
+
+	bcm2835_sdhci_raw_writel(host, newval, reg & ~3);
+}
+
+static u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg)
+{
+	u32 val = bcm2835_sdhci_raw_readl(host, reg);
+
+	return val;
+}
+
+static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg)
+{
+	u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3));
+	u32 word_num = (reg >> 1) & 1;
+	u32 word_shift = word_num * 16;
+	u32 word = (val >> word_shift) & 0xffff;
+
+	return word;
+}
+
+static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
+{
+	u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3));
+	u32 byte_num = reg & 3;
+	u32 byte_shift = byte_num * 8;
+	u32 byte = (val >> byte_shift) & 0xff;
+
+	return byte;
+}
+
+static const struct sdhci_ops bcm2835_ops = {
+	.write_l = bcm2835_sdhci_writel,
+	.write_w = bcm2835_sdhci_writew,
+	.write_b = bcm2835_sdhci_writeb,
+	.read_l = bcm2835_sdhci_readl,
+	.read_w = bcm2835_sdhci_readw,
+	.read_b = bcm2835_sdhci_readb,
+};
+
+int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq)
+{
+	struct bcm2835_sdhci_host *bcm_host;
+	struct sdhci_host *host;
+
+	bcm_host = malloc(sizeof(*bcm_host));
+	if (!bcm_host) {
+		printf("sdhci_host malloc fail!\n");
+		return 1;
+	}
+
+	/*
+	 * See the comments in bcm2835_sdhci_raw_writel().
+	 *
+	 * This should probably be dynamically calculated based on the actual
+	 * frequency. However, this is the longest we'll have to wait, and
+	 * doesn't seem to slow access down too much, so the added complexity
+	 * doesn't seem worth it for now.
+	 *
+	 * 1/MIN_FREQ is (max) time per tick of eMMC clock.
+	 * 2/MIN_FREQ is time for two ticks.
+	 * Multiply by 1000000 to get uS per two ticks.
+	 * +1 for hack rounding.
+	 */
+	bcm_host->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1;
+	bcm_host->last_write = 0;
+
+	host = &bcm_host->host;
+	host->name = "bcm2835_sdhci";
+	host->ioaddr = (void *)regbase;
+	host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B |
+		SDHCI_QUIRK_WAIT_SEND_CMD;
+	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+	host->ops = &bcm2835_ops;
+
+	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+	add_sdhci(host, emmc_freq, MIN_FREQ);
+
+	return 0;
+}
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 15 21:26:59 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 15 Jan 2013 19:26:59 -0700
Subject: [PATCH V5 REPOST 7/7] ARM: rpi_b: enable SD controller,
 add related env/cmds
In-Reply-To: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
References: <1358303219-17503-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1358303219-17503-7-git-send-email-swarren@wwwdotorg.org>

Enable the SD controller driver for the Raspberry Pi. Enable a number
of useful MMC, partition, and filesystem-related commands. Set up the
environment to provide standard locations for loading a kernel, DTB,
etc. Provide a boot command that loads and executes boot.scr.uimg from
the SD card; this is written considering future extensibilty to USB
storage.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v5: No change.
v4:
* Merged with video patch series due to dependencies in rpi_b.h.
* Rebased onto latest u-boot-arm/master; no real changes.
v3: No such version was posted.
v2: No change.
---
 arch/arm/include/asm/arch-bcm2835/mbox.h |   26 ++++++++++++
 board/raspberrypi/rpi_b/rpi_b.c          |   26 ++++++++++++
 include/configs/rpi_b.h                  |   68 ++++++++++++++++++++++++++++--
 3 files changed, 117 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h b/arch/arm/include/asm/arch-bcm2835/mbox.h
index 4752091..b07c4a0 100644
--- a/arch/arm/include/asm/arch-bcm2835/mbox.h
+++ b/arch/arm/include/asm/arch-bcm2835/mbox.h
@@ -144,6 +144,32 @@ struct bcm2835_mbox_tag_get_arm_mem {
 	} body;
 };
 
+#define BCM2835_MBOX_TAG_GET_CLOCK_RATE	0x00030002
+
+#define BCM2835_MBOX_CLOCK_ID_EMMC	1
+#define BCM2835_MBOX_CLOCK_ID_UART	2
+#define BCM2835_MBOX_CLOCK_ID_ARM	3
+#define BCM2835_MBOX_CLOCK_ID_CORE	4
+#define BCM2835_MBOX_CLOCK_ID_V3D	5
+#define BCM2835_MBOX_CLOCK_ID_H264	6
+#define BCM2835_MBOX_CLOCK_ID_ISP	7
+#define BCM2835_MBOX_CLOCK_ID_SDRAM	8
+#define BCM2835_MBOX_CLOCK_ID_PIXEL	9
+#define BCM2835_MBOX_CLOCK_ID_PWM	10
+
+struct bcm2835_mbox_tag_get_clock_rate {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			u32 clock_id;
+		} req;
+		struct {
+			u32 clock_id;
+			u32 rate_hz;
+		} resp;
+	} body;
+};
+
 #define BCM2835_MBOX_TAG_ALLOCATE_BUFFER	0x00040001
 
 struct bcm2835_mbox_tag_allocate_buffer {
diff --git a/board/raspberrypi/rpi_b/rpi_b.c b/board/raspberrypi/rpi_b/rpi_b.c
index 3c654a1..6b3e095 100644
--- a/board/raspberrypi/rpi_b/rpi_b.c
+++ b/board/raspberrypi/rpi_b/rpi_b.c
@@ -16,6 +16,7 @@
 
 #include <common.h>
 #include <asm/arch/mbox.h>
+#include <asm/arch/sdhci.h>
 #include <asm/global_data.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -26,6 +27,12 @@ struct msg_get_arm_mem {
 	u32 end_tag;
 };
 
+struct msg_get_clock_rate {
+	struct bcm2835_mbox_hdr hdr;
+	struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
+	u32 end_tag;
+};
+
 int dram_init(void)
 {
 	ALLOC_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1, 16);
@@ -51,3 +58,22 @@ int board_init(void)
 
 	return 0;
 }
+
+int board_mmc_init(void)
+{
+	ALLOC_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1, 16);
+	int ret;
+
+	BCM2835_MBOX_INIT_HDR(msg_clk);
+	BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE);
+	msg_clk->get_clock_rate.body.req.clock_id = BCM2835_MBOX_CLOCK_ID_EMMC;
+
+	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_clk->hdr);
+	if (ret) {
+		printf("bcm2835: Could not query eMMC clock rate\n");
+		return -1;
+	}
+
+	return bcm2835_sdhci_init(BCM2835_SDHCI_BASE,
+				  msg_clk->get_clock_rate.body.resp.rate_hz);
+}
diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index e485a06..3d55d36 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -51,6 +51,7 @@
 #define CONFIG_SYS_MALLOC_LEN		SZ_4M
 #define CONFIG_SYS_MEMTEST_START	0x00100000
 #define CONFIG_SYS_MEMTEST_END		0x00200000
+#define CONFIG_LOADADDR			0x00200000
 
 /* Flash */
 #define CONFIG_SYS_NO_FLASH
@@ -70,6 +71,13 @@
 #define CONFIG_VIDEO_BCM2835
 #define CONFIG_SYS_WHITE_ON_BLACK
 
+/* SD/MMC configuration */
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC
+#define CONFIG_SDHCI
+#define CONFIG_MMC_SDHCI_IO_ACCESSORS
+#define CONFIG_BCM2835_SDHCI
+
 /* Console UART */
 #define CONFIG_PL011_SERIAL
 #define CONFIG_PL011_CLOCK		3000000
@@ -85,12 +93,59 @@
 /* Environment */
 #define CONFIG_ENV_SIZE			SZ_16K
 #define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_VARS_UBOOT_CONFIG
 #define CONFIG_SYS_LOAD_ADDR		0x1000000
 #define CONFIG_CONSOLE_MUX
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
-					"stderr=serial,lcd\0" \
-					"stdout=serial,lcd\0"
+/*
+ * Memory layout for where various images get loaded by boot scripts:
+ *
+ * scriptaddr can be pretty much anywhere that doesn't conflict with something
+ *   else. Put it low in memory to avoid conflicts.
+ *
+ * kernel_addr_r must be within the first 128M of RAM in order for the
+ *   kernel's CONFIG_AUTO_ZRELADDR option to work. Since the kernel will
+ *   decompress itself to 0x8000 after the start of RAM, kernel_addr_r
+ *   should not overlap that area, or the kernel will have to copy itself
+ *   somewhere else before decompression. Similarly, the address of any other
+ *   data passed to the kernel shouldn't overlap the start of RAM. Pushing
+ *   this up to 16M allows for a sizable kernel to be decompressed below the
+ *   compressed load address.
+ *
+ * fdt_addr_r simply shouldn't overlap anything else. Choosing 32M allows for
+ *   the compressed kernel to be up to 16M too.
+ *
+ * ramdisk_addr_r simply shouldn't overlap anything else. Choosing 33M allows
+ *   for the FDT/DTB to be up to 1M, which is hopefully plenty.
+ */
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"stdin=serial\0" \
+	"stderr=serial,lcd\0" \
+	"stdout=serial,lcd\0" \
+	"scriptaddr=0x00000000\0" \
+	"kernel_addr_r=0x01000000\0" \
+	"fdt_addr_r=0x02000000\0" \
+	"ramdisk_addr_r=0x02100000\0" \
+	"boot_targets=mmc0\0" \
+	\
+	"script_boot=" \
+		"if fatload ${devtype} ${devnum}:1 " \
+					"${scriptaddr} boot.scr.uimg; then " \
+			"source ${scriptaddr}; " \
+		"fi;\0" \
+	\
+	"mmc_boot=" \
+		"setenv devtype mmc; " \
+		"if mmc dev ${devnum}; then " \
+			"run script_boot; " \
+		"fi\0" \
+	\
+	"bootcmd_mmc0=setenv devnum 0; run mmc_boot\0" \
+
+#define CONFIG_BOOTCOMMAND \
+	"for target in ${boot_targets}; do run bootcmd_${target}; done"
+
+#define CONFIG_BOOTDELAY		2
 
 /* Shell */
 #define CONFIG_SYS_HUSH_PARSER
@@ -105,6 +160,13 @@
 #include <config_cmd_default.h>
 #define CONFIG_CMD_BOOTZ
 #define CONFIG_CMD_GPIO
+#define CONFIG_CMD_MMC
+#define CONFIG_DOS_PARTITION
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_CMD_PART
+#define CONFIG_CMD_FS_GENERIC
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT
 /* Some things don't make sense on this HW or yet */
 #undef CONFIG_CMD_FPGA
 #undef CONFIG_CMD_NET
-- 
1.7.10.4



From protectools2 at qq.com  Mon Jan 21 17:06:16 2013
From: protectools2 at qq.com (Diamond segments Supply)
Date: Mon, 21 Jan 2013 22:06:16 +0000
Subject: =?GB2312?B?RGlhbW9uZCBzZWdtZW50cyBTdXBwbHnT68T6ubLP7cHL1dXGrA==?=
Message-ID: <90e6ba3fd86591497a04d3d3ab1a@google.com>

Dear Sir,

Now we are very gald to inform you that we have a promotion for our Diamond  
Segments with attractive price and good cutting speed with long life.
We can supply different grit of : 20# to 300# , and soft to hard bond for  
different purpose.
These segments are used for HTC PAD, HUSQVARNA PAD and other type of  
Grinding cup wheel .

Please check the ATTACHED PICTURE.If you need any diamond segments in other  
size,please kindly send us the Length,Width and Height for your diamond  
segments,we will make the good quotation for you soon!

If you have any other inquiry for diamond tools,please kindly send us,we  
will give you competitive price to support you!

I am looking forward to seeing your early reply,thanks for your time!

Have a good day!

Best Regards!

selina wang
PROTEC TOOLS CO.,LTD
Add: No24 Lane 99 Xinzhe east road,Fengxian,Shanghai,China 201424
-------------- next part --------------
A non-text attachment was scrubbed...
Name: QQ??20130109212555.jpg
Type: image/jpeg
Size: 21893 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rpi-kernel/attachments/20130121/eca553f6/attachment.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 2.jpg
Type: image/jpeg
Size: 38739 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rpi-kernel/attachments/20130121/eca553f6/attachment-0001.jpg>

From protectools2 at qq.com  Tue Jan 22 06:06:17 2013
From: protectools2 at qq.com (Diamond segments Supply)
Date: Tue, 22 Jan 2013 11:06:17 +0000
Subject: =?GB2312?B?RGlhbW9uZCBzZWdtZW50cyBTdXBwbHnT68T6ubLP7cHL1dXGrA==?=
Message-ID: <bcaec51017af1fbeaf04d3de918b@google.com>

Dear Sir,

Now we are very gald to inform you that we have a promotion for our Diamond  
Segments with attractive price and good cutting speed with long life.
We can supply different grit of : 20# to 300# , and soft to hard bond for  
different purpose.
These segments are used for HTC PAD, HUSQVARNA PAD and other type of  
Grinding cup wheel .

Please check the ATTACHED PICTURE.If you need any diamond segments in other  
size,please kindly send us the Length,Width and Height for your diamond  
segments,we will make the good quotation for you soon!

If you have any other inquiry for diamond tools,please kindly send us,we  
will give you competitive price to support you!

I am looking forward to seeing your early reply,thanks for your time!

Have a good day!

Best Regards!

selina wang
PROTEC TOOLS CO.,LTD
Add: No24 Lane 99 Xinzhe east road,Fengxian,Shanghai,China 201424
-------------- next part --------------
A non-text attachment was scrubbed...
Name: QQ??20130109212555.jpg
Type: image/jpeg
Size: 21893 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rpi-kernel/attachments/20130122/4716d5b4/attachment.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 2.jpg
Type: image/jpeg
Size: 38739 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rpi-kernel/attachments/20130122/4716d5b4/attachment-0001.jpg>

From swarren at wwwdotorg.org  Tue Jan 29 00:22:56 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Mon, 28 Jan 2013 22:22:56 -0700
Subject: [PATCH V2 REPOST] i2c: add bcm2835 driver
Message-ID: <1359436976-20437-1-git-send-email-swarren@wwwdotorg.org>

This implements a very basic I2C host driver for the BCM2835 SoC. Missing
features so far are:

* 10-bit addressing.
* DMA.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v2:
* Implemented clock divider configuration based on desired bus rate.
* Make use of module_platform_driver().
* Removed use of devinit.
---
 .../devicetree/bindings/i2c/brcm,bcm2835-i2c.txt   |   20 ++
 drivers/i2c/busses/Kconfig                         |   12 +
 drivers/i2c/busses/Makefile                        |    1 +
 drivers/i2c/busses/i2c-bcm2835.c                   |  346 ++++++++++++++++++++
 4 files changed, 379 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>;
+};
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 8bb810e..3cc40ab 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -319,6 +319,18 @@ config I2C_AU1550
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-au1550.
 
+config I2C_BCM2835
+	tristate "Broadcom BCM2835 I2C controller"
+	depends on ARCH_BCM2835
+	help
+	  If you say yes to this option, support will be included for the
+	  BCM2835 I2C controller.
+
+	  If you don't know what to do here, say N.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-bcm2835.
+
 config I2C_BLACKFIN_TWI
 	tristate "Blackfin TWI I2C support"
 	depends on BLACKFIN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 6181f3f..a52a891 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
 # Embedded system I2C/SMBus host controller drivers
 obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
+obj-$(CONFIG_I2C_BCM2835)	+= i2c-bcm2835.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CBUS_GPIO)	+= i2c-cbus-gpio.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
new file mode 100644
index 0000000..22a29de
--- /dev/null
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -0,0 +1,346 @@
+/*
+ * BCM2835 master mode driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define BCM2835_I2C_C		0x0
+#define BCM2835_I2C_S		0x4
+#define BCM2835_I2C_DLEN	0x8
+#define BCM2835_I2C_A		0xc
+#define BCM2835_I2C_FIFO	0x10
+#define BCM2835_I2C_DIV		0x14
+#define BCM2835_I2C_DEL		0x18
+#define BCM2835_I2C_CLKT	0x1c
+
+#define BCM2835_I2C_C_READ	BIT(0)
+#define BCM2835_I2C_C_CLEAR	BIT(4) /* bits 4 and 5 both clear */
+#define BCM2835_I2C_C_ST	BIT(7)
+#define BCM2835_I2C_C_INTD	BIT(8)
+#define BCM2835_I2C_C_INTT	BIT(9)
+#define BCM2835_I2C_C_INTR	BIT(10)
+#define BCM2835_I2C_C_I2CEN	BIT(15)
+
+#define BCM2835_I2C_S_TA	BIT(0)
+#define BCM2835_I2C_S_DONE	BIT(1)
+#define BCM2835_I2C_S_TXW	BIT(2)
+#define BCM2835_I2C_S_RXR	BIT(3)
+#define BCM2835_I2C_S_TXD	BIT(4)
+#define BCM2835_I2C_S_RXD	BIT(5)
+#define BCM2835_I2C_S_TXE	BIT(6)
+#define BCM2835_I2C_S_RXF	BIT(7)
+#define BCM2835_I2C_S_ERR	BIT(8)
+#define BCM2835_I2C_S_CLKT	BIT(9)
+#define BCM2835_I2C_S_LEN	BIT(10) /* Fake bit for SW error reporting */
+
+#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000))
+
+struct bcm2835_i2c_dev {
+	struct device *dev;
+	void __iomem *regs;
+	struct clk *clk;
+	struct i2c_adapter adapter;
+	struct completion completion;
+	u32 msg_err;
+	u8 *msg_buf;
+	size_t msg_buf_remaining;
+};
+
+static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev,
+				      u32 reg, u32 val)
+{
+	writel(val, i2c_dev->regs + reg);
+}
+
+static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg)
+{
+	return readl(i2c_dev->regs + reg);
+}
+
+static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 val;
+
+	for (;;) {
+		if (!i2c_dev->msg_buf_remaining)
+			return;
+		val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		if (!(val & BCM2835_I2C_S_TXD))
+			break;
+		bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_FIFO,
+				   *i2c_dev->msg_buf);
+		i2c_dev->msg_buf++;
+		i2c_dev->msg_buf_remaining--;
+	}
+}
+
+static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 val;
+
+	for (;;) {
+		if (!i2c_dev->msg_buf_remaining)
+			return;
+		val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		if (!(val & BCM2835_I2C_S_RXD))
+			break;
+		*i2c_dev->msg_buf = bcm2835_i2c_readl(i2c_dev,
+						      BCM2835_I2C_FIFO);
+		i2c_dev->msg_buf++;
+		i2c_dev->msg_buf_remaining--;
+	}
+}
+
+static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+{
+	struct bcm2835_i2c_dev *i2c_dev = data;
+	u32 val, err;
+
+	val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
+
+	err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
+	if (err) {
+		i2c_dev->msg_err = err;
+		complete(&i2c_dev->completion);
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_RXD) {
+		bcm2835_drain_rxfifo(i2c_dev);
+		if (!(val & BCM2835_I2C_S_DONE))
+			return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_DONE) {
+		if (i2c_dev->msg_buf_remaining)
+			i2c_dev->msg_err = BCM2835_I2C_S_LEN;
+		else
+			i2c_dev->msg_err = 0;
+		complete(&i2c_dev->completion);
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_TXD) {
+		bcm2835_fill_txfifo(i2c_dev);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+				struct i2c_msg *msg)
+{
+	u32 c;
+	int ret;
+
+	i2c_dev->msg_buf = msg->buf;
+	i2c_dev->msg_buf_remaining = msg->len;
+	INIT_COMPLETION(i2c_dev->completion);
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+
+	if (msg->flags & I2C_M_RD) {
+		c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
+	} else {
+		c = BCM2835_I2C_C_INTT;
+		bcm2835_fill_txfifo(i2c_dev);
+	}
+	c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN;
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
+
+	ret = wait_for_completion_timeout(&i2c_dev->completion,
+					  BCM2835_I2C_TIMEOUT);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+	if (WARN_ON(ret == 0)) {
+		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	if (likely(!i2c_dev->msg_err))
+		return 0;
+
+	if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) &&
+	    (msg->flags & I2C_M_IGNORE_NAK))
+		return 0;
+
+	dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
+
+	if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
+		return -EREMOTEIO;
+	else
+		return -EIO;
+}
+
+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+			    int num)
+{
+	struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < num; i++) {
+		ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]);
+		if (ret)
+			break;
+	}
+
+	return ret ?: i;
+}
+
+static u32 bcm2835_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm bcm2835_i2c_algo = {
+	.master_xfer	= bcm2835_i2c_xfer,
+	.functionality	= bcm2835_i2c_func,
+};
+
+static int bcm2835_i2c_probe(struct platform_device *pdev)
+{
+	struct bcm2835_i2c_dev *i2c_dev;
+	struct resource *mem, *requested, *irq;
+	u32 bus_clk_rate, divider;
+	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;
+	}
+
+	i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(i2c_dev->clk)) {
+		dev_err(&pdev->dev, "Could not get clock\n");
+		return PTR_ERR(i2c_dev->clk);
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+				   &bus_clk_rate);
+	if (ret < 0) {
+		dev_warn(&pdev->dev,
+			 "Could not read clock-frequency property\n");
+		bus_clk_rate = 100000;
+	}
+
+	divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate);
+	/*
+	 * Per the datasheet, the register is always interpreted as an even
+	 * number, by rounding down. In other words, the LSB is ignored. So,
+	 * if the LSB is set, increment the divider to avoid any issue.
+	 */
+	if (divider & 1)
+		divider++;
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
+
+	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;
+}
+
+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,
+	},
+};
+module_platform_driver(bcm2835_i2c_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren at wwwdotorg.org>");
+MODULE_DESCRIPTION("BCM2835 I2C bus adapter");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:i2c-bcm2835");
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 01:42:19 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Mon, 28 Jan 2013 23:42:19 -0700
Subject: [GIT PULL 1/4] ARM: bcm2835: cleanup
Message-ID: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>

This pull request simply converts the bcm2835 clocksource driver to use
the recently added CLKSRC_OF feature.

The branch is based on v3.8-rc3, followed by a merge of arm-soc's
timer/cleanup branch.

(For this and pull 4/4, feel free to cherry-pick the one commit if you
want to avoid the short pull requests!)

----------------------------------------------------------------

The following changes since commit b2fc382aad0a8f52803acdc3ac4e5540dbcdf1f6:

  Merge remote-tracking branch 'korg_arm-soc/timer/cleanup' into cleanup

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-cleanup

for you to fetch changes up to c1b724f6659a7e9e32f8fcf6409d053e1b7bccad:

  ARM: bcm2835: make use of CLKSRC_OF

----------------------------------------------------------------

Stephen Warren (1):
      ARM: bcm2835: make use of CLKSRC_OF

 arch/arm/Kconfig                    |    1 +
 arch/arm/mach-bcm2835/bcm2835.c     |    4 ++--
 drivers/clocksource/bcm2835_timer.c |    5 +++--
 include/linux/bcm2835_timer.h       |   22 ----------------------
 4 files changed, 6 insertions(+), 26 deletions(-)
 delete mode 100644 include/linux/bcm2835_timer.h


From olof at lixom.net  Tue Jan 29 12:58:53 2013
From: olof at lixom.net (Olof Johansson)
Date: Tue, 29 Jan 2013 09:58:53 -0800
Subject: [GIT PULL 1/4] ARM: bcm2835: cleanup
In-Reply-To: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>
References: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <20130129175853.GD17935@quad.lixom.net>

On Mon, Jan 28, 2013 at 11:42:19PM -0700, Stephen Warren wrote:
> This pull request simply converts the bcm2835 clocksource driver to use
> the recently added CLKSRC_OF feature.
> 
> The branch is based on v3.8-rc3, followed by a merge of arm-soc's
> timer/cleanup branch.
> 
> (For this and pull 4/4, feel free to cherry-pick the one commit if you
> want to avoid the short pull requests!)
> 
> ----------------------------------------------------------------
> 
> The following changes since commit b2fc382aad0a8f52803acdc3ac4e5540dbcdf1f6:
> 
>   Merge remote-tracking branch 'korg_arm-soc/timer/cleanup' into cleanup
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-cleanup

Thanks, pulled branch 1-4.


-Olof


From swarren at wwwdotorg.org  Tue Jan 29 21:37:38 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 19:37:38 -0700
Subject: [PATCH V5 REPOST 2 3/7] lcd: calculate line_length after
 lcd_ctrl_init()
In-Reply-To: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
References: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359513462-10941-3-git-send-email-swarren@wwwdotorg.org>

When an LCD driver is actually driving a regular external display, e.g.
an HDMI monitor, the display resolution might not be known until the
display controller has initialized, i.e. during lcd_ctrl_init(). However,
lcd.c calculates lcd_line_length before calling this function, thus
relying on a hard-coded resolution in struct panel_info.

Instead, defer this calculation until after lcd_ctrl_init() has had the
chance to dynamically determine the resolution. This needs to happen
before lcd_clear(), since the value is used there.

grep indicates that no code outside lcd.c uses this lcd_line_length; in
particular, no lcd_ctrl_init() implementations read it.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
Acked-by: Anatolij Gustschin <agust at denx.de>
--
v5: No change; merged patch series.
v4: Adjusted to addition of lcd_get_size() function. Rebased.
v3: No change.
---
 common/lcd.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/lcd.c b/common/lcd.c
index 66d4f94..9fa4e5c 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -384,8 +384,6 @@ int drv_lcd_init (void)
 
 	lcd_base = (void *)(gd->fb_base);
 
-	lcd_get_size(&lcd_line_length);
-
 	lcd_init(lcd_base);		/* LCD initialization */
 
 	/* Device initialization */
@@ -468,6 +466,8 @@ static int lcd_init(void *lcdbase)
 	debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
 
 	lcd_ctrl_init(lcdbase);
+	lcd_get_size(&lcd_line_length);
+	lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
 	lcd_is_enabled = 1;
 	lcd_clear();
 	lcd_enable ();
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 21:37:37 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 19:37:37 -0700
Subject: [PATCH V5 REPOST 2 2/7] ARM: rpi_b: use bcm2835 mbox driver to get
 memory size
In-Reply-To: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
References: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359513462-10941-2-git-send-email-swarren@wwwdotorg.org>

The firmware running on the bcm2835 SoC's VideoCore CPU determines how
much of the system RAM is available for use by the ARM CPU. Previously,
U-Boot assumed that only 128MB was available, since this was the
smallest value configured by any public firmware. However, we can now
query the actual value at run-time from the firmware using the mbox
property protocol.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v5: No change; merged patch series.
v4: No change; rebased.
v3: No change.
v2: Updated to use macros etc. added in v2 of mbox driver patch.
---
 board/raspberrypi/rpi_b/rpi_b.c |   21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/board/raspberrypi/rpi_b/rpi_b.c b/board/raspberrypi/rpi_b/rpi_b.c
index 688b0aa..3c654a1 100644
--- a/board/raspberrypi/rpi_b/rpi_b.c
+++ b/board/raspberrypi/rpi_b/rpi_b.c
@@ -15,13 +15,32 @@
  */
 
 #include <common.h>
+#include <asm/arch/mbox.h>
 #include <asm/global_data.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct msg_get_arm_mem {
+	struct bcm2835_mbox_hdr hdr;
+	struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
+	u32 end_tag;
+};
+
 int dram_init(void)
 {
-	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+	ALLOC_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1, 16);
+	int ret;
+
+	BCM2835_MBOX_INIT_HDR(msg);
+	BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY);
+
+	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
+	if (ret) {
+		printf("bcm2835: Could not query ARM memory size\n");
+		return -1;
+	}
+
+	gd->ram_size = msg->get_arm_mem.body.resp.mem_size;
 
 	return 0;
 }
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 21:37:39 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 19:37:39 -0700
Subject: [PATCH V5 REPOST 2 4/7] ARM: rpi_b: disable rpi_b dcache explicitly
In-Reply-To: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
References: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359513462-10941-4-git-send-email-swarren@wwwdotorg.org>

There appears to be no implementation of flush_dcache_range() for
ARM1176, so explicitly disable dcache support to avoid references to
that function from the LCD core in the next patch. This was presumably
not noticed before simply because no drivers for the rpi_b were
attempting DMA.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v5: No change; merged patch series.
v4: New patch.
---
 include/configs/rpi_b.h |    1 +
 1 file changed, 1 insertion(+)

diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index cf62e45..5db31f5 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -23,6 +23,7 @@
 #define CONFIG_ARM1176
 #define CONFIG_BCM2835
 #define CONFIG_ARCH_CPU_INIT
+#define CONFIG_SYS_DCACHE_OFF
 /*
  * 2835 is a SKU in a series for which the 2708 is the first or primary SoC,
  * so 2708 has historically been used rather than a dedicated 2835 ID.
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 21:37:40 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 19:37:40 -0700
Subject: [PATCH V5 REPOST 2 5/7] video: add a driver for the bcm2835
In-Reply-To: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
References: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359513462-10941-5-git-send-email-swarren@wwwdotorg.org>

The firmware running on the bcm2835 SoC's VideoCore CPU manages the
display controller. Add a simple "LCD" driver that communicates with the
firmware using the property mailbox protocol. This configures the
display and frame-buffer to match whatever physical resolution the
firmware chosen when booting, which is typically the native resolution
of the attached display device, presumably unless otherwise specified
in config.txt on the boot media.

Enable this driver in the Raspberry Pi board configuration.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
Acked-by: Anatolij Gustschin <agust at denx.de>
---
v5: No change; merged patch series.
v4: No change; rebased.
v3: Re-license to GPL-v2 or later. Fix typo in commit description.
v2: New patch.
---
 drivers/video/Makefile  |    1 +
 drivers/video/bcm2835.c |  127 +++++++++++++++++++++++++++++++++++++++++++++++
 include/configs/rpi_b.h |   16 ++++++
 3 files changed, 144 insertions(+)
 create mode 100644 drivers/video/bcm2835.c

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 170a358..e8cecca 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_S6E63D6) += s6e63d6.o
 COBJS-$(CONFIG_LD9040) += ld9040.o
 COBJS-$(CONFIG_SED156X) += sed156x.o
 COBJS-$(CONFIG_VIDEO_AMBA) += amba.o
+COBJS-$(CONFIG_VIDEO_BCM2835) += bcm2835.o
 COBJS-$(CONFIG_VIDEO_COREBOOT) += coreboot_fb.o
 COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o
 COBJS-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
new file mode 100644
index 0000000..1e9a84a
--- /dev/null
+++ b/drivers/video/bcm2835.c
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <lcd.h>
+#include <asm/arch/mbox.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Global variables that lcd.c expects to exist */
+int lcd_line_length;
+int lcd_color_fg;
+int lcd_color_bg;
+void *lcd_base;
+void *lcd_console_address;
+short console_col;
+short console_row;
+vidinfo_t panel_info;
+char lcd_cursor_enabled;
+ushort lcd_cursor_width;
+ushort lcd_cursor_height;
+
+struct msg_query {
+	struct bcm2835_mbox_hdr hdr;
+	struct bcm2835_mbox_tag_physical_w_h physical_w_h;
+	u32 end_tag;
+};
+
+struct msg_setup {
+	struct bcm2835_mbox_hdr hdr;
+	struct bcm2835_mbox_tag_physical_w_h physical_w_h;
+	struct bcm2835_mbox_tag_virtual_w_h virtual_w_h;
+	struct bcm2835_mbox_tag_depth depth;
+	struct bcm2835_mbox_tag_pixel_order pixel_order;
+	struct bcm2835_mbox_tag_alpha_mode alpha_mode;
+	struct bcm2835_mbox_tag_virtual_offset virtual_offset;
+	struct bcm2835_mbox_tag_overscan overscan;
+	struct bcm2835_mbox_tag_allocate_buffer allocate_buffer;
+	u32 end_tag;
+};
+
+void lcd_ctrl_init(void *lcdbase)
+{
+	ALLOC_ALIGN_BUFFER(struct msg_query, msg_query, 1, 16);
+	ALLOC_ALIGN_BUFFER(struct msg_setup, msg_setup, 1, 16);
+	int ret;
+	u32 w, h;
+
+	debug("bcm2835: Query resolution...\n");
+
+	BCM2835_MBOX_INIT_HDR(msg_query);
+	BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h,
+					GET_PHYSICAL_W_H);
+	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr);
+	if (ret) {
+		printf("bcm2835: Could not query display resolution\n");
+		/* FIXME: How to disable the LCD to prevent errors? hang()? */
+		return;
+	}
+
+	w = msg_query->physical_w_h.body.resp.width;
+	h = msg_query->physical_w_h.body.resp.height;
+
+	debug("bcm2835: Setting up display for %d x %d\n", w, h);
+
+	BCM2835_MBOX_INIT_HDR(msg_setup);
+	BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H);
+	msg_setup->physical_w_h.body.req.width = w;
+	msg_setup->physical_w_h.body.req.height = h;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H);
+	msg_setup->virtual_w_h.body.req.width = w;
+	msg_setup->virtual_w_h.body.req.height = h;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH);
+	msg_setup->depth.body.req.bpp = 16;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER);
+	msg_setup->pixel_order.body.req.order = BCM2835_MBOX_PIXEL_ORDER_BGR;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE);
+	msg_setup->alpha_mode.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET);
+	msg_setup->virtual_offset.body.req.x = 0;
+	msg_setup->virtual_offset.body.req.y = 0;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN);
+	msg_setup->overscan.body.req.top = 0;
+	msg_setup->overscan.body.req.bottom = 0;
+	msg_setup->overscan.body.req.left = 0;
+	msg_setup->overscan.body.req.right = 0;
+	BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER);
+	msg_setup->allocate_buffer.body.req.alignment = 0x100;
+
+	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr);
+	if (ret) {
+		printf("bcm2835: Could not configure display\n");
+		/* FIXME: How to disable the LCD to prevent errors? hang()? */
+		return;
+	}
+
+	w = msg_setup->physical_w_h.body.resp.width;
+	h = msg_setup->physical_w_h.body.resp.height;
+
+	debug("bcm2835: Final resolution is %d x %d\n", w, h);
+
+	panel_info.vl_col = w;
+	panel_info.vl_row = h;
+	panel_info.vl_bpix = LCD_COLOR16;
+
+	gd->fb_base = msg_setup->allocate_buffer.body.resp.fb_address;
+	lcd_base = (void *)gd->fb_base;
+}
+
+void lcd_enable(void)
+{
+}
diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index 5db31f5..e485a06 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -58,6 +58,17 @@
 /* Devices */
 /* GPIO */
 #define CONFIG_BCM2835_GPIO
+/* LCD */
+#define CONFIG_LCD
+#define LCD_BPP				LCD_COLOR16
+/*
+ * Prevent allocation of RAM for FB; the real FB address is queried
+ * dynamically from the VideoCore co-processor, and comes from RAM
+ * not owned by the ARM CPU.
+ */
+#define CONFIG_FB_ADDR			0
+#define CONFIG_VIDEO_BCM2835
+#define CONFIG_SYS_WHITE_ON_BLACK
 
 /* Console UART */
 #define CONFIG_PL011_SERIAL
@@ -75,6 +86,11 @@
 #define CONFIG_ENV_SIZE			SZ_16K
 #define CONFIG_ENV_IS_NOWHERE
 #define CONFIG_SYS_LOAD_ADDR		0x1000000
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
+					"stderr=serial,lcd\0" \
+					"stdout=serial,lcd\0"
 
 /* Shell */
 #define CONFIG_SYS_HUSH_PARSER
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 21:37:36 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 19:37:36 -0700
Subject: [PATCH V5 REPOST 2 1/7] ARM: bcm2835: add mailbox driver
Message-ID: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>

The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU")
and the ARM CPU. The ARM CPU is often thought of as the main CPU.
However, the VideoCore actually controls the initial SoC boot, and hides
much of the hardware behind a protocol. This protocol is transported
using the SoC's mailbox hardware module.

Here, we add a very simplistic driver for the mailbox module, and define
a few structures for the property messages.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v5: No change; merged patch series.
v4: No change; rebased.
v3: Re-license to GPL-v2 or later.
v2:
* Added documentation to mbox.h.
* Implemented macros to set up headers and tags.
* Implemented error-checking of response bits in bcm2835_mbox_call_prop().
* Reworked tag structs based on experience writing LCD driver.
* Added a lot more video-related tag structs.
* Added debug spew and error messages to mbox.c; useful when debugging LCD.
* Removed __packed attributes from message structs.
* Removed stale FIXME comments.
---
 arch/arm/cpu/arm1176/bcm2835/Makefile    |    2 +-
 arch/arm/cpu/arm1176/bcm2835/mbox.c      |  164 ++++++++++++
 arch/arm/include/asm/arch-bcm2835/mbox.h |  407 ++++++++++++++++++++++++++++++
 3 files changed, 572 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/cpu/arm1176/bcm2835/mbox.c
 create mode 100644 arch/arm/include/asm/arch-bcm2835/mbox.h

diff --git a/arch/arm/cpu/arm1176/bcm2835/Makefile b/arch/arm/cpu/arm1176/bcm2835/Makefile
index 95da6a8..135de42 100644
--- a/arch/arm/cpu/arm1176/bcm2835/Makefile
+++ b/arch/arm/cpu/arm1176/bcm2835/Makefile
@@ -17,7 +17,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(SOC).o
 
 SOBJS	:= lowlevel_init.o
-COBJS	:= init.o reset.o timer.o
+COBJS	:= init.o reset.o timer.o mbox.o
 
 SRCS	:= $(SOBJS:.o=.c) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/arch/arm/cpu/arm1176/bcm2835/mbox.c b/arch/arm/cpu/arm1176/bcm2835/mbox.c
new file mode 100644
index 0000000..fd65e33
--- /dev/null
+++ b/arch/arm/cpu/arm1176/bcm2835/mbox.c
@@ -0,0 +1,164 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/mbox.h>
+
+#define TIMEOUT (100 * 1000) /* 100mS in uS */
+
+int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv)
+{
+	struct bcm2835_mbox_regs *regs =
+		(struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR;
+	ulong endtime = get_timer(0) + TIMEOUT;
+	u32 val;
+
+	debug("time: %lu timeout: %lu\n", get_timer(0), endtime);
+
+	if (send & BCM2835_CHAN_MASK) {
+		printf("mbox: Illegal mbox data 0x%08x\n", send);
+		return -1;
+	}
+
+	/* Drain any stale responses */
+
+	for (;;) {
+		val = readl(&regs->status);
+		if (val & BCM2835_MBOX_STATUS_RD_EMPTY)
+			break;
+		if (get_timer(0) >= endtime) {
+			printf("mbox: Timeout draining stale responses\n");
+			return -1;
+		}
+		val = readl(&regs->read);
+	}
+
+	/* Wait for space to send */
+
+	for (;;) {
+		val = readl(&regs->status);
+		if (!(val & BCM2835_MBOX_STATUS_WR_FULL))
+			break;
+		if (get_timer(0) >= endtime) {
+			printf("mbox: Timeout waiting for send space\n");
+			return -1;
+		}
+	}
+
+	/* Send the request */
+
+	val = BCM2835_MBOX_PACK(chan, send);
+	debug("mbox: TX raw: 0x%08x\n", val);
+	writel(val, &regs->write);
+
+	/* Wait for the response */
+
+	for (;;) {
+		val = readl(&regs->status);
+		if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY))
+			break;
+		if (get_timer(0) >= endtime) {
+			printf("mbox: Timeout waiting for response\n");
+			return -1;
+		}
+	}
+
+	/* Read the response */
+
+	val = readl(&regs->read);
+	debug("mbox: RX raw: 0x%08x\n", val);
+
+	/* Validate the response */
+
+	if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) {
+		printf("mbox: Response channel mismatch\n");
+		return -1;
+	}
+
+	*recv = BCM2835_MBOX_UNPACK_DATA(val);
+
+	return 0;
+}
+
+#ifdef DEBUG
+void dump_buf(struct bcm2835_mbox_hdr *buffer)
+{
+	u32 *p;
+	u32 words;
+	int i;
+
+	p = (u32 *)buffer;
+	words = buffer->buf_size / 4;
+	for (i = 0; i < words; i++)
+		printf("    0x%04x: 0x%08x\n", i * 4, p[i]);
+}
+#endif
+
+int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
+{
+	int ret;
+	u32 rbuffer;
+	struct bcm2835_mbox_tag_hdr *tag;
+	int tag_index;
+
+#ifdef DEBUG
+	printf("mbox: TX buffer\n");
+	dump_buf(buffer);
+#endif
+
+	ret = bcm2835_mbox_call_raw(chan, (u32)buffer, &rbuffer);
+	if (ret)
+		return ret;
+	if (rbuffer != (u32)buffer) {
+		printf("mbox: Response buffer mismatch\n");
+		return -1;
+	}
+
+#ifdef DEBUG
+	printf("mbox: RX buffer\n");
+	dump_buf(buffer);
+#endif
+
+	/* Validate overall response status */
+
+	if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) {
+		printf("mbox: Header response code invalid\n");
+		return -1;
+	}
+
+	/* Validate each tag's response status */
+
+	tag = (void *)(buffer + 1);
+	tag_index = 0;
+	while (tag->tag) {
+		if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) {
+			printf("mbox: Tag %d missing val_len response bit\n",
+				tag_index);
+			return -1;
+		}
+		/*
+		 * Clear the reponse bit so clients can just look right at the
+		 * length field without extra processing
+		 */
+		tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
+		tag = (void *)(((u8 *)tag) + sizeof(*tag) + tag->val_buf_size);
+		tag_index++;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h b/arch/arm/include/asm/arch-bcm2835/mbox.h
new file mode 100644
index 0000000..4752091
--- /dev/null
+++ b/arch/arm/include/asm/arch-bcm2835/mbox.h
@@ -0,0 +1,407 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ */
+
+#ifndef _BCM2835_MBOX_H
+#define _BCM2835_MBOX_H
+
+#include <linux/compiler.h>
+
+/*
+ * The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU")
+ * and the ARM CPU. The ARM CPU is often thought of as the main CPU.
+ * However, the VideoCore actually controls the initial SoC boot, and hides
+ * much of the hardware behind a protocol. This protocol is transported
+ * using the SoC's mailbox hardware module.
+ *
+ * The mailbox hardware supports passing 32-bit values back and forth.
+ * Presumably by software convention of the firmware, the bottom 4 bits of the
+ * value are used to indicate a logical channel, and the upper 28 bits are the
+ * actual payload. Various channels exist using these simple raw messages. See
+ * https://github.com/raspberrypi/firmware/wiki/Mailboxes for a list. As an
+ * example, the messages on the power management channel are a bitmask of
+ * devices whose power should be enabled.
+ *
+ * The property mailbox channel passes messages that contain the (16-byte
+ * aligned) ARM physical address of a memory buffer. This buffer is passed to
+ * the VC for processing, is modified in-place by the VC, and the address then
+ * passed back to the ARM CPU as the response mailbox message to indicate
+ * request completion. The buffers have a generic and extensible format; each
+ * buffer contains a standard header, a list of "tags", and a terminating zero
+ * entry. Each tag contains an ID indicating its type, and length fields for
+ * generic parsing. With some limitations, an arbitrary set of tags may be
+ * combined together into a single message buffer. This file defines structs
+ * representing the header and many individual tag layouts and IDs.
+ */
+
+/* Raw mailbox HW */
+
+#define BCM2835_MBOX_PHYSADDR	0x2000b880
+
+struct bcm2835_mbox_regs {
+	u32 read;
+	u32 rsvd0[5];
+	u32 status;
+	u32 config;
+	u32 write;
+};
+
+#define BCM2835_MBOX_STATUS_WR_FULL	0x80000000
+#define BCM2835_MBOX_STATUS_RD_EMPTY	0x40000000
+
+/* Lower 4-bits are channel ID */
+#define BCM2835_CHAN_MASK		0xf
+#define BCM2835_MBOX_PACK(chan, data)	(((data) & (~BCM2835_CHAN_MASK)) | \
+					 (chan & BCM2835_CHAN_MASK))
+#define BCM2835_MBOX_UNPACK_CHAN(val)	((val) & BCM2835_CHAN_MASK)
+#define BCM2835_MBOX_UNPACK_DATA(val)	((val) & (~BCM2835_CHAN_MASK))
+
+/* Property mailbox buffer structures */
+
+#define BCM2835_MBOX_PROP_CHAN		8
+
+/* All message buffers must start with this header */
+struct bcm2835_mbox_hdr {
+	u32 buf_size;
+	u32 code;
+};
+
+#define BCM2835_MBOX_REQ_CODE		0
+#define BCM2835_MBOX_RESP_CODE_SUCCESS	0x80000000
+
+#define BCM2835_MBOX_INIT_HDR(_m_) { \
+		memset((_m_), 0, sizeof(*(_m_))); \
+		(_m_)->hdr.buf_size = sizeof(*(_m_)); \
+		(_m_)->hdr.code = 0; \
+		(_m_)->end_tag = 0; \
+	}
+
+/*
+ * A message buffer contains a list of tags. Each tag must also start with
+ * a standardized header.
+ */
+struct bcm2835_mbox_tag_hdr {
+	u32 tag;
+	u32 val_buf_size;
+	u32 val_len;
+};
+
+#define BCM2835_MBOX_INIT_TAG(_t_, _id_) { \
+		(_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \
+		(_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \
+		(_t_)->tag_hdr.val_len = sizeof((_t_)->body.req); \
+	}
+
+#define BCM2835_MBOX_INIT_TAG_NO_REQ(_t_, _id_) { \
+		(_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \
+		(_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \
+		(_t_)->tag_hdr.val_len = 0; \
+	}
+
+/* When responding, the VC sets this bit in val_len to indicate a response */
+#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE	0x80000000
+
+/*
+ * Below we define the ID and struct for many possible tags. This header only
+ * defines individual tag structs, not entire message structs, since in
+ * general an arbitrary set of tags may be combined into a single message.
+ * Clients of the mbox API are expected to define their own overall message
+ * structures by combining the header, a set of tags, and a terminating
+ * entry. For example,
+ *
+ * struct msg {
+ *     struct bcm2835_mbox_hdr hdr;
+ *     struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
+ *     ... perhaps other tags here ...
+ *     u32 end_tag;
+ * };
+ */
+
+#define BCM2835_MBOX_TAG_GET_ARM_MEMORY		0x00010005
+
+struct bcm2835_mbox_tag_get_arm_mem {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+		} req;
+		struct {
+			u32 mem_base;
+			u32 mem_size;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER	0x00040001
+
+struct bcm2835_mbox_tag_allocate_buffer {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			u32 alignment;
+		} req;
+		struct {
+			u32 fb_address;
+			u32 fb_size;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_RELEASE_BUFFER		0x00048001
+
+struct bcm2835_mbox_tag_release_buffer {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+		} req;
+		struct {
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_BLANK_SCREEN		0x00040002
+
+struct bcm2835_mbox_tag_blank_screen {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			/* bit 0 means on, other bots reserved */
+			u32 state;
+		} req;
+		struct {
+			u32 state;
+		} resp;
+	} body;
+};
+
+/* Physical means output signal */
+#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H	0x00040003
+#define BCM2835_MBOX_TAG_TEST_PHYSICAL_W_H	0x00044003
+#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H	0x00048003
+
+struct bcm2835_mbox_tag_physical_w_h {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 width;
+			u32 height;
+		} req;
+		struct {
+			u32 width;
+			u32 height;
+		} resp;
+	} body;
+};
+
+/* Virtual means display buffer */
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H	0x00040004
+#define BCM2835_MBOX_TAG_TEST_VIRTUAL_W_H	0x00044004
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H	0x00048004
+
+struct bcm2835_mbox_tag_virtual_w_h {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 width;
+			u32 height;
+		} req;
+		struct {
+			u32 width;
+			u32 height;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_DEPTH		0x00040005
+#define BCM2835_MBOX_TAG_TEST_DEPTH		0x00044005
+#define BCM2835_MBOX_TAG_SET_DEPTH		0x00048005
+
+struct bcm2835_mbox_tag_depth {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 bpp;
+		} req;
+		struct {
+			u32 bpp;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PIXEL_ORDER	0x00040006
+#define BCM2835_MBOX_TAG_TEST_PIXEL_ORDER	0x00044005
+#define BCM2835_MBOX_TAG_SET_PIXEL_ORDER	0x00048006
+
+#define BCM2835_MBOX_PIXEL_ORDER_BGR		0
+#define BCM2835_MBOX_PIXEL_ORDER_RGB		1
+
+struct bcm2835_mbox_tag_pixel_order {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 order;
+		} req;
+		struct {
+			u32 order;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_ALPHA_MODE		0x00040007
+#define BCM2835_MBOX_TAG_TEST_ALPHA_MODE	0x00044007
+#define BCM2835_MBOX_TAG_SET_ALPHA_MODE		0x00048007
+
+#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE	0
+#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT	1
+#define BCM2835_MBOX_ALPHA_MODE_IGNORED		2
+
+struct bcm2835_mbox_tag_alpha_mode {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 alpha;
+		} req;
+		struct {
+			u32 alpha;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PITCH		0x00040008
+
+struct bcm2835_mbox_tag_pitch {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+		} req;
+		struct {
+			u32 pitch;
+		} resp;
+	} body;
+};
+
+/* Offset of display window within buffer */
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET	0x00040009
+#define BCM2835_MBOX_TAG_TEST_VIRTUAL_OFFSET	0x00044009
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET	0x00048009
+
+struct bcm2835_mbox_tag_virtual_offset {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 x;
+			u32 y;
+		} req;
+		struct {
+			u32 x;
+			u32 y;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_OVERSCAN		0x0004000a
+#define BCM2835_MBOX_TAG_TEST_OVERSCAN		0x0004400a
+#define BCM2835_MBOX_TAG_SET_OVERSCAN		0x0004800a
+
+struct bcm2835_mbox_tag_overscan {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		/* req not used for get */
+		struct {
+			u32 top;
+			u32 bottom;
+			u32 left;
+			u32 right;
+		} req;
+		struct {
+			u32 top;
+			u32 bottom;
+			u32 left;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PALETTE		0x0004000b
+
+struct bcm2835_mbox_tag_get_palette {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+		} req;
+		struct {
+			u32 data[1024];
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_TEST_PALETTE		0x0004400b
+
+struct bcm2835_mbox_tag_test_palette {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			u32 offset;
+			u32 num_entries;
+			u32 data[256];
+		} req;
+		struct {
+			u32 is_invalid;
+		} resp;
+	} body;
+};
+
+#define BCM2835_MBOX_TAG_SET_PALETTE		0x0004800b
+
+struct bcm2835_mbox_tag_set_palette {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			u32 offset;
+			u32 num_entries;
+			u32 data[256];
+		} req;
+		struct {
+			u32 is_invalid;
+		} resp;
+	} body;
+};
+
+/*
+ * Pass a raw u32 message to the VC, and receive a raw u32 back.
+ *
+ * Returns 0 for success, any other value for error.
+ */
+int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv);
+
+/*
+ * Pass a complete property-style buffer to the VC, and wait until it has
+ * been processed.
+ *
+ * This function expects a pointer to the mbox_hdr structure in an attempt
+ * to ensure some degree of type safety. However, some number of tags and
+ * a termination value are expected to immediately follow the header in
+ * memory, as required by the property protocol.
+ *
+ * Returns 0 for success, any other value for error.
+ */
+int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer);
+
+#endif
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 21:37:41 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 19:37:41 -0700
Subject: [PATCH V5 REPOST 2 6/7] mmc: add bcm2835 driver
In-Reply-To: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
References: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359513462-10941-6-git-send-email-swarren@wwwdotorg.org>

This adds a simple driver for the BCM2835's SD controller.

Workarounds are implemented for:
* Register writes can't be too close to each-other in time, or they will
  be lost.
* Register accesses must all be 32-bit, so implement custom accessors.

This code was extracted from:
git://github.com/gonzoua/u-boot-pi.git master
which was created by Oleksandr Tymoshenko.

Portions of the code there were obviously based on the Linux kernel at:
git://github.com/raspberrypi/linux.git rpi-3.6.y
commit f5b930b "Main bcm2708 linux port" signed-off-by Dom Cobley.

swarren changed the following for upstream:
* Removed hack udelay()s in bcm2835_sdhci_raw_writel(); setting
  SDHCI_QUIRK_WAIT_SEND_CMD appears to solve the issues.
* Remove register logging from read*/write* functions.
* Sort out confusion with min/max_freq values passed to add_sdhci().
* Use more descriptive variable names and calculations in IO accessors.
* Simplified and commented twoticks_delay calculation.
* checkpatch fixes.

Cc: Andy Fleming <afleming at gmail.com>
Signed-off-by: Oleksandr Tymoshenko <gonzo at bluezbox.com>
Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v5: Invent struct bcm2835_sdhci_host to avoid static/global variables.
v4:
* Merged with video patch series due to dependencies in rpi_b.h.
* Rebased onto latest u-boot-arm/master; no real changes.
v3: No such version was posted.
v2:
* Use more descriptive variable names and calculations in IO accessors.
* Add Oleksandr's S-o-b.
* Rewrite commit description to note that the Linux code this was derived
  from was S-o-b Dom Cobley.
---
 arch/arm/include/asm/arch-bcm2835/sdhci.h |   24 ++++
 drivers/mmc/Makefile                      |    1 +
 drivers/mmc/bcm2835_sdhci.c               |  189 +++++++++++++++++++++++++++++
 3 files changed, 214 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-bcm2835/sdhci.h
 create mode 100644 drivers/mmc/bcm2835_sdhci.c

diff --git a/arch/arm/include/asm/arch-bcm2835/sdhci.h b/arch/arm/include/asm/arch-bcm2835/sdhci.h
new file mode 100644
index 0000000..a4f867b
--- /dev/null
+++ b/arch/arm/include/asm/arch-bcm2835/sdhci.h
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _BCM2835_SDHCI_H_
+#define _BCM2835_SDHCI_H_
+
+#define BCM2835_SDHCI_BASE 0x20300000
+
+int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq);
+
+#endif
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 65791aa..1d6faa2 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -43,6 +43,7 @@ COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o
 COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
 COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
 COBJS-$(CONFIG_SDHCI) += sdhci.o
+COBJS-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o
 COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
 COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
new file mode 100644
index 0000000..b0afc3c
--- /dev/null
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -0,0 +1,189 @@
+/*
+ * This code was extracted from:
+ * git://github.com/gonzoua/u-boot-pi.git master
+ * and hence presumably (C) 2012 Oleksandr Tymoshenko
+ *
+ * Tweaks for U-Boot upstreaming
+ * (C) 2012 Stephen Warren
+ *
+ * Portions (e.g. read/write macros, concepts for back-to-back register write
+ * timing workarounds) obviously extracted from the Linux kernel at:
+ * https://github.com/raspberrypi/linux.git rpi-3.6.y
+ *
+ * The Linux kernel code has the following (c) and license, which is hence
+ * propagated to Oleksandr's tree and here:
+ *
+ * Support for SDHCI device on 2835
+ * Based on sdhci-bcm2708.c (c) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * SDHCI platform device - Arasan SD controller in BCM2708
+ *
+ * Inspired by sdhci-pci.c, by Pierre Ossman
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <sdhci.h>
+
+/* 400KHz is max freq for card ID etc. Use that as min */
+#define MIN_FREQ 400000
+
+struct bcm2835_sdhci_host {
+	struct sdhci_host host;
+	uint twoticks_delay;
+	ulong last_write;
+};
+
+static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host)
+{
+	return (struct bcm2835_sdhci_host *)host;
+}
+
+static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val,
+						int reg)
+{
+	struct bcm2835_sdhci_host *bcm_host = to_bcm(host);
+
+	/*
+	 * The Arasan has a bugette whereby it may lose the content of
+	 * successive writes to registers that are within two SD-card clock
+	 * cycles of each other (a clock domain crossing problem).
+	 * It seems, however, that the data register does not have this problem.
+	 * (Which is just as well - otherwise we'd have to nobble the DMA engine
+	 * too)
+	 */
+	while (get_timer(bcm_host->last_write) < bcm_host->twoticks_delay)
+		;
+
+	writel(val, host->ioaddr + reg);
+	bcm_host->last_write = get_timer(0);
+}
+
+static inline u32 bcm2835_sdhci_raw_readl(struct sdhci_host *host, int reg)
+{
+	return readl(host->ioaddr + reg);
+}
+
+static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
+{
+	bcm2835_sdhci_raw_writel(host, val, reg);
+}
+
+static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
+{
+	static u32 shadow;
+	u32 oldval = (reg == SDHCI_COMMAND) ? shadow :
+		bcm2835_sdhci_raw_readl(host, reg & ~3);
+	u32 word_num = (reg >> 1) & 1;
+	u32 word_shift = word_num * 16;
+	u32 mask = 0xffff << word_shift;
+	u32 newval = (oldval & ~mask) | (val << word_shift);
+
+	if (reg == SDHCI_TRANSFER_MODE)
+		shadow = newval;
+	else
+		bcm2835_sdhci_raw_writel(host, newval, reg & ~3);
+}
+
+static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+	u32 oldval = bcm2835_sdhci_raw_readl(host, reg & ~3);
+	u32 byte_num = reg & 3;
+	u32 byte_shift = byte_num * 8;
+	u32 mask = 0xff << byte_shift;
+	u32 newval = (oldval & ~mask) | (val << byte_shift);
+
+	bcm2835_sdhci_raw_writel(host, newval, reg & ~3);
+}
+
+static u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg)
+{
+	u32 val = bcm2835_sdhci_raw_readl(host, reg);
+
+	return val;
+}
+
+static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg)
+{
+	u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3));
+	u32 word_num = (reg >> 1) & 1;
+	u32 word_shift = word_num * 16;
+	u32 word = (val >> word_shift) & 0xffff;
+
+	return word;
+}
+
+static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
+{
+	u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3));
+	u32 byte_num = reg & 3;
+	u32 byte_shift = byte_num * 8;
+	u32 byte = (val >> byte_shift) & 0xff;
+
+	return byte;
+}
+
+static const struct sdhci_ops bcm2835_ops = {
+	.write_l = bcm2835_sdhci_writel,
+	.write_w = bcm2835_sdhci_writew,
+	.write_b = bcm2835_sdhci_writeb,
+	.read_l = bcm2835_sdhci_readl,
+	.read_w = bcm2835_sdhci_readw,
+	.read_b = bcm2835_sdhci_readb,
+};
+
+int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq)
+{
+	struct bcm2835_sdhci_host *bcm_host;
+	struct sdhci_host *host;
+
+	bcm_host = malloc(sizeof(*bcm_host));
+	if (!bcm_host) {
+		printf("sdhci_host malloc fail!\n");
+		return 1;
+	}
+
+	/*
+	 * See the comments in bcm2835_sdhci_raw_writel().
+	 *
+	 * This should probably be dynamically calculated based on the actual
+	 * frequency. However, this is the longest we'll have to wait, and
+	 * doesn't seem to slow access down too much, so the added complexity
+	 * doesn't seem worth it for now.
+	 *
+	 * 1/MIN_FREQ is (max) time per tick of eMMC clock.
+	 * 2/MIN_FREQ is time for two ticks.
+	 * Multiply by 1000000 to get uS per two ticks.
+	 * +1 for hack rounding.
+	 */
+	bcm_host->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1;
+	bcm_host->last_write = 0;
+
+	host = &bcm_host->host;
+	host->name = "bcm2835_sdhci";
+	host->ioaddr = (void *)regbase;
+	host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B |
+		SDHCI_QUIRK_WAIT_SEND_CMD;
+	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+	host->ops = &bcm2835_ops;
+
+	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+	add_sdhci(host, emmc_freq, MIN_FREQ);
+
+	return 0;
+}
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 21:37:42 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 19:37:42 -0700
Subject: [PATCH V5 REPOST 2 7/7] ARM: rpi_b: enable SD controller,
 add related env/cmds
In-Reply-To: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
References: <1359513462-10941-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359513462-10941-7-git-send-email-swarren@wwwdotorg.org>

Enable the SD controller driver for the Raspberry Pi. Enable a number
of useful MMC, partition, and filesystem-related commands. Set up the
environment to provide standard locations for loading a kernel, DTB,
etc. Provide a boot command that loads and executes boot.scr.uimg from
the SD card; this is written considering future extensibilty to USB
storage.

Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
v5: No change.
v4:
* Merged with video patch series due to dependencies in rpi_b.h.
* Rebased onto latest u-boot-arm/master; no real changes.
v3: No such version was posted.
v2: No change.
---
 arch/arm/include/asm/arch-bcm2835/mbox.h |   26 ++++++++++++
 board/raspberrypi/rpi_b/rpi_b.c          |   26 ++++++++++++
 include/configs/rpi_b.h                  |   68 ++++++++++++++++++++++++++++--
 3 files changed, 117 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/arch-bcm2835/mbox.h b/arch/arm/include/asm/arch-bcm2835/mbox.h
index 4752091..b07c4a0 100644
--- a/arch/arm/include/asm/arch-bcm2835/mbox.h
+++ b/arch/arm/include/asm/arch-bcm2835/mbox.h
@@ -144,6 +144,32 @@ struct bcm2835_mbox_tag_get_arm_mem {
 	} body;
 };
 
+#define BCM2835_MBOX_TAG_GET_CLOCK_RATE	0x00030002
+
+#define BCM2835_MBOX_CLOCK_ID_EMMC	1
+#define BCM2835_MBOX_CLOCK_ID_UART	2
+#define BCM2835_MBOX_CLOCK_ID_ARM	3
+#define BCM2835_MBOX_CLOCK_ID_CORE	4
+#define BCM2835_MBOX_CLOCK_ID_V3D	5
+#define BCM2835_MBOX_CLOCK_ID_H264	6
+#define BCM2835_MBOX_CLOCK_ID_ISP	7
+#define BCM2835_MBOX_CLOCK_ID_SDRAM	8
+#define BCM2835_MBOX_CLOCK_ID_PIXEL	9
+#define BCM2835_MBOX_CLOCK_ID_PWM	10
+
+struct bcm2835_mbox_tag_get_clock_rate {
+	struct bcm2835_mbox_tag_hdr tag_hdr;
+	union {
+		struct {
+			u32 clock_id;
+		} req;
+		struct {
+			u32 clock_id;
+			u32 rate_hz;
+		} resp;
+	} body;
+};
+
 #define BCM2835_MBOX_TAG_ALLOCATE_BUFFER	0x00040001
 
 struct bcm2835_mbox_tag_allocate_buffer {
diff --git a/board/raspberrypi/rpi_b/rpi_b.c b/board/raspberrypi/rpi_b/rpi_b.c
index 3c654a1..6b3e095 100644
--- a/board/raspberrypi/rpi_b/rpi_b.c
+++ b/board/raspberrypi/rpi_b/rpi_b.c
@@ -16,6 +16,7 @@
 
 #include <common.h>
 #include <asm/arch/mbox.h>
+#include <asm/arch/sdhci.h>
 #include <asm/global_data.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -26,6 +27,12 @@ struct msg_get_arm_mem {
 	u32 end_tag;
 };
 
+struct msg_get_clock_rate {
+	struct bcm2835_mbox_hdr hdr;
+	struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
+	u32 end_tag;
+};
+
 int dram_init(void)
 {
 	ALLOC_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1, 16);
@@ -51,3 +58,22 @@ int board_init(void)
 
 	return 0;
 }
+
+int board_mmc_init(void)
+{
+	ALLOC_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1, 16);
+	int ret;
+
+	BCM2835_MBOX_INIT_HDR(msg_clk);
+	BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE);
+	msg_clk->get_clock_rate.body.req.clock_id = BCM2835_MBOX_CLOCK_ID_EMMC;
+
+	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_clk->hdr);
+	if (ret) {
+		printf("bcm2835: Could not query eMMC clock rate\n");
+		return -1;
+	}
+
+	return bcm2835_sdhci_init(BCM2835_SDHCI_BASE,
+				  msg_clk->get_clock_rate.body.resp.rate_hz);
+}
diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index e485a06..3d55d36 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -51,6 +51,7 @@
 #define CONFIG_SYS_MALLOC_LEN		SZ_4M
 #define CONFIG_SYS_MEMTEST_START	0x00100000
 #define CONFIG_SYS_MEMTEST_END		0x00200000
+#define CONFIG_LOADADDR			0x00200000
 
 /* Flash */
 #define CONFIG_SYS_NO_FLASH
@@ -70,6 +71,13 @@
 #define CONFIG_VIDEO_BCM2835
 #define CONFIG_SYS_WHITE_ON_BLACK
 
+/* SD/MMC configuration */
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC
+#define CONFIG_SDHCI
+#define CONFIG_MMC_SDHCI_IO_ACCESSORS
+#define CONFIG_BCM2835_SDHCI
+
 /* Console UART */
 #define CONFIG_PL011_SERIAL
 #define CONFIG_PL011_CLOCK		3000000
@@ -85,12 +93,59 @@
 /* Environment */
 #define CONFIG_ENV_SIZE			SZ_16K
 #define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_VARS_UBOOT_CONFIG
 #define CONFIG_SYS_LOAD_ADDR		0x1000000
 #define CONFIG_CONSOLE_MUX
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
-#define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
-					"stderr=serial,lcd\0" \
-					"stdout=serial,lcd\0"
+/*
+ * Memory layout for where various images get loaded by boot scripts:
+ *
+ * scriptaddr can be pretty much anywhere that doesn't conflict with something
+ *   else. Put it low in memory to avoid conflicts.
+ *
+ * kernel_addr_r must be within the first 128M of RAM in order for the
+ *   kernel's CONFIG_AUTO_ZRELADDR option to work. Since the kernel will
+ *   decompress itself to 0x8000 after the start of RAM, kernel_addr_r
+ *   should not overlap that area, or the kernel will have to copy itself
+ *   somewhere else before decompression. Similarly, the address of any other
+ *   data passed to the kernel shouldn't overlap the start of RAM. Pushing
+ *   this up to 16M allows for a sizable kernel to be decompressed below the
+ *   compressed load address.
+ *
+ * fdt_addr_r simply shouldn't overlap anything else. Choosing 32M allows for
+ *   the compressed kernel to be up to 16M too.
+ *
+ * ramdisk_addr_r simply shouldn't overlap anything else. Choosing 33M allows
+ *   for the FDT/DTB to be up to 1M, which is hopefully plenty.
+ */
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"stdin=serial\0" \
+	"stderr=serial,lcd\0" \
+	"stdout=serial,lcd\0" \
+	"scriptaddr=0x00000000\0" \
+	"kernel_addr_r=0x01000000\0" \
+	"fdt_addr_r=0x02000000\0" \
+	"ramdisk_addr_r=0x02100000\0" \
+	"boot_targets=mmc0\0" \
+	\
+	"script_boot=" \
+		"if fatload ${devtype} ${devnum}:1 " \
+					"${scriptaddr} boot.scr.uimg; then " \
+			"source ${scriptaddr}; " \
+		"fi;\0" \
+	\
+	"mmc_boot=" \
+		"setenv devtype mmc; " \
+		"if mmc dev ${devnum}; then " \
+			"run script_boot; " \
+		"fi\0" \
+	\
+	"bootcmd_mmc0=setenv devnum 0; run mmc_boot\0" \
+
+#define CONFIG_BOOTCOMMAND \
+	"for target in ${boot_targets}; do run bootcmd_${target}; done"
+
+#define CONFIG_BOOTDELAY		2
 
 /* Shell */
 #define CONFIG_SYS_HUSH_PARSER
@@ -105,6 +160,13 @@
 #include <config_cmd_default.h>
 #define CONFIG_CMD_BOOTZ
 #define CONFIG_CMD_GPIO
+#define CONFIG_CMD_MMC
+#define CONFIG_DOS_PARTITION
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_CMD_PART
+#define CONFIG_CMD_FS_GENERIC
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT
 /* Some things don't make sense on this HW or yet */
 #undef CONFIG_CMD_FPGA
 #undef CONFIG_CMD_NET
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 23:22:04 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 21:22:04 -0700
Subject: [PATCH] mmc: sdhci-pltfm: Add a common clk API based
 implementation of get_timeout_clock
In-Reply-To: <510794DB.3050606@metafoo.de>
References: <1359397632-31646-1-git-send-email-lars@metafoo.de>
 <51076205.6040704@wwwdotorg.org> <510794DB.3050606@metafoo.de>
Message-ID: <51089FEC.6040603@wwwdotorg.org>

On 01/29/2013 02:22 AM, Lars-Peter Clausen wrote:
> On 01/29/2013 06:45 AM, Stephen Warren wrote:
>> On 01/28/2013 11:27 AM, Lars-Peter Clausen wrote:
>>> Quite a few drivers have a implementation of the get_timeout_clock callback
>>> which simply returns the result of clk_get_rate on devices clock. This patch
>>> adds a common implementation of this to the sdhci-pltfm module and replaces all
>>> custom implementations with the common one.
>>>
>>> Signed-off-by: Lars-Peter Clausen <lars at metafoo.de>
>>> ---
>>> I've only runtime tested this patch on a platform which is not yet upstream. For
>>> the drivers which are modified in this patch I've only done compile time
>>> testing. But I think all changes, but maybe the bcm2835 one, are straight
>>> forward.
>>
>> It seems to work fine for bcm2835. So,
>>
>> Tested-by: Stephen Warren <swarren at wwwdotorg.org>
>>
>>> @@ -148,9 +131,9 @@ static struct sdhci_ops bcm2835_sdhci_ops = {
>>>  	.read_l = bcm2835_sdhci_readl,
>>>  	.read_w = bcm2835_sdhci_readw,
>>>  	.read_b = bcm2835_sdhci_readb,
>>> -	.get_max_clock = bcm2835_sdhci_get_max_clock,
>>> +	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
>>>  	.get_min_clock = bcm2835_sdhci_get_min_clock,
>>> -	.get_timeout_clock = bcm2835_sdhci_get_timeout_clock,
>>> +	.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
>>>  };
>>
>> Rather than requiring .get_max_clock and .get_timeout_clock to be set by
>> each driver, perhaps the SDHCI core can call
>> sdhci_pltfm_clk_get_max_clock() if the function pointer is NULL?
> 
> Yea, this part of the bcm2835 driver confused me a bit. So there is the
> SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK quirk which causes the sdhci core to use
> the max clock as a basis to calculate the timeout clock.

It's quite possible that sdhci-bcm2835.c should simply be modified to
set that quirk, and the implementation of .get_timeout_clock() removed
from sdhci-bcm2835.c. I see that a couple of downstream drivers for this
HW do in fact set that quirk, so it should be safe. I made this change
and it seems to work fine; I'll send the patch.

> But it divides it by 1000.

I wonder if that's just the units the clock is stored in; I see various
"* 1000" in the usage of host->timeout_clk. Unfortunately, there don't
appear to be any other implementations of .get_timeout_clock() to
compare with.

> I don't know the bcm2835 sdhci controller hardware, but is it
> possible that the current timeout clock value is too large by a factor of
> 1000? This wouldn't cause problems with normal transfers, but may increase
> the timeout delay for failed transfers.

Quite possibly.


From swarren at wwwdotorg.org  Tue Jan 29 23:26:21 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Tue, 29 Jan 2013 21:26:21 -0700
Subject: [PATCH] mmc: bcm2835: set SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
Message-ID: <1359519981-23358-1-git-send-email-swarren@wwwdotorg.org>

SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK does basically the same as
implementing struct sdhci_ops .get_timeout_clock, so simply set that
quirk and remove the custom code to simplify the driver.

Reported-by: Lars-Peter Clausen <lars at metafoo.de>
Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
 drivers/mmc/host/sdhci-bcm2835.c |   12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c
index 453825f..21fc735 100644
--- a/drivers/mmc/host/sdhci-bcm2835.c
+++ b/drivers/mmc/host/sdhci-bcm2835.c
@@ -133,14 +133,6 @@ unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
 	return MIN_FREQ;
 }
 
-unsigned int bcm2835_sdhci_get_timeout_clock(struct sdhci_host *host)
-{
-	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct bcm2835_sdhci *bcm2835_host = pltfm_host->priv;
-
-	return clk_get_rate(bcm2835_host->clk);
-}
-
 static struct sdhci_ops bcm2835_sdhci_ops = {
 	.write_l = bcm2835_sdhci_writel,
 	.write_w = bcm2835_sdhci_writew,
@@ -150,11 +142,11 @@ static struct sdhci_ops bcm2835_sdhci_ops = {
 	.read_b = bcm2835_sdhci_readb,
 	.get_max_clock = bcm2835_sdhci_get_max_clock,
 	.get_min_clock = bcm2835_sdhci_get_min_clock,
-	.get_timeout_clock = bcm2835_sdhci_get_timeout_clock,
 };
 
 static struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
-	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION,
+	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+			SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
 	.ops = &bcm2835_sdhci_ops,
 };
 
-- 
1.7.10.4



From swarren at wwwdotorg.org  Tue Jan 29 01:42:20 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Mon, 28 Jan 2013 23:42:20 -0700
Subject: [GIT PULL 2/4] ARM: bcm2835: SoC driver updates
In-Reply-To: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>
References: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359441742-32647-2-git-send-email-swarren@wwwdotorg.org>

The bcm2835 clock driver is enhanced to allow fixed clocks to be probed
from device tree.

A system power-off implementation is added.

This branch is based on v3.8-rc3.

----------------------------------------------------------------

The following changes since commit 9931faca02c604c22335f5a935a501bb2ace6e20:

  Linux 3.8-rc3

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-soc

for you to fetch changes up to 45e9d77a22b7b25373c7b8c0ea0b146168025360:

  ARM: bcm2835: add a pm_power_off implementation

----------------------------------------------------------------

Dom Cobley (1):
      ARM: bcm2835: add a pm_power_off implementation

Stephen Warren (1):
      clk: bcm2835: probe for fixed-clock in device tree

 arch/arm/mach-bcm2835/bcm2835.c |   28 ++++++++++++++++++++++++++++
 drivers/clk/clk-bcm2835.c       |    9 +++++++++
 2 files changed, 37 insertions(+)


From swarren at wwwdotorg.org  Tue Jan 29 01:42:21 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Mon, 28 Jan 2013 23:42:21 -0700
Subject: [GIT PULL 3/4] ARM: bcm2835: device tree updates
In-Reply-To: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>
References: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359441742-32647-3-git-send-email-swarren@wwwdotorg.org>

The SoC's SDHCI and MMC controllers are added to device tree, and enabled
in the Raspberry Pi board device tree. Some fixed clocks are added to the
device tree to support these drivers. These could be replaced by real
clocks in the future.

A hard-coded memreserve is removed from device tree; the bootloader should
specify the correct memory node content instead, since the memory layout
is dynamic.

This branch is based on v3.8-rc3.

----------------------------------------------------------------

The following changes since commit 9931faca02c604c22335f5a935a501bb2ace6e20:

  Linux 3.8-rc3

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-dt

for you to fetch changes up to 9692c191ffffbd5255bec222b8f0f2854932a408:

  ARM: bcm2835: fix clock node aliasing in device tree

----------------------------------------------------------------

Stephen Warren (4):
      ARM: bcm2835 rpi: remove hard-coded memreserve from DT
      ARM: bcm2835: add SDHCI node to DT
      ARM: bcm2835: add I2C controllers to DT
      ARM: bcm2835: fix clock node aliasing in device tree

 arch/arm/boot/dts/bcm2835-rpi-b.dts |   16 ++++++++++-
 arch/arm/boot/dts/bcm2835.dtsi      |   44 ++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 1 deletion(-)


From swarren at wwwdotorg.org  Tue Jan 29 01:42:22 2013
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Mon, 28 Jan 2013 23:42:22 -0700
Subject: [GIT PULL 4/4] ARM: bcm2835: defconfig update
In-Reply-To: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>
References: <1359441742-32647-1-git-send-email-swarren@wwwdotorg.org>
Message-ID: <1359441742-32647-4-git-send-email-swarren@wwwdotorg.org>

The SDHCI and I2C subsytems and drivers are enabled.

Various filesystems are enabled for use with the SDHCI driver.

Various other options expected by distros are enabled. This allows the
"Raspbian" filesystem published by the Raspberry Pi Foundation to boot
to a serial console prompt.

This branch is based on v3.8-rc3.

----------------------------------------------------------------

The following changes since commit 9931faca02c604c22335f5a935a501bb2ace6e20:

  Linux 3.8-rc3

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.9-defconfig

for you to fetch changes up to d1dc7c6c6a6666fff1d40009c71965dc6600d521:

  ARM: bcm2835: defconfig updates

----------------------------------------------------------------

Stephen Warren (1):
      ARM: bcm2835: defconfig updates

 arch/arm/configs/bcm2835_defconfig |   43 ++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 10 deletions(-)


