diff options
author | Tom Rini <trini@konsulko.com> | 2019-10-12 10:10:59 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2019-10-12 10:10:59 -0400 |
commit | 0c9cc5155cb5027ae17ace986f349e2f0d1fb9a3 (patch) | |
tree | 49c59081ca15147dcc311880648732a5d4fc019a /drivers | |
parent | 36317705cb5ab43db25fede2446d2352de527630 (diff) | |
parent | 7d2dc6af540fad77bff2a3ff16cdc2f9d9df72eb (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.c | 1 | ||||
-rw-r--r-- | drivers/ata/ahci.c | 11 | ||||
-rw-r--r-- | drivers/pci/Kconfig | 8 | ||||
-rw-r--r-- | drivers/pci/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/pcie_mediatek.c | 279 | ||||
-rw-r--r-- | drivers/phy/Kconfig | 11 | ||||
-rw-r--r-- | drivers/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/phy/phy-mtk-tphy.c | 362 | ||||
-rw-r--r-- | drivers/power/regulator/regulator_common.c | 7 | ||||
-rw-r--r-- | drivers/spi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/spi/bcm63xx_hsspi.c | 47 |
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; |