aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.c3
-rw-r--r--drivers/block/ide.c152
-rw-r--r--drivers/firmware/psci.c68
-rw-r--r--drivers/misc/Kconfig5
-rw-r--r--drivers/net/Kconfig7
-rw-r--r--drivers/net/calxedaxgmac.c192
-rw-r--r--drivers/net/octeontx/bgx.c20
-rw-r--r--drivers/net/octeontx/smi.c2
-rw-r--r--drivers/power/regulator/Kconfig10
-rw-r--r--drivers/power/regulator/Makefile1
-rw-r--r--drivers/power/regulator/anatop_regulator.c278
-rw-r--r--drivers/sysreset/sysreset-uclass.c11
-rw-r--r--drivers/sysreset/sysreset_psci.c8
13 files changed, 561 insertions, 196 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 2ef21ec508a..98b288254be 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1190,6 +1190,9 @@ int ahci_probe_scsi(struct udevice *ahci_dev, ulong base)
*/
uc_plat->max_id = max_t(unsigned long, uc_priv->n_ports,
uc_plat->max_id);
+ /* If port count is less than max_id, update max_id */
+ if (uc_priv->n_ports < uc_plat->max_id)
+ uc_plat->max_id = uc_priv->n_ports;
return 0;
}
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 43a0776099c..862a85bc87b 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -130,56 +130,38 @@ OUT:
* ATAPI Support
*/
-#if defined(CONFIG_IDE_SWAP_IO)
/* since ATAPI may use commands with not 4 bytes alligned length
* we have our own transfer functions, 2 bytes alligned */
__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
{
+ uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
ushort *dbuf;
- volatile ushort *pbuf;
- pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
dbuf = (ushort *)sect_buf;
- debug("in output data shorts base for read is %lx\n",
- (unsigned long) pbuf);
+ debug("in output data shorts base for read is %p\n", (void *)paddr);
while (shorts--) {
EIEIO;
- *pbuf = *dbuf++;
+ outw(cpu_to_le16(*dbuf++), paddr);
}
}
__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
{
+ uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
ushort *dbuf;
- volatile ushort *pbuf;
- pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
dbuf = (ushort *)sect_buf;
- debug("in input data shorts base for read is %lx\n",
- (unsigned long) pbuf);
+ debug("in input data shorts base for read is %p\n", (void *)paddr);
while (shorts--) {
EIEIO;
- *dbuf++ = *pbuf;
+ *dbuf++ = le16_to_cpu(inw(paddr));
}
}
-#else /* ! CONFIG_IDE_SWAP_IO */
-__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts)
-{
- outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
-}
-
-__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
-{
- insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
-}
-
-#endif /* CONFIG_IDE_SWAP_IO */
-
/*
* Wait until (Status & mask) == res, or timeout (in ms)
* Return last status
@@ -636,19 +618,6 @@ static void ide_ident(struct blk_desc *dev_desc)
sizeof(dev_desc->vendor));
ident_cpy((unsigned char *)dev_desc->product, iop.serial_no,
sizeof(dev_desc->product));
-#ifdef __LITTLE_ENDIAN
- /*
- * firmware revision, model, and serial number have Big Endian Byte
- * order in Word. Convert all three to little endian.
- *
- * See CF+ and CompactFlash Specification Revision 2.0:
- * 6.2.1.6: Identify Drive, Table 39 for more details
- */
-
- strswab(dev_desc->revision);
- strswab(dev_desc->vendor);
- strswab(dev_desc->product);
-#endif /* __LITTLE_ENDIAN */
if ((iop.config & 0x0080) == 0x0080)
dev_desc->removable = 1;
@@ -662,26 +631,22 @@ static void ide_ident(struct blk_desc *dev_desc)
}
#endif /* CONFIG_ATAPI */
-#ifdef __BIG_ENDIAN
- /* swap shorts */
- dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16);
-#else /* ! __BIG_ENDIAN */
- /*
- * do not swap shorts on little endian
- *
- * See CF+ and CompactFlash Specification Revision 2.0:
- * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details.
- */
- dev_desc->lba = iop.lba_capacity;
-#endif /* __BIG_ENDIAN */
+ iop.lba_capacity[0] = be16_to_cpu(iop.lba_capacity[0]);
+ iop.lba_capacity[1] = be16_to_cpu(iop.lba_capacity[1]);
+ dev_desc->lba =
+ ((unsigned long)iop.lba_capacity[0]) |
+ ((unsigned long)iop.lba_capacity[1] << 16);
#ifdef CONFIG_LBA48
if (iop.command_set_2 & 0x0400) { /* LBA 48 support */
dev_desc->lba48 = 1;
- dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] |
- ((unsigned long long) iop.lba48_capacity[1] << 16) |
- ((unsigned long long) iop.lba48_capacity[2] << 32) |
- ((unsigned long long) iop.lba48_capacity[3] << 48);
+ for (int i = 0; i < 4; i++)
+ iop.lba48_capacity[i] = be16_to_cpu(iop.lba48_capacity[i]);
+ dev_desc->lba =
+ ((unsigned long long)iop.lba48_capacity[0] |
+ ((unsigned long long)iop.lba48_capacity[1] << 16) |
+ ((unsigned long long)iop.lba48_capacity[2] << 32) |
+ ((unsigned long long)iop.lba48_capacity[3] << 48));
} else {
dev_desc->lba48 = 0;
}
@@ -846,90 +811,59 @@ void ide_init(void)
#endif
}
-/* We only need to swap data if we are running on a big endian cpu. */
-#if defined(__LITTLE_ENDIAN)
__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
{
- ide_input_data(dev, sect_buf, words);
-}
-#else
-__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
-{
- volatile ushort *pbuf =
- (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
+ uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
ushort *dbuf = (ushort *)sect_buf;
- debug("in input swap data base for read is %lx\n",
- (unsigned long) pbuf);
+ debug("in input swap data base for read is %p\n", (void *)paddr);
while (words--) {
-#ifdef __MIPS__
- *dbuf++ = swab16p((u16 *)pbuf);
- *dbuf++ = swab16p((u16 *)pbuf);
-#else
- *dbuf++ = ld_le16(pbuf);
- *dbuf++ = ld_le16(pbuf);
-#endif /* !MIPS */
+ EIEIO;
+ *dbuf++ = be16_to_cpu(inw(paddr));
+ EIEIO;
+ *dbuf++ = be16_to_cpu(inw(paddr));
}
}
-#endif /* __LITTLE_ENDIAN */
-
-#if defined(CONFIG_IDE_SWAP_IO)
__weak void ide_output_data(int dev, const ulong *sect_buf, int words)
{
+#if defined(CONFIG_IDE_AHB)
+ ide_write_data(dev, sect_buf, words);
+#else
+ uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
ushort *dbuf;
- volatile ushort *pbuf;
- pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
dbuf = (ushort *)sect_buf;
while (words--) {
EIEIO;
- *pbuf = *dbuf++;
+ outw(cpu_to_le16(*dbuf++), paddr);
EIEIO;
- *pbuf = *dbuf++;
+ outw(cpu_to_le16(*dbuf++), paddr);
}
+#endif /* CONFIG_IDE_AHB */
}
-#else /* ! CONFIG_IDE_SWAP_IO */
-__weak void ide_output_data(int dev, const ulong *sect_buf, int words)
-{
-#if defined(CONFIG_IDE_AHB)
- ide_write_data(dev, sect_buf, words);
-#else
- outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
-#endif
-}
-#endif /* CONFIG_IDE_SWAP_IO */
-#if defined(CONFIG_IDE_SWAP_IO)
__weak void ide_input_data(int dev, ulong *sect_buf, int words)
{
+#if defined(CONFIG_IDE_AHB)
+ ide_read_data(dev, sect_buf, words);
+#else
+ uintptr_t paddr = (ATA_CURR_BASE(dev) + ATA_DATA_REG);
ushort *dbuf;
- volatile ushort *pbuf;
- pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG);
dbuf = (ushort *)sect_buf;
- debug("in input data base for read is %lx\n", (unsigned long) pbuf);
+ debug("in input data base for read is %p\n", (void *)paddr);
while (words--) {
EIEIO;
- *dbuf++ = *pbuf;
+ *dbuf++ = le16_to_cpu(inw(paddr));
EIEIO;
- *dbuf++ = *pbuf;
+ *dbuf++ = le16_to_cpu(inw(paddr));
}
+#endif /* CONFIG_IDE_AHB */
}
-#else /* ! CONFIG_IDE_SWAP_IO */
-__weak void ide_input_data(int dev, ulong *sect_buf, int words)
-{
-#if defined(CONFIG_IDE_AHB)
- ide_read_data(dev, sect_buf, words);
-#else
- insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1);
-#endif
-}
-
-#endif /* CONFIG_IDE_SWAP_IO */
#ifdef CONFIG_BLK
ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
@@ -1019,14 +953,14 @@ ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
if (lba48) {
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
- ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT);
+ ide_outb(device, ATA_COMMAND, ATA_CMD_PIO_READ_EXT);
} else
#endif
{
ide_outb(device, ATA_DEV_HD, ATA_LBA |
ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
- ide_outb(device, ATA_COMMAND, ATA_CMD_READ);
+ ide_outb(device, ATA_COMMAND, ATA_CMD_PIO_READ);
}
udelay(50);
@@ -1116,14 +1050,14 @@ ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
if (lba48) {
ide_outb(device, ATA_DEV_HD,
ATA_LBA | ATA_DEVICE(device));
- ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
+ ide_outb(device, ATA_COMMAND, ATA_CMD_PIO_WRITE_EXT);
} else
#endif
{
ide_outb(device, ATA_DEV_HD, ATA_LBA |
ATA_DEVICE(device) | ((blknr >> 24) & 0xF));
- ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE);
+ ide_outb(device, ATA_COMMAND, ATA_CMD_PIO_WRITE);
}
udelay(50);
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 68953cc4f4e..be57552aba0 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -13,6 +13,7 @@
#include <log.h>
#include <dm/lists.h>
#include <efi_loader.h>
+#include <sysreset.h>
#include <linux/delay.h>
#include <linux/libfdt.h>
#include <linux/arm-smccc.h>
@@ -26,6 +27,18 @@
#define PSCI_METHOD_HVC 1
#define PSCI_METHOD_SMC 2
+/*
+ * While a 64-bit OS can make calls with SMC32 calling conventions, for some
+ * calls it is necessary to use SMC64 to pass or return 64-bit values.
+ * For such calls PSCI_FN_NATIVE(version, name) will choose the appropriate
+ * (native-width) function ID.
+ */
+#if defined(CONFIG_ARM64)
+#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name
+#else
+#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name
+#endif
+
#if CONFIG_IS_ENABLED(EFI_LOADER)
int __efi_runtime_data psci_method;
#else
@@ -53,6 +66,34 @@ unsigned long __efi_runtime invoke_psci_fn
return res.a0;
}
+static int psci_features(u32 psci_func_id)
+{
+ return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,
+ psci_func_id, 0, 0);
+}
+
+static u32 psci_0_2_get_version(void)
+{
+ return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
+}
+
+static bool psci_is_system_reset2_supported(void)
+{
+ int ret;
+ u32 ver;
+
+ ver = psci_0_2_get_version();
+
+ if (PSCI_VERSION_MAJOR(ver) >= 1) {
+ ret = psci_features(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2));
+
+ if (ret != PSCI_RET_NOT_SUPPORTED)
+ return true;
+ }
+
+ return false;
+}
+
static int psci_bind(struct udevice *dev)
{
/* No SYSTEM_RESET support for PSCI 0.1 */
@@ -141,6 +182,33 @@ void reset_misc(void)
}
#endif /* CONFIG_PSCI_RESET */
+void psci_sys_reset(u32 type)
+{
+ bool reset2_supported;
+
+ do_psci_probe();
+
+ reset2_supported = psci_is_system_reset2_supported();
+
+ if (type == SYSRESET_WARM && reset2_supported) {
+ /*
+ * reset_type[31] = 0 (architectural)
+ * reset_type[30:0] = 0 (SYSTEM_WARM_RESET)
+ * cookie = 0 (ignored by the implementation)
+ */
+ invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), 0, 0, 0);
+ } else {
+ invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
+ }
+}
+
+void psci_sys_poweroff(void)
+{
+ do_psci_probe();
+
+ invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+}
+
#ifdef CONFIG_CMD_POWEROFF
int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c650471ff7c..997b7132211 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -211,10 +211,9 @@ config FSL_SEC_MON
like software violations or hardware security violations.
config IRQ
- bool "Intel Interrupt controller"
- depends on X86 || SANDBOX
+ bool "Interrupt controller"
help
- This enables support for Intel interrupt controllers, including ITSS.
+ This enables support for interrupt controllers, including ITSS.
Some devices have extra features, such as Apollo Lake. The
device has its own uclass since there are several operations
involved.
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 72822eaec4b..382639044bf 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -180,6 +180,13 @@ config CORTINA_NI_ENET
This driver supports the Cortina-Access Ethernet MAC for
all supported CAxxxx SoCs.
+config CALXEDA_XGMAC
+ bool "Calxeda XGMAC support"
+ depends on DM_ETH
+ help
+ This driver supports the XGMAC in Calxeda Highbank and Midway
+ machines.
+
config DWC_ETH_QOS
bool "Synopsys DWC Ethernet QOS device support"
depends on DM_ETH
diff --git a/drivers/net/calxedaxgmac.c b/drivers/net/calxedaxgmac.c
index 8b2ee49b441..b98d709117a 100644
--- a/drivers/net/calxedaxgmac.c
+++ b/drivers/net/calxedaxgmac.c
@@ -10,6 +10,8 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <asm/io.h>
+#include <dm.h>
+#include <dm/device-internal.h> /* for dev_set_priv() */
#define TX_NUM_DESC 1
#define RX_NUM_DESC 32
@@ -212,6 +214,18 @@ struct xgmac_dma_desc {
__le32 res[3];
};
+static struct xgmac_regs *xgmac_get_regs(struct eth_pdata *pdata)
+{
+ /*
+ * We use PHYS_64BIT on Highbank, so phys_addr_t is bigger than
+ * a pointer. U-Boot doesn't use LPAE (not even the MMU on highbank),
+ * so we can't access anything above 4GB.
+ * We have a check in the probe function below the ensure this,
+ * so casting to a 32-bit pointer type is fine here.
+ */
+ return (struct xgmac_regs *)(uintptr_t)pdata->iobase;
+}
+
/* XGMAC Descriptor Access Helpers */
static inline void desc_set_buf_len(struct xgmac_dma_desc *p, u32 buf_sz)
{
@@ -304,8 +318,6 @@ struct calxeda_eth_dev {
u32 tx_currdesc;
u32 rx_currdesc;
-
- struct eth_device *dev;
} __aligned(32);
/*
@@ -313,10 +325,10 @@ struct calxeda_eth_dev {
* advanced descriptors.
*/
-static void init_rx_desc(struct calxeda_eth_dev *priv)
+static void init_rx_desc(struct eth_pdata *pdata, struct calxeda_eth_dev *priv)
{
struct xgmac_dma_desc *rxdesc = priv->rx_chain;
- struct xgmac_regs *regs = (struct xgmac_regs *)priv->dev->iobase;
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
void *rxbuffer = priv->rxbuffer;
int i;
@@ -330,17 +342,16 @@ static void init_rx_desc(struct calxeda_eth_dev *priv)
}
}
-static void init_tx_desc(struct calxeda_eth_dev *priv)
+static void init_tx_desc(struct eth_pdata *pdata, struct calxeda_eth_dev *priv)
{
- struct xgmac_regs *regs = (struct xgmac_regs *)priv->dev->iobase;
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
desc_init_tx_desc(priv->tx_chain, TX_NUM_DESC);
writel((ulong)priv->tx_chain, &regs->txdesclist);
}
-static int xgmac_reset(struct eth_device *dev)
+static int xgmac_reset(struct xgmac_regs *regs)
{
- struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
int timeout = MAC_TIMEOUT;
u32 value;
@@ -356,27 +367,28 @@ static int xgmac_reset(struct eth_device *dev)
return timeout;
}
-static void xgmac_hwmacaddr(struct eth_device *dev)
+static void xgmac_hwmacaddr(struct eth_pdata *pdata)
{
- struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
u32 macaddr[2];
- memcpy(macaddr, dev->enetaddr, 6);
+ memcpy(macaddr, pdata->enetaddr, ARP_HLEN);
writel(macaddr[1], &regs->macaddr[0].hi);
writel(macaddr[0], &regs->macaddr[0].lo);
}
-static int xgmac_init(struct eth_device *dev, struct bd_info * bis)
+static int xgmac_eth_start(struct udevice *dev)
{
- struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
- struct calxeda_eth_dev *priv = dev->priv;
- int value;
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
+ struct calxeda_eth_dev *priv = dev_get_priv(dev);
+ u32 value;
- if (xgmac_reset(dev) < 0)
- return -1;
+ if (xgmac_reset(regs) < 0)
+ return -ETIMEDOUT;
/* set the hardware MAC address */
- xgmac_hwmacaddr(dev);
+ xgmac_hwmacaddr(pdata);
/* set the AXI bus modes */
value = XGMAC_DMA_BUSMODE_ATDS |
@@ -401,8 +413,8 @@ static int xgmac_init(struct eth_device *dev, struct bd_info * bis)
writel(value, &regs->flow_control);
/* Initialize the descriptor chains */
- init_rx_desc(priv);
- init_tx_desc(priv);
+ init_rx_desc(pdata, priv);
+ init_tx_desc(pdata, priv);
/* must set to 0, or when started up will cause issues */
priv->tx_currdesc = 0;
@@ -425,10 +437,11 @@ static int xgmac_init(struct eth_device *dev, struct bd_info * bis)
return 0;
}
-static int xgmac_tx(struct eth_device *dev, void *packet, int length)
+static int xgmac_tx(struct udevice *dev, void *packet, int length)
{
- struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
- struct calxeda_eth_dev *priv = dev->priv;
+ struct calxeda_eth_dev *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
u32 currdesc = priv->tx_currdesc;
struct xgmac_dma_desc *txdesc = &priv->tx_chain[currdesc];
int timeout;
@@ -453,35 +466,45 @@ static int xgmac_tx(struct eth_device *dev, void *packet, int length)
return 0;
}
-static int xgmac_rx(struct eth_device *dev)
+static int xgmac_rx(struct udevice *dev, int flags, uchar **packetp)
{
- struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
- struct calxeda_eth_dev *priv = dev->priv;
+ struct calxeda_eth_dev *priv = dev_get_priv(dev);
u32 currdesc = priv->rx_currdesc;
struct xgmac_dma_desc *rxdesc = &priv->rx_chain[currdesc];
int length = 0;
/* check if the host has the desc */
if (desc_get_owner(rxdesc))
- return -1; /* something bad happened */
+ return -EAGAIN; /* the MAC is still chewing on it */
length = desc_get_rx_frame_len(rxdesc);
+ *packetp = desc_get_buf_addr(rxdesc);
- net_process_received_packet(desc_get_buf_addr(rxdesc), length);
+ priv->rx_currdesc = (currdesc + 1) & (RX_NUM_DESC - 1);
+
+ return length;
+}
+
+static int xgmac_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
+ struct calxeda_eth_dev *priv = dev_get_priv(dev);
+ u32 rxdesc = ((char *)packet - priv->rxbuffer) / ETH_BUF_SZ;
+ struct xgmac_dma_desc *p = &priv->rx_chain[rxdesc];
/* set descriptor back to owned by XGMAC */
- desc_set_rx_owner(rxdesc);
+ desc_set_rx_owner(p);
writel(1, &regs->rxpoll);
- priv->rx_currdesc = (currdesc + 1) & (RX_NUM_DESC - 1);
-
- return length;
+ return 0;
}
-static void xgmac_halt(struct eth_device *dev)
+static void xgmac_eth_stop(struct udevice *dev)
{
- struct xgmac_regs *regs = (struct xgmac_regs *)dev->iobase;
- struct calxeda_eth_dev *priv = dev->priv;
+ struct calxeda_eth_dev *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
int value;
/* Disable TX/RX */
@@ -499,47 +522,88 @@ static void xgmac_halt(struct eth_device *dev)
priv->rx_currdesc = 0;
}
-int calxedaxgmac_initialize(u32 id, ulong base_addr)
+/*
+ * Changing the MAC address is not a good idea, as the fabric would
+ * need to know about this as well (it does not learn MAC addresses).
+ */
+static int xgmac_eth_write_hwaddr(struct udevice *dev)
+{
+ return -ENOSYS;
+}
+
+static int xgmac_eth_read_rom_hwaddr(struct udevice *dev)
{
- struct eth_device *dev;
- struct calxeda_eth_dev *priv;
- struct xgmac_regs *regs;
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
u32 macaddr[2];
- regs = (struct xgmac_regs *)base_addr;
+ /* The MAC address is already configured, so read it from registers. */
+ macaddr[1] = readl(&regs->macaddr[0].hi);
+ macaddr[0] = readl(&regs->macaddr[0].lo);
+ memcpy(pdata->enetaddr, macaddr, ARP_HLEN);
- /* check hardware version */
- if (readl(&regs->version) != 0x1012)
- return -1;
+ return 0;
+}
- dev = malloc(sizeof(*dev));
- if (!dev)
- return 0;
- memset(dev, 0, sizeof(*dev));
+static int xgmac_ofdata_to_platdata(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct calxeda_eth_dev *priv;
/* Structure must be aligned, because it contains the descriptors */
priv = memalign(32, sizeof(*priv));
- if (!priv) {
- free(dev);
- return 0;
+ if (!priv)
+ return -ENOMEM;
+ dev_set_priv(dev, priv);
+
+ pdata->iobase = devfdt_get_addr(dev);
+ if (pdata->iobase == FDT_ADDR_T_NONE) {
+ printf("%s: Cannot find XGMAC base address\n", __func__);
+ return -EINVAL;
+ }
+ if (pdata->iobase >= (1ULL << 32)) {
+ printf("%s: MMIO base address cannot be above 4GB\n", __func__);
+ return -EINVAL;
}
- dev->iobase = (int)base_addr;
- dev->priv = priv;
- priv->dev = dev;
- sprintf(dev->name, "xgmac%d", id);
+ return 0;
+}
- /* The MAC address is already configured, so read it from registers. */
- macaddr[1] = readl(&regs->macaddr[0].hi);
- macaddr[0] = readl(&regs->macaddr[0].lo);
- memcpy(dev->enetaddr, macaddr, 6);
+static int xgmac_eth_probe(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct xgmac_regs *regs = xgmac_get_regs(pdata);
- dev->init = xgmac_init;
- dev->send = xgmac_tx;
- dev->recv = xgmac_rx;
- dev->halt = xgmac_halt;
+ /* check hardware version */
+ if (readl(&regs->version) != 0x1012)
+ return -ENODEV;
- eth_register(dev);
+ xgmac_eth_read_rom_hwaddr(dev);
- return 1;
+ return 0;
}
+
+static const struct eth_ops xgmac_eth_ops = {
+ .start = xgmac_eth_start,
+ .send = xgmac_tx,
+ .recv = xgmac_rx,
+ .free_pkt = xgmac_free_pkt,
+ .stop = xgmac_eth_stop,
+ .write_hwaddr = xgmac_eth_write_hwaddr,
+ .read_rom_hwaddr = xgmac_eth_read_rom_hwaddr,
+};
+
+static const struct udevice_id xgmac_eth_ids[] = {
+ { .compatible = "calxeda,hb-xgmac" },
+ { }
+};
+
+U_BOOT_DRIVER(eth_xgmac) = {
+ .name = "eth_xgmac",
+ .id = UCLASS_ETH,
+ .of_match = xgmac_eth_ids,
+ .of_to_plat = xgmac_ofdata_to_platdata,
+ .probe = xgmac_eth_probe,
+ .ops = &xgmac_eth_ops,
+ .plat_auto = sizeof(struct eth_pdata),
+};
diff --git a/drivers/net/octeontx/bgx.c b/drivers/net/octeontx/bgx.c
index 2ea54be84da..a5c0c9fe2b3 100644
--- a/drivers/net/octeontx/bgx.c
+++ b/drivers/net/octeontx/bgx.c
@@ -36,7 +36,6 @@ struct lmac {
int dmac;
u8 mac[6];
bool link_up;
- bool init_pend;
int lmacid; /* ID within BGX */
int phy_addr; /* ID on board */
struct udevice *dev;
@@ -849,6 +848,7 @@ static int bgx_lmac_enable(struct bgx *bgx, int8_t lmacid)
u64 cfg;
lmac = &bgx->lmac[lmacid];
+ lmac->bgx = bgx;
debug("%s: lmac: %p, lmacid = %d\n", __func__, lmac, lmacid);
@@ -895,16 +895,6 @@ int bgx_poll_for_link(int node, int bgx_idx, int lmacid)
debug("%s: %d, lmac: %d/%d/%d %p\n",
__FILE__, __LINE__,
node, bgx_idx, lmacid, lmac);
- if (lmac->init_pend) {
- ret = bgx_lmac_enable(lmac->bgx, lmacid);
- if (ret < 0) {
- printf("BGX%d LMAC%d lmac_enable failed\n", bgx_idx,
- lmacid);
- return ret;
- }
- lmac->init_pend = 0;
- mdelay(100);
- }
if (lmac->qlm_mode == QLM_MODE_SGMII ||
lmac->qlm_mode == QLM_MODE_RGMII ||
lmac->qlm_mode == QLM_MODE_QSGMII) {
@@ -1461,6 +1451,7 @@ int octeontx_bgx_remove(struct udevice *dev)
int octeontx_bgx_probe(struct udevice *dev)
{
+ int err;
struct bgx *bgx = dev_get_priv(dev);
u8 lmac = 0;
int qlm[4] = {-1, -1, -1, -1};
@@ -1540,8 +1531,11 @@ skip_qlm_config:
struct lmac *tlmac = &bgx->lmac[lmac];
tlmac->dev = dev;
- tlmac->init_pend = 1;
- tlmac->bgx = bgx;
+ err = bgx_lmac_enable(bgx, lmac);
+ if (err) {
+ printf("BGX%d failed to enable lmac%d\n",
+ bgx->bgx_id, lmac);
+ }
}
return 0;
diff --git a/drivers/net/octeontx/smi.c b/drivers/net/octeontx/smi.c
index 91dcd05e4b3..27f4423c6ac 100644
--- a/drivers/net/octeontx/smi.c
+++ b/drivers/net/octeontx/smi.c
@@ -325,6 +325,8 @@ int octeontx_smi_probe(struct udevice *dev)
return -1;
}
+ node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+ "cavium,thunder-8890-mdio-nexus");
fdt_for_each_subnode(subnode, gd->fdt_blob, node) {
ret = fdt_node_check_compatible(gd->fdt_blob, subnode,
"cavium,thunder-8890-mdio");
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 5d6180229e9..17942e29933 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -312,6 +312,16 @@ config DM_REGULATOR_STPMIC1
by the PMIC device. This driver is controlled by a device tree node
which includes voltage limits.
+config DM_REGULATOR_ANATOP
+ bool "Enable driver for ANATOP regulators"
+ depends on DM_REGULATOR
+ select REGMAP
+ select SYSCON
+ help
+ Enable support for the Freescale i.MX on-chip ANATOP LDO
+ regulators. It is recommended that this option be enabled on
+ i.MX6 platform.
+
config SPL_DM_REGULATOR_STPMIC1
bool "Enable driver for STPMIC1 regulators in SPL"
depends on SPL_DM_REGULATOR && PMIC_STPMIC1
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index b2f5972ea79..677134c822c 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_DM_REGULATOR_TPS62360) += tps62360_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o
obj-$(CONFIG_DM_REGULATOR_TPS65941) += tps65941_regulator.o
obj-$(CONFIG_DM_REGULATOR_SCMI) += scmi_regulator.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_ANATOP) += anatop_regulator.o
diff --git a/drivers/power/regulator/anatop_regulator.c b/drivers/power/regulator/anatop_regulator.c
new file mode 100644
index 00000000000..096a1565d5a
--- /dev/null
+++ b/drivers/power/regulator/anatop_regulator.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2021 Linaro
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <dm/device-internal.h>
+#include <dm/device_compat.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */
+#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */
+
+#define LDO_POWER_GATE 0x00
+#define LDO_FET_FULL_ON 0x1f
+
+#define BIT_WIDTH_MAX 32
+
+#define ANATOP_REGULATOR_STEP 25000
+#define MIN_DROPOUT_UV 125000
+
+struct anatop_regulator {
+ const char *name;
+ struct regmap *regmap;
+ struct udevice *supply;
+ u32 control_reg;
+ u32 vol_bit_shift;
+ u32 vol_bit_width;
+ u32 min_bit_val;
+ u32 min_voltage;
+ u32 max_voltage;
+ u32 delay_reg;
+ u32 delay_bit_shift;
+ u32 delay_bit_width;
+};
+
+static u32 anatop_get_bits(struct udevice *dev, u32 addr, int bit_shift,
+ int bit_width)
+{
+ const struct anatop_regulator *anatop_reg = dev_get_plat(dev);
+ int err;
+ u32 val, mask;
+
+ if (bit_width == BIT_WIDTH_MAX)
+ mask = ~0;
+ else
+ mask = (1 << bit_width) - 1;
+
+ err = regmap_read(anatop_reg->regmap, addr, &val);
+ if (err) {
+ dev_dbg(dev, "cannot read reg (%d)\n", err);
+ return err;
+ }
+
+ val = (val >> bit_shift) & mask;
+
+ return val;
+}
+
+static int anatop_set_bits(struct udevice *dev, u32 addr, int bit_shift,
+ int bit_width, u32 data)
+{
+ const struct anatop_regulator *anatop_reg = dev_get_plat(dev);
+ int err;
+ u32 val, mask;
+
+ if (bit_width == 32)
+ mask = ~0;
+ else
+ mask = (1 << bit_width) - 1;
+
+ err = regmap_read(anatop_reg->regmap, addr, &val);
+ if (err) {
+ dev_dbg(dev, "cannot read reg (%d)\n", err);
+ return err;
+ }
+ val = val & ~(mask << bit_shift);
+ err = regmap_write(anatop_reg->regmap,
+ addr, (data << bit_shift) | val);
+ if (err) {
+ dev_dbg(dev, "cannot write reg (%d)\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int anatop_get_voltage(struct udevice *dev)
+{
+ const struct anatop_regulator *anatop_reg = dev_get_plat(dev);
+ u32 sel;
+ u32 val;
+
+ if (!anatop_reg->control_reg)
+ return -ENOSYS;
+
+ val = anatop_get_bits(dev,
+ anatop_reg->control_reg,
+ anatop_reg->vol_bit_shift,
+ anatop_reg->vol_bit_width);
+
+ sel = val - anatop_reg->min_bit_val;
+
+ return sel * ANATOP_REGULATOR_STEP + anatop_reg->min_voltage;
+}
+
+static int anatop_set_voltage(struct udevice *dev, int uV)
+{
+ const struct anatop_regulator *anatop_reg = dev_get_plat(dev);
+ u32 val;
+ u32 sel;
+ int ret;
+
+ dev_dbg(dev, "uv %d, min %d, max %d\n", uV, anatop_reg->min_voltage,
+ anatop_reg->max_voltage);
+
+ if (uV < anatop_reg->min_voltage)
+ return -EINVAL;
+
+ if (!anatop_reg->control_reg)
+ return -ENOSYS;
+
+ sel = DIV_ROUND_UP(uV - anatop_reg->min_voltage,
+ ANATOP_REGULATOR_STEP);
+ if (sel * ANATOP_REGULATOR_STEP + anatop_reg->min_voltage >
+ anatop_reg->max_voltage)
+ return -EINVAL;
+ val = anatop_reg->min_bit_val + sel;
+ dev_dbg(dev, "calculated val %d\n", val);
+
+ if (anatop_reg->supply) {
+ ret = regulator_set_value(anatop_reg->supply,
+ uV + MIN_DROPOUT_UV);
+ if (ret)
+ return ret;
+ }
+
+ ret = anatop_set_bits(dev,
+ anatop_reg->control_reg,
+ anatop_reg->vol_bit_shift,
+ anatop_reg->vol_bit_width,
+ val);
+
+ return ret;
+}
+
+static const struct dm_regulator_ops anatop_regulator_ops = {
+ .set_value = anatop_set_voltage,
+ .get_value = anatop_get_voltage,
+};
+
+static int anatop_regulator_probe(struct udevice *dev)
+{
+ struct anatop_regulator *anatop_reg;
+ struct dm_regulator_uclass_plat *uc_pdata;
+ struct udevice *syscon;
+ int ret = 0;
+ u32 val;
+
+ anatop_reg = dev_get_plat(dev);
+ uc_pdata = dev_get_uclass_plat(dev);
+
+ anatop_reg->name = ofnode_read_string(dev_ofnode(dev),
+ "regulator-name");
+ if (!anatop_reg->name)
+ return log_msg_ret("regulator-name", -EINVAL);
+
+ ret = device_get_supply_regulator(dev, "vin-supply",
+ &anatop_reg->supply);
+ if (ret != -ENODEV) {
+ if (ret)
+ return log_msg_ret("get vin-supply", ret);
+
+ ret = regulator_set_enable(anatop_reg->supply, true);
+ if (ret)
+ return ret;
+ }
+
+ ret = dev_read_u32(dev,
+ "anatop-reg-offset",
+ &anatop_reg->control_reg);
+ if (ret)
+ return log_msg_ret("anatop-reg-offset", ret);
+
+ ret = dev_read_u32(dev,
+ "anatop-vol-bit-width",
+ &anatop_reg->vol_bit_width);
+ if (ret)
+ return log_msg_ret("anatop-vol-bit-width", ret);
+
+ ret = dev_read_u32(dev,
+ "anatop-vol-bit-shift",
+ &anatop_reg->vol_bit_shift);
+ if (ret)
+ return log_msg_ret("anatop-vol-bit-shift", ret);
+
+ ret = dev_read_u32(dev,
+ "anatop-min-bit-val",
+ &anatop_reg->min_bit_val);
+ if (ret)
+ return log_msg_ret("anatop-min-bit-val", ret);
+
+ ret = dev_read_u32(dev,
+ "anatop-min-voltage",
+ &anatop_reg->min_voltage);
+ if (ret)
+ return log_msg_ret("anatop-min-voltage", ret);
+
+ ret = dev_read_u32(dev,
+ "anatop-max-voltage",
+ &anatop_reg->max_voltage);
+ if (ret)
+ return log_msg_ret("anatop-max-voltage", ret);
+
+ /* read LDO ramp up setting, only for core reg */
+ dev_read_u32(dev, "anatop-delay-reg-offset",
+ &anatop_reg->delay_reg);
+ dev_read_u32(dev, "anatop-delay-bit-width",
+ &anatop_reg->delay_bit_width);
+ dev_read_u32(dev, "anatop-delay-bit-shift",
+ &anatop_reg->delay_bit_shift);
+
+ syscon = dev_get_parent(dev);
+ if (!syscon) {
+ dev_dbg(dev, "unable to find syscon device\n");
+ return -ENOENT;
+ }
+
+ anatop_reg->regmap = syscon_get_regmap(syscon);
+ if (IS_ERR(anatop_reg->regmap)) {
+ dev_dbg(dev, "unable to find regmap (%ld)\n",
+ PTR_ERR(anatop_reg->regmap));
+ return -ENOENT;
+ }
+
+ /* check whether need to care about LDO ramp up speed */
+ if (anatop_reg->delay_bit_width) {
+ /*
+ * the delay for LDO ramp up time is
+ * based on the register setting, we need
+ * to calculate how many steps LDO need to
+ * ramp up, and how much delay needed. (us)
+ */
+ val = anatop_get_bits(dev,
+ anatop_reg->delay_reg,
+ anatop_reg->delay_bit_shift,
+ anatop_reg->delay_bit_width);
+ uc_pdata->ramp_delay = (LDO_RAMP_UP_UNIT_IN_CYCLES << val)
+ / LDO_RAMP_UP_FREQ_IN_MHZ + 1;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id of_anatop_regulator_match_tbl[] = {
+ { .compatible = "fsl,anatop-regulator", },
+ { /* end */ }
+};
+
+U_BOOT_DRIVER(anatop_regulator) = {
+ .name = "anatop_regulator",
+ .id = UCLASS_REGULATOR,
+ .ops = &anatop_regulator_ops,
+ .of_match = of_anatop_regulator_match_tbl,
+ .plat_auto = sizeof(struct anatop_regulator),
+ .probe = anatop_regulator_probe,
+};
diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c
index 9512f6881fc..279b087d16d 100644
--- a/drivers/sysreset/sysreset-uclass.c
+++ b/drivers/sysreset/sysreset-uclass.c
@@ -122,10 +122,19 @@ void reset_cpu(void)
#if IS_ENABLED(CONFIG_SYSRESET_CMD_RESET)
int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
+ enum sysreset_t reset_type = SYSRESET_COLD;
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+
+ if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'w') {
+ reset_type = SYSRESET_WARM;
+ }
+
printf("resetting ...\n");
mdelay(100);
- sysreset_walk_halt(SYSRESET_COLD);
+ sysreset_walk_halt(reset_type);
return 0;
}
diff --git a/drivers/sysreset/sysreset_psci.c b/drivers/sysreset/sysreset_psci.c
index c7907b3226d..83ecbcb9d2c 100644
--- a/drivers/sysreset/sysreset_psci.c
+++ b/drivers/sysreset/sysreset_psci.c
@@ -11,22 +11,18 @@
static int psci_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
- unsigned long function_id;
-
switch (type) {
case SYSRESET_WARM:
case SYSRESET_COLD:
- function_id = PSCI_0_2_FN_SYSTEM_RESET;
+ psci_sys_reset(type);
break;
case SYSRESET_POWER_OFF:
- function_id = PSCI_0_2_FN_SYSTEM_OFF;
+ psci_sys_poweroff();
break;
default:
return -ENOSYS;
}
- invoke_psci_fn(function_id, 0, 0, 0);
-
return -EINPROGRESS;
}