[coreboot-gerrit] Patch set updated for coreboot: ad2bc09 broadcom/cygnus: add usb phy driver

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Tue Apr 21 16:36:00 CEST 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9918

-gerrit

commit ad2bc09a8b710a88513ca5d9d8f16939ceae2b19
Author: Daisuke Nojiri <dnojiri at chromium.org>
Date:   Wed Feb 25 17:39:42 2015 -0800

    broadcom/cygnus: add usb phy driver
    
    The code originates from
    https://github.com/Broadcom/cygnus-linux/commit/d0752a61273decb16db0fe8d09291f9cc326ed24.
    
    BUG=chrome-os-partner:37439
    BRANCH=purin
    TEST=booted kernel from a usb stick on the ref board
    
    Change-Id: I51ecf4e1d6890e4286402c26721f4d063ab04711
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: fac506e758cb63a947bbdcfbddf9b8edecf7cd2f
    Original-Signed-off-by: Daisuke Nojiri <dnojiri at chromium.org>
    Original-Reviewed-on: https://chrome-internal-review.googlesource.com/202386
    Original-Reviewed-by: Scott Branden <sbranden at broadcom.com>
    Original-Commit-Queue: Daisuke Nojiri <dnojiri at google.com>
    Original-Tested-by: Daisuke Nojiri <dnojiri at google.com>
    Original-Change-Id: I027affea293af8744c997a2ed3dec741977bd328
    Original-Reviewed-on: https://chromium-review.googlesource.com/264560
    Original-Reviewed-by: Stefan Reinauer <reinauer at chromium.org>
---
 src/soc/broadcom/cygnus/Makefile.inc         |   1 +
 src/soc/broadcom/cygnus/include/soc/cygnus.h |  26 +++++
 src/soc/broadcom/cygnus/soc.c                |   2 +
 src/soc/broadcom/cygnus/usb.c                | 166 +++++++++++++++++++++++++++
 4 files changed, 195 insertions(+)

diff --git a/src/soc/broadcom/cygnus/Makefile.inc b/src/soc/broadcom/cygnus/Makefile.inc
index dce4e3d..e22d38d 100644
--- a/src/soc/broadcom/cygnus/Makefile.inc
+++ b/src/soc/broadcom/cygnus/Makefile.inc
@@ -54,6 +54,7 @@ ramstage-y += soc.c
 ramstage-y += timer.c
 ramstage-$(CONFIG_SPI_FLASH) += spi.c
 ramstage-$(CONFIG_DRIVERS_UART) += ns16550.c
+ramstage-y += usb.c
 
 CPPFLAGS_common += -Isrc/soc/broadcom/cygnus/include/
 
diff --git a/src/soc/broadcom/cygnus/include/soc/cygnus.h b/src/soc/broadcom/cygnus/include/soc/cygnus.h
new file mode 100644
index 0000000..8eb7dff
--- /dev/null
+++ b/src/soc/broadcom/cygnus/include/soc/cygnus.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SOC_BROADCOM_CYGNUS_H__
+#define __SOC_BROADCOM_CYGNUS_H__
+
+void usb_init(void);
+
+#endif
+
diff --git a/src/soc/broadcom/cygnus/soc.c b/src/soc/broadcom/cygnus/soc.c
index c9597f2..399409f 100644
--- a/src/soc/broadcom/cygnus/soc.c
+++ b/src/soc/broadcom/cygnus/soc.c
@@ -18,6 +18,7 @@
  */
 
 #include <device/device.h>
+#include <soc/cygnus.h>
 #include <soc/sdram.h>
 #include <stddef.h>
 #include <stdlib.h>
@@ -26,6 +27,7 @@
 static void soc_init(device_t dev)
 {
 	ram_resource(dev, 0, (uintptr_t)_dram/KiB, sdram_size_mb()*(MiB/KiB));
+	usb_init();
 }
 
 static void soc_noop(device_t dev)
