summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-10-12 10:10:59 -0400
committerTom Rini <trini@konsulko.com>2019-10-12 10:10:59 -0400
commit0c9cc5155cb5027ae17ace986f349e2f0d1fb9a3 (patch)
tree49c59081ca15147dcc311880648732a5d4fc019a /drivers
parent36317705cb5ab43db25fede2446d2352de527630 (diff)
parent7d2dc6af540fad77bff2a3ff16cdc2f9d9df72eb (diff)
Merge branch '2019-10-11-master-imports'
- Assorted cleanups - FAT bugfixes - mediatek platform updates
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci-pci.c1
-rw-r--r--drivers/ata/ahci.c11
-rw-r--r--drivers/pci/Kconfig8
-rw-r--r--drivers/pci/Makefile1
-rw-r--r--drivers/pci/pcie_mediatek.c279
-rw-r--r--drivers/phy/Kconfig11
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/phy-mtk-tphy.c362
-rw-r--r--drivers/power/regulator/regulator_common.c7
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/bcm63xx_hsspi.c47
11 files changed, 700 insertions, 30 deletions
diff --git a/drivers/ata/ahci-pci.c b/drivers/ata/ahci-pci.c
index 1ca439d3fa..11ec98b56f 100644
--- a/drivers/ata/ahci-pci.c
+++ b/drivers/ata/ahci-pci.c
@@ -35,6 +35,7 @@ U_BOOT_DRIVER(ahci_pci) = {
static struct pci_device_id ahci_pci_supported[] = {
{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, ~0) },
+ { PCI_DEVICE(0x1b21, 0x0611) },
{},
};
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 9a08575053..21a89eba5a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -548,6 +548,7 @@ static int ahci_port_start(struct ahci_uc_priv *uc_priv, u8 port)
{
struct ahci_ioports *pp = &(uc_priv->port[port]);
void __iomem *port_mmio = pp->port_mmio;
+ u64 dma_addr;
u32 port_status;
void __iomem *mem;
@@ -593,10 +594,12 @@ static int ahci_port_start(struct ahci_uc_priv *uc_priv, u8 port)
pp->cmd_tbl_sg =
(struct ahci_sg *)(uintptr_t)virt_to_phys((void *)mem);
- writel_with_flush((unsigned long)pp->cmd_slot,
- port_mmio + PORT_LST_ADDR);
-
- writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR);
+ dma_addr = (ulong)pp->cmd_slot;
+ writel_with_flush(dma_addr, port_mmio + PORT_LST_ADDR);
+ writel_with_flush(dma_addr >> 32, port_mmio + PORT_LST_ADDR_HI);
+ dma_addr = (ulong)pp->rx_fis;
+ writel_with_flush(dma_addr, port_mmio + PORT_FIS_ADDR);
+ writel_with_flush(dma_addr >> 32, port_mmio + PORT_FIS_ADDR_HI);
#ifdef CONFIG_SUNXI_AHCI
sunxi_dma_init(port_mmio);
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index bdfc0c1796..19e7b50046 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -151,4 +151,12 @@ config PCI_KEYSTONE
help
Say Y here if you want to enable PCI controller support on AM654 SoC.
+config PCIE_MEDIATEK
+ bool "MediaTek PCIe Gen2 controller"
+ depends on DM_PCI
+ depends on ARCH_MEDIATEK
+ help
+ Say Y here if you want to enable Gen2 PCIe controller,
+ which could be found on MT7623 SoC family.
+
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e54a98b8c9..b1d3dc8610 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie_layerscape_gen4.o \
obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o
obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o
obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o
+obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o
diff --git a/drivers/pci/pcie_mediatek.c b/drivers/pci/pcie_mediatek.c
new file mode 100644
index 0000000000..a0dcb258b0
--- /dev/null
+++ b/drivers/pci/pcie_mediatek.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek PCIe host controller driver.
+ *
+ * Copyright (c) 2017-2019 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ * Honghui Zhang <honghui.zhang@mediatek.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <pci.h>
+#include <reset.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+#include <linux/list.h>
+
+/* PCIe shared registers */
+#define PCIE_SYS_CFG 0x00
+#define PCIE_INT_ENABLE 0x0c
+#define PCIE_CFG_ADDR 0x20
+#define PCIE_CFG_DATA 0x24
+
+/* PCIe per port registers */
+#define PCIE_BAR0_SETUP 0x10
+#define PCIE_CLASS 0x34
+#define PCIE_LINK_STATUS 0x50
+
+#define PCIE_PORT_INT_EN(x) BIT(20 + (x))
+#define PCIE_PORT_PERST(x) BIT(1 + (x))
+#define PCIE_PORT_LINKUP BIT(0)
+#define PCIE_BAR_MAP_MAX GENMASK(31, 16)
+
+#define PCIE_BAR_ENABLE BIT(0)
+#define PCIE_REVISION_ID BIT(0)
+#define PCIE_CLASS_CODE (0x60400 << 8)
+#define PCIE_CONF_REG(regn) (((regn) & GENMASK(7, 2)) | \
+ ((((regn) >> 8) & GENMASK(3, 0)) << 24))
+#define PCIE_CONF_ADDR(regn, bdf) \
+ (PCIE_CONF_REG(regn) | (bdf))
+
+/* MediaTek specific configuration registers */
+#define PCIE_FTS_NUM 0x70c
+#define PCIE_FTS_NUM_MASK GENMASK(15, 8)
+#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8)
+
+#define PCIE_FC_CREDIT 0x73c
+#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16))
+#define PCIE_FC_CREDIT_VAL(x) ((x) << 16)
+
+struct mtk_pcie_port {
+ void __iomem *base;
+ struct list_head list;
+ struct mtk_pcie *pcie;
+ struct reset_ctl reset;
+ struct clk sys_ck;
+ struct phy phy;
+ u32 slot;
+};
+
+struct mtk_pcie {
+ void __iomem *base;
+ struct clk free_ck;
+ struct list_head ports;
+};
+
+static int mtk_pcie_config_address(struct udevice *udev, pci_dev_t bdf,
+ uint offset, void **paddress)
+{
+ struct mtk_pcie *pcie = dev_get_priv(udev);
+
+ writel(PCIE_CONF_ADDR(offset, bdf), pcie->base + PCIE_CFG_ADDR);
+ *paddress = pcie->base + PCIE_CFG_DATA + (offset & 3);
+
+ return 0;
+}
+
+static int mtk_pcie_read_config(struct udevice *bus, pci_dev_t bdf,
+ uint offset, ulong *valuep,
+ enum pci_size_t size)
+{
+ return pci_generic_mmap_read_config(bus, mtk_pcie_config_address,
+ bdf, offset, valuep, size);
+}
+
+static int mtk_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
+ uint offset, ulong value,
+ enum pci_size_t size)
+{
+ return pci_generic_mmap_write_config(bus, mtk_pcie_config_address,
+ bdf, offset, value, size);
+}
+
+static const struct dm_pci_ops mtk_pcie_ops = {
+ .read_config = mtk_pcie_read_config,
+ .write_config = mtk_pcie_write_config,
+};
+
+static void mtk_pcie_port_free(struct mtk_pcie_port *port)
+{
+ list_del(&port->list);
+ free(port);
+}
+
+static int mtk_pcie_startup_port(struct mtk_pcie_port *port)
+{
+ struct mtk_pcie *pcie = port->pcie;
+ u32 slot = PCI_DEV(port->slot << 11);
+ u32 val;
+ int err;
+
+ /* assert port PERST_N */
+ setbits_le32(pcie->base + PCIE_SYS_CFG, PCIE_PORT_PERST(port->slot));
+ /* de-assert port PERST_N */
+ clrbits_le32(pcie->base + PCIE_SYS_CFG, PCIE_PORT_PERST(port->slot));
+
+ /* 100ms timeout value should be enough for Gen1/2 training */
+ err = readl_poll_timeout(port->base + PCIE_LINK_STATUS, val,
+ !!(val & PCIE_PORT_LINKUP), 100000);
+ if (err)
+ return -ETIMEDOUT;
+
+ /* disable interrupt */
+ clrbits_le32(pcie->base + PCIE_INT_ENABLE,
+ PCIE_PORT_INT_EN(port->slot));
+
+ /* map to all DDR region. We need to set it before cfg operation. */
+ writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE,
+ port->base + PCIE_BAR0_SETUP);
+
+ /* configure class code and revision ID */
+ writel(PCIE_CLASS_CODE | PCIE_REVISION_ID, port->base + PCIE_CLASS);
+
+ /* configure FC credit */
+ writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, slot),
+ pcie->base + PCIE_CFG_ADDR);
+ clrsetbits_le32(pcie->base + PCIE_CFG_DATA, PCIE_FC_CREDIT_MASK,
+ PCIE_FC_CREDIT_VAL(0x806c));
+
+ /* configure RC FTS number to 250 when it leaves L0s */
+ writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, slot), pcie->base + PCIE_CFG_ADDR);
+ clrsetbits_le32(pcie->base + PCIE_CFG_DATA, PCIE_FTS_NUM_MASK,
+ PCIE_FTS_NUM_L0(0x50));
+
+ return 0;
+}
+
+static void mtk_pcie_enable_port(struct mtk_pcie_port *port)
+{
+ int err;
+
+ err = clk_enable(&port->sys_ck);
+ if (err)
+ goto exit;
+
+ err = reset_assert(&port->reset);
+ if (err)
+ goto exit;
+
+ err = reset_deassert(&port->reset);
+ if (err)
+ goto exit;
+
+ err = generic_phy_init(&port->phy);
+ if (err)
+ goto exit;
+
+ err = generic_phy_power_on(&port->phy);
+ if (err)
+ goto exit;
+
+ if (!mtk_pcie_startup_port(port))
+ return;
+
+ pr_err("Port%d link down\n", port->slot);
+exit:
+ mtk_pcie_port_free(port);
+}
+
+static int mtk_pcie_parse_port(struct udevice *dev, u32 slot)
+{
+ struct mtk_pcie *pcie = dev_get_priv(dev);
+ struct mtk_pcie_port *port;
+ char name[10];
+ int err;
+
+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ snprintf(name, sizeof(name), "port%d", slot);
+ port->base = dev_remap_addr_name(dev, name);
+ if (!port->base)
+ return -ENOENT;
+
+ snprintf(name, sizeof(name), "sys_ck%d", slot);
+ err = clk_get_by_name(dev, name, &port->sys_ck);
+ if (err)
+ return err;
+
+ err = reset_get_by_index(dev, slot, &port->reset);
+ if (err)
+ return err;
+
+ err = generic_phy_get_by_index(dev, slot, &port->phy);
+ if (err)
+ return err;
+
+ port->slot = slot;
+ port->pcie = pcie;
+
+ INIT_LIST_HEAD(&port->list);
+ list_add_tail(&port->list, &pcie->ports);
+
+ return 0;
+}
+
+static int mtk_pcie_probe(struct udevice *dev)
+{
+ struct mtk_pcie *pcie = dev_get_priv(dev);
+ struct mtk_pcie_port *port, *tmp;
+ ofnode subnode;
+ int err;
+
+ INIT_LIST_HEAD(&pcie->ports);
+
+ pcie->base = dev_remap_addr_name(dev, "subsys");
+ if (!pcie->base)
+ return -ENOENT;
+
+ err = clk_get_by_name(dev, "free_ck", &pcie->free_ck);
+ if (err)
+ return err;
+
+ /* enable top level clock */
+ err = clk_enable(&pcie->free_ck);
+ if (err)
+ return err;
+
+ dev_for_each_subnode(subnode, dev) {
+ struct fdt_pci_addr addr;
+ u32 slot = 0;
+
+ if (!ofnode_is_available(subnode))
+ continue;
+
+ err = ofnode_read_pci_addr(subnode, 0, "reg", &addr);
+ if (err)
+ return err;
+
+ slot = PCI_DEV(addr.phys_hi);
+
+ err = mtk_pcie_parse_port(dev, slot);
+ if (err)
+ return err;
+ }
+
+ /* enable each port, and then check link status */
+ list_for_each_entry_safe(port, tmp, &pcie->ports, list)
+ mtk_pcie_enable_port(port);
+
+ return 0;
+}
+
+static const struct udevice_id mtk_pcie_ids[] = {
+ { .compatible = "mediatek,mt7623-pcie", },
+ { }
+};
+
+U_BOOT_DRIVER(pcie_mediatek) = {
+ .name = "pcie_mediatek",
+ .id = UCLASS_PCI,
+ .of_match = mtk_pcie_ids,
+ .ops = &mtk_pcie_ops,
+ .probe = mtk_pcie_probe,
+ .priv_auto_alloc_size = sizeof(struct mtk_pcie),
+};
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 02312273e2..e317373a5c 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -205,4 +205,15 @@ config MT76X8_USB_PHY
This PHY is found on MT76x8 devices supporting USB.
+config PHY_MTK_TPHY
+ bool "MediaTek T-PHY Driver"
+ depends on PHY
+ depends on ARCH_MEDIATEK
+ help
+ MediaTek T-PHY driver supports usb2.0, usb3.0 ports, PCIe and
+ SATA, and meanwhile supports two version T-PHY which have
+ different banks layout, the T-PHY with shared banks between
+ multi-ports is first version, otherwise is second veriosn,
+ so you can easily distinguish them by banks layout.
+
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 3157f1b7ee..43ce62e08c 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
obj-$(CONFIG_MT76X8_USB_PHY) += mt76x8-usb-phy.o
obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o
+obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o
diff --git a/drivers/phy/phy-mtk-tphy.c b/drivers/phy/phy-mtk-tphy.c
new file mode 100644
index 0000000000..3701481256
--- /dev/null
+++ b/drivers/phy/phy-mtk-tphy.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2015 - 2019 MediaTek Inc.
+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
+ * Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <mapmem.h>
+#include <asm/io.h>
+
+#include <dt-bindings/phy/phy.h>
+
+/* version V1 sub-banks offset base address */
+/* banks shared by multiple phys */
+#define SSUSB_SIFSLV_V1_SPLLC 0x000 /* shared by u3 phys */
+#define SSUSB_SIFSLV_V1_CHIP 0x300 /* shared by u3 phys */
+/* u3/pcie/sata phy banks */
+#define SSUSB_SIFSLV_V1_U3PHYD 0x000
+#define SSUSB_SIFSLV_V1_U3PHYA 0x200
+
+#define U3P_U3_CHIP_GPIO_CTLD 0x0c
+#define P3C_REG_IP_SW_RST BIT(31)
+#define P3C_MCU_BUS_CK_GATE_EN BIT(30)
+#define P3C_FORCE_IP_SW_RST BIT(29)
+
+#define U3P_U3_CHIP_GPIO_CTLE 0x10
+#define P3C_RG_SWRST_U3_PHYD BIT(25)
+#define P3C_RG_SWRST_U3_PHYD_FORCE_EN BIT(24)
+
+#define U3P_U3_PHYA_REG0 0x000
+#define P3A_RG_CLKDRV_OFF GENMASK(3, 2)
+#define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2)
+
+#define U3P_U3_PHYA_REG1 0x004
+#define P3A_RG_CLKDRV_AMP GENMASK(31, 29)
+#define P3A_RG_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29)
+
+#define U3P_U3_PHYA_DA_REG0 0x100
+#define P3A_RG_XTAL_EXT_PE2H GENMASK(17, 16)
+#define P3A_RG_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16)
+#define P3A_RG_XTAL_EXT_PE1H GENMASK(13, 12)
+#define P3A_RG_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12)
+#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
+#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
+
+#define U3P_U3_PHYA_DA_REG4 0x108
+#define P3A_RG_PLL_DIVEN_PE2H GENMASK(21, 19)
+#define P3A_RG_PLL_BC_PE2H GENMASK(7, 6)
+#define P3A_RG_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6)
+
+#define U3P_U3_PHYA_DA_REG5 0x10c
+#define P3A_RG_PLL_BR_PE2H GENMASK(29, 28)
+#define P3A_RG_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28)
+#define P3A_RG_PLL_IC_PE2H GENMASK(15, 12)
+#define P3A_RG_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12)
+
+#define U3P_U3_PHYA_DA_REG6 0x110
+#define P3A_RG_PLL_IR_PE2H GENMASK(19, 16)
+#define P3A_RG_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16)
+
+#define U3P_U3_PHYA_DA_REG7 0x114
+#define P3A_RG_PLL_BP_PE2H GENMASK(19, 16)
+#define P3A_RG_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16)
+
+#define U3P_U3_PHYA_DA_REG20 0x13c
+#define P3A_RG_PLL_DELTA1_PE2H GENMASK(31, 16)
+#define P3A_RG_PLL_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16)
+
+#define U3P_U3_PHYA_DA_REG25 0x148
+#define P3A_RG_PLL_DELTA_PE2H GENMASK(15, 0)
+#define P3A_RG_PLL_DELTA_PE2H_VAL(x) (0xffff & (x))
+
+#define U3P_U3_PHYD_RXDET1 0x128
+#define P3D_RG_RXDET_STB2_SET GENMASK(17, 9)
+#define P3D_RG_RXDET_STB2_SET_VAL(x) ((0x1ff & (x)) << 9)
+
+#define U3P_U3_PHYD_RXDET2 0x12c
+#define P3D_RG_RXDET_STB2_SET_P3 GENMASK(8, 0)
+#define P3D_RG_RXDET_STB2_SET_P3_VAL(x) (0x1ff & (x))
+
+struct u3phy_banks {
+ void __iomem *spllc;
+ void __iomem *chip;
+ void __iomem *phyd; /* include u3phyd_bank2 */
+ void __iomem *phya; /* include u3phya_da */
+};
+
+struct mtk_phy_instance {
+ void __iomem *port_base;
+ const struct device_node *np;
+
+ struct u3phy_banks u3_banks;
+
+ /* reference clock of anolog phy */
+ struct clk ref_clk;
+ u32 index;
+ u8 type;
+};
+
+struct mtk_tphy {
+ void __iomem *sif_base;
+ struct mtk_phy_instance **phys;
+ int nphys;
+};
+
+static void pcie_phy_instance_init(struct mtk_tphy *tphy,
+ struct mtk_phy_instance *instance)
+{
+ struct u3phy_banks *u3_banks = &instance->u3_banks;
+
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG0,
+ P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H,
+ P3A_RG_XTAL_EXT_PE1H_VAL(0x2) |
+ P3A_RG_XTAL_EXT_PE2H_VAL(0x2));
+
+ /* ref clk drive */
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG1, P3A_RG_CLKDRV_AMP,
+ P3A_RG_CLKDRV_AMP_VAL(0x4));
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG0, P3A_RG_CLKDRV_OFF,
+ P3A_RG_CLKDRV_OFF_VAL(0x1));
+
+ /* SSC delta -5000ppm */
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG20,
+ P3A_RG_PLL_DELTA1_PE2H,
+ P3A_RG_PLL_DELTA1_PE2H_VAL(0x3c));
+
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG25,
+ P3A_RG_PLL_DELTA_PE2H,
+ P3A_RG_PLL_DELTA_PE2H_VAL(0x36));
+
+ /* change pll BW 0.6M */
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG5,
+ P3A_RG_PLL_BR_PE2H | P3A_RG_PLL_IC_PE2H,
+ P3A_RG_PLL_BR_PE2H_VAL(0x1) |
+ P3A_RG_PLL_IC_PE2H_VAL(0x1));
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG4,
+ P3A_RG_PLL_DIVEN_PE2H | P3A_RG_PLL_BC_PE2H,
+ P3A_RG_PLL_BC_PE2H_VAL(0x3));
+
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG6,
+ P3A_RG_PLL_IR_PE2H, P3A_RG_PLL_IR_PE2H_VAL(0x2));
+ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG7,
+ P3A_RG_PLL_BP_PE2H, P3A_RG_PLL_BP_PE2H_VAL(0xa));
+
+ /* Tx Detect Rx Timing: 10us -> 5us */
+ clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET1,
+ P3D_RG_RXDET_STB2_SET,
+ P3D_RG_RXDET_STB2_SET_VAL(0x10));
+ clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET2,
+ P3D_RG_RXDET_STB2_SET_P3,
+ P3D_RG_RXDET_STB2_SET_P3_VAL(0x10));
+
+ /* wait for PCIe subsys register to active */
+ udelay(3000);
+}
+
+static void pcie_phy_instance_power_on(struct mtk_tphy *tphy,
+ struct mtk_phy_instance *instance)
+{
+ struct u3phy_banks *bank = &instance->u3_banks;
+
+ clrbits_le32(bank->chip + U3P_U3_CHIP_GPIO_CTLD,
+ P3C_FORCE_IP_SW_RST | P3C_REG_IP_SW_RST);
+ clrbits_le32(bank->chip + U3P_U3_CHIP_GPIO_CTLE,
+ P3C_RG_SWRST_U3_PHYD_FORCE_EN | P3C_RG_SWRST_U3_PHYD);
+}
+
+static void pcie_phy_instance_power_off(struct mtk_tphy *tphy,
+ struct mtk_phy_instance *instance)
+
+{
+ struct u3phy_banks *bank = &instance->u3_banks;
+
+ setbits_le32(bank->chip + U3P_U3_CHIP_GPIO_CTLD,
+ P3C_FORCE_IP_SW_RST | P3C_REG_IP_SW_RST);
+ setbits_le32(bank->chip + U3P_U3_CHIP_GPIO_CTLE,
+ P3C_RG_SWRST_U3_PHYD_FORCE_EN | P3C_RG_SWRST_U3_PHYD);
+}
+
+static void phy_v1_banks_init(struct mtk_tphy *tphy,
+ struct mtk_phy_instance *instance)
+{
+ struct u3phy_banks *u3_banks = &instance->u3_banks;
+
+ switch (instance->type) {
+ case PHY_TYPE_PCIE:
+ u3_banks->spllc = tphy->sif_base + SSUSB_SIFSLV_V1_SPLLC;
+ u3_banks->chip = tphy->sif_base + SSUSB_SIFSLV_V1_CHIP;
+ u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD;
+ u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA;
+ break;
+ default:
+ return;
+ }
+}
+
+static int mtk_phy_init(struct phy *phy)
+{
+ struct mtk_tphy *tphy = dev_get_priv(phy->dev);
+ struct mtk_phy_instance *instance = tphy->phys[phy->id];
+ int ret;
+
+ /* we may use a fixed-clock here */
+ ret = clk_enable(&instance->ref_clk);
+ if (ret && ret != -ENOSYS)
+ return ret;
+
+ switch (instance->type) {
+ case PHY_TYPE_PCIE:
+ pcie_phy_instance_init(tphy, instance);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mtk_phy_power_on(struct phy *phy)
+{
+ struct mtk_tphy *tphy = dev_get_priv(phy->dev);
+ struct mtk_phy_instance *instance = tphy->phys[phy->id];
+
+ pcie_phy_instance_power_on(tphy, instance);
+
+ return 0;
+}
+
+static int mtk_phy_power_off(struct phy *phy)
+{
+ struct mtk_tphy *tphy = dev_get_priv(phy->dev);
+ struct mtk_phy_instance *instance = tphy->phys[phy->id];
+
+ pcie_phy_instance_power_off(tphy, instance);
+
+ return 0;
+}
+
+static int mtk_phy_exit(struct phy *phy)
+{
+ struct mtk_tphy *tphy = dev_get_priv(phy->dev);
+ struct mtk_phy_instance *instance = tphy->phys[phy->id];
+
+ clk_disable(&instance->ref_clk);
+
+ return 0;
+}
+
+static int mtk_phy_xlate(struct phy *phy,
+ struct ofnode_phandle_args *args)
+{
+ struct mtk_tphy *tphy = dev_get_priv(phy->dev);
+ struct mtk_phy_instance *instance = NULL;
+ const struct device_node *phy_np = ofnode_to_np(args->node);
+ u32 index;
+
+ if (!phy_np) {
+ dev_err(phy->dev, "null pointer phy node\n");
+ return -EINVAL;
+ }
+
+ if (args->args_count < 1) {
+ dev_err(phy->dev, "invalid number of cells in 'phy' property\n");
+ return -EINVAL;
+ }
+
+ for (index = 0; index < tphy->nphys; index++)
+ if (phy_np == tphy->phys[index]->np) {
+ instance = tphy->phys[index];
+ break;
+ }
+
+ if (!instance) {
+ dev_err(phy->dev, "failed to find appropriate phy\n");
+ return -EINVAL;
+ }
+
+ phy->id = index;
+ instance->type = args->args[1];
+ if (!(instance->type == PHY_TYPE_USB2 ||
+ instance->type == PHY_TYPE_USB3 ||
+ instance->type == PHY_TYPE_PCIE ||
+ instance->type == PHY_TYPE_SATA)) {
+ dev_err(phy->dev, "unsupported device type\n");
+ return -EINVAL;
+ }
+
+ phy_v1_banks_init(tphy, instance);
+
+ return 0;
+}
+
+static const struct phy_ops mtk_tphy_ops = {
+ .init = mtk_phy_init,
+ .exit = mtk_phy_exit,
+ .power_on = mtk_phy_power_on,
+ .power_off = mtk_phy_power_off,
+ .of_xlate = mtk_phy_xlate,
+};
+
+static int mtk_tphy_probe(struct udevice *dev)
+{
+ struct mtk_tphy *tphy = dev_get_priv(dev);
+ ofnode subnode;
+ int index = 0;
+
+ dev_for_each_subnode(subnode, dev)
+ tphy->nphys++;
+
+ tphy->phys = devm_kcalloc(dev, tphy->nphys, sizeof(*tphy->phys),
+ GFP_KERNEL);
+ if (!tphy->phys)
+ return -ENOMEM;
+
+ tphy->sif_base = dev_read_addr_ptr(dev);
+ if (!tphy->sif_base)
+ return -ENOENT;
+
+ dev_for_each_subnode(subnode, dev) {
+ struct mtk_phy_instance *instance;
+ fdt_addr_t addr;
+ int err;
+
+ instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+ if (!instance)
+ return -ENOMEM;
+
+ addr = ofnode_get_addr(subnode);
+ if (addr == FDT_ADDR_T_NONE)
+ return -ENOMEM;
+
+ instance->port_base = map_sysmem(addr, 0);
+ instance->index = index;
+ instance->np = ofnode_to_np(subnode);
+ tphy->phys[index] = instance;
+ index++;
+
+ err = clk_get_by_index_nodev(subnode, 0, &instance->ref_clk);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id mtk_tphy_id_table[] = {
+ { .compatible = "mediatek,generic-tphy-v1", },
+ { }
+};
+
+U_BOOT_DRIVER(mtk_tphy) = {
+ .name = "mtk-tphy",
+ .id = UCLASS_PHY,
+ .of_match = mtk_tphy_id_table,
+ .ops = &mtk_tphy_ops,
+ .probe = mtk_tphy_probe,
+ .priv_auto_alloc_size = sizeof(struct mtk_tphy),
+};
diff --git a/drivers/power/regulator/regulator_common.c b/drivers/power/regulator/regulator_common.c
index 3dabbe2a85..2041086567 100644
--- a/drivers/power/regulator/regulator_common.c
+++ b/drivers/power/regulator/regulator_common.c
@@ -12,10 +12,15 @@ int regulator_common_ofdata_to_platdata(struct udevice *dev,
struct regulator_common_platdata *dev_pdata, const char *enable_gpio_name)
{
struct gpio_desc *gpio;
+ struct dm_regulator_uclass_platdata *uc_pdata;
int flags = GPIOD_IS_OUT;
int ret;
- if (dev_read_bool(dev, "enable-active-high"))
+ uc_pdata = dev_get_uclass_platdata(dev);
+
+ if (!dev_read_bool(dev, "enable-active-high"))
+ flags |= GPIOD_ACTIVE_LOW;
+ if (uc_pdata->boot_on)
flags |= GPIOD_IS_OUT_ACTIVE;
/* Get optional enable GPIO desc */
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 8dd3213d48..b8ca2bdedd 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -67,7 +67,7 @@ config ATMEL_SPI
config BCM63XX_HSSPI
bool "BCM63XX HSSPI driver"
- depends on ARCH_BMIPS
+ depends on (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158)
help
Enable the BCM6328 HSSPI driver. This driver can be used to
access the SPI NOR flash on platforms embedding this Broadcom
diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c
index 4f527fa74a..e82b80c107 100644
--- a/drivers/spi/bcm63xx_hsspi.c
+++ b/drivers/spi/bcm63xx_hsspi.c
@@ -120,9 +120,9 @@ static int bcm63xx_hsspi_set_mode(struct udevice *bus, uint mode)
/* clock polarity */
if (mode & SPI_CPOL)
- setbits_be32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK);
+ setbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK);
else
- clrbits_be32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK);
+ clrbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK);
return 0;
}
@@ -146,7 +146,7 @@ static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv,
set = DIV_ROUND_UP(2048, set);
set &= SPI_PFL_CLK_FREQ_MASK;
set |= SPI_PFL_CLK_RSTLOOP_MASK;
- writel_be(set, priv->regs + SPI_PFL_CLK_REG(plat->cs));
+ writel(set, priv->regs + SPI_PFL_CLK_REG(plat->cs));
/* profile signal */
set = 0;
@@ -164,7 +164,7 @@ static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv,
if (priv->speed > SPI_MAX_SYNC_CLOCK)
set |= SPI_PFL_SIG_ASYNCIN_MASK;
- clrsetbits_be32(priv->regs + SPI_PFL_SIG_REG(plat->cs), clr, set);
+ clrsetbits_32(priv->regs + SPI_PFL_SIG_REG(plat->cs), clr, set);
/* global control */
set = 0;
@@ -182,13 +182,13 @@ static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv,
else
set |= BIT(!plat->cs);
- clrsetbits_be32(priv->regs + SPI_CTL_REG, clr, set);
+ clrsetbits_32(priv->regs + SPI_CTL_REG, clr, set);
}
static void bcm63xx_hsspi_deactivate_cs(struct bcm63xx_hsspi_priv *priv)
{
/* restore cs polarities */
- clrsetbits_be32(priv->regs + SPI_CTL_REG, SPI_CTL_CS_POL_MASK,
+ clrsetbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CS_POL_MASK,
priv->cs_pols);
}
@@ -247,7 +247,7 @@ static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen,
SPI_PFL_MODE_MDWRSZ_MASK;
if (plat->mode & SPI_3WIRE)
val |= SPI_PFL_MODE_3WIRE_MASK;
- writel_be(val, priv->regs + SPI_PFL_MODE_REG(plat->cs));
+ writel(val, priv->regs + SPI_PFL_MODE_REG(plat->cs));
/* transfer loop */
while (data_bytes > 0) {
@@ -262,7 +262,7 @@ static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen,
}
/* set fifo operation */
- writew_be(opcode | (curr_step & HSSPI_FIFO_OP_BYTES_MASK),
+ writew(cpu_to_be16(opcode | (curr_step & HSSPI_FIFO_OP_BYTES_MASK)),
priv->regs + HSSPI_FIFO_OP_REG);
/* issue the transfer */
@@ -271,10 +271,10 @@ static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen,
SPI_CMD_PFL_MASK;
val |= (!plat->cs << SPI_CMD_SLAVE_SHIFT) &
SPI_CMD_SLAVE_MASK;
- writel_be(val, priv->regs + SPI_CMD_REG);
+ writel(val, priv->regs + SPI_CMD_REG);
/* wait for completion */
- ret = wait_for_bit_be32(priv->regs + SPI_STAT_REG,
+ ret = wait_for_bit_32(priv->regs + SPI_STAT_REG,
SPI_STAT_SRCBUSY_MASK, false,
1000, false);
if (ret) {
@@ -349,48 +349,47 @@ static int bcm63xx_hsspi_probe(struct udevice *dev)
return ret;
ret = clk_enable(&clk);
- if (ret < 0)
+ if (ret < 0 && ret != -ENOSYS)
return ret;
ret = clk_free(&clk);
- if (ret < 0)
+ if (ret < 0 && ret != -ENOSYS)
return ret;
/* get clock rate */
ret = clk_get_by_name(dev, "pll", &clk);
- if (ret < 0)
+ if (ret < 0 && ret != -ENOSYS)
return ret;
priv->clk_rate = clk_get_rate(&clk);
ret = clk_free(&clk);
- if (ret < 0)
+ if (ret < 0 && ret != -ENOSYS)
return ret;
/* perform reset */
ret = reset_get_by_index(dev, 0, &rst_ctl);
- if (ret < 0)
- return ret;
-
- ret = reset_deassert(&rst_ctl);
- if (ret < 0)
- return ret;
+ if (ret >= 0) {
+ ret = reset_deassert(&rst_ctl);
+ if (ret < 0)
+ return ret;
+ }
ret = reset_free(&rst_ctl);
if (ret < 0)
return ret;
/* initialize hardware */
- writel_be(0, priv->regs + SPI_IR_MASK_REG);
+ writel(0, priv->regs + SPI_IR_MASK_REG);
/* clear pending interrupts */
- writel_be(SPI_IR_CLEAR_ALL, priv->regs + SPI_IR_STAT_REG);
+ writel(SPI_IR_CLEAR_ALL, priv->regs + SPI_IR_STAT_REG);
/* enable clk gate */
- setbits_be32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_GATE_MASK);
+ setbits_32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_GATE_MASK);
/* read default cs polarities */
- priv->cs_pols = readl_be(priv->regs + SPI_CTL_REG) &
+ priv->cs_pols = readl(priv->regs + SPI_CTL_REG) &
SPI_CTL_CS_POL_MASK;
return 0;