diff --git a/src/soc/broadcom/cygnus/usb.c b/src/soc/broadcom/cygnus/usb.c
new file mode 100644
index 0000000..d95efd1
--- /dev/null
+++ b/src/soc/broadcom/cygnus/usb.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <delay.h>
+#include <console/console.h>
+#include <soc/cygnus.h>
+
+#define CDRU_USBPHY_CLK_RST_SEL_OFFSET			0x11b4
+#define CDRU_USBPHY2_HOST_DEV_SEL_OFFSET		0x11b8
+#define CDRU_SPARE_REG_0_OFFSET				0x1238
+#define CRMU_USB_PHY_AON_CTRL_OFFSET			0x00028
+#define CDRU_USB_DEV_SUSPEND_RESUME_CTRL_OFFSET		0x1210
+#define CDRU_USBPHY_P2_STATUS_OFFSET			0x1200
+
+#define CDRU_USB_DEV_SUSPEND_RESUME_CTRL_DISABLE	0
+#define PHY2_DEV_HOST_CTRL_SEL_DEVICE			0
+#define PHY2_DEV_HOST_CTRL_SEL_HOST			1
+#define CDRU_USBPHY_P2_STATUS__USBPHY_ILDO_ON_FLAG	1
+#define CDRU_USBPHY_P2_STATUS__USBPHY_PLL_LOCK		0
+#define CRMU_USBPHY_P0_AFE_CORERDY_VDDC			1
+#define CRMU_USBPHY_P0_RESETB				2
+#define CRMU_USBPHY_P1_AFE_CORERDY_VDDC			9
+#define CRMU_USBPHY_P1_RESETB				10
+#define CRMU_USBPHY_P2_AFE_CORERDY_VDDC			17
+#define CRMU_USBPHY_P2_RESETB				18
+
+#define USB2_IDM_IDM_IO_CONTROL_DIRECT_OFFSET		0x0408
+#define USB2_IDM_IDM_IO_CONTROL_DIRECT__clk_enable	0
+#define USB2_IDM_IDM_RESET_CONTROL_OFFSET		0x0800
+#define USB2_IDM_IDM_RESET_CONTROL__RESET		0
+
+#define PLL_LOCK_RETRY_COUNT	1000
+#define MAX_REGULATOR_NAME_LEN  25
+#define NUM_PHYS		3
+
+struct bcm_phy_instance {
+	struct phy *generic_phy;
+	int port;
+	int host_mode; /* 1 - Host , 0 - device */
+	int power; /* 1 -powered_on 0 -powered off */
+	struct regulator *vbus_supply;
+};
+
+struct bcm_phy_driver {
+	void *usbphy_regs;
+	void *usb2h_idm_regs;
+	void *usb2d_idm_regs;
+	int num_phys, idm_host_enabled;
+	struct bcm_phy_instance instances[NUM_PHYS];
+};
+
+static struct bcm_phy_driver phy_driver;
+
+static int bcm_phy_init(struct bcm_phy_instance *instance_ptr)
+{
+	/* Only PORT 2 is capabale of being device and host
+	 * Default setting is device, check if it is set to host */
+	if (instance_ptr->port == 2) {
+		if (instance_ptr->host_mode == PHY2_DEV_HOST_CTRL_SEL_HOST)
+			write32(phy_driver.usbphy_regs + CDRU_USBPHY2_HOST_DEV_SEL_OFFSET,
+				PHY2_DEV_HOST_CTRL_SEL_HOST);
+		else
+			die("usb device mode unsupported\n");
+	}
+
+	return 0;
+}
+
+static int bcm_phy_poweron(struct bcm_phy_instance *instance_ptr)
+{
+	int clock_reset_flag = 1;
+	u32 val;
+
+	/* Bring the AFE block out of reset to start powering up the PHY */
+	val = read32(phy_driver.usbphy_regs + CRMU_USB_PHY_AON_CTRL_OFFSET);
+	if (instance_ptr->port == 0)
+		val |= (1 << CRMU_USBPHY_P0_AFE_CORERDY_VDDC);
+	else if (instance_ptr->port == 1)
+		val |= (1 << CRMU_USBPHY_P1_AFE_CORERDY_VDDC);
+	else if (instance_ptr->port == 2)
+		val |= (1 << CRMU_USBPHY_P2_AFE_CORERDY_VDDC);
+	write32(phy_driver.usbphy_regs + CRMU_USB_PHY_AON_CTRL_OFFSET, val);
+
+	instance_ptr->power = 1;
+
+	/* Check if the port 2 is configured for device */
+	if (instance_ptr->port == 2 &&
+		instance_ptr->host_mode == PHY2_DEV_HOST_CTRL_SEL_DEVICE)
+		die("usb device mode unsupported\n");
+
+	val = read32(phy_driver.usbphy_regs + CDRU_USBPHY_CLK_RST_SEL_OFFSET);
+
+	/* Check if the phy that is configured
+	 * to provide clock and reset is powered on*/
+	if (val >= 0 && val < phy_driver.num_phys) {
+		if (phy_driver.instances[val].power == 1)
+			clock_reset_flag = 0;
+	}
+
+	/* if not set the current phy */
+	if (clock_reset_flag) {
+		val = instance_ptr->port;
+		write32(phy_driver.usbphy_regs + CDRU_USBPHY_CLK_RST_SEL_OFFSET,
+			val);
+	}
+
+	if (phy_driver.idm_host_enabled != 1) {
+		/* Enable clock to USB and get the USB out of reset */
+		setbits_le32(phy_driver.usb2h_idm_regs +
+			     USB2_IDM_IDM_IO_CONTROL_DIRECT_OFFSET,
+			     (1 << USB2_IDM_IDM_IO_CONTROL_DIRECT__clk_enable));
+		clrbits_le32(phy_driver.usb2h_idm_regs +
+			     USB2_IDM_IDM_RESET_CONTROL_OFFSET,
+			     (1 << USB2_IDM_IDM_RESET_CONTROL__RESET));
+		phy_driver.idm_host_enabled = 1;
+	}
+
+	return 0;
+}
+
+static int bcm_phy_probe(void)
+{
+	int i;
+
+	phy_driver.num_phys = NUM_PHYS;
+	phy_driver.usbphy_regs = (void *)0x0301c000;
+	phy_driver.usb2h_idm_regs = (void *)0x18115000;
+	phy_driver.usb2d_idm_regs = (void *)0x18111000;
+	phy_driver.idm_host_enabled = 0;
+
+	/* Shutdown all ports. They can be powered up as required */
+	clrbits_le32(phy_driver.usbphy_regs + CRMU_USB_PHY_AON_CTRL_OFFSET,
+		     (1 << CRMU_USBPHY_P0_AFE_CORERDY_VDDC) |
+		     (1 << CRMU_USBPHY_P0_RESETB) |
+		     (1 << CRMU_USBPHY_P1_AFE_CORERDY_VDDC) |
+		     (1 << CRMU_USBPHY_P1_RESETB) |
+		     (1 << CRMU_USBPHY_P2_AFE_CORERDY_VDDC) |
+		     (1 << CRMU_USBPHY_P2_RESETB));
+
+	for (i = 0; i < phy_driver.num_phys; i++) {
+		phy_driver.instances[i].port = i;
+		phy_driver.instances[i].host_mode = PHY2_DEV_HOST_CTRL_SEL_HOST;
+	}
+
+	return 0;
+}
+
+void usb_init(void)
+{
+	bcm_phy_probe();
+	/* currently, we only need thus support port 0 */
+	bcm_phy_init(&phy_driver.instances[0]);
+	bcm_phy_poweron(&phy_driver.instances[0]);
+	printk(BIOS_INFO, "usb phy[%d] is powered on\n", 0);
+}



More information about the coreboot-gerrit mailing list