summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/block/dwc_ahsata.c2
-rw-r--r--drivers/core/Kconfig6
-rw-r--r--drivers/dma/Makefile2
-rw-r--r--drivers/dma/keystone_nav.c320
-rw-r--r--drivers/dma/keystone_nav_cfg.c27
-rw-r--r--drivers/dma/ti-edma3.c384
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/bcm2835_gpio.c89
-rw-r--r--drivers/gpio/gpio-uclass.c236
-rw-r--r--drivers/gpio/intel_ich6_gpio.c250
-rw-r--r--drivers/gpio/kw_gpio.c4
-rw-r--r--drivers/gpio/mxc_gpio.c116
-rw-r--r--drivers/gpio/omap_gpio.c183
-rw-r--r--drivers/gpio/s5p_gpio.c101
-rw-r--r--drivers/gpio/sandbox.c93
-rw-r--r--drivers/gpio/sunxi_gpio.c170
-rw-r--r--drivers/gpio/tegra_gpio.c113
-rw-r--r--drivers/i2c/Makefile4
-rw-r--r--drivers/i2c/designware_i2c.c298
-rw-r--r--drivers/i2c/i2c_core.c8
-rw-r--r--drivers/i2c/mxs_i2c.c187
-rw-r--r--drivers/i2c/tegra_i2c.c7
-rw-r--r--drivers/input/tegra-kbc.c2
-rw-r--r--drivers/mmc/Makefile22
-rw-r--r--drivers/mmc/bcm2835_sdhci.c1
-rw-r--r--drivers/mmc/omap_hsmmc.c19
-rw-r--r--drivers/mmc/s5p_sdhci.c2
-rw-r--r--drivers/mmc/sdhci.c6
-rw-r--r--drivers/mmc/sunxi_mmc.c58
-rw-r--r--drivers/mmc/tegra_mmc.c3
-rw-r--r--drivers/mtd/cfi_flash.c50
-rw-r--r--drivers/mtd/nand/mxs_nand.c9
-rw-r--r--drivers/mtd/nand/omap_gpmc.c36
-rw-r--r--drivers/net/davinci_emac.c1
-rw-r--r--drivers/net/e1000.c14
-rw-r--r--drivers/net/e1000.h1
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/fec_mxc.c8
-rw-r--r--drivers/net/keystone_net.c415
-rw-r--r--drivers/net/phy/marvell.c53
-rw-r--r--drivers/net/phy/phy.c9
-rw-r--r--drivers/net/sh_eth.c102
-rw-r--r--drivers/net/sh_eth.h14
-rw-r--r--drivers/net/smc911x.c1
-rw-r--r--drivers/net/uli526x.c2
-rw-r--r--drivers/pci/pci.c8
-rw-r--r--drivers/power/power_spi.c33
-rw-r--r--drivers/power/twl4030.c6
-rw-r--r--drivers/serial/Kconfig12
-rw-r--r--drivers/serial/Makefile3
-rw-r--r--drivers/serial/ns16550.c17
-rw-r--r--drivers/serial/serial-uclass.c99
-rw-r--r--drivers/serial/serial.c150
-rw-r--r--drivers/serial/serial_coreboot.c38
-rw-r--r--drivers/serial/serial_dw.c39
-rw-r--r--drivers/serial/serial_mxc.c2
-rw-r--r--drivers/serial/serial_ns16550.c21
-rw-r--r--drivers/serial/serial_omap.c47
-rw-r--r--drivers/serial/serial_pl01x.c2
-rw-r--r--drivers/serial/serial_s3c24x0.c10
-rw-r--r--drivers/serial/serial_sh.c4
-rw-r--r--drivers/serial/serial_sh.h10
-rw-r--r--drivers/serial/serial_uniphier.c208
-rw-r--r--drivers/soc/Makefile5
-rw-r--r--drivers/soc/keystone/Makefile1
-rw-r--r--drivers/soc/keystone/keystone_serdes.c210
-rw-r--r--drivers/spi/Kconfig6
-rw-r--r--drivers/spi/altera_spi.c132
-rw-r--r--drivers/spi/mxc_spi.c41
-rw-r--r--drivers/usb/eth/asix.c1
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/dwc2.c1053
-rw-r--r--drivers/usb/host/dwc2.h782
-rw-r--r--drivers/usb/host/ehci-hcd.c69
-rw-r--r--drivers/usb/host/ehci-rmobile.c8
-rw-r--r--drivers/usb/host/ehci-sunxi.c12
-rw-r--r--drivers/usb/host/xhci-keystone.c329
-rw-r--r--drivers/video/cfb_console.c14
-rw-r--r--drivers/video/exynos_fb.c32
-rw-r--r--drivers/video/ipu_common.c2
-rw-r--r--drivers/video/ipu_disp.c15
-rw-r--r--drivers/video/mxc_ipuv3_fb.c2
83 files changed, 5011 insertions, 1854 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index d8361d95fd..33227c8bd6 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -19,3 +19,5 @@ obj-$(CONFIG_QE) += qe/
obj-y += memory/
obj-y += pwm/
obj-y += input/
+# SOC specific infrastructure drivers.
+obj-y += soc/
diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c
index 29f478bfbe..c68fd2f256 100644
--- a/drivers/block/dwc_ahsata.c
+++ b/drivers/block/dwc_ahsata.c
@@ -878,7 +878,7 @@ int sata_port_status(int dev, int port)
probe_ent = (struct ahci_probe_ent *)sata_dev_desc[dev].priv;
port_mmio = (struct sata_port_regs *)probe_ent->port[port].port_mmio;
- return readl(&(port_mmio->ssts)) && SATA_PORT_SSTS_DET_MASK;
+ return readl(&(port_mmio->ssts)) & SATA_PORT_SSTS_DET_MASK;
}
/*
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index e69de29bb2..d2799dc861 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -0,0 +1,6 @@
+config DM
+ bool "Enable Driver Model"
+ depends on !SPL_BUILD
+ help
+ This config option enables Driver Model.
+ To use legacy drivers, say N.
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index a79c3919dd..4c8fcc2575 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -8,3 +8,5 @@
obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
obj-$(CONFIG_APBH_DMA) += apbh_dma.o
obj-$(CONFIG_FSL_DMA) += fsl_dma.o
+obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
+obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
diff --git a/drivers/dma/keystone_nav.c b/drivers/dma/keystone_nav.c
new file mode 100644
index 0000000000..dfca75abdc
--- /dev/null
+++ b/drivers/dma/keystone_nav.c
@@ -0,0 +1,320 @@
+/*
+ * Multicore Navigator driver for TI Keystone 2 devices.
+ *
+ * (C) Copyright 2012-2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ti-common/keystone_nav.h>
+
+struct qm_config qm_memmap = {
+ .stat_cfg = CONFIG_KSNAV_QM_QUEUE_STATUS_BASE,
+ .queue = (void *)CONFIG_KSNAV_QM_MANAGER_QUEUES_BASE,
+ .mngr_vbusm = CONFIG_KSNAV_QM_BASE_ADDRESS,
+ .i_lram = CONFIG_KSNAV_QM_LINK_RAM_BASE,
+ .proxy = (void *)CONFIG_KSNAV_QM_MANAGER_Q_PROXY_BASE,
+ .status_ram = CONFIG_KSNAV_QM_STATUS_RAM_BASE,
+ .mngr_cfg = (void *)CONFIG_KSNAV_QM_CONF_BASE,
+ .intd_cfg = CONFIG_KSNAV_QM_INTD_CONF_BASE,
+ .desc_mem = (void *)CONFIG_KSNAV_QM_DESC_SETUP_BASE,
+ .region_num = CONFIG_KSNAV_QM_REGION_NUM,
+ .pdsp_cmd = CONFIG_KSNAV_QM_PDSP1_CMD_BASE,
+ .pdsp_ctl = CONFIG_KSNAV_QM_PDSP1_CTRL_BASE,
+ .pdsp_iram = CONFIG_KSNAV_QM_PDSP1_IRAM_BASE,
+ .qpool_num = CONFIG_KSNAV_QM_QPOOL_NUM,
+};
+
+/*
+ * We are going to use only one type of descriptors - host packet
+ * descriptors. We staticaly allocate memory for them here
+ */
+struct qm_host_desc desc_pool[HDESC_NUM] __aligned(sizeof(struct qm_host_desc));
+
+static struct qm_config *qm_cfg;
+
+inline int num_of_desc_to_reg(int num_descr)
+{
+ int j, num;
+
+ for (j = 0, num = 32; j < 15; j++, num *= 2) {
+ if (num_descr <= num)
+ return j;
+ }
+
+ return 15;
+}
+
+int _qm_init(struct qm_config *cfg)
+{
+ u32 j;
+
+ qm_cfg = cfg;
+
+ qm_cfg->mngr_cfg->link_ram_base0 = qm_cfg->i_lram;
+ qm_cfg->mngr_cfg->link_ram_size0 = HDESC_NUM * 8;
+ qm_cfg->mngr_cfg->link_ram_base1 = 0;
+ qm_cfg->mngr_cfg->link_ram_size1 = 0;
+ qm_cfg->mngr_cfg->link_ram_base2 = 0;
+
+ qm_cfg->desc_mem[0].base_addr = (u32)desc_pool;
+ qm_cfg->desc_mem[0].start_idx = 0;
+ qm_cfg->desc_mem[0].desc_reg_size =
+ (((sizeof(struct qm_host_desc) >> 4) - 1) << 16) |
+ num_of_desc_to_reg(HDESC_NUM);
+
+ memset(desc_pool, 0, sizeof(desc_pool));
+ for (j = 0; j < HDESC_NUM; j++)
+ qm_push(&desc_pool[j], qm_cfg->qpool_num);
+
+ return QM_OK;
+}
+
+int qm_init(void)
+{
+ return _qm_init(&qm_memmap);
+}
+
+void qm_close(void)
+{
+ u32 j;
+
+ queue_close(qm_cfg->qpool_num);
+
+ qm_cfg->mngr_cfg->link_ram_base0 = 0;
+ qm_cfg->mngr_cfg->link_ram_size0 = 0;
+ qm_cfg->mngr_cfg->link_ram_base1 = 0;
+ qm_cfg->mngr_cfg->link_ram_size1 = 0;
+ qm_cfg->mngr_cfg->link_ram_base2 = 0;
+
+ for (j = 0; j < qm_cfg->region_num; j++) {
+ qm_cfg->desc_mem[j].base_addr = 0;
+ qm_cfg->desc_mem[j].start_idx = 0;
+ qm_cfg->desc_mem[j].desc_reg_size = 0;
+ }
+
+ qm_cfg = NULL;
+}
+
+void qm_push(struct qm_host_desc *hd, u32 qnum)
+{
+ u32 regd;
+
+ cpu_to_bus((u32 *)hd, sizeof(struct qm_host_desc)/4);
+ regd = (u32)hd | ((sizeof(struct qm_host_desc) >> 4) - 1);
+ writel(regd, &qm_cfg->queue[qnum].ptr_size_thresh);
+}
+
+void qm_buff_push(struct qm_host_desc *hd, u32 qnum,
+ void *buff_ptr, u32 buff_len)
+{
+ hd->orig_buff_len = buff_len;
+ hd->buff_len = buff_len;
+ hd->orig_buff_ptr = (u32)buff_ptr;
+ hd->buff_ptr = (u32)buff_ptr;
+ qm_push(hd, qnum);
+}
+
+struct qm_host_desc *qm_pop(u32 qnum)
+{
+ u32 uhd;
+
+ uhd = readl(&qm_cfg->queue[qnum].ptr_size_thresh) & ~0xf;
+ if (uhd)
+ cpu_to_bus((u32 *)uhd, sizeof(struct qm_host_desc)/4);
+
+ return (struct qm_host_desc *)uhd;
+}
+
+struct qm_host_desc *qm_pop_from_free_pool(void)
+{
+ return qm_pop(qm_cfg->qpool_num);
+}
+
+void queue_close(u32 qnum)
+{
+ struct qm_host_desc *hd;
+
+ while ((hd = qm_pop(qnum)))
+ ;
+}
+
+/**
+ * DMA API
+ */
+
+static int ksnav_rx_disable(struct pktdma_cfg *pktdma)
+{
+ u32 j, v, k;
+
+ for (j = 0; j < pktdma->rx_ch_num; j++) {
+ v = readl(&pktdma->rx_ch[j].cfg_a);
+ if (!(v & CPDMA_CHAN_A_ENABLE))
+ continue;
+
+ writel(v | CPDMA_CHAN_A_TDOWN, &pktdma->rx_ch[j].cfg_a);
+ for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) {
+ udelay(100);
+ v = readl(&pktdma->rx_ch[j].cfg_a);
+ if (!(v & CPDMA_CHAN_A_ENABLE))
+ continue;
+ }
+ /* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */
+ }
+
+ /* Clear all of the flow registers */
+ for (j = 0; j < pktdma->rx_flow_num; j++) {
+ writel(0, &pktdma->rx_flows[j].control);
+ writel(0, &pktdma->rx_flows[j].tags);
+ writel(0, &pktdma->rx_flows[j].tag_sel);
+ writel(0, &pktdma->rx_flows[j].fdq_sel[0]);
+ writel(0, &pktdma->rx_flows[j].fdq_sel[1]);
+ writel(0, &pktdma->rx_flows[j].thresh[0]);
+ writel(0, &pktdma->rx_flows[j].thresh[1]);
+ writel(0, &pktdma->rx_flows[j].thresh[2]);
+ }
+
+ return QM_OK;
+}
+
+static int ksnav_tx_disable(struct pktdma_cfg *pktdma)
+{
+ u32 j, v, k;
+
+ for (j = 0; j < pktdma->tx_ch_num; j++) {
+ v = readl(&pktdma->tx_ch[j].cfg_a);
+ if (!(v & CPDMA_CHAN_A_ENABLE))
+ continue;
+
+ writel(v | CPDMA_CHAN_A_TDOWN, &pktdma->tx_ch[j].cfg_a);
+ for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) {
+ udelay(100);
+ v = readl(&pktdma->tx_ch[j].cfg_a);
+ if (!(v & CPDMA_CHAN_A_ENABLE))
+ continue;
+ }
+ /* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */
+ }
+
+ return QM_OK;
+}
+
+int ksnav_init(struct pktdma_cfg *pktdma, struct rx_buff_desc *rx_buffers)
+{
+ u32 j, v;
+ struct qm_host_desc *hd;
+ u8 *rx_ptr;
+
+ if (pktdma == NULL || rx_buffers == NULL ||
+ rx_buffers->buff_ptr == NULL || qm_cfg == NULL)
+ return QM_ERR;
+
+ pktdma->rx_flow = rx_buffers->rx_flow;
+
+ /* init rx queue */
+ rx_ptr = rx_buffers->buff_ptr;
+
+ for (j = 0; j < rx_buffers->num_buffs; j++) {
+ hd = qm_pop(qm_cfg->qpool_num);
+ if (hd == NULL)
+ return QM_ERR;
+
+ qm_buff_push(hd, pktdma->rx_free_q,
+ rx_ptr, rx_buffers->buff_len);
+
+ rx_ptr += rx_buffers->buff_len;
+ }
+
+ ksnav_rx_disable(pktdma);
+
+ /* configure rx channels */
+ v = CPDMA_REG_VAL_MAKE_RX_FLOW_A(1, 1, 0, 0, 0, 0, 0, pktdma->rx_rcv_q);
+ writel(v, &pktdma->rx_flows[pktdma->rx_flow].control);
+ writel(0, &pktdma->rx_flows[pktdma->rx_flow].tags);
+ writel(0, &pktdma->rx_flows[pktdma->rx_flow].tag_sel);
+
+ v = CPDMA_REG_VAL_MAKE_RX_FLOW_D(0, pktdma->rx_free_q, 0,
+ pktdma->rx_free_q);
+
+ writel(v, &pktdma->rx_flows[pktdma->rx_flow].fdq_sel[0]);
+ writel(v, &pktdma->rx_flows[pktdma->rx_flow].fdq_sel[1]);
+ writel(0, &pktdma->rx_flows[pktdma->rx_flow].thresh[0]);
+ writel(0, &pktdma->rx_flows[pktdma->rx_flow].thresh[1]);
+ writel(0, &pktdma->rx_flows[pktdma->rx_flow].thresh[2]);
+
+ for (j = 0; j < pktdma->rx_ch_num; j++)
+ writel(CPDMA_CHAN_A_ENABLE, &pktdma->rx_ch[j].cfg_a);
+
+ /* configure tx channels */
+ /* Disable loopback in the tx direction */
+ writel(0, &pktdma->global->emulation_control);
+
+ /* Set QM base address, only for K2x devices */
+ writel(CONFIG_KSNAV_QM_BASE_ADDRESS, &pktdma->global->qm_base_addr[0]);
+
+ /* Enable all channels. The current state isn't important */
+ for (j = 0; j < pktdma->tx_ch_num; j++) {
+ writel(0, &pktdma->tx_ch[j].cfg_b);
+ writel(CPDMA_CHAN_A_ENABLE, &pktdma->tx_ch[j].cfg_a);
+ }
+
+ return QM_OK;
+}
+
+int ksnav_close(struct pktdma_cfg *pktdma)
+{
+ if (!pktdma)
+ return QM_ERR;
+
+ ksnav_tx_disable(pktdma);
+ ksnav_rx_disable(pktdma);
+
+ queue_close(pktdma->rx_free_q);
+ queue_close(pktdma->rx_rcv_q);
+ queue_close(pktdma->tx_snd_q);
+
+ return QM_OK;
+}
+
+int ksnav_send(struct pktdma_cfg *pktdma, u32 *pkt, int num_bytes, u32 swinfo2)
+{
+ struct qm_host_desc *hd;
+
+ hd = qm_pop(qm_cfg->qpool_num);
+ if (hd == NULL)
+ return QM_ERR;
+
+ hd->desc_info = num_bytes;
+ hd->swinfo[2] = swinfo2;
+ hd->packet_info = qm_cfg->qpool_num;
+
+ qm_buff_push(hd, pktdma->tx_snd_q, pkt, num_bytes);
+
+ return QM_OK;
+}
+
+void *ksnav_recv(struct pktdma_cfg *pktdma, u32 **pkt, int *num_bytes)
+{
+ struct qm_host_desc *hd;
+
+ hd = qm_pop(pktdma->rx_rcv_q);
+ if (!hd)
+ return NULL;
+
+ *pkt = (u32 *)hd->buff_ptr;
+ *num_bytes = hd->desc_info & 0x3fffff;
+
+ return hd;
+}
+
+void ksnav_release_rxhd(struct pktdma_cfg *pktdma, void *hd)
+{
+ struct qm_host_desc *_hd = (struct qm_host_desc *)hd;
+
+ _hd->buff_len = _hd->orig_buff_len;
+ _hd->buff_ptr = _hd->orig_buff_ptr;
+
+ qm_push(_hd, pktdma->rx_free_q);
+}
diff --git a/drivers/dma/keystone_nav_cfg.c b/drivers/dma/keystone_nav_cfg.c
new file mode 100644
index 0000000000..bdd30a0262
--- /dev/null
+++ b/drivers/dma/keystone_nav_cfg.c
@@ -0,0 +1,27 @@
+/*
+ * Multicore Navigator driver for TI Keystone 2 devices.
+ *
+ * (C) Copyright 2012-2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/ti-common/keystone_nav.h>
+
+#ifdef CONFIG_KSNAV_PKTDMA_NETCP
+/* NETCP Pktdma */
+struct pktdma_cfg netcp_pktdma = {
+ .global = (void *)CONFIG_KSNAV_NETCP_PDMA_CTRL_BASE,
+ .tx_ch = (void *)CONFIG_KSNAV_NETCP_PDMA_TX_BASE,
+ .tx_ch_num = CONFIG_KSNAV_NETCP_PDMA_TX_CH_NUM,
+ .rx_ch = (void *)CONFIG_KSNAV_NETCP_PDMA_RX_BASE,
+ .rx_ch_num = CONFIG_KSNAV_NETCP_PDMA_RX_CH_NUM,
+ .tx_sched = (u32 *)CONFIG_KSNAV_NETCP_PDMA_SCHED_BASE,
+ .rx_flows = (void *)CONFIG_KSNAV_NETCP_PDMA_RX_FLOW_BASE,
+ .rx_flow_num = CONFIG_KSNAV_NETCP_PDMA_RX_FLOW_NUM,
+ .rx_free_q = CONFIG_KSNAV_NETCP_PDMA_RX_FREE_QUEUE,
+ .rx_rcv_q = CONFIG_KSNAV_NETCP_PDMA_RX_RCV_QUEUE,
+ .tx_snd_q = CONFIG_KSNAV_NETCP_PDMA_TX_SND_QUEUE,
+};
+#endif
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c
new file mode 100644
index 0000000000..8184ded9fa
--- /dev/null
+++ b/drivers/dma/ti-edma3.c
@@ -0,0 +1,384 @@
+/*
+ * Enhanced Direct Memory Access (EDMA3) Controller
+ *
+ * (C) Copyright 2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <asm/ti-common/ti-edma3.h>
+
+#define EDMA3_SL_BASE(slot) (0x4000 + ((slot) << 5))
+#define EDMA3_SL_MAX_NUM 512
+#define EDMA3_SLOPT_FIFO_WIDTH_MASK (0x7 << 8)
+
+#define EDMA3_QCHMAP(ch) 0x0200 + ((ch) << 2)
+#define EDMA3_CHMAP_PARSET_MASK 0x1ff
+#define EDMA3_CHMAP_PARSET_SHIFT 0x5
+#define EDMA3_CHMAP_TRIGWORD_SHIFT 0x2
+
+#define EDMA3_QEMCR 0x314
+#define EDMA3_IPR 0x1068
+#define EDMA3_IPRH 0x106c
+#define EDMA3_ICR 0x1070
+#define EDMA3_ICRH 0x1074
+#define EDMA3_QEECR 0x1088
+#define EDMA3_QEESR 0x108c
+#define EDMA3_QSECR 0x1094
+
+/**
+ * qedma3_start - start qdma on a channel
+ * @base: base address of edma
+ * @cfg: pinter to struct edma3_channel_config where you can set
+ * the slot number to associate with, the chnum, which corresponds
+ * your quick channel number 0-7, complete code - transfer complete code
+ * and trigger slot word - which has to correspond to the word number in
+ * edma3_slot_layout struct for generating event.
+ *
+ */
+void qedma3_start(u32 base, struct edma3_channel_config *cfg)
+{
+ u32 qchmap;
+
+ /* Clear the pending int bit */
+ if (cfg->complete_code < 32)
+ __raw_writel(1 << cfg->complete_code, base + EDMA3_ICR);
+ else
+ __raw_writel(1 << cfg->complete_code, base + EDMA3_ICRH);
+
+ /* Map parameter set and trigger word 7 to quick channel */
+ qchmap = ((EDMA3_CHMAP_PARSET_MASK & cfg->slot)
+ << EDMA3_CHMAP_PARSET_SHIFT) |
+ (cfg->trigger_slot_word << EDMA3_CHMAP_TRIGWORD_SHIFT);
+
+ __raw_writel(qchmap, base + EDMA3_QCHMAP(cfg->chnum));
+
+ /* Clear missed event if set*/
+ __raw_writel(1 << cfg->chnum, base + EDMA3_QSECR);
+ __raw_writel(1 << cfg->chnum, base + EDMA3_QEMCR);
+
+ /* Enable qdma channel event */
+ __raw_writel(1 << cfg->chnum, base + EDMA3_QEESR);
+}
+
+/**
+ * edma3_set_dest - set initial DMA destination address in parameter RAM slot
+ * @base: base address of edma
+ * @slot: parameter RAM slot being configured
+ * @dst: physical address of destination (memory, controller FIFO, etc)
+ * @addressMode: INCR, except in very rare cases
+ * @width: ignored unless @addressMode is FIFO, else specifies the
+ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+ *
+ * Note that the destination address is modified during the DMA transfer
+ * according to edma3_set_dest_index().
+ */
+void edma3_set_dest(u32 base, int slot, u32 dst, enum edma3_address_mode mode,
+ enum edma3_fifo_width width)
+{
+ u32 opt;
+ struct edma3_slot_layout *rg;
+
+ rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
+
+ opt = __raw_readl(&rg->opt);
+ if (mode == FIFO)
+ opt = (opt & EDMA3_SLOPT_FIFO_WIDTH_MASK) |
+ (EDMA3_SLOPT_DST_ADDR_CONST_MODE |
+ EDMA3_SLOPT_FIFO_WIDTH_SET(width));
+ else
+ opt &= ~EDMA3_SLOPT_DST_ADDR_CONST_MODE;
+
+ __raw_writel(opt, &rg->opt);
+ __raw_writel(dst, &rg->dst);
+}
+
+/**
+ * edma3_set_dest_index - configure DMA destination address indexing
+ * @base: base address of edma
+ * @slot: parameter RAM slot being configured
+ * @bidx: byte offset between destination arrays in a frame
+ * @cidx: byte offset between destination frames in a block
+ *
+ * Offsets are specified to support either contiguous or discontiguous
+ * memory transfers, or repeated access to a hardware register, as needed.
+ * When accessing hardware registers, both offsets are normally zero.
+ */
+void edma3_set_dest_index(u32 base, unsigned slot, int bidx, int cidx)
+{
+ u32 src_dst_bidx;
+ u32 src_dst_cidx;
+ struct edma3_slot_layout *rg;
+
+ rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
+
+ src_dst_bidx = __raw_readl(&rg->src_dst_bidx);
+ src_dst_cidx = __raw_readl(&rg->src_dst_cidx);
+
+ __raw_writel((src_dst_bidx & 0x0000ffff) | (bidx << 16),
+ &rg->src_dst_bidx);
+ __raw_writel((src_dst_cidx & 0x0000ffff) | (cidx << 16),
+ &rg->src_dst_cidx);
+}
+
+/**
+ * edma3_set_dest_addr - set destination address for slot only
+ */
+void edma3_set_dest_addr(u32 base, int slot, u32 dst)
+{
+ struct edma3_slot_layout *rg;
+
+ rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
+ __raw_writel(dst, &rg->dst);
+}
+
+/**
+ * edma3_set_src - set initial DMA source address in parameter RAM slot
+ * @base: base address of edma
+ * @slot: parameter RAM slot being configured
+ * @src_port: physical address of source (memory, controller FIFO, etc)
+ * @mode: INCR, except in very rare cases
+ * @width: ignored unless @addressMode is FIFO, else specifies the
+ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+ *
+ * Note that the source address is modified during the DMA transfer
+ * according to edma3_set_src_index().
+ */
+void edma3_set_src(u32 base, int slot, u32 src, enum edma3_address_mode mode,
+ enum edma3_fifo_width width)
+{
+ u32 opt;
+ struct edma3_slot_layout *rg;
+
+ rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
+
+ opt = __raw_readl(&rg->opt);
+ if (mode == FIFO)
+ opt = (opt & EDMA3_SLOPT_FIFO_WIDTH_MASK) |
+ (EDMA3_SLOPT_DST_ADDR_CONST_MODE |
+ EDMA3_SLOPT_FIFO_WIDTH_SET(width));
+ else
+ opt &= ~EDMA3_SLOPT_DST_ADDR_CONST_MODE;
+
+ __raw_writel(opt, &rg->opt);
+ __raw_writel(src, &rg->src);
+}
+
+/**
+ * edma3_set_src_index - configure DMA source address indexing
+ * @base: base address of edma
+ * @slot: parameter RAM slot being configured
+ * @bidx: byte offset between source arrays in a frame
+ * @cidx: byte offset between source frames in a block
+ *
+ * Offsets are specified to support either contiguous or discontiguous
+ * memory transfers, or repeated access to a hardware register, as needed.
+ * When accessing hardware registers, both offsets are normally zero.
+ */
+void edma3_set_src_index(u32 base, unsigned slot, int bidx, int cidx)
+{
+ u32 src_dst_bidx;
+ u32 src_dst_cidx;
+ struct edma3_slot_layout *rg;
+
+ rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
+
+ src_dst_bidx = __raw_readl(&rg->src_dst_bidx);
+ src_dst_cidx = __raw_readl(&rg->src_dst_cidx);
+
+ __raw_writel((src_dst_bidx & 0xffff0000) | bidx,
+ &rg->src_dst_bidx);
+ __raw_writel((src_dst_cidx & 0xffff0000) | cidx,
+ &rg->src_dst_cidx);
+}
+
+/**
+ * edma3_set_src_addr - set source address for slot only
+ */
+void edma3_set_src_addr(u32 base, int slot, u32 src)
+{
+ struct edma3_slot_layout *rg;
+
+ rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
+ __raw_writel(src, &rg->src);
+}
+
+/**
+ * edma3_set_transfer_params - configure DMA transfer parameters
+ * @base: base address of edma
+ * @slot: parameter RAM slot being configured
+ * @acnt: how many bytes per array (at least one)
+ * @bcnt: how many arrays per frame (at least one)
+ * @ccnt: how many frames per block (at least one)
+ * @bcnt_rld: used only for A-Synchronized transfers; this specifies
+ * the value to reload into bcnt when it decrements to zero
+ * @sync_mode: ASYNC or ABSYNC
+ *
+ * See the EDMA3 documentation to understand how to configure and link
+ * transfers using the fields in PaRAM slots. If you are not doing it
+ * all at once with edma3_write_slot(), you will use this routine
+ * plus two calls each for source and destination, setting the initial
+ * address and saying how to index that address.
+ *
+ * An example of an A-Synchronized transfer is a serial link using a
+ * single word shift register. In that case, @acnt would be equal to
+ * that word size; the serial controller issues a DMA synchronization
+ * event to transfer each word, and memory access by the DMA transfer
+ * controller will be word-at-a-time.
+ *
+ * An example of an AB-Synchronized transfer is a device using a FIFO.
+ * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
+ * The controller with the FIFO issues DMA synchronization events when
+ * the FIFO threshold is reached, and the DMA transfer controller will
+ * transfer one frame to (or from) the FIFO. It will probably use
+ * efficient burst modes to access memory.
+ */
+void edma3_set_transfer_params(u32 base, int slot, int acnt,
+ int bcnt, int ccnt, u16 bcnt_rld,
+ enum edma3_sync_dimension sync_mode)
+{
+ u32 opt;
+ u32 link_bcntrld;
+ struct edma3_slot_layout *rg;
+
+ rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
+
+ link_bcntrld = __raw_readl(&rg->link_bcntrld);
+
+ __raw_writel((bcnt_rld << 16) | (0x0000ffff & link_bcntrld),
+ &rg->link_bcntrld);
+
+ opt = __raw_readl(&rg->opt);
+ if (sync_mode == ASYNC)
+ __raw_writel(opt & ~EDMA3_SLOPT_AB_SYNC, &rg->opt);
+ else
+ __raw_writel(opt | EDMA3_SLOPT_AB_SYNC, &rg->opt);
+
+ /* Set the acount, bcount, ccount registers */
+ __raw_writel((bcnt << 16) | (acnt & 0xffff), &rg->a_b_cnt);
+ __raw_writel(0xffff & ccnt, &rg->ccnt);
+}
+
+/**
+ * edma3_write_slot - write parameter RAM data for slot
+ * @base: base address of edma
+ * @slot: number of parameter RAM slot being modified
+ * @param: data to be written into parameter RAM slot
+ *
+ * Use this to assign all parameters of a transfer at once. This
+ * allows more efficient setup of transfers than issuing multiple
+ * calls to set up those parameters in small pieces, and provides
+ * complete control over all transfer options.
+ */
+void edma3_write_slot(u32 base, int slot, struct edma3_slot_layout *param)
+{
+ int i;
+ u32 *p = (u32 *)param;
+ u32 *addr = (u32 *)(base + EDMA3_SL_BASE(slot));
+
+ for (i = 0; i < sizeof(struct edma3_slot_layout)/4; i += 4)
+ __raw_writel(*p++, addr++);
+}
+
+/**
+ * edma3_read_slot - read parameter RAM data from slot
+ * @base: base address of edma
+ * @slot: number of parameter RAM slot being copied
+ * @param: where to store copy of parameter RAM data
+ *
+ * Use this to read data from a parameter RAM slot, perhaps to
+ * save them as a template for later reuse.
+ */
+void edma3_read_slot(u32 base, int slot, struct edma3_slot_layout *param)
+{
+ int i;
+ u32 *p = (u32 *)param;
+ u32 *addr = (u32 *)(base + EDMA3_SL_BASE(slot));
+
+ for (i = 0; i < sizeof(struct edma3_slot_layout)/4; i += 4)
+ *p++ = __raw_readl(addr++);
+}
+
+void edma3_slot_configure(u32 base, int slot, struct edma3_slot_config *cfg)
+{
+ struct edma3_slot_layout *rg;
+
+ rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
+
+ __raw_writel(cfg->opt, &rg->opt);
+ __raw_writel(cfg->src, &rg->src);
+ __raw_writel((cfg->bcnt << 16) | (cfg->acnt & 0xffff), &rg->a_b_cnt);
+ __raw_writel(cfg->dst, &rg->dst);
+ __raw_writel((cfg->dst_bidx << 16) |
+ (cfg->src_bidx & 0xffff), &rg->src_dst_bidx);
+ __raw_writel((cfg->bcntrld << 16) |
+ (cfg->link & 0xffff), &rg->link_bcntrld);
+ __raw_writel((cfg->dst_cidx << 16) |
+ (cfg->src_cidx & 0xffff), &rg->src_dst_cidx);
+ __raw_writel(0xffff & cfg->ccnt, &rg->ccnt);
+}
+
+/**
+ * edma3_check_for_transfer - check if transfer coplete by checking
+ * interrupt pending bit. Clear interrupt pending bit if complete.
+ * @base: base address of edma
+ * @cfg: pinter to struct edma3_channel_config which was passed
+ * to qedma3_start when you started qdma channel
+ *
+ * Return 0 if complete, 1 if not.
+ */
+int edma3_check_for_transfer(u32 base, struct edma3_channel_config *cfg)
+{
+ u32 inum;
+ u32 ipr_base;
+ u32 icr_base;
+
+ if (cfg->complete_code < 32) {
+ ipr_base = base + EDMA3_IPR;
+ icr_base = base + EDMA3_ICR;
+ inum = 1 << cfg->complete_code;
+ } else {
+ ipr_base = base + EDMA3_IPRH;
+ icr_base = base + EDMA3_ICRH;
+ inum = 1 << (cfg->complete_code - 32);
+ }
+
+ /* check complete interrupt */
+ if (!(__raw_readl(ipr_base) & inum))
+ return 1;
+
+ /* clean up the pending int bit */
+ __raw_writel(inum, icr_base);
+
+ return 0;
+}
+
+/**
+ * qedma3_stop - stops dma on the channel passed
+ * @base: base address of edma
+ * @cfg: pinter to struct edma3_channel_config which was passed
+ * to qedma3_start when you started qdma channel
+ */
+void qedma3_stop(u32 base, struct edma3_channel_config *cfg)
+{
+ /* Disable qdma channel event */
+ __raw_writel(1 << cfg->chnum, base + EDMA3_QEECR);
+
+ /* clean up the interrupt indication */
+ if (cfg->complete_code < 32)
+ __raw_writel(1 << cfg->complete_code, base + EDMA3_ICR);
+ else
+ __raw_writel(1 << cfg->complete_code, base + EDMA3_ICRH);
+
+ /* Clear missed event if set*/
+ __raw_writel(1 << cfg->chnum, base + EDMA3_QSECR);
+ __raw_writel(1 << cfg->chnum, base + EDMA3_QEMCR);
+
+ /* Clear the channel map */
+ __raw_writel(0, base + EDMA3_QCHMAP(cfg->chnum));
+}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e69de29bb2..d21302f8da 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -0,0 +1,6 @@
+config DM_GPIO
+ bool "Enable Driver Model for GPIO drivers"
+ depends on DM
+ help
+ If you want to use driver model for GPIO drivers, say Y.
+ To use legacy GPIO drivers, say N.
diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c
index 332cfc2b23..0244c01882 100644
--- a/drivers/gpio/bcm2835_gpio.c
+++ b/drivers/gpio/bcm2835_gpio.c
@@ -11,67 +11,10 @@
#include <asm/gpio.h>
#include <asm/io.h>
-#define GPIO_NAME_SIZE 20
-
struct bcm2835_gpios {
- char label[BCM2835_GPIO_COUNT][GPIO_NAME_SIZE];
struct bcm2835_gpio_regs *reg;
};
-/**
- * gpio_is_requested() - check if a GPIO has been requested
- *
- * @bank: Bank to check
- * @offset: GPIO offset within bank to check
- * @return true if marked as requested, false if not
- */
-static inline bool gpio_is_requested(struct bcm2835_gpios *gpios, int offset)
-{
- return *gpios->label[offset] != '\0';
-}
-
-static int check_requested(struct udevice *dev, unsigned offset,
- const char *func)
-{
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
- if (!gpio_is_requested(gpios, offset)) {
- printf("omap_gpio: %s: error: gpio %s%d not requested\n",
- func, uc_priv->bank_name, offset);
- return -EPERM;
- }
-
- return 0;
-}
-
-static int bcm2835_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
-{
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
-
- if (gpio_is_requested(gpios, offset))
- return -EBUSY;
-
- strncpy(gpios->label[offset], label, GPIO_NAME_SIZE);
- gpios->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
- return 0;
-}
-
-static int bcm2835_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
- gpios->label[offset][0] = '\0';
-
- return 0;
-}
-
static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
@@ -142,9 +85,6 @@ static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct bcm2835_gpios *gpios = dev_get_priv(dev);
- if (!gpio_is_requested(gpios, offset))
- return GPIOF_UNUSED;
-
/* GPIOF_FUNC is not implemented yet */
if (bcm2835_gpio_is_output(gpios, offset))
return GPIOF_OUTPUT;
@@ -152,42 +92,13 @@ static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
-static int bcm2835_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct bcm2835_gpios *gpios = dev_get_priv(dev);
- const char *label;
- bool requested;
- bool is_output;
- int size;
-
- label = gpios->label[offset];
- is_output = bcm2835_gpio_is_output(gpios, offset);
- size = snprintf(buf, bufsize, "%s%d: ",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
- buf += size;
- bufsize -= size;
- requested = gpio_is_requested(gpios, offset);
- snprintf(buf, bufsize, "%s: %d [%c]%s%s",
- is_output ? "out" : " in",
- bcm2835_get_value(gpios, offset),
- requested ? 'x' : ' ',
- requested ? " " : "",
- label);
-
- return 0;
-}
static const struct dm_gpio_ops gpio_bcm2835_ops = {
- .request = bcm2835_gpio_request,
- .free = bcm2835_gpio_free,
.direction_input = bcm2835_gpio_direction_input,
.direction_output = bcm2835_gpio_direction_output,
.get_value = bcm2835_gpio_get_value,
.set_value = bcm2835_gpio_set_value,
.get_function = bcm2835_gpio_get_function,
- .get_state = bcm2835_gpio_get_state,
};
static int bcm2835_gpio_probe(struct udevice *dev)
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index f1bbc58796..45e9a5ad22 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -7,7 +7,9 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
+#include <malloc.h>
#include <asm/gpio.h>
+#include <linux/ctype.h>
/**
* gpio_to_device() - Convert global GPIO number to device, number
@@ -43,35 +45,47 @@ static int gpio_to_device(unsigned int gpio, struct udevice **devp,
int gpio_lookup_name(const char *name, struct udevice **devp,
unsigned int *offsetp, unsigned int *gpiop)
{
- struct gpio_dev_priv *uc_priv;
+ struct gpio_dev_priv *uc_priv = NULL;
struct udevice *dev;
+ ulong offset;
+ int numeric;
int ret;
if (devp)
*devp = NULL;
+ numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
for (ret = uclass_first_device(UCLASS_GPIO, &dev);
dev;
ret = uclass_next_device(&dev)) {
- ulong offset;
int len;
uc_priv = dev->uclass_priv;
+ if (numeric != -1) {
+ offset = numeric - uc_priv->gpio_base;
+ /* Allow GPIOs to be numbered from 0 */
+ if (offset >= 0 && offset < uc_priv->gpio_count)
+ break;
+ }
+
len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
if (!strncasecmp(name, uc_priv->bank_name, len)) {
- if (strict_strtoul(name + len, 10, &offset))
- continue;
- if (devp)
- *devp = dev;
- if (offsetp)
- *offsetp = offset;
- if (gpiop)
- *gpiop = uc_priv->gpio_base + offset;
- return 0;
+ if (!strict_strtoul(name + len, 10, &offset))
+ break;
}
}
- return ret ? ret : -EINVAL;
+ if (!dev)
+ return ret ? ret : -EINVAL;
+
+ if (devp)
+ *devp = dev;
+ if (offsetp)
+ *offsetp = offset;
+ if (gpiop)
+ *gpiop = uc_priv->gpio_base + offset;
+
+ return 0;
}
/**
@@ -79,24 +93,62 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
* gpio: GPIO number
* label: Name for the requested GPIO
*
+ * The label is copied and allocated so the caller does not need to keep
+ * the pointer around.
+ *
* This function implements the API that's compatible with current
* GPIO API used in U-Boot. The request is forwarded to particular
* GPIO driver. Returns 0 on success, negative value on error.
*/
int gpio_request(unsigned gpio, const char *label)
{
+ struct gpio_dev_priv *uc_priv;
unsigned int offset;
struct udevice *dev;
+ char *str;
int ret;
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
- if (!gpio_get_ops(dev)->request)
- return 0;
+ uc_priv = dev->uclass_priv;
+ if (uc_priv->name[offset])
+ return -EBUSY;
+ str = strdup(label);
+ if (!str)
+ return -ENOMEM;
+ if (gpio_get_ops(dev)->request) {
+ ret = gpio_get_ops(dev)->request(dev, offset, label);
+ if (ret) {
+ free(str);
+ return ret;
+ }
+ }
+ uc_priv->name[offset] = str;
+
+ return 0;
+}
+
+/**
+ * gpio_requestf() - [COMPAT] Request GPIO
+ * @gpio: GPIO number
+ * @fmt: Format string for the requested GPIO
+ * @...: Arguments for the printf() format string
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_requestf(unsigned gpio, const char *fmt, ...)
+{
+ va_list args;
+ char buf[40];
- return gpio_get_ops(dev)->request(dev, offset, label);
+ va_start(args, fmt);
+ vscnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ return gpio_request(gpio, buf);
}
/**
@@ -109,6 +161,7 @@ int gpio_request(unsigned gpio, const char *label)
*/
int gpio_free(unsigned gpio)
{
+ struct gpio_dev_priv *uc_priv;
unsigned int offset;
struct udevice *dev;
int ret;
@@ -117,9 +170,34 @@ int gpio_free(unsigned gpio)
if (ret)
return ret;
- if (!gpio_get_ops(dev)->free)
- return 0;
- return gpio_get_ops(dev)->free(dev, offset);
+ uc_priv = dev->uclass_priv;
+ if (!uc_priv->name[offset])
+ return -ENXIO;
+ if (gpio_get_ops(dev)->free) {
+ ret = gpio_get_ops(dev)->free(dev, offset);
+ if (ret)
+ return ret;
+ }
+
+ free(uc_priv->name[offset]);
+ uc_priv->name[offset] = NULL;
+
+ return 0;
+}
+
+static int check_reserved(struct udevice *dev, unsigned offset,
+ const char *func)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ if (!uc_priv->name[offset]) {
+ printf("%s: %s: error: gpio %s%d not reserved\n",
+ dev->name, func,
+ uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+ return -EBUSY;
+ }
+
+ return 0;
}
/**
@@ -139,8 +217,9 @@ int gpio_direction_input(unsigned gpio)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
+ ret = check_reserved(dev, offset, "dir_input");
- return gpio_get_ops(dev)->direction_input(dev, offset);
+ return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
}
/**
@@ -161,8 +240,10 @@ int gpio_direction_output(unsigned gpio, int value)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
+ ret = check_reserved(dev, offset, "dir_output");
- return gpio_get_ops(dev)->direction_output(dev, offset, value);
+ return ret ? ret :
+ gpio_get_ops(dev)->direction_output(dev, offset, value);
}
/**
@@ -183,8 +264,9 @@ int gpio_get_value(unsigned gpio)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
+ ret = check_reserved(dev, offset, "get_value");
- return gpio_get_ops(dev)->get_value(dev, offset);
+ return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
}
/**
@@ -205,8 +287,9 @@ int gpio_set_value(unsigned gpio, int value)
ret = gpio_to_device(gpio, &dev, &offset);
if (ret)
return ret;
+ ret = check_reserved(dev, offset, "set_value");
- return gpio_get_ops(dev)->set_value(dev, offset, value);
+ return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
}
const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
@@ -221,8 +304,94 @@ const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
return priv->bank_name;
}
+static const char * const gpio_function[GPIOF_COUNT] = {
+ "input",
+ "output",
+ "unused",
+ "unknown",
+ "func",
+};
+
+int get_function(struct udevice *dev, int offset, bool skip_unused,
+ const char **namep)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
+
+ BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+ if (!device_active(dev))
+ return -ENODEV;
+ if (offset < 0 || offset >= uc_priv->gpio_count)
+ return -EINVAL;
+ if (namep)
+ *namep = uc_priv->name[offset];
+ if (skip_unused && !uc_priv->name[offset])
+ return GPIOF_UNUSED;
+ if (ops->get_function) {
+ int ret;
+
+ ret = ops->get_function(dev, offset);
+ if (ret < 0)
+ return ret;
+ if (ret >= ARRAY_SIZE(gpio_function))
+ return -ENODATA;
+ return ret;
+ }
+
+ return GPIOF_UNKNOWN;
+}
+
+int gpio_get_function(struct udevice *dev, int offset, const char **namep)
+{
+ return get_function(dev, offset, true, namep);
+}
+
+int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
+{
+ return get_function(dev, offset, false, namep);
+}
+
+int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
+{
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
+ struct gpio_dev_priv *priv;
+ char *str = buf;
+ int func;
+ int ret;
+ int len;
+
+ BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+
+ *buf = 0;
+ priv = dev->uclass_priv;
+ ret = gpio_get_raw_function(dev, offset, NULL);
+ if (ret < 0)
+ return ret;
+ func = ret;
+ len = snprintf(str, buffsize, "%s%d: %s",
+ priv->bank_name ? priv->bank_name : "",
+ offset, gpio_function[func]);
+ if (func == GPIOF_INPUT || func == GPIOF_OUTPUT ||
+ func == GPIOF_UNUSED) {
+ const char *label;
+ bool used;
+
+ ret = ops->get_value(dev, offset);
+ if (ret < 0)
+ return ret;
+ used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
+ snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
+ ret,
+ used ? 'x' : ' ',
+ used ? " " : "",
+ label ? label : "");
+ }
+
+ return 0;
+}
+
/* We need to renumber the GPIOs when any driver is probed/removed */
-static int gpio_renumber(void)
+static int gpio_renumber(struct udevice *removed_dev)
{
struct gpio_dev_priv *uc_priv;
struct udevice *dev;
@@ -237,7 +406,7 @@ static int gpio_renumber(void)
/* Ensure that we have a base for each bank */
base = 0;
uclass_foreach_dev(dev, uc) {
- if (device_active(dev)) {
+ if (device_active(dev) && dev != removed_dev) {
uc_priv = dev->uclass_priv;
uc_priv->gpio_base = base;
base += uc_priv->gpio_count;
@@ -249,12 +418,27 @@ static int gpio_renumber(void)
static int gpio_post_probe(struct udevice *dev)
{
- return gpio_renumber();
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
+ if (!uc_priv->name)
+ return -ENOMEM;
+
+ return gpio_renumber(NULL);
}
static int gpio_pre_remove(struct udevice *dev)
{
- return gpio_renumber();
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ int i;
+
+ for (i = 0; i < uc_priv->gpio_count; i++) {
+ if (uc_priv->name[i])
+ free(uc_priv->name[i]);
+ }
+ free(uc_priv->name);
+
+ return gpio_renumber(dev);
}
UCLASS_DRIVER(gpio) = {
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7d9fac7233..d3381b0369 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -27,88 +27,46 @@
*/
#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
#include <pci.h>
#include <asm/gpio.h>
#include <asm/io.h>
+#define GPIO_PER_BANK 32
+
/* Where in config space is the register that points to the GPIO registers? */
#define PCI_CFG_GPIOBASE 0x48
-#define NUM_BANKS 3
-
-/* Within the I/O space, where are the registers to control the GPIOs? */
-static struct {
- u8 use_sel;
- u8 io_sel;
- u8 lvl;
-} gpio_bank[NUM_BANKS] = {
- { 0x00, 0x04, 0x0c }, /* Bank 0 */
- { 0x30, 0x34, 0x38 }, /* Bank 1 */
- { 0x40, 0x44, 0x48 } /* Bank 2 */
+struct ich6_bank_priv {
+ /* These are I/O addresses */
+ uint32_t use_sel;
+ uint32_t io_sel;
+ uint32_t lvl;
};
-static pci_dev_t dev; /* handle for 0:1f:0 */
-static u32 gpiobase; /* offset into I/O space */
-static int found_it_once; /* valid GPIO device? */
-static u32 lock[NUM_BANKS]; /* "lock" for access to pins */
-
-static int bad_arg(int num, int *bank, int *bitnum)
-{
- int i = num / 32;
- int j = num % 32;
-
- if (num < 0 || i > NUM_BANKS) {
- debug("%s: bogus gpio num: %d\n", __func__, num);
- return -1;
- }
- *bank = i;
- *bitnum = j;
- return 0;
-}
-
-static int mark_gpio(int bank, int bitnum)
-{
- if (lock[bank] & (1UL << bitnum)) {
- debug("%s: %d.%d already marked\n", __func__, bank, bitnum);
- return -1;
- }
- lock[bank] |= (1 << bitnum);
- return 0;
-}
-
-static void clear_gpio(int bank, int bitnum)
-{
- lock[bank] &= ~(1 << bitnum);
-}
-
-static int notmine(int num, int *bank, int *bitnum)
-{
- if (bad_arg(num, bank, bitnum))
- return -1;
- return !(lock[*bank] & (1UL << *bitnum));
-}
-
-static int gpio_init(void)
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
{
+ struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+ pci_dev_t pci_dev; /* handle for 0:1f:0 */
u8 tmpbyte;
u16 tmpword;
u32 tmplong;
-
- /* Have we already done this? */
- if (found_it_once)
- return 0;
+ u32 gpiobase;
+ int offset;
/* Where should it be? */
- dev = PCI_BDF(0, 0x1f, 0);
+ pci_dev = PCI_BDF(0, 0x1f, 0);
/* Is the device present? */
- pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword);
+ pci_read_config_word(pci_dev, PCI_VENDOR_ID, &tmpword);
if (tmpword != PCI_VENDOR_ID_INTEL) {
debug("%s: wrong VendorID\n", __func__);
- return -1;
+ return -ENODEV;
}
- pci_read_config_word(dev, PCI_DEVICE_ID, &tmpword);
+ pci_read_config_word(pci_dev, PCI_DEVICE_ID, &tmpword);
debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
/*
* We'd like to validate the Device ID too, but pretty much any
@@ -118,37 +76,37 @@ static int gpio_init(void)
*/
/* I/O should already be enabled (it's a RO bit). */
- pci_read_config_word(dev, PCI_COMMAND, &tmpword);
+ pci_read_config_word(pci_dev, PCI_COMMAND, &tmpword);
if (!(tmpword & PCI_COMMAND_IO)) {
debug("%s: device IO not enabled\n", __func__);
- return -1;
+ return -ENODEV;
}
/* Header Type must be normal (bits 6-0 only; see spec.) */
- pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte);
+ pci_read_config_byte(pci_dev, PCI_HEADER_TYPE, &tmpbyte);
if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
debug("%s: invalid Header type\n", __func__);
- return -1;
+ return -ENODEV;
}
/* Base Class must be a bridge device */
- pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte);
+ pci_read_config_byte(pci_dev, PCI_CLASS_CODE, &tmpbyte);
if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
debug("%s: invalid class\n", __func__);
- return -1;
+ return -ENODEV;
}
/* Sub Class must be ISA */
- pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte);
+ pci_read_config_byte(pci_dev, PCI_CLASS_SUB_CODE, &tmpbyte);
if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
debug("%s: invalid subclass\n", __func__);
- return -1;
+ return -ENODEV;
}
/* Programming Interface must be 0x00 (no others exist) */
- pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte);
+ pci_read_config_byte(pci_dev, PCI_CLASS_PROG, &tmpbyte);
if (tmpbyte != 0x00) {
debug("%s: invalid interface type\n", __func__);
- return -1;
+ return -ENODEV;
}
/*
@@ -156,11 +114,11 @@ static int gpio_init(void)
* that it was unused (or undocumented). Check that it looks
* okay: not all ones or zeros, and mapped to I/O space (bit 0).
*/
- pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong);
+ pci_read_config_dword(pci_dev, PCI_CFG_GPIOBASE, &tmplong);
if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
!(tmplong & 0x00000001)) {
debug("%s: unexpected GPIOBASE value\n", __func__);
- return -1;
+ return -ENODEV;
}
/*
@@ -170,105 +128,137 @@ static int gpio_init(void)
* an I/O address, not a memory address, so mask that off.
*/
gpiobase = tmplong & 0xfffffffe;
+ offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
+ if (offset == -1) {
+ debug("%s: Invalid register offset %d\n", __func__, offset);
+ return -EINVAL;
+ }
+ plat->base_addr = gpiobase + offset;
+ plat->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+ "bank-name", NULL);
- /* Finally. These are the droids we're looking for. */
- found_it_once = 1;
return 0;
}
-int gpio_request(unsigned num, const char *label /* UNUSED */)
+int ich6_gpio_probe(struct udevice *dev)
{
- u32 tmplong;
- int i = 0, j = 0;
+ struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
+
+ uc_priv->gpio_count = GPIO_PER_BANK;
+ uc_priv->bank_name = plat->bank_name;
+ bank->use_sel = plat->base_addr;
+ bank->io_sel = plat->base_addr + 4;
+ bank->lvl = plat->base_addr + 8;
- /* Is the hardware ready? */
- if (gpio_init())
- return -1;
+ return 0;
+}
- if (bad_arg(num, &i, &j))
- return -1;
+int ich6_gpio_request(struct udevice *dev, unsigned offset, const char *label)
+{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
+ u32 tmplong;
/*
* Make sure that the GPIO pin we want isn't already in use for some
* built-in hardware function. We have to check this for every
* requested pin.
*/
- tmplong = inl(gpiobase + gpio_bank[i].use_sel);
- if (!(tmplong & (1UL << j))) {
+ tmplong = inl(bank->use_sel);
+ if (!(tmplong & (1UL << offset))) {
debug("%s: gpio %d is reserved for internal use\n", __func__,
- num);
- return -1;
+ offset);
+ return -EPERM;
}
- return mark_gpio(i, j);
-}
-
-int gpio_free(unsigned num)
-{
- int i = 0, j = 0;
-
- if (notmine(num, &i, &j))
- return -1;
-
- clear_gpio(i, j);
return 0;
}
-int gpio_direction_input(unsigned num)
+static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
- int i = 0, j = 0;
-
- if (notmine(num, &i, &j))
- return -1;
- tmplong = inl(gpiobase + gpio_bank[i].io_sel);
- tmplong |= (1UL << j);
- outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+ tmplong = inl(bank->io_sel);
+ tmplong |= (1UL << offset);
+ outl(bank->io_sel, tmplong);
return 0;
}
-int gpio_direction_output(unsigned num, int value)
+static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
- int i = 0, j = 0;
- if (notmine(num, &i, &j))
- return -1;
-
- tmplong = inl(gpiobase + gpio_bank[i].io_sel);
- tmplong &= ~(1UL << j);
- outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+ tmplong = inl(bank->io_sel);
+ tmplong &= ~(1UL << offset);
+ outl(bank->io_sel, tmplong);
return 0;
}
-int gpio_get_value(unsigned num)
+static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
+
{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
- int i = 0, j = 0;
int r;
- if (notmine(num, &i, &j))
- return -1;
-
- tmplong = inl(gpiobase + gpio_bank[i].lvl);
- r = (tmplong & (1UL << j)) ? 1 : 0;
+ tmplong = inl(bank->lvl);
+ r = (tmplong & (1UL << offset)) ? 1 : 0;
return r;
}
-int gpio_set_value(unsigned num, int value)
+static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
u32 tmplong;
- int i = 0, j = 0;
- if (notmine(num, &i, &j))
- return -1;
-
- tmplong = inl(gpiobase + gpio_bank[i].lvl);
+ tmplong = inl(bank->lvl);
if (value)
- tmplong |= (1UL << j);
+ tmplong |= (1UL << offset);
else
- tmplong &= ~(1UL << j);
- outl(gpiobase + gpio_bank[i].lvl, tmplong);
+ tmplong &= ~(1UL << offset);
+ outl(bank->lvl, tmplong);
return 0;
}
+
+static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ struct ich6_bank_priv *bank = dev_get_priv(dev);
+ u32 mask = 1UL << offset;
+
+ if (!(inl(bank->use_sel) & mask))
+ return GPIOF_FUNC;
+ if (inl(bank->io_sel) & mask)
+ return GPIOF_INPUT;
+ else
+ return GPIOF_OUTPUT;
+}
+
+static const struct dm_gpio_ops gpio_ich6_ops = {
+ .request = ich6_gpio_request,
+ .direction_input = ich6_gpio_direction_input,
+ .direction_output = ich6_gpio_direction_output,
+ .get_value = ich6_gpio_get_value,
+ .set_value = ich6_gpio_set_value,
+ .get_function = ich6_gpio_get_function,
+};
+
+static const struct udevice_id intel_ich6_gpio_ids[] = {
+ { .compatible = "intel,ich6-gpio" },
+ { }
+};
+
+U_BOOT_DRIVER(gpio_ich6) = {
+ .name = "gpio_ich6",
+ .id = UCLASS_GPIO,
+ .of_match = intel_ich6_gpio_ids,
+ .ops = &gpio_ich6_ops,
+ .ofdata_to_platdata = gpio_ich6_ofdata_to_platdata,
+ .probe = ich6_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct ich6_bank_priv),
+ .platdata_auto_alloc_size = sizeof(struct ich6_bank_platdata),
+};
diff --git a/drivers/gpio/kw_gpio.c b/drivers/gpio/kw_gpio.c
index 4fca0894e6..43b27e3fea 100644
--- a/drivers/gpio/kw_gpio.c
+++ b/drivers/gpio/kw_gpio.c
@@ -36,7 +36,7 @@ void __set_direction(unsigned pin, int input)
u = readl(GPIO_IO_CONF(pin));
}
-void __set_level(unsigned pin, int high)
+static void __set_level(unsigned pin, int high)
{
u32 u;
@@ -48,7 +48,7 @@ void __set_level(unsigned pin, int high)
writel(u, GPIO_OUT(pin));
}
-void __set_blinking(unsigned pin, int blink)
+static void __set_blinking(unsigned pin, int blink)
{
u32 u;
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index 3f7b7d2441..8bb9e39b72 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -20,7 +20,6 @@ enum mxc_gpio_direction {
MXC_GPIO_DIRECTION_OUT,
};
-#define GPIO_NAME_SIZE 20
#define GPIO_PER_BANK 32
struct mxc_gpio_plat {
@@ -28,7 +27,6 @@ struct mxc_gpio_plat {
};
struct mxc_bank_info {
- char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
struct gpio_regs *regs;
};
@@ -152,18 +150,6 @@ int gpio_direction_output(unsigned gpio, int value)
#endif
#ifdef CONFIG_DM_GPIO
-/**
- * gpio_is_requested() - check if a GPIO has been requested
- *
- * @bank: Bank to check
- * @offset: GPIO offset within bank to check
- * @return true if marked as requested, false if not
- */
-static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset)
-{
- return *bank->label[offset] != '\0';
-}
-
static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
{
u32 val;
@@ -208,35 +194,10 @@ static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
return (readl(&regs->gpio_psr) >> offset) & 0x01;
}
-static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
-{
- return (readl(&regs->gpio_dr) >> offset) & 0x01;
-}
-
-static int check_requested(struct udevice *dev, unsigned offset,
- const char *func)
-{
- struct mxc_bank_info *bank = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
- if (!gpio_is_requested(bank, offset)) {
- printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
- func, uc_priv->bank_name, offset);
- return -EPERM;
- }
-
- return 0;
-}
-
/* set GPIO pin 'gpio' as an input */
static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO direction as input. */
mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
@@ -249,11 +210,6 @@ static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO output value. */
mxc_gpio_bank_set_value(bank->regs, offset, value);
@@ -268,11 +224,6 @@ static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
return mxc_gpio_bank_get_value(bank->regs, offset);
}
@@ -282,80 +233,16 @@ static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
mxc_gpio_bank_set_value(bank->regs, offset, value);
return 0;
}
-static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct mxc_bank_info *bank = dev_get_priv(dev);
- const char *label;
- bool requested;
- bool is_output;
- int size;
-
- label = bank->label[offset];
- is_output = mxc_gpio_is_output(bank->regs, offset);
- size = snprintf(buf, bufsize, "%s%d: ",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
- buf += size;
- bufsize -= size;
- requested = gpio_is_requested(bank, offset);
- snprintf(buf, bufsize, "%s: %d [%c]%s%s",
- is_output ? "out" : " in",
- is_output ?
- mxc_gpio_bank_get_output_value(bank->regs, offset) :
- mxc_gpio_bank_get_value(bank->regs, offset),
- requested ? 'x' : ' ',
- requested ? " " : "",
- label);
-
- return 0;
-}
-
-static int mxc_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
-{
- struct mxc_bank_info *bank = dev_get_priv(dev);
-
- if (gpio_is_requested(bank, offset))
- return -EBUSY;
-
- strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
- bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
- return 0;
-}
-
-static int mxc_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct mxc_bank_info *bank = dev_get_priv(dev);
- int ret;
-
- ret = check_requested(dev, offset, __func__);
- if (ret)
- return ret;
- bank->label[offset][0] = '\0';
-
- return 0;
-}
-
static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
- if (!gpio_is_requested(bank, offset))
- return GPIOF_UNUSED;
-
/* GPIOF_FUNC is not implemented yet */
if (mxc_gpio_is_output(bank->regs, offset))
return GPIOF_OUTPUT;
@@ -364,14 +251,11 @@ static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
}
static const struct dm_gpio_ops gpio_mxc_ops = {
- .request = mxc_gpio_request,
- .free = mxc_gpio_free,
.direction_input = mxc_gpio_direction_input,
.direction_output = mxc_gpio_direction_output,
.get_value = mxc_gpio_get_value,
.set_value = mxc_gpio_set_value,
.get_function = mxc_gpio_get_function,
- .get_state = mxc_gpio_get_state,
};
static const struct mxc_gpio_plat mxc_plat[] = {
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index 13dcf79873..f3a7ccb51e 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -19,6 +19,7 @@
* Written by Juha Yrjölä <juha.yrjola@nokia.com>
*/
#include <common.h>
+#include <dm.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/errno.h>
@@ -26,10 +27,17 @@
#define OMAP_GPIO_DIR_OUT 0
#define OMAP_GPIO_DIR_IN 1
-static inline const struct gpio_bank *get_gpio_bank(int gpio)
-{
- return &omap_gpio_bank[gpio >> 5];
-}
+#ifdef CONFIG_DM_GPIO
+
+#define GPIO_PER_BANK 32
+
+struct gpio_bank {
+ /* TODO(sjg@chromium.org): Can we use a struct here? */
+ void *base; /* address of registers in physical memory */
+ enum gpio_method method;
+};
+
+#endif
static inline int get_gpio_index(int gpio)
{
@@ -41,15 +49,6 @@ int gpio_is_valid(int gpio)
return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
}
-static int check_gpio(int gpio)
-{
- if (!gpio_is_valid(gpio)) {
- printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
- return -1;
- }
- return 0;
-}
-
static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
int is_input)
{
@@ -118,6 +117,48 @@ static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
__raw_writel(l, reg);
}
+static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
+{
+ void *reg = bank->base;
+ int input;
+
+ switch (bank->method) {
+ case METHOD_GPIO_24XX:
+ input = _get_gpio_direction(bank, gpio);
+ switch (input) {
+ case OMAP_GPIO_DIR_IN:
+ reg += OMAP_GPIO_DATAIN;
+ break;
+ case OMAP_GPIO_DIR_OUT:
+ reg += OMAP_GPIO_DATAOUT;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ return (__raw_readl(reg) & (1 << gpio)) != 0;
+}
+
+#ifndef CONFIG_DM_GPIO
+
+static inline const struct gpio_bank *get_gpio_bank(int gpio)
+{
+ return &omap_gpio_bank[gpio >> 5];
+}
+
+static int check_gpio(int gpio)
+{
+ if (!gpio_is_valid(gpio)) {
+ printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
+ return -1;
+ }
+ return 0;
+}
+
/**
* Set value of the specified gpio
*/
@@ -139,32 +180,12 @@ int gpio_set_value(unsigned gpio, int value)
int gpio_get_value(unsigned gpio)
{
const struct gpio_bank *bank;
- void *reg;
- int input;
if (check_gpio(gpio) < 0)
return -1;
bank = get_gpio_bank(gpio);
- reg = bank->base;
- switch (bank->method) {
- case METHOD_GPIO_24XX:
- input = _get_gpio_direction(bank, get_gpio_index(gpio));
- switch (input) {
- case OMAP_GPIO_DIR_IN:
- reg += OMAP_GPIO_DATAIN;
- break;
- case OMAP_GPIO_DIR_OUT:
- reg += OMAP_GPIO_DATAOUT;
- break;
- default:
- return -1;
- }
- break;
- default:
- return -1;
- }
- return (__raw_readl(reg)
- & (1 << get_gpio_index(gpio))) != 0;
+
+ return _get_gpio_value(bank, get_gpio_index(gpio));
}
/**
@@ -220,3 +241,95 @@ int gpio_free(unsigned gpio)
{
return 0;
}
+
+#else /* new driver model interface CONFIG_DM_GPIO */
+
+/* set GPIO pin 'gpio' as an input */
+static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ /* Configure GPIO direction as input. */
+ _set_gpio_direction(bank, offset, 1);
+
+ return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ _set_gpio_dataout(bank, offset, value);
+ _set_gpio_direction(bank, offset, 0);
+
+ return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ return _get_gpio_value(bank, offset);
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ _set_gpio_dataout(bank, offset, value);
+
+ return 0;
+}
+
+static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+
+ /* GPIOF_FUNC is not implemented yet */
+ if (_get_gpio_direction(bank->base, offset) == OMAP_GPIO_DIR_OUT)
+ return GPIOF_OUTPUT;
+ else
+ return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops gpio_omap_ops = {
+ .direction_input = omap_gpio_direction_input,
+ .direction_output = omap_gpio_direction_output,
+ .get_value = omap_gpio_get_value,
+ .set_value = omap_gpio_set_value,
+ .get_function = omap_gpio_get_function,
+};
+
+static int omap_gpio_probe(struct udevice *dev)
+{
+ struct gpio_bank *bank = dev_get_priv(dev);
+ struct omap_gpio_platdata *plat = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ char name[18], *str;
+
+ sprintf(name, "GPIO%d_", plat->bank_index);
+ str = strdup(name);
+ if (!str)
+ return -ENOMEM;
+ uc_priv->bank_name = str;
+ uc_priv->gpio_count = GPIO_PER_BANK;
+ bank->base = (void *)plat->base;
+ bank->method = plat->method;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(gpio_omap) = {
+ .name = "gpio_omap",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_omap_ops,
+ .probe = omap_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct gpio_bank),
+};
+
+#endif /* CONFIG_DM_GPIO */
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 13d74eb951..6c41a42c17 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -33,8 +33,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define RATE_MASK(gpio) (0x1 << (gpio + 16))
#define RATE_SET(gpio) (0x1 << (gpio + 16))
-#define GPIO_NAME_SIZE 20
-
/* Platform data for each bank */
struct exynos_gpio_platdata {
struct s5p_gpio_bank *bank;
@@ -43,7 +41,6 @@ struct exynos_gpio_platdata {
/* Information about each bank at run-time */
struct exynos_bank_info {
- char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
struct s5p_gpio_bank *bank;
};
@@ -189,61 +186,10 @@ int s5p_gpio_get_pin(unsigned gpio)
/* Driver model interface */
#ifndef CONFIG_SPL_BUILD
-static int exynos_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct exynos_bank_info *state = dev_get_priv(dev);
- const char *label;
- bool is_output;
- int size;
- int cfg;
-
- label = state->label[offset];
- cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
- is_output = cfg == S5P_GPIO_OUTPUT;
- size = snprintf(buf, bufsize, "%s%d: ",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
- buf += size;
- bufsize -= size;
- if (is_output || cfg == S5P_GPIO_INPUT) {
- snprintf(buf, bufsize, "%s: %d [%c]%s%s",
- is_output ? "out" : " in",
- s5p_gpio_get_value(state->bank, offset),
- *label ? 'x' : ' ',
- *label ? " " : "",
- label);
- } else {
- snprintf(buf, bufsize, "sfpio");
- }
-
- return 0;
-}
-
-static int check_reserved(struct udevice *dev, unsigned offset,
- const char *func)
-{
- struct exynos_bank_info *state = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
- if (!*state->label[offset]) {
- printf("exynos_gpio: %s: error: gpio %s%d not reserved\n",
- func, uc_priv->bank_name, offset);
- return -EPERM;
- }
-
- return 0;
-}
-
/* set GPIO pin 'gpio' as an input */
static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO direction as input. */
s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
@@ -256,11 +202,6 @@ static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO output value. */
s5p_gpio_set_value(state->bank, offset, value);
@@ -275,11 +216,6 @@ static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
return s5p_gpio_get_value(state->bank, offset);
}
@@ -289,43 +225,11 @@ static int exynos_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
s5p_gpio_set_value(state->bank, offset, value);
return 0;
}
-
-static int exynos_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
-{
- struct exynos_bank_info *state = dev_get_priv(dev);
-
- if (*state->label[offset])
- return -EBUSY;
-
- strncpy(state->label[offset], label, GPIO_NAME_SIZE);
- state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
- return 0;
-}
-
-static int exynos_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct exynos_bank_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
- state->label[offset][0] = '\0';
-
- return 0;
-}
#endif /* nCONFIG_SPL_BUILD */
/*
@@ -362,8 +266,6 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
struct exynos_bank_info *state = dev_get_priv(dev);
int cfg;
- if (!*state->label[offset])
- return GPIOF_UNUSED;
cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
if (cfg == S5P_GPIO_OUTPUT)
return GPIOF_OUTPUT;
@@ -374,14 +276,11 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
}
static const struct dm_gpio_ops gpio_exynos_ops = {
- .request = exynos_gpio_request,
- .free = exynos_gpio_free,
.direction_input = exynos_gpio_direction_input,
.direction_output = exynos_gpio_direction_output,
.get_value = exynos_gpio_get_value,
.set_value = exynos_gpio_set_value,
.get_function = exynos_gpio_get_function,
- .get_state = exynos_gpio_get_state,
};
static int gpio_exynos_probe(struct udevice *dev)
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 75ada5d387..53c80d5be6 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -14,7 +14,6 @@ DECLARE_GLOBAL_DATA_PTR;
/* Flags for each GPIO */
#define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */
#define GPIOF_HIGH (1 << 1) /* Currently set high */
-#define GPIOF_RESERVED (1 << 2) /* Is in use / requested */
struct gpio_state {
const char *label; /* label given by requester */
@@ -54,18 +53,6 @@ static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag,
return 0;
}
-static int check_reserved(struct udevice *dev, unsigned offset,
- const char *func)
-{
- if (!get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
- printf("sandbox_gpio: %s: error: offset %u not reserved\n",
- func, offset);
- return -1;
- }
-
- return 0;
-}
-
/*
* Back-channel sandbox-internal-only access to GPIO state
*/
@@ -101,9 +88,6 @@ static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
{
debug("%s: offset:%u\n", __func__, offset);
- if (check_reserved(dev, offset, __func__))
- return -1;
-
return sandbox_gpio_set_direction(dev, offset, 0);
}
@@ -113,9 +97,6 @@ static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
{
debug("%s: offset:%u, value = %d\n", __func__, offset, value);
- if (check_reserved(dev, offset, __func__))
- return -1;
-
return sandbox_gpio_set_direction(dev, offset, 1) |
sandbox_gpio_set_value(dev, offset, value);
}
@@ -125,9 +106,6 @@ static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
{
debug("%s: offset:%u\n", __func__, offset);
- if (check_reserved(dev, offset, __func__))
- return -1;
-
return sandbox_gpio_get_value(dev, offset);
}
@@ -136,9 +114,6 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
{
debug("%s: offset:%u, value = %d\n", __func__, offset, value);
- if (check_reserved(dev, offset, __func__))
- return -1;
-
if (!sandbox_gpio_get_direction(dev, offset)) {
printf("sandbox_gpio: error: set_value on input gpio %u\n",
offset);
@@ -148,69 +123,19 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
return sandbox_gpio_set_value(dev, offset, value);
}
-static int sb_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
+static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct gpio_state *state = dev_get_priv(dev);
-
- debug("%s: offset:%u, label:%s\n", __func__, offset, label);
-
- if (offset >= uc_priv->gpio_count) {
- printf("sandbox_gpio: error: invalid gpio %u\n", offset);
- return -1;
- }
-
- if (get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
- printf("sandbox_gpio: error: gpio %u already reserved\n",
- offset);
- return -1;
- }
-
- state[offset].label = label;
- return set_gpio_flag(dev, offset, GPIOF_RESERVED, 1);
-}
-
-static int sb_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct gpio_state *state = dev_get_priv(dev);
-
- debug("%s: offset:%u\n", __func__, offset);
-
- if (check_reserved(dev, offset, __func__))
- return -1;
-
- state[offset].label = NULL;
- return set_gpio_flag(dev, offset, GPIOF_RESERVED, 0);
-}
-
-static int sb_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct gpio_state *state = dev_get_priv(dev);
- const char *label;
-
- label = state[offset].label;
- snprintf(buf, bufsize, "%s%d: %s: %d [%c]%s%s",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset,
- sandbox_gpio_get_direction(dev, offset) ? "out" : " in",
- sandbox_gpio_get_value(dev, offset),
- get_gpio_flag(dev, offset, GPIOF_RESERVED) ? 'x' : ' ',
- label ? " " : "",
- label ? label : "");
-
- return 0;
+ if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
+ return GPIOF_OUTPUT;
+ return GPIOF_INPUT;
}
static const struct dm_gpio_ops gpio_sandbox_ops = {
- .request = sb_gpio_request,
- .free = sb_gpio_free,
.direction_input = sb_gpio_direction_input,
.direction_output = sb_gpio_direction_output,
.get_value = sb_gpio_get_value,
.set_value = sb_gpio_set_value,
- .get_state = sb_gpio_get_state,
+ .get_function = sb_gpio_get_function,
};
static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
@@ -239,6 +164,13 @@ static int gpio_sandbox_probe(struct udevice *dev)
return 0;
}
+static int gpio_sandbox_remove(struct udevice *dev)
+{
+ free(dev->priv);
+
+ return 0;
+}
+
static const struct udevice_id sandbox_gpio_ids[] = {
{ .compatible = "sandbox,gpio" },
{ }
@@ -250,5 +182,6 @@ U_BOOT_DRIVER(gpio_sandbox) = {
.of_match = sandbox_gpio_ids,
.ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
.probe = gpio_sandbox_probe,
+ .remove = gpio_sandbox_remove,
.ops = &gpio_sandbox_ops,
};
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 0c50a8f332..44135e5bb7 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -11,9 +11,25 @@
*/
#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
#include <asm/io.h>
#include <asm/gpio.h>
+#include <dm/device-internal.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SUNXI_GPIOS_PER_BANK SUNXI_GPIO_A_NR
+
+struct sunxi_gpio_platdata {
+ struct sunxi_gpio *regs;
+ const char *bank_name; /* Name of bank, e.g. "B" */
+ int gpio_count;
+};
+
+#ifndef CONFIG_DM_GPIO
static int sunxi_gpio_output(u32 pin, u32 val)
{
u32 dat;
@@ -100,3 +116,157 @@ int sunxi_name_to_gpio(const char *name)
return -1;
return group * 32 + pin;
}
+#endif
+
+#ifdef CONFIG_DM_GPIO
+static int sunxi_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+ struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
+
+ sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_INPUT);
+
+ return 0;
+}
+
+static int sunxi_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
+ u32 num = GPIO_NUM(offset);
+
+ sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
+ clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
+
+ return 0;
+}
+
+static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+ struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
+ u32 num = GPIO_NUM(offset);
+ unsigned dat;
+
+ dat = readl(&plat->regs->dat);
+ dat >>= num;
+
+ return dat & 0x1;
+}
+
+static int sunxi_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
+{
+ struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
+ u32 num = GPIO_NUM(offset);
+
+ clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
+ return 0;
+}
+
+static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
+ int func;
+
+ func = sunxi_gpio_get_cfgbank(plat->regs, offset);
+ if (func == SUNXI_GPIO_OUTPUT)
+ return GPIOF_OUTPUT;
+ else if (func == SUNXI_GPIO_INPUT)
+ return GPIOF_INPUT;
+ else
+ return GPIOF_FUNC;
+}
+
+static const struct dm_gpio_ops gpio_sunxi_ops = {
+ .direction_input = sunxi_gpio_direction_input,
+ .direction_output = sunxi_gpio_direction_output,
+ .get_value = sunxi_gpio_get_value,
+ .set_value = sunxi_gpio_set_value,
+ .get_function = sunxi_gpio_get_function,
+};
+
+/**
+ * Returns the name of a GPIO bank
+ *
+ * GPIO banks are named A, B, C, ...
+ *
+ * @bank: Bank number (0, 1..n-1)
+ * @return allocated string containing the name
+ */
+static char *gpio_bank_name(int bank)
+{
+ char *name;
+
+ name = malloc(2);
+ if (name) {
+ name[0] = 'A' + bank;
+ name[1] = '\0';
+ }
+
+ return name;
+}
+
+static int gpio_sunxi_probe(struct udevice *dev)
+{
+ struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ /* Tell the uclass how many GPIOs we have */
+ if (plat) {
+ uc_priv->gpio_count = plat->gpio_count;
+ uc_priv->bank_name = plat->bank_name;
+ }
+
+ return 0;
+}
+/**
+ * We have a top-level GPIO device with no actual GPIOs. It has a child
+ * device for each Sunxi bank.
+ */
+static int gpio_sunxi_bind(struct udevice *parent)
+{
+ struct sunxi_gpio_platdata *plat = parent->platdata;
+ struct sunxi_gpio_reg *ctlr;
+ int bank;
+ int ret;
+
+ /* If this is a child device, there is nothing to do here */
+ if (plat)
+ return 0;
+
+ ctlr = (struct sunxi_gpio_reg *)fdtdec_get_addr(gd->fdt_blob,
+ parent->of_offset, "reg");
+ for (bank = 0; bank < SUNXI_GPIO_BANKS; bank++) {
+ struct sunxi_gpio_platdata *plat;
+ struct udevice *dev;
+
+ plat = calloc(1, sizeof(*plat));
+ if (!plat)
+ return -ENOMEM;
+ plat->regs = &ctlr->gpio_bank[bank];
+ plat->bank_name = gpio_bank_name(bank);
+ plat->gpio_count = SUNXI_GPIOS_PER_BANK;
+
+ ret = device_bind(parent, parent->driver,
+ plat->bank_name, plat, -1, &dev);
+ if (ret)
+ return ret;
+ dev->of_offset = parent->of_offset;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id sunxi_gpio_ids[] = {
+ { .compatible = "allwinner,sun7i-a20-pinctrl" },
+ { }
+};
+
+U_BOOT_DRIVER(gpio_sunxi) = {
+ .name = "gpio_sunxi",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_sunxi_ops,
+ .of_match = sunxi_gpio_ids,
+ .bind = gpio_sunxi_bind,
+ .probe = gpio_sunxi_probe,
+};
+#endif
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 70663fc4de..88f7ef5bf0 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -39,7 +39,6 @@ struct tegra_gpio_platdata {
/* Information about each port at run-time */
struct tegra_port_info {
- char label[TEGRA_GPIOS_PER_PORT][GPIO_NAME_SIZE];
struct gpio_ctlr_bank *bank;
int base_gpio; /* Port number for this port (0, 1,.., n-1) */
};
@@ -132,21 +131,6 @@ static void set_level(unsigned gpio, int high)
writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
}
-static int check_reserved(struct udevice *dev, unsigned offset,
- const char *func)
-{
- struct tegra_port_info *state = dev_get_priv(dev);
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
- if (!*state->label[offset]) {
- printf("tegra_gpio: %s: error: gpio %s%d not reserved\n",
- func, uc_priv->bank_name, offset);
- return -EBUSY;
- }
-
- return 0;
-}
-
/* set GPIO pin 'gpio' as an output, with polarity 'value' */
int tegra_spl_gpio_direction_output(int gpio, int value)
{
@@ -171,59 +155,16 @@ static int tegra_gpio_request(struct udevice *dev, unsigned offset,
{
struct tegra_port_info *state = dev_get_priv(dev);
- if (!label)
- return -EINVAL;
-
- if (*state->label[offset])
- return -EBUSY;
-
- strncpy(state->label[offset], label, GPIO_NAME_SIZE);
- state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
/* Configure as a GPIO */
set_config(state->base_gpio + offset, 1);
return 0;
}
-static int tegra_gpio_free(struct udevice *dev, unsigned offset)
-{
- struct tegra_port_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
- state->label[offset][0] = '\0';
-
- return 0;
-}
-
-/* read GPIO OUT value of pin 'gpio' */
-static int tegra_gpio_get_output_value(unsigned gpio)
-{
- struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
- struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
- int val;
-
- debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n",
- gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
-
- val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
-
- return (val >> GPIO_BIT(gpio)) & 1;
-}
-
-
/* set GPIO pin 'gpio' as an input */
static int tegra_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct tegra_port_info *state = dev_get_priv(dev);
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO direction as input. */
set_direction(state->base_gpio + offset, 0);
@@ -237,11 +178,6 @@ static int tegra_gpio_direction_output(struct udevice *dev, unsigned offset,
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
/* Configure GPIO output value. */
set_level(gpio, value);
@@ -257,13 +193,8 @@ static int tegra_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
- int ret;
int val;
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
-
debug("%s: pin = %d (port %d:bit %d)\n", __func__,
gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
@@ -277,11 +208,6 @@ static int tegra_gpio_set_value(struct udevice *dev, unsigned offset, int value)
{
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
- int ret;
-
- ret = check_reserved(dev, offset, __func__);
- if (ret)
- return ret;
debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
@@ -317,8 +243,6 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
struct tegra_port_info *state = dev_get_priv(dev);
int gpio = state->base_gpio + offset;
- if (!*state->label[offset])
- return GPIOF_UNUSED;
if (!get_config(gpio))
return GPIOF_FUNC;
else if (get_direction(gpio))
@@ -327,50 +251,13 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
-static int tegra_gpio_get_state(struct udevice *dev, unsigned int offset,
- char *buf, int bufsize)
-{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
- struct tegra_port_info *state = dev_get_priv(dev);
- int gpio = state->base_gpio + offset;
- const char *label;
- int is_output;
- int is_gpio;
- int size;
-
- label = state->label[offset];
- is_gpio = get_config(gpio); /* GPIO, not SFPIO */
- size = snprintf(buf, bufsize, "%s%d: ",
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
- buf += size;
- bufsize -= size;
- if (is_gpio) {
- is_output = get_direction(gpio);
-
- snprintf(buf, bufsize, "%s: %d [%c]%s%s",
- is_output ? "out" : " in",
- is_output ?
- tegra_gpio_get_output_value(gpio) :
- tegra_gpio_get_value(dev, offset),
- *label ? 'x' : ' ',
- *label ? " " : "",
- label);
- } else {
- snprintf(buf, bufsize, "sfpio");
- }
-
- return 0;
-}
-
static const struct dm_gpio_ops gpio_tegra_ops = {
.request = tegra_gpio_request,
- .free = tegra_gpio_free,
.direction_input = tegra_gpio_direction_input,
.direction_output = tegra_gpio_direction_output,
.get_value = tegra_gpio_get_value,
.set_value = tegra_gpio_set_value,
.get_function = tegra_gpio_get_function,
- .get_state = tegra_gpio_get_state,
};
/**
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 416ea4f2c8..d067897244 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -6,21 +6,21 @@
#
obj-$(CONFIG_BFIN_TWI_I2C) += bfin-twi_i2c.o
-obj-$(CONFIG_DW_I2C) += designware_i2c.o
obj-$(CONFIG_I2C_MV) += mv_i2c.o
-obj-$(CONFIG_I2C_MXS) += mxs_i2c.o
obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
obj-$(CONFIG_U8500_I2C) += u8500_i2c.o
obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
obj-$(CONFIG_SYS_I2C) += i2c_core.o
obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
+obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
obj-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o
obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o
obj-$(CONFIG_SYS_I2C_KONA) += kona_i2c.o
obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o
obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
+obj-$(CONFIG_SYS_I2C_MXS) += mxs_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o
obj-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index c891ebd39e..e768cdedb0 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -6,16 +6,33 @@
*/
#include <common.h>
+#include <i2c.h>
#include <asm/io.h>
#include "designware_i2c.h"
-#ifdef CONFIG_I2C_MULTI_BUS
-static unsigned int bus_initialized[CONFIG_SYS_I2C_BUS_MAX];
-static unsigned int current_bus = 0;
+static struct i2c_regs *i2c_get_base(struct i2c_adapter *adap)
+{
+ switch (adap->hwadapnr) {
+#if CONFIG_SYS_I2C_BUS_MAX >= 4
+ case 3:
+ return (struct i2c_regs *)CONFIG_SYS_I2C_BASE3;
+#endif
+#if CONFIG_SYS_I2C_BUS_MAX >= 3
+ case 2:
+ return (struct i2c_regs *)CONFIG_SYS_I2C_BASE2;
#endif
+#if CONFIG_SYS_I2C_BUS_MAX >= 2
+ case 1:
+ return (struct i2c_regs *)CONFIG_SYS_I2C_BASE1;
+#endif
+ case 0:
+ return (struct i2c_regs *)CONFIG_SYS_I2C_BASE;
+ default:
+ printf("Wrong I2C-adapter number %d\n", adap->hwadapnr);
+ }
-static struct i2c_regs *i2c_regs_p =
- (struct i2c_regs *)CONFIG_SYS_I2C_BASE;
+ return NULL;
+}
/*
* set_speed - Set the i2c speed mode (standard, high, fast)
@@ -23,51 +40,52 @@ static struct i2c_regs *i2c_regs_p =
*
* Set the i2c speed mode (standard, high, fast)
*/
-static void set_speed(int i2c_spd)
+static void set_speed(struct i2c_adapter *adap, int i2c_spd)
{
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
unsigned int cntl;
unsigned int hcnt, lcnt;
unsigned int enbl;
/* to set speed cltr must be disabled */
- enbl = readl(&i2c_regs_p->ic_enable);
+ enbl = readl(&i2c_base->ic_enable);
enbl &= ~IC_ENABLE_0B;
- writel(enbl, &i2c_regs_p->ic_enable);
+ writel(enbl, &i2c_base->ic_enable);
- cntl = (readl(&i2c_regs_p->ic_con) & (~IC_CON_SPD_MSK));
+ cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
switch (i2c_spd) {
case IC_SPEED_MODE_MAX:
cntl |= IC_CON_SPD_HS;
hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
- writel(hcnt, &i2c_regs_p->ic_hs_scl_hcnt);
+ writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
- writel(lcnt, &i2c_regs_p->ic_hs_scl_lcnt);
+ writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
break;
case IC_SPEED_MODE_STANDARD:
cntl |= IC_CON_SPD_SS;
hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
- writel(hcnt, &i2c_regs_p->ic_ss_scl_hcnt);
+ writel(hcnt, &i2c_base->ic_ss_scl_hcnt);
lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
- writel(lcnt, &i2c_regs_p->ic_ss_scl_lcnt);
+ writel(lcnt, &i2c_base->ic_ss_scl_lcnt);
break;
case IC_SPEED_MODE_FAST:
default:
cntl |= IC_CON_SPD_FS;
hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
- writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt);
+ writel(hcnt, &i2c_base->ic_fs_scl_hcnt);
lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
- writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt);
+ writel(lcnt, &i2c_base->ic_fs_scl_lcnt);
break;
}
- writel(cntl, &i2c_regs_p->ic_con);
+ writel(cntl, &i2c_base->ic_con);
/* Enable back i2c now speed set */
enbl |= IC_ENABLE_0B;
- writel(enbl, &i2c_regs_p->ic_enable);
+ writel(enbl, &i2c_base->ic_enable);
}
/*
@@ -76,35 +94,20 @@ static void set_speed(int i2c_spd)
*
* Set the i2c speed.
*/
-int i2c_set_bus_speed(int speed)
+static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap,
+ unsigned int speed)
{
+ int i2c_spd;
+
if (speed >= I2C_MAX_SPEED)
- set_speed(IC_SPEED_MODE_MAX);
+ i2c_spd = IC_SPEED_MODE_MAX;
else if (speed >= I2C_FAST_SPEED)
- set_speed(IC_SPEED_MODE_FAST);
+ i2c_spd = IC_SPEED_MODE_FAST;
else
- set_speed(IC_SPEED_MODE_STANDARD);
+ i2c_spd = IC_SPEED_MODE_STANDARD;
- return 0;
-}
-
-/*
- * i2c_get_bus_speed - Gets the i2c speed
- *
- * Gets the i2c speed.
- */
-int i2c_get_bus_speed(void)
-{
- u32 cntl;
-
- cntl = (readl(&i2c_regs_p->ic_con) & IC_CON_SPD_MSK);
-
- if (cntl == IC_CON_SPD_HS)
- return I2C_MAX_SPEED;
- else if (cntl == IC_CON_SPD_FS)
- return I2C_FAST_SPEED;
- else if (cntl == IC_CON_SPD_SS)
- return I2C_STANDARD_SPEED;
+ set_speed(adap, i2c_spd);
+ adap->speed = speed;
return 0;
}
@@ -112,34 +115,32 @@ int i2c_get_bus_speed(void)
/*
* i2c_init - Init function
* @speed: required i2c speed
- * @slaveadd: slave address for the device
+ * @slaveaddr: slave address for the device
*
* Initialization function.
*/
-void i2c_init(int speed, int slaveadd)
+static void dw_i2c_init(struct i2c_adapter *adap, int speed,
+ int slaveaddr)
{
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
unsigned int enbl;
/* Disable i2c */
- enbl = readl(&i2c_regs_p->ic_enable);
+ enbl = readl(&i2c_base->ic_enable);
enbl &= ~IC_ENABLE_0B;
- writel(enbl, &i2c_regs_p->ic_enable);
+ writel(enbl, &i2c_base->ic_enable);
- writel((IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM), &i2c_regs_p->ic_con);
- writel(IC_RX_TL, &i2c_regs_p->ic_rx_tl);
- writel(IC_TX_TL, &i2c_regs_p->ic_tx_tl);
- i2c_set_bus_speed(speed);
- writel(IC_STOP_DET, &i2c_regs_p->ic_intr_mask);
- writel(slaveadd, &i2c_regs_p->ic_sar);
+ writel((IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM), &i2c_base->ic_con);
+ writel(IC_RX_TL, &i2c_base->ic_rx_tl);
+ writel(IC_TX_TL, &i2c_base->ic_tx_tl);
+ dw_i2c_set_bus_speed(adap, speed);
+ writel(IC_STOP_DET, &i2c_base->ic_intr_mask);
+ writel(slaveaddr, &i2c_base->ic_sar);
/* Enable i2c */
- enbl = readl(&i2c_regs_p->ic_enable);
+ enbl = readl(&i2c_base->ic_enable);
enbl |= IC_ENABLE_0B;
- writel(enbl, &i2c_regs_p->ic_enable);
-
-#ifdef CONFIG_I2C_MULTI_BUS
- bus_initialized[current_bus] = 1;
-#endif
+ writel(enbl, &i2c_base->ic_enable);
}
/*
@@ -148,21 +149,22 @@ void i2c_init(int speed, int slaveadd)
*
* Sets the target slave address.
*/
-static void i2c_setaddress(unsigned int i2c_addr)
+static void i2c_setaddress(struct i2c_adapter *adap, unsigned int i2c_addr)
{
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
unsigned int enbl;
/* Disable i2c */
- enbl = readl(&i2c_regs_p->ic_enable);
+ enbl = readl(&i2c_base->ic_enable);
enbl &= ~IC_ENABLE_0B;
- writel(enbl, &i2c_regs_p->ic_enable);
+ writel(enbl, &i2c_base->ic_enable);
- writel(i2c_addr, &i2c_regs_p->ic_tar);
+ writel(i2c_addr, &i2c_base->ic_tar);
/* Enable i2c */
- enbl = readl(&i2c_regs_p->ic_enable);
+ enbl = readl(&i2c_base->ic_enable);
enbl |= IC_ENABLE_0B;
- writel(enbl, &i2c_regs_p->ic_enable);
+ writel(enbl, &i2c_base->ic_enable);
}
/*
@@ -170,10 +172,12 @@ static void i2c_setaddress(unsigned int i2c_addr)
*
* Flushes the i2c RX FIFO
*/
-static void i2c_flush_rxfifo(void)
+static void i2c_flush_rxfifo(struct i2c_adapter *adap)
{
- while (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE)
- readl(&i2c_regs_p->ic_cmd_data);
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
+
+ while (readl(&i2c_base->ic_status) & IC_STATUS_RFNE)
+ readl(&i2c_base->ic_cmd_data);
}
/*
@@ -181,12 +185,13 @@ static void i2c_flush_rxfifo(void)
*
* Waits for bus busy
*/
-static int i2c_wait_for_bb(void)
+static int i2c_wait_for_bb(struct i2c_adapter *adap)
{
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
unsigned long start_time_bb = get_timer(0);
- while ((readl(&i2c_regs_p->ic_status) & IC_STATUS_MA) ||
- !(readl(&i2c_regs_p->ic_status) & IC_STATUS_TFE)) {
+ while ((readl(&i2c_base->ic_status) & IC_STATUS_MA) ||
+ !(readl(&i2c_base->ic_status) & IC_STATUS_TFE)) {
/* Evaluate timeout */
if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB))
@@ -196,40 +201,44 @@ static int i2c_wait_for_bb(void)
return 0;
}
-static int i2c_xfer_init(uchar chip, uint addr, int alen)
+static int i2c_xfer_init(struct i2c_adapter *adap, uchar chip, uint addr,
+ int alen)
{
- if (i2c_wait_for_bb())
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
+
+ if (i2c_wait_for_bb(adap))
return 1;
- i2c_setaddress(chip);
+ i2c_setaddress(adap, chip);
while (alen) {
alen--;
/* high byte address going out first */
writel((addr >> (alen * 8)) & 0xff,
- &i2c_regs_p->ic_cmd_data);
+ &i2c_base->ic_cmd_data);
}
return 0;
}
-static int i2c_xfer_finish(void)
+static int i2c_xfer_finish(struct i2c_adapter *adap)
{
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
ulong start_stop_det = get_timer(0);
while (1) {
- if ((readl(&i2c_regs_p->ic_raw_intr_stat) & IC_STOP_DET)) {
- readl(&i2c_regs_p->ic_clr_stop_det);
+ if ((readl(&i2c_base->ic_raw_intr_stat) & IC_STOP_DET)) {
+ readl(&i2c_base->ic_clr_stop_det);
break;
} else if (get_timer(start_stop_det) > I2C_STOPDET_TO) {
break;
}
}
- if (i2c_wait_for_bb()) {
+ if (i2c_wait_for_bb(adap)) {
printf("Timed out waiting for bus\n");
return 1;
}
- i2c_flush_rxfifo();
+ i2c_flush_rxfifo(adap);
return 0;
}
@@ -244,8 +253,10 @@ static int i2c_xfer_finish(void)
*
* Read from i2c memory.
*/
-int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+static int dw_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
+ int alen, u8 *buffer, int len)
{
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
unsigned long start_time_rx;
#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
@@ -260,25 +271,25 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
* still be one byte because the extra address bits are
* hidden in the chip address.
*/
- chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+ dev |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
addr &= ~(CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW << (alen * 8));
- debug("%s: fix addr_overflow: chip %02x addr %02x\n", __func__, chip,
+ debug("%s: fix addr_overflow: dev %02x addr %02x\n", __func__, dev,
addr);
#endif
- if (i2c_xfer_init(chip, addr, alen))
+ if (i2c_xfer_init(adap, dev, addr, alen))
return 1;
start_time_rx = get_timer(0);
while (len) {
if (len == 1)
- writel(IC_CMD | IC_STOP, &i2c_regs_p->ic_cmd_data);
+ writel(IC_CMD | IC_STOP, &i2c_base->ic_cmd_data);
else
- writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
+ writel(IC_CMD, &i2c_base->ic_cmd_data);
- if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) {
- *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data);
+ if (readl(&i2c_base->ic_status) & IC_STATUS_RFNE) {
+ *buffer++ = (uchar)readl(&i2c_base->ic_cmd_data);
len--;
start_time_rx = get_timer(0);
@@ -287,7 +298,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
}
}
- return i2c_xfer_finish();
+ return i2c_xfer_finish(adap);
}
/*
@@ -300,8 +311,10 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
*
* Write to i2c memory.
*/
-int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+static int dw_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
+ int alen, u8 *buffer, int len)
{
+ struct i2c_regs *i2c_base = i2c_get_base(adap);
int nb = len;
unsigned long start_time_tx;
@@ -317,23 +330,25 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
* still be one byte because the extra address bits are
* hidden in the chip address.
*/
- chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+ dev |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
addr &= ~(CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW << (alen * 8));
- debug("%s: fix addr_overflow: chip %02x addr %02x\n", __func__, chip,
+ debug("%s: fix addr_overflow: dev %02x addr %02x\n", __func__, dev,
addr);
#endif
- if (i2c_xfer_init(chip, addr, alen))
+ if (i2c_xfer_init(adap, dev, addr, alen))
return 1;
start_time_tx = get_timer(0);
while (len) {
- if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) {
- if (--len == 0)
- writel(*buffer | IC_STOP, &i2c_regs_p->ic_cmd_data);
- else
- writel(*buffer, &i2c_regs_p->ic_cmd_data);
+ if (readl(&i2c_base->ic_status) & IC_STATUS_TFNF) {
+ if (--len == 0) {
+ writel(*buffer | IC_STOP,
+ &i2c_base->ic_cmd_data);
+ } else {
+ writel(*buffer, &i2c_base->ic_cmd_data);
+ }
buffer++;
start_time_tx = get_timer(0);
@@ -343,13 +358,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
}
}
- return i2c_xfer_finish();
+ return i2c_xfer_finish(adap);
}
/*
* i2c_probe - Probe the i2c chip
*/
-int i2c_probe(uchar chip)
+static int dw_i2c_probe(struct i2c_adapter *adap, u8 dev)
{
u32 tmp;
int ret;
@@ -357,80 +372,31 @@ int i2c_probe(uchar chip)
/*
* Try to read the first location of the chip.
*/
- ret = i2c_read(chip, 0, 1, (uchar *)&tmp, 1);
+ ret = dw_i2c_read(adap, dev, 0, 1, (uchar *)&tmp, 1);
if (ret)
- i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ dw_i2c_init(adap, adap->speed, adap->slaveaddr);
return ret;
}
-#ifdef CONFIG_I2C_MULTI_BUS
-int i2c_set_bus_num(unsigned int bus)
-{
- switch (bus) {
- case 0:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE;
- break;
-#ifdef CONFIG_SYS_I2C_BASE1
- case 1:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE1;
- break;
-#endif
-#ifdef CONFIG_SYS_I2C_BASE2
- case 2:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE2;
- break;
-#endif
-#ifdef CONFIG_SYS_I2C_BASE3
- case 3:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE3;
- break;
-#endif
-#ifdef CONFIG_SYS_I2C_BASE4
- case 4:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE4;
- break;
-#endif
-#ifdef CONFIG_SYS_I2C_BASE5
- case 5:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE5;
- break;
-#endif
-#ifdef CONFIG_SYS_I2C_BASE6
- case 6:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE6;
- break;
-#endif
-#ifdef CONFIG_SYS_I2C_BASE7
- case 7:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE7;
- break;
-#endif
-#ifdef CONFIG_SYS_I2C_BASE8
- case 8:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE8;
- break;
-#endif
-#ifdef CONFIG_SYS_I2C_BASE9
- case 9:
- i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE9;
- break;
-#endif
- default:
- printf("Bad bus: %d\n", bus);
- return -1;
- }
+U_BOOT_I2C_ADAP_COMPLETE(dw_0, dw_i2c_init, dw_i2c_probe, dw_i2c_read,
+ dw_i2c_write, dw_i2c_set_bus_speed,
+ CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 0)
- current_bus = bus;
-
- if (!bus_initialized[current_bus])
- i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+#if CONFIG_SYS_I2C_BUS_MAX >= 2
+U_BOOT_I2C_ADAP_COMPLETE(dw_1, dw_i2c_init, dw_i2c_probe, dw_i2c_read,
+ dw_i2c_write, dw_i2c_set_bus_speed,
+ CONFIG_SYS_I2C_SPEED1, CONFIG_SYS_I2C_SLAVE1, 1)
+#endif
- return 0;
-}
+#if CONFIG_SYS_I2C_BUS_MAX >= 3
+U_BOOT_I2C_ADAP_COMPLETE(dw_2, dw_i2c_init, dw_i2c_probe, dw_i2c_read,
+ dw_i2c_write, dw_i2c_set_bus_speed,
+ CONFIG_SYS_I2C_SPEED2, CONFIG_SYS_I2C_SLAVE2, 2)
+#endif
-int i2c_get_bus_num(void)
-{
- return current_bus;
-}
+#if CONFIG_SYS_I2C_BUS_MAX >= 4
+U_BOOT_I2C_ADAP_COMPLETE(dw_3, dw_i2c_init, dw_i2c_probe, dw_i2c_read,
+ dw_i2c_write, dw_i2c_set_bus_speed,
+ CONFIG_SYS_I2C_SPEED3, CONFIG_SYS_I2C_SLAVE3, 3)
#endif
diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
index 18d6736601..d34b749a56 100644
--- a/drivers/i2c/i2c_core.c
+++ b/drivers/i2c/i2c_core.c
@@ -229,11 +229,9 @@ static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr)
}
/* implement possible board specific board init */
-static void __def_i2c_init_board(void)
+__weak void i2c_init_board(void)
{
}
-void i2c_init_board(void)
- __attribute__((weak, alias("__def_i2c_init_board")));
/*
* i2c_init_all():
@@ -395,9 +393,7 @@ void i2c_reg_write(uint8_t addr, uint8_t reg, uint8_t val)
i2c_write(addr, reg, 1, &val, 1);
}
-void __i2c_init(int speed, int slaveaddr)
+__weak void i2c_init(int speed, int slaveaddr)
{
i2c_init_bus(i2c_get_bus_num(), speed, slaveaddr);
}
-void i2c_init(int speed, int slaveaddr)
- __attribute__((weak, alias("__i2c_init")));
diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
index de3b19402b..87e05c7125 100644
--- a/drivers/i2c/mxs_i2c.c
+++ b/drivers/i2c/mxs_i2c.c
@@ -24,11 +24,74 @@
#define MXS_I2C_MAX_TIMEOUT 1000000
-static void mxs_i2c_reset(void)
+static struct mxs_i2c_regs *mxs_i2c_get_base(struct i2c_adapter *adap)
{
- struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
+ if (adap->hwadapnr == 0)
+ return (struct mxs_i2c_regs *)MXS_I2C0_BASE;
+ else
+ return (struct mxs_i2c_regs *)MXS_I2C1_BASE;
+}
+
+static unsigned int mxs_i2c_get_bus_speed(struct i2c_adapter *adap)
+{
+ struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap);
+ uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
+ uint32_t timing0;
+
+ timing0 = readl(&i2c_regs->hw_i2c_timing0);
+ /*
+ * This is a reverse version of the algorithm presented in
+ * i2c_set_bus_speed(). Please refer there for details.
+ */
+ return clk / ((((timing0 >> 16) - 3) * 2) + 38);
+}
+
+static uint mxs_i2c_set_bus_speed(struct i2c_adapter *adap, uint speed)
+{
+ struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap);
+ /*
+ * The timing derivation algorithm. There is no documentation for this
+ * algorithm available, it was derived by using the scope and fiddling
+ * with constants until the result observed on the scope was good enough
+ * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be
+ * possible to assume the algorithm works for other frequencies as well.
+ *
+ * Note it was necessary to cap the frequency on both ends as it's not
+ * possible to configure completely arbitrary frequency for the I2C bus
+ * clock.
+ */
+ uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
+ uint32_t base = ((clk / speed) - 38) / 2;
+ uint16_t high_count = base + 3;
+ uint16_t low_count = base - 3;
+ uint16_t rcv_count = (high_count * 3) / 4;
+ uint16_t xmit_count = low_count / 4;
+
+ if (speed > 540000) {
+ printf("MXS I2C: Speed too high (%d Hz)\n", speed);
+ return -EINVAL;
+ }
+
+ if (speed < 12000) {
+ printf("MXS I2C: Speed too low (%d Hz)\n", speed);
+ return -EINVAL;
+ }
+
+ writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0);
+ writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1);
+
+ writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) |
+ (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET),
+ &i2c_regs->hw_i2c_timing2);
+
+ return 0;
+}
+
+static void mxs_i2c_reset(struct i2c_adapter *adap)
+{
+ struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap);
int ret;
- int speed = i2c_get_bus_speed();
+ int speed = mxs_i2c_get_bus_speed(adap);
ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
if (ret) {
@@ -43,12 +106,12 @@ static void mxs_i2c_reset(void)
writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set);
- i2c_set_bus_speed(speed);
+ mxs_i2c_set_bus_speed(adap, speed);
}
-static void mxs_i2c_setup_read(uint8_t chip, int len)
+static void mxs_i2c_setup_read(struct i2c_adapter *adap, uint8_t chip, int len)
{
- struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
+ struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap);
writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START |
I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
@@ -64,10 +127,10 @@ static void mxs_i2c_setup_read(uint8_t chip, int len)
writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
}
-static int mxs_i2c_write(uchar chip, uint addr, int alen,
- uchar *buf, int blen, int stop)
+static int mxs_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
+ int alen, uchar *buf, int blen, int stop)
{
- struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
+ struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap);
uint32_t data, tmp;
int i, remain, off;
int timeout = MXS_I2C_MAX_TIMEOUT;
@@ -122,9 +185,9 @@ static int mxs_i2c_write(uchar chip, uint addr, int alen,
return 0;
}
-static int mxs_i2c_wait_for_ack(void)
+static int mxs_i2c_wait_for_ack(struct i2c_adapter *adap)
{
- struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
+ struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap);
uint32_t tmp;
int timeout = MXS_I2C_MAX_TIMEOUT;
@@ -156,32 +219,34 @@ static int mxs_i2c_wait_for_ack(void)
return 0;
err:
- mxs_i2c_reset();
+ mxs_i2c_reset(adap);
return 1;
}
-int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+static int mxs_i2c_if_read(struct i2c_adapter *adap, uint8_t chip,
+ uint addr, int alen, uint8_t *buffer,
+ int len)
{
- struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
+ struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap);
uint32_t tmp = 0;
int timeout = MXS_I2C_MAX_TIMEOUT;
int ret;
int i;
- ret = mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
+ ret = mxs_i2c_write(adap, chip, addr, alen, NULL, 0, 0);
if (ret) {
debug("MXS I2C: Failed writing address\n");
return ret;
}
- ret = mxs_i2c_wait_for_ack();
+ ret = mxs_i2c_wait_for_ack(adap);
if (ret) {
debug("MXS I2C: Failed writing address\n");
return ret;
}
- mxs_i2c_setup_read(chip, len);
- ret = mxs_i2c_wait_for_ack();
+ mxs_i2c_setup_read(adap, chip, len);
+ ret = mxs_i2c_wait_for_ack(adap);
if (ret) {
debug("MXS I2C: Failed reading address\n");
return ret;
@@ -209,91 +274,47 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
return 0;
}
-int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+static int mxs_i2c_if_write(struct i2c_adapter *adap, uint8_t chip,
+ uint addr, int alen, uint8_t *buffer,
+ int len)
{
int ret;
- ret = mxs_i2c_write(chip, addr, alen, buffer, len, 1);
+ ret = mxs_i2c_write(adap, chip, addr, alen, buffer, len, 1);
if (ret) {
debug("MXS I2C: Failed writing address\n");
return ret;
}
- ret = mxs_i2c_wait_for_ack();
+ ret = mxs_i2c_wait_for_ack(adap);
if (ret)
debug("MXS I2C: Failed writing address\n");
return ret;
}
-int i2c_probe(uchar chip)
+static int mxs_i2c_probe(struct i2c_adapter *adap, uint8_t chip)
{
int ret;
- ret = mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
+ ret = mxs_i2c_write(adap, chip, 0, 1, NULL, 0, 1);
if (!ret)
- ret = mxs_i2c_wait_for_ack();
- mxs_i2c_reset();
+ ret = mxs_i2c_wait_for_ack(adap);
+ mxs_i2c_reset(adap);
return ret;
}
-int i2c_set_bus_speed(unsigned int speed)
+static void mxs_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
{
- struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
- /*
- * The timing derivation algorithm. There is no documentation for this
- * algorithm available, it was derived by using the scope and fiddling
- * with constants until the result observed on the scope was good enough
- * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be
- * possible to assume the algorithm works for other frequencies as well.
- *
- * Note it was necessary to cap the frequency on both ends as it's not
- * possible to configure completely arbitrary frequency for the I2C bus
- * clock.
- */
- uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
- uint32_t base = ((clk / speed) - 38) / 2;
- uint16_t high_count = base + 3;
- uint16_t low_count = base - 3;
- uint16_t rcv_count = (high_count * 3) / 4;
- uint16_t xmit_count = low_count / 4;
-
- if (speed > 540000) {
- printf("MXS I2C: Speed too high (%d Hz)\n", speed);
- return -EINVAL;
- }
-
- if (speed < 12000) {
- printf("MXS I2C: Speed too low (%d Hz)\n", speed);
- return -EINVAL;
- }
-
- writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0);
- writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1);
-
- writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) |
- (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET),
- &i2c_regs->hw_i2c_timing2);
-
- return 0;
-}
-
-unsigned int i2c_get_bus_speed(void)
-{
- struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
- uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
- uint32_t timing0;
-
- timing0 = readl(&i2c_regs->hw_i2c_timing0);
- /*
- * This is a reverse version of the algorithm presented in
- * i2c_set_bus_speed(). Please refer there for details.
- */
- return clk / ((((timing0 >> 16) - 3) * 2) + 38);
-}
-
-void i2c_init(int speed, int slaveadd)
-{
- mxs_i2c_reset();
- i2c_set_bus_speed(speed);
+ mxs_i2c_reset(adap);
+ mxs_i2c_set_bus_speed(adap, speed);
return;
}
+
+U_BOOT_I2C_ADAP_COMPLETE(mxs0, mxs_i2c_init, mxs_i2c_probe,
+ mxs_i2c_if_read, mxs_i2c_if_write,
+ mxs_i2c_set_bus_speed,
+ CONFIG_SYS_I2C_SPEED, 0, 0)
+U_BOOT_I2C_ADAP_COMPLETE(mxs1, mxs_i2c_init, mxs_i2c_probe,
+ mxs_i2c_if_read, mxs_i2c_if_write,
+ mxs_i2c_set_bus_speed,
+ CONFIG_SYS_I2C_SPEED, 0, 1)
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 257b72f0f7..562211e7de 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -471,8 +471,8 @@ static void tegra_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
}
/* i2c write version without the register address */
-int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer, int len,
- bool end_with_repeated_start)
+static int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
+ int len, bool end_with_repeated_start)
{
int rc;
@@ -493,7 +493,8 @@ int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer, int len,
}
/* i2c read version without the register address */
-int i2c_read_data(struct i2c_bus *bus, uchar chip, uchar *buffer, int len)
+static int i2c_read_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
+ int len)
{
int rc;
diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c
index 7e36db0a71..0ef94f7a00 100644
--- a/drivers/input/tegra-kbc.c
+++ b/drivers/input/tegra-kbc.c
@@ -181,7 +181,7 @@ static void kbd_wait_for_fifo_init(struct keyb *config)
* @param input Input configuration
* @return 1, to indicate that we have something to look at
*/
-int tegra_kbc_check(struct input_config *input)
+static int tegra_kbc_check(struct input_config *input)
{
kbd_wait_for_fifo_init(&config);
check_for_keys(&config);
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 464cee16d1..461d7d8ec1 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -5,37 +5,39 @@
# SPDX-License-Identifier: GPL-2.0+
#
+obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
+obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o
obj-$(CONFIG_BFIN_SDH) += bfin_sdh.o
obj-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o
+obj-$(CONFIG_DWMMC) += dw_mmc.o
+obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o
obj-$(CONFIG_FTSDC021) += ftsdc021_sdhci.o
obj-$(CONFIG_GENERIC_MMC) += mmc.o
obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
+obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o
obj-$(CONFIG_MMC_SPI) += mmc_spi.o
-obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
+obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o
obj-$(CONFIG_MV_SDHCI) += mv_sdhci.o
+obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
obj-$(CONFIG_MXC_MMC) += mxcmmc.o
obj-$(CONFIG_MXS_MMC) += mxsmmc.o
obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
-obj-$(CONFIG_SDHCI) += sdhci.o
-obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o
-obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o
+obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
obj-$(CONFIG_S3C_SDI) += s3c_sdi.o
obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
+obj-$(CONFIG_SDHCI) += sdhci.o
obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
+obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o
obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
-obj-$(CONFIG_DWMMC) += dw_mmc.o
-obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
-obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o
obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
-obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
-obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
+
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
else
obj-$(CONFIG_GENERIC_MMC) += mmc_write.o
endif
-obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
+
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
index 82079d67cd..92f7d8942f 100644
--- a/drivers/mmc/bcm2835_sdhci.c
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -40,6 +40,7 @@
#include <malloc.h>
#include <sdhci.h>
#include <asm/arch/timer.h>
+#include <asm/arch-bcm2835/sdhci.h>
/* 400KHz is max freq for card ID etc. Use that as min */
#define MIN_FREQ 400000
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 5b0c302069..ffb5284a00 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -67,14 +67,19 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
#ifdef OMAP_HSMMC_USE_GPIO
static int omap_mmc_setup_gpio_in(int gpio, const char *label)
{
- if (!gpio_is_valid(gpio))
- return -1;
+ int ret;
- if (gpio_request(gpio, label) < 0)
+#ifndef CONFIG_DM_GPIO
+ if (!gpio_is_valid(gpio))
return -1;
+#endif
+ ret = gpio_request(gpio, label);
+ if (ret)
+ return ret;
- if (gpio_direction_input(gpio) < 0)
- return -1;
+ ret = gpio_direction_input(gpio);
+ if (ret)
+ return ret;
return gpio;
}
@@ -606,7 +611,8 @@ static int omap_hsmmc_getcd(struct mmc *mmc)
if (cd_gpio < 0)
return 1;
- return gpio_get_value(cd_gpio);
+ /* NOTE: assumes card detect signal is active-low */
+ return !gpio_get_value(cd_gpio);
}
static int omap_hsmmc_getwp(struct mmc *mmc)
@@ -619,6 +625,7 @@ static int omap_hsmmc_getwp(struct mmc *mmc)
if (wp_gpio < 0)
return 0;
+ /* NOTE: assumes write protect signal is active-high */
return gpio_get_value(wp_gpio);
}
#endif
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index 0dea45d079..a5d34876bb 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -123,7 +123,7 @@ static int do_sdhci_init(struct sdhci_host *host)
if (fdt_gpio_isvalid(&host->cd_gpio)) {
sprintf(str, "sdhci%d_cd", host->index & 0xf);
gpio_request(host->cd_gpio.gpio, str);
- gpio_direction_output(host->cd_gpio.gpio, 1);
+ gpio_direction_input(host->cd_gpio.gpio);
if (gpio_get_value(host->cd_gpio.gpio))
return -ENODEV;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 3125d13ba3..de88e19609 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -124,7 +124,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
#endif
#define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT 100
-int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
+static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
struct sdhci_host *host = mmc->priv;
@@ -355,7 +355,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}
-void sdhci_set_ios(struct mmc *mmc)
+static void sdhci_set_ios(struct mmc *mmc)
{
u32 ctrl;
struct sdhci_host *host = mmc->priv;
@@ -393,7 +393,7 @@ void sdhci_set_ios(struct mmc *mmc)
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}
-int sdhci_init(struct mmc *mmc)
+static int sdhci_init(struct mmc *mmc)
{
struct sdhci_host *host = mmc->priv;
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index d4e574fe19..231f0a0315 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -14,12 +14,13 @@
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
#include <asm/arch/mmc.h>
+#include <asm-generic/gpio.h>
struct sunxi_mmc_host {
unsigned mmc_no;
uint32_t *mclkreg;
- unsigned database;
unsigned fatal_err;
unsigned mod_clk;
struct sunxi_mmc *reg;
@@ -29,10 +30,22 @@ struct sunxi_mmc_host {
/* support 4 mmc hosts */
struct sunxi_mmc_host mmc_host[4];
+static int sunxi_mmc_getcd_gpio(int sdc_no)
+{
+ switch (sdc_no) {
+ case 0: return sunxi_name_to_gpio(CONFIG_MMC0_CD_PIN);
+ case 1: return sunxi_name_to_gpio(CONFIG_MMC1_CD_PIN);
+ case 2: return sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN);
+ case 3: return sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN);
+ }
+ return -1;
+}
+
static int mmc_resource_init(int sdc_no)
{
struct sunxi_mmc_host *mmchost = &mmc_host[sdc_no];
struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ int cd_pin, ret = 0;
debug("init mmc %d resource\n", sdc_no);
@@ -57,10 +70,13 @@ static int mmc_resource_init(int sdc_no)
printf("Wrong mmc number %d\n", sdc_no);
return -1;
}
- mmchost->database = (unsigned int)mmchost->reg + 0x100;
mmchost->mmc_no = sdc_no;
- return 0;
+ cd_pin = sunxi_mmc_getcd_gpio(sdc_no);
+ if (cd_pin != -1)
+ ret = gpio_request(cd_pin, "mmc_cd");
+
+ return ret;
}
static int mmc_clk_io_on(int sdc_no)
@@ -75,6 +91,11 @@ static int mmc_clk_io_on(int sdc_no)
/* config ahb clock */
setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
+#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I)
+ /* unassert reset */
+ setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no));
+#endif
+
/* config mod clock */
pll_clk = clock_get_pll6();
/* should be close to 100 MHz but no more, so round up */
@@ -194,9 +215,9 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
}
if (reading)
- buff[i] = readl(mmchost->database);
+ buff[i] = readl(&mmchost->reg->fifo);
else
- writel(buff[i], mmchost->database);
+ writel(buff[i], &mmchost->reg->fifo);
}
return 0;
@@ -343,13 +364,26 @@ out:
return error;
}
+static int sunxi_mmc_getcd(struct mmc *mmc)
+{
+ struct sunxi_mmc_host *mmchost = mmc->priv;
+ int cd_pin;
+
+ cd_pin = sunxi_mmc_getcd_gpio(mmchost->mmc_no);
+ if (cd_pin == -1)
+ return 1;
+
+ return !gpio_direction_input(cd_pin);
+}
+
static const struct mmc_ops sunxi_mmc_ops = {
.send_cmd = mmc_send_cmd,
.set_ios = mmc_set_ios,
.init = mmc_core_init,
+ .getcd = sunxi_mmc_getcd,
};
-int sunxi_mmc_init(int sdc_no)
+struct mmc *sunxi_mmc_init(int sdc_no)
{
struct mmc_config *cfg = &mmc_host[sdc_no].cfg;
@@ -361,16 +395,18 @@ int sunxi_mmc_init(int sdc_no)
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
cfg->host_caps = MMC_MODE_4BIT;
cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || defined(CONFIG_MACH_SUN8I)
+ cfg->host_caps |= MMC_MODE_HC;
+#endif
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
cfg->f_min = 400000;
cfg->f_max = 52000000;
- mmc_resource_init(sdc_no);
- mmc_clk_io_on(sdc_no);
+ if (mmc_resource_init(sdc_no) != 0)
+ return NULL;
- if (mmc_create(cfg, &mmc_host[sdc_no]) == NULL)
- return -1;
+ mmc_clk_io_on(sdc_no);
- return 0;
+ return mmc_create(cfg, &mmc_host[sdc_no]);
}
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 2642fe2065..2bd36b0ee7 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -13,6 +13,7 @@
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/mmc.h>
#include <asm/arch-tegra/tegra_mmc.h>
#include <mmc.h>
@@ -508,7 +509,7 @@ static int tegra_mmc_core_init(struct mmc *mmc)
return 0;
}
-int tegra_mmc_getcd(struct mmc *mmc)
+static int tegra_mmc_getcd(struct mmc *mmc)
{
struct mmc_host *host = mmc->priv;
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 9b3175d87f..50983b837b 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -63,6 +63,12 @@ flash_info_t flash_info[CFI_MAX_FLASH_BANKS]; /* FLASH chips info */
#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_8BIT
#endif
+#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
+#define __maybe_weak __weak
+#else
+#define __maybe_weak static
+#endif
+
/*
* 0xffff is an undefined value for the configuration register. When
* this value is returned, the configuration register shall not be
@@ -81,14 +87,12 @@ static u16 cfi_flash_config_reg(int i)
int cfi_flash_num_flash_banks = CONFIG_SYS_MAX_FLASH_BANKS_DETECT;
#endif
-static phys_addr_t __cfi_flash_bank_addr(int i)
+__weak phys_addr_t cfi_flash_bank_addr(int i)
{
return ((phys_addr_t [])CONFIG_SYS_FLASH_BANKS_LIST)[i];
}
-phys_addr_t cfi_flash_bank_addr(int i)
- __attribute__((weak, alias("__cfi_flash_bank_addr")));
-static unsigned long __cfi_flash_bank_size(int i)
+__weak unsigned long cfi_flash_bank_size(int i)
{
#ifdef CONFIG_SYS_FLASH_BANKS_SIZES
return ((unsigned long [])CONFIG_SYS_FLASH_BANKS_SIZES)[i];
@@ -96,71 +100,49 @@ static unsigned long __cfi_flash_bank_size(int i)
return 0;
#endif
}
-unsigned long cfi_flash_bank_size(int i)
- __attribute__((weak, alias("__cfi_flash_bank_size")));
-static void __flash_write8(u8 value, void *addr)
+__maybe_weak void flash_write8(u8 value, void *addr)
{
__raw_writeb(value, addr);
}
-static void __flash_write16(u16 value, void *addr)
+__maybe_weak void flash_write16(u16 value, void *addr)
{
__raw_writew(value, addr);
}
-static void __flash_write32(u32 value, void *addr)
+__maybe_weak void flash_write32(u32 value, void *addr)
{
__raw_writel(value, addr);
}
-static void __flash_write64(u64 value, void *addr)
+__maybe_weak void flash_write64(u64 value, void *addr)
{
/* No architectures currently implement __raw_writeq() */
*(volatile u64 *)addr = value;
}
-static u8 __flash_read8(void *addr)
+__maybe_weak u8 flash_read8(void *addr)
{
return __raw_readb(addr);
}
-static u16 __flash_read16(void *addr)
+__maybe_weak u16 flash_read16(void *addr)
{
return __raw_readw(addr);
}
-static u32 __flash_read32(void *addr)
+__maybe_weak u32 flash_read32(void *addr)
{
return __raw_readl(addr);
}
-static u64 __flash_read64(void *addr)
+__maybe_weak u64 flash_read64(void *addr)
{
/* No architectures currently implement __raw_readq() */
return *(volatile u64 *)addr;
}
-#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
-void flash_write8(u8 value, void *addr)__attribute__((weak, alias("__flash_write8")));
-void flash_write16(u16 value, void *addr)__attribute__((weak, alias("__flash_write16")));
-void flash_write32(u32 value, void *addr)__attribute__((weak, alias("__flash_write32")));
-void flash_write64(u64 value, void *addr)__attribute__((weak, alias("__flash_write64")));
-u8 flash_read8(void *addr)__attribute__((weak, alias("__flash_read8")));
-u16 flash_read16(void *addr)__attribute__((weak, alias("__flash_read16")));
-u32 flash_read32(void *addr)__attribute__((weak, alias("__flash_read32")));
-u64 flash_read64(void *addr)__attribute__((weak, alias("__flash_read64")));
-#else
-#define flash_write8 __flash_write8
-#define flash_write16 __flash_write16
-#define flash_write32 __flash_write32
-#define flash_write64 __flash_write64
-#define flash_read8 __flash_read8
-#define flash_read16 __flash_read16
-#define flash_read32 __flash_read32
-#define flash_read64 __flash_read64
-#endif
-
/*-----------------------------------------------------------------------
*/
#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index 036c113ad3..7a064ab1bf 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -146,8 +146,13 @@ static uint32_t mxs_nand_aux_status_offset(void)
static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
uint32_t page_oob_size)
{
- if (page_data_size == 2048)
- return 8;
+ if (page_data_size == 2048) {
+ if (page_oob_size == 64)
+ return 8;
+
+ if (page_oob_size == 112)
+ return 14;
+ }
if (page_data_size == 4096) {
if (page_oob_size == 128)
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index db1599e9a6..40d670563c 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -75,7 +75,7 @@ static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
#ifdef CONFIG_SPL_BUILD
/* Check wait pin as dev ready indicator */
-int omap_spl_dev_ready(struct mtd_info *mtd)
+static int omap_spl_dev_ready(struct mtd_info *mtd)
{
return gpmc_cfg->status & (1 << 8);
}
@@ -162,23 +162,6 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
}
/*
- * omap_reverse_list - re-orders list elements in reverse order [internal]
- * @list: pointer to start of list
- * @length: length of list
-*/
-void omap_reverse_list(u8 *list, unsigned int length)
-{
- unsigned int i, j;
- unsigned int half_length = length / 2;
- u8 tmp;
- for (i = 0, j = length - 1; i < half_length; i++, j--) {
- tmp = list[i];
- list[i] = list[j];
- list[j] = tmp;
- }
-}
-
-/*
* omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
* @mtd: MTD device structure
* @mode: Read/Write mode
@@ -351,6 +334,23 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
#ifdef CONFIG_NAND_OMAP_ELM
/*
+ * omap_reverse_list - re-orders list elements in reverse order [internal]
+ * @list: pointer to start of list
+ * @length: length of list
+*/
+static void omap_reverse_list(u8 *list, unsigned int length)
+{
+ unsigned int i, j;
+ unsigned int half_length = length / 2;
+ u8 tmp;
+ for (i = 0, j = length - 1; i < half_length; i++, j--) {
+ tmp = list[i];
+ list[i] = list[j];
+ list[j] = tmp;
+ }
+}
+
+/*
* omap_correct_data_bch - Compares the ecc read from nand spare area
* with ECC registers values and corrects one bit error if it has occured
*
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 439f8ae99e..08bc1afcf6 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -27,6 +27,7 @@
#include <net.h>
#include <miiphy.h>
#include <malloc.h>
+#include <netdev.h>
#include <linux/compiler.h>
#include <asm/arch/emac_defs.h>
#include <asm/io.h>
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 6e8765cf7b..6531030463 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -92,7 +92,10 @@ static struct pci_device_id e1000_supported[] = {
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_SERDES_DPT},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_COPPER_SPT},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_SERDES_SPT},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_UNPROGRAMMED},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I211_UNPROGRAMMED},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_COPPER},
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I211_COPPER},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_COPPER_FLASHLESS},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS},
@@ -1112,8 +1115,11 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
if (e1000_get_hw_eeprom_semaphore(hw))
return -E1000_ERR_SWFW_SYNC;
- swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
- if ((swfw_sync & swmask) && !(swfw_sync & fwmask))
+ if (hw->mac_type == e1000_igb)
+ swfw_sync = E1000_READ_REG(hw, I210_SW_FW_SYNC);
+ else
+ swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+ if (!(swfw_sync & (fwmask | swmask)))
break;
/* firmware currently using resource (fwmask) */
@@ -1374,7 +1380,10 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_ICH8_IGP_M:
hw->mac_type = e1000_ich8lan;
break;
+ case PCI_DEVICE_ID_INTEL_I210_UNPROGRAMMED:
+ case PCI_DEVICE_ID_INTEL_I211_UNPROGRAMMED:
case PCI_DEVICE_ID_INTEL_I210_COPPER:
+ case PCI_DEVICE_ID_INTEL_I211_COPPER:
case PCI_DEVICE_ID_INTEL_I210_COPPER_FLASHLESS:
case PCI_DEVICE_ID_INTEL_I210_SERDES:
case PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS:
@@ -4429,7 +4438,6 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
if (hw->mac_type >= e1000_82571)
mdelay(10);
-
} else {
/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
* bit to put the PHY into reset. Then, take it out of reset.
diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h
index b025ecc4fc..6d110eb5d5 100644
--- a/drivers/net/e1000.h
+++ b/drivers/net/e1000.h
@@ -2497,6 +2497,7 @@ struct e1000_hw {
#define ICH_GFPREG_BASE_MASK 0x1FFF
#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
+#define E1000_I210_SW_FW_SYNC 0x5B50 /* Software-Firmware Synchronization - RW */
#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
/* SPI EEPROM Status Register */
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 1e4ea0c892..a23a5852ee 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -230,7 +230,7 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length);
static int eepro100_recv (struct eth_device *dev);
static void eepro100_halt (struct eth_device *dev);
-#if defined(CONFIG_E500) || defined(CONFIG_DB64360) || defined(CONFIG_DB64460)
+#if defined(CONFIG_E500)
#define bus_to_phys(a) (a)
#define phys_to_bus(a) (a)
#else
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 549d648613..b57247032f 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -11,6 +11,7 @@
#include <common.h>
#include <malloc.h>
#include <net.h>
+#include <netdev.h>
#include <miiphy.h>
#include "fec_mxc.h"
@@ -179,13 +180,14 @@ static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr,
return 0;
}
-int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr)
+static int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr,
+ int regAddr)
{
return fec_mdio_read(bus->priv, phyAddr, regAddr);
}
-int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr,
- u16 data)
+static int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr,
+ int regAddr, u16 data)
{
return fec_mdio_write(bus->priv, phyAddr, regAddr, data);
}
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index d22b722bc5..bedab1d606 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -10,15 +10,16 @@
#include <command.h>
#include <net.h>
+#include <phy.h>
+#include <errno.h>
#include <miiphy.h>
#include <malloc.h>
-#include <asm/arch/emac_defs.h>
-#include <asm/arch/psc_defs.h>
-#include <asm/arch/keystone_nav.h>
-
-unsigned int emac_dbg;
+#include <asm/ti-common/keystone_nav.h>
+#include <asm/ti-common/keystone_net.h>
+#include <asm/ti-common/keystone_serdes.h>
unsigned int emac_open;
+static struct mii_dev *mdio_bus;
static unsigned int sys_has_mdio = 1;
#ifdef KEYSTONE2_EMAC_GIG_ENABLE
@@ -30,6 +31,7 @@ static unsigned int sys_has_mdio = 1;
#define RX_BUFF_NUMS 24
#define RX_BUFF_LEN 1520
#define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN
+#define SGMII_ANEG_TIMEOUT 4000
static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16);
@@ -40,15 +42,7 @@ struct rx_buff_desc net_rx_buffs = {
.rx_flow = 22,
};
-static void keystone2_eth_mdio_enable(void);
-
-static int gen_get_link_speed(int phy_addr);
-
-/* EMAC Addresses */
-static volatile struct emac_regs *adap_emac =
- (struct emac_regs *)EMAC_EMACSL_BASE_ADDR;
-static volatile struct mdio_regs *adap_mdio =
- (struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
+static void keystone2_net_serdes_setup(void);
int keystone2_eth_read_mac_addr(struct eth_device *dev)
{
@@ -74,64 +68,67 @@ int keystone2_eth_read_mac_addr(struct eth_device *dev)
return 0;
}
-static void keystone2_eth_mdio_enable(void)
+/* MDIO */
+
+static int keystone2_mdio_reset(struct mii_dev *bus)
{
- u_int32_t clkdiv;
+ u_int32_t clkdiv;
+ struct mdio_regs *adap_mdio = bus->priv;
clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
- writel((clkdiv & 0xffff) |
- MDIO_CONTROL_ENABLE |
- MDIO_CONTROL_FAULT |
- MDIO_CONTROL_FAULT_ENABLE,
+ writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE |
+ MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE,
&adap_mdio->control);
while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE)
;
+
+ return 0;
}
-/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
-int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
+/**
+ * keystone2_mdio_read - read a PHY register via MDIO interface.
+ * Blocks until operation is complete.
+ */
+static int keystone2_mdio_read(struct mii_dev *bus,
+ int addr, int devad, int reg)
{
- int tmp;
+ int tmp;
+ struct mdio_regs *adap_mdio = bus->priv;
while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
;
- writel(MDIO_USERACCESS0_GO |
- MDIO_USERACCESS0_WRITE_READ |
- ((reg_num & 0x1f) << 21) |
- ((phy_addr & 0x1f) << 16),
+ writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ |
+ ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16),
&adap_mdio->useraccess0);
/* Wait for command to complete */
while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO)
;
- if (tmp & MDIO_USERACCESS0_ACK) {
- *data = tmp & 0xffff;
- return 0;
- }
+ if (tmp & MDIO_USERACCESS0_ACK)
+ return tmp & 0xffff;
- *data = -1;
return -1;
}
-/*
- * Write to a PHY register via MDIO inteface.
+/**
+ * keystone2_mdio_write - write to a PHY register via MDIO interface.
* Blocks until operation is complete.
*/
-int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
+static int keystone2_mdio_write(struct mii_dev *bus,
+ int addr, int devad, int reg, u16 val)
{
+ struct mdio_regs *adap_mdio = bus->priv;
+
while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
;
- writel(MDIO_USERACCESS0_GO |
- MDIO_USERACCESS0_WRITE_WRITE |
- ((reg_num & 0x1f) << 21) |
- ((phy_addr & 0x1f) << 16) |
- (data & 0xffff),
- &adap_mdio->useraccess0);
+ writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE |
+ ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) |
+ (val & 0xffff), &adap_mdio->useraccess0);
/* Wait for command to complete */
while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
@@ -140,19 +137,6 @@ int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
return 0;
}
-/* PHY functions for a generic PHY */
-static int gen_get_link_speed(int phy_addr)
-{
- u_int16_t tmp;
-
- if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) &&
- (tmp & 0x04)) {
- return 0;
- }
-
- return -1;
-}
-
static void __attribute__((unused))
keystone2_eth_gigabit_enable(struct eth_device *dev)
{
@@ -160,8 +144,10 @@ static void __attribute__((unused))
struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
if (sys_has_mdio) {
- if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) ||
- !(data & (1 << 6))) /* speed selection MSB */
+ data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr,
+ MDIO_DEVAD_NONE, 0);
+ /* speed selection MSB */
+ if (!(data & (1 << 6)))
return;
}
@@ -169,10 +155,10 @@ static void __attribute__((unused))
* Check if link detected is giga-bit
* If Gigabit mode detected, enable gigbit in MAC
*/
- writel(readl(&(adap_emac[eth_priv->slave_port - 1].maccontrol)) |
+ writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) +
+ CPGMACSL_REG_CTL) |
EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
- &(adap_emac[eth_priv->slave_port - 1].maccontrol))
- ;
+ DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL);
}
int keystone_sgmii_link_status(int port)
@@ -181,38 +167,11 @@ int keystone_sgmii_link_status(int port)
status = __raw_readl(SGMII_STATUS_REG(port));
- return status & SGMII_REG_STATUS_LINK;
+ return (status & SGMII_REG_STATUS_LOCK) &&
+ (status & SGMII_REG_STATUS_LINK);
}
-
-int keystone_get_link_status(struct eth_device *dev)
-{
- struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
- int sgmii_link;
- int link_state = 0;
-#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1
- int j;
-
- for (j = 0; (j < CONFIG_GET_LINK_STATUS_ATTEMPTS) && (link_state == 0);
- j++) {
-#endif
- sgmii_link =
- keystone_sgmii_link_status(eth_priv->slave_port - 1);
-
- if (sgmii_link) {
- link_state = 1;
-
- if (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY)
- if (gen_get_link_speed(eth_priv->phy_addr))
- link_state = 0;
- }
-#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1
- }
-#endif
- return link_state;
-}
-
-int keystone_sgmii_config(int port, int interface)
+int keystone_sgmii_config(struct phy_device *phy_dev, int port, int interface)
{
unsigned int i, status, mask;
unsigned int mr_adv_ability, control;
@@ -273,11 +232,35 @@ int keystone_sgmii_config(int port, int interface)
if (control & SGMII_REG_CONTROL_AUTONEG)
mask |= SGMII_REG_STATUS_AUTONEG;
- for (i = 0; i < 1000; i++) {
+ status = __raw_readl(SGMII_STATUS_REG(port));
+ if ((status & mask) == mask)
+ return 0;
+
+ printf("\n%s Waiting for SGMII auto negotiation to complete",
+ phy_dev->dev->name);
+ while ((status & mask) != mask) {
+ /*
+ * Timeout reached ?
+ */
+ if (i > SGMII_ANEG_TIMEOUT) {
+ puts(" TIMEOUT !\n");
+ phy_dev->link = 0;
+ return 0;
+ }
+
+ if (ctrlc()) {
+ puts("user interrupt!\n");
+ phy_dev->link = 0;
+ return -EINTR;
+ }
+
+ if ((i++ % 500) == 0)
+ printf(".");
+
+ udelay(1000); /* 1 ms */
status = __raw_readl(SGMII_STATUS_REG(port));
- if ((status & mask) == mask)
- break;
}
+ puts(" done\n");
return 0;
}
@@ -332,6 +315,11 @@ int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg)
writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN);
writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL);
+#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L)
+ /* Map RX packet flow priority to 0 */
+ writel(0, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RX_PRI_MAP);
+#endif
+
return ret;
}
@@ -393,15 +381,15 @@ int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num)
if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE;
- return netcp_send(buffer, num_bytes, (slave_port_num) << 16);
+ return ksnav_send(&netcp_pktdma, buffer,
+ num_bytes, (slave_port_num) << 16);
}
/* Eth device open */
static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
{
- u_int32_t clkdiv;
- int link;
struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+ struct phy_device *phy_dev = eth_priv->phy_dev;
debug("+ emac_open\n");
@@ -410,15 +398,12 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
sys_has_mdio =
(eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
- psc_enable_module(KS2_LPSC_PA);
- psc_enable_module(KS2_LPSC_CPGMAC);
-
- sgmii_serdes_setup_156p25mhz();
+ keystone2_net_serdes_setup();
if (sys_has_mdio)
- keystone2_eth_mdio_enable();
+ keystone2_mdio_reset(mdio_bus);
- keystone_sgmii_config(eth_priv->slave_port - 1,
+ keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1,
eth_priv->sgmii_link_type);
udelay(10000);
@@ -431,7 +416,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
printf("ERROR: qm_init()\n");
return -1;
}
- if (netcp_init(&net_rx_buffs)) {
+ if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) {
qm_close();
printf("ERROR: netcp_init()\n");
return -1;
@@ -445,18 +430,11 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
hw_config_streaming_switch();
if (sys_has_mdio) {
- /* Init MDIO & get link state */
- clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
- writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE |
- MDIO_CONTROL_FAULT, &adap_mdio->control)
- ;
-
- /* We need to wait for MDIO to start */
- udelay(1000);
-
- link = keystone_get_link_status(dev);
- if (link == 0) {
- netcp_close();
+ keystone2_mdio_reset(mdio_bus);
+
+ phy_startup(phy_dev);
+ if (phy_dev->link == 0) {
+ ksnav_close(&netcp_pktdma);
qm_close();
return -1;
}
@@ -476,6 +454,9 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
/* Eth device close */
void keystone2_eth_close(struct eth_device *dev)
{
+ struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+ struct phy_device *phy_dev = eth_priv->phy_dev;
+
debug("+ emac_close\n");
if (!emac_open)
@@ -483,16 +464,15 @@ void keystone2_eth_close(struct eth_device *dev)
ethss_stop();
- netcp_close();
+ ksnav_close(&netcp_pktdma);
qm_close();
+ phy_shutdown(phy_dev);
emac_open = 0;
debug("- emac_close\n");
}
-static int tx_send_loop;
-
/*
* This function sends a single packet on the network and returns
* positive number (number of bytes transmitted) or negative for error
@@ -502,22 +482,15 @@ static int keystone2_eth_send_packet(struct eth_device *dev,
{
int ret_status = -1;
struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+ struct phy_device *phy_dev = eth_priv->phy_dev;
- tx_send_loop = 0;
-
- if (keystone_get_link_status(dev) == 0)
+ genphy_update_link(phy_dev);
+ if (phy_dev->link == 0)
return -1;
- emac_gigabit_enable(dev);
-
if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0)
return ret_status;
- if (keystone_get_link_status(dev) == 0)
- return -1;
-
- emac_gigabit_enable(dev);
-
return length;
}
@@ -530,13 +503,13 @@ static int keystone2_eth_rcv_packet(struct eth_device *dev)
int pkt_size;
u32 *pkt;
- hd = netcp_recv(&pkt, &pkt_size);
+ hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size);
if (hd == NULL)
return 0;
NetReceive((uchar *)pkt, pkt_size);
- netcp_release_rxhd(hd);
+ ksnav_release_rxhd(&netcp_pktdma, hd);
return pkt_size;
}
@@ -546,7 +519,9 @@ static int keystone2_eth_rcv_packet(struct eth_device *dev)
*/
int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
{
+ int res;
struct eth_device *dev;
+ struct phy_device *phy_dev;
dev = malloc(sizeof(struct eth_device));
if (dev == NULL)
@@ -567,145 +542,55 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
eth_register(dev);
- return 0;
-}
-
-void sgmii_serdes_setup_156p25mhz(void)
-{
- unsigned int cnt;
-
- /*
- * configure Serializer/Deserializer (SerDes) hardware. SerDes IP
- * hardware vendor published only register addresses and their values
- * to be used for configuring SerDes. So had to use hardcoded values
- * below.
- */
- clrsetbits_le32(0x0232a000, 0xffff0000, 0x00800000);
- clrsetbits_le32(0x0232a014, 0x0000ffff, 0x00008282);
- clrsetbits_le32(0x0232a060, 0x00ffffff, 0x00142438);
- clrsetbits_le32(0x0232a064, 0x00ffff00, 0x00c3c700);
- clrsetbits_le32(0x0232a078, 0x0000ff00, 0x0000c000);
-
- clrsetbits_le32(0x0232a204, 0xff0000ff, 0x38000080);
- clrsetbits_le32(0x0232a208, 0x000000ff, 0x00000000);
- clrsetbits_le32(0x0232a20c, 0xff000000, 0x02000000);
- clrsetbits_le32(0x0232a210, 0xff000000, 0x1b000000);
- clrsetbits_le32(0x0232a214, 0x0000ffff, 0x00006fb8);
- clrsetbits_le32(0x0232a218, 0xffff00ff, 0x758000e4);
- clrsetbits_le32(0x0232a2ac, 0x0000ff00, 0x00004400);
- clrsetbits_le32(0x0232a22c, 0x00ffff00, 0x00200800);
- clrsetbits_le32(0x0232a280, 0x00ff00ff, 0x00820082);
- clrsetbits_le32(0x0232a284, 0xffffffff, 0x1d0f0385);
-
- clrsetbits_le32(0x0232a404, 0xff0000ff, 0x38000080);
- clrsetbits_le32(0x0232a408, 0x000000ff, 0x00000000);
- clrsetbits_le32(0x0232a40c, 0xff000000, 0x02000000);
- clrsetbits_le32(0x0232a410, 0xff000000, 0x1b000000);
- clrsetbits_le32(0x0232a414, 0x0000ffff, 0x00006fb8);
- clrsetbits_le32(0x0232a418, 0xffff00ff, 0x758000e4);
- clrsetbits_le32(0x0232a4ac, 0x0000ff00, 0x00004400);
- clrsetbits_le32(0x0232a42c, 0x00ffff00, 0x00200800);
- clrsetbits_le32(0x0232a480, 0x00ff00ff, 0x00820082);
- clrsetbits_le32(0x0232a484, 0xffffffff, 0x1d0f0385);
-
- clrsetbits_le32(0x0232a604, 0xff0000ff, 0x38000080);
- clrsetbits_le32(0x0232a608, 0x000000ff, 0x00000000);
- clrsetbits_le32(0x0232a60c, 0xff000000, 0x02000000);
- clrsetbits_le32(0x0232a610, 0xff000000, 0x1b000000);
- clrsetbits_le32(0x0232a614, 0x0000ffff, 0x00006fb8);
- clrsetbits_le32(0x0232a618, 0xffff00ff, 0x758000e4);
- clrsetbits_le32(0x0232a6ac, 0x0000ff00, 0x00004400);
- clrsetbits_le32(0x0232a62c, 0x00ffff00, 0x00200800);
- clrsetbits_le32(0x0232a680, 0x00ff00ff, 0x00820082);
- clrsetbits_le32(0x0232a684, 0xffffffff, 0x1d0f0385);
-
- clrsetbits_le32(0x0232a804, 0xff0000ff, 0x38000080);
- clrsetbits_le32(0x0232a808, 0x000000ff, 0x00000000);
- clrsetbits_le32(0x0232a80c, 0xff000000, 0x02000000);
- clrsetbits_le32(0x0232a810, 0xff000000, 0x1b000000);
- clrsetbits_le32(0x0232a814, 0x0000ffff, 0x00006fb8);
- clrsetbits_le32(0x0232a818, 0xffff00ff, 0x758000e4);
- clrsetbits_le32(0x0232a8ac, 0x0000ff00, 0x00004400);
- clrsetbits_le32(0x0232a82c, 0x00ffff00, 0x00200800);
- clrsetbits_le32(0x0232a880, 0x00ff00ff, 0x00820082);
- clrsetbits_le32(0x0232a884, 0xffffffff, 0x1d0f0385);
-
- clrsetbits_le32(0x0232aa00, 0x0000ff00, 0x00000800);
- clrsetbits_le32(0x0232aa08, 0xffff0000, 0x38a20000);
- clrsetbits_le32(0x0232aa30, 0x00ffff00, 0x008a8a00);
- clrsetbits_le32(0x0232aa84, 0x0000ff00, 0x00000600);
- clrsetbits_le32(0x0232aa94, 0xff000000, 0x10000000);
- clrsetbits_le32(0x0232aaa0, 0xff000000, 0x81000000);
- clrsetbits_le32(0x0232aabc, 0xff000000, 0xff000000);
- clrsetbits_le32(0x0232aac0, 0x000000ff, 0x0000008b);
- clrsetbits_le32(0x0232ab08, 0xffff0000, 0x583f0000);
- clrsetbits_le32(0x0232ab0c, 0x000000ff, 0x0000004e);
- clrsetbits_le32(0x0232a000, 0x000000ff, 0x00000003);
- clrsetbits_le32(0x0232aa00, 0x000000ff, 0x0000005f);
-
- clrsetbits_le32(0x0232aa48, 0x00ffff00, 0x00fd8c00);
- clrsetbits_le32(0x0232aa54, 0x00ffffff, 0x002fec72);
- clrsetbits_le32(0x0232aa58, 0xffffff00, 0x00f92100);
- clrsetbits_le32(0x0232aa5c, 0xffffffff, 0x00040060);
- clrsetbits_le32(0x0232aa60, 0xffffffff, 0x00008000);
- clrsetbits_le32(0x0232aa64, 0xffffffff, 0x0c581220);
- clrsetbits_le32(0x0232aa68, 0xffffffff, 0xe13b0602);
- clrsetbits_le32(0x0232aa6c, 0xffffffff, 0xb8074cc1);
- clrsetbits_le32(0x0232aa70, 0xffffffff, 0x3f02e989);
- clrsetbits_le32(0x0232aa74, 0x000000ff, 0x00000001);
- clrsetbits_le32(0x0232ab20, 0x00ff0000, 0x00370000);
- clrsetbits_le32(0x0232ab1c, 0xff000000, 0x37000000);
- clrsetbits_le32(0x0232ab20, 0x000000ff, 0x0000005d);
-
- /*Bring SerDes out of Reset if SerDes is Shutdown & is in Reset Mode*/
- clrbits_le32(0x0232a010, 1 << 28);
-
- /* Enable TX and RX via the LANExCTL_STS 0x0000 + x*4 */
- clrbits_le32(0x0232a228, 1 << 29);
- writel(0xF800F8C0, 0x0232bfe0);
- clrbits_le32(0x0232a428, 1 << 29);
- writel(0xF800F8C0, 0x0232bfe4);
- clrbits_le32(0x0232a628, 1 << 29);
- writel(0xF800F8C0, 0x0232bfe8);
- clrbits_le32(0x0232a828, 1 << 29);
- writel(0xF800F8C0, 0x0232bfec);
-
- /*Enable pll via the pll_ctrl 0x0014*/
- writel(0xe0000000, 0x0232bff4)
- ;
-
- /*Waiting for SGMII Serdes PLL lock.*/
- for (cnt = 10000; cnt > 0 && ((readl(0x02090114) & 0x10) == 0); cnt--)
- ;
-
- for (cnt = 10000; cnt > 0 && ((readl(0x02090214) & 0x10) == 0); cnt--)
- ;
-
- for (cnt = 10000; cnt > 0 && ((readl(0x02090414) & 0x10) == 0); cnt--)
- ;
+ /* Register MDIO bus if it's not registered yet */
+ if (!mdio_bus) {
+ mdio_bus = mdio_alloc();
+ mdio_bus->read = keystone2_mdio_read;
+ mdio_bus->write = keystone2_mdio_write;
+ mdio_bus->reset = keystone2_mdio_reset;
+ mdio_bus->priv = (void *)EMAC_MDIO_BASE_ADDR;
+ sprintf(mdio_bus->name, "ethernet-mdio");
+
+ res = mdio_register(mdio_bus);
+ if (res)
+ return res;
+ }
- for (cnt = 10000; cnt > 0 && ((readl(0x02090514) & 0x10) == 0); cnt--)
- ;
+ /* Create phy device and bind it with driver */
+#ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE
+ phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr,
+ dev, PHY_INTERFACE_MODE_SGMII);
+ phy_config(phy_dev);
+#else
+ phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr,
+ PHY_INTERFACE_MODE_SGMII);
+ phy_dev->dev = dev;
+#endif
+ eth_priv->phy_dev = phy_dev;
- udelay(45000);
+ return 0;
}
-void sgmii_serdes_shutdown(void)
+struct ks2_serdes ks2_serdes_sgmii_156p25mhz = {
+ .clk = SERDES_CLOCK_156P25M,
+ .rate = SERDES_RATE_5G,
+ .rate_mode = SERDES_QUARTER_RATE,
+ .intf = SERDES_PHY_SGMII,
+ .loopback = 0,
+};
+
+static void keystone2_net_serdes_setup(void)
{
- /*
- * shutdown SerDes hardware. SerDes hardware vendor published only
- * register addresses and their values. So had to use hardcoded
- * values below.
- */
- clrbits_le32(0x0232bfe0, 3 << 29 | 3 << 13);
- setbits_le32(0x02320228, 1 << 29);
- clrbits_le32(0x0232bfe4, 3 << 29 | 3 << 13);
- setbits_le32(0x02320428, 1 << 29);
- clrbits_le32(0x0232bfe8, 3 << 29 | 3 << 13);
- setbits_le32(0x02320628, 1 << 29);
- clrbits_le32(0x0232bfec, 3 << 29 | 3 << 13);
- setbits_le32(0x02320828, 1 << 29);
-
- clrbits_le32(0x02320034, 3 << 29);
- setbits_le32(0x02320010, 1 << 28);
+ ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE,
+ &ks2_serdes_sgmii_156p25mhz,
+ CONFIG_KSNET_SERDES_LANES_PER_SGMII);
+
+#if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L)
+ ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE,
+ &ks2_serdes_sgmii_156p25mhz,
+ CONFIG_KSNET_SERDES_LANES_PER_SGMII);
+#endif
+
+ /* wait till setup */
+ udelay(5000);
}
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index d2ecadc890..9437c3bbcc 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -276,6 +276,57 @@ static int m88e1111s_config(struct phy_device *phydev)
return 0;
}
+/**
+ * m88e1518_phy_writebits - write bits to a register
+ */
+void m88e1518_phy_writebits(struct phy_device *phydev,
+ u8 reg_num, u16 offset, u16 len, u16 data)
+{
+ u16 reg, mask;
+
+ if ((len + offset) >= 16)
+ mask = 0 - (1 << offset);
+ else
+ mask = (1 << (len + offset)) - (1 << offset);
+
+ reg = phy_read(phydev, MDIO_DEVAD_NONE, reg_num);
+
+ reg &= ~mask;
+ reg |= data << offset;
+
+ phy_write(phydev, MDIO_DEVAD_NONE, reg_num, reg);
+}
+
+static int m88e1518_config(struct phy_device *phydev)
+{
+ /*
+ * As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512
+ * /88E1514 Rev A0, Errata Section 3.1
+ */
+ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+ phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00ff); /* page 0xff */
+ phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B);
+ phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144);
+ phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28);
+ phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2146);
+ phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xB233);
+ phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D);
+ phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C);
+ phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159);
+ phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000); /* reg page 0 */
+ phy_write(phydev, MDIO_DEVAD_NONE, 22, 18); /* reg page 18 */
+ /* Write HWCFG_MODE = SGMII to Copper */
+ m88e1518_phy_writebits(phydev, 20, 0, 3, 1);
+
+ /* Phy reset */
+ m88e1518_phy_writebits(phydev, 20, 15, 1, 1);
+ phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); /* reg page 18 */
+ udelay(100);
+ }
+
+ return m88e1111s_config(phydev);
+}
+
/* Marvell 88E1118 */
static int m88e1118_config(struct phy_device *phydev)
{
@@ -493,7 +544,7 @@ static struct phy_driver M88E1518_driver = {
.uid = 0x1410dd1,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
- .config = &m88e1111s_config,
+ .config = &m88e1518_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 1d6c14f2ad..467c972243 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -575,7 +575,7 @@ static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
* Description: Reads the ID registers of the PHY at @addr on the
* @bus, stores it in @phy_id and returns zero on success.
*/
-int __weak get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
+static int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
{
int phy_reg;
@@ -648,7 +648,7 @@ static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus,
if (phydev)
return phydev;
}
- printf("Phy not found\n");
+ printf("Phy %d not found\n", ffs(phy_mask) - 1);
return phy_device_create(bus, ffs(phy_mask) - 1, 0xffffffff, interface);
}
@@ -785,16 +785,13 @@ int phy_startup(struct phy_device *phydev)
return 0;
}
-static int __board_phy_config(struct phy_device *phydev)
+__weak int board_phy_config(struct phy_device *phydev)
{
if (phydev->drv->config)
return phydev->drv->config(phydev);
return 0;
}
-int board_phy_config(struct phy_device *phydev)
- __attribute__((weak, alias("__board_phy_config")));
-
int phy_config(struct phy_device *phydev)
{
/* Invoke an optional board-specific helper */
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 451c33e1a1..4bf493ed45 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -2,9 +2,9 @@
* sh_eth.c - Driver for Renesas ethernet controler.
*
* Copyright (C) 2008, 2011 Renesas Solutions Corp.
- * Copyright (c) 2008, 2011 Nobuhiro Iwamatsu
+ * Copyright (c) 2008, 2011, 2014 2014 Nobuhiro Iwamatsu
* Copyright (c) 2007 Carlos Munoz <carlos@kenati.com>
- * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013, 2014 Renesas Electronics Corporation
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -83,6 +83,8 @@ int sh_eth_send(struct eth_device *dev, void *packet, int len)
else
port_info->tx_desc_cur->td0 = TD_TACT | TD_TFP;
+ flush_cache_wback(port_info->tx_desc_cur, sizeof(struct tx_desc_s));
+
/* Restart the transmitter if disabled */
if (!(sh_eth_read(eth, EDTRR) & EDTRR_TRNS))
sh_eth_write(eth, EDTRR_TRNS, EDTRR);
@@ -133,6 +135,10 @@ int sh_eth_recv(struct eth_device *dev)
port_info->rx_desc_cur->rd0 = RD_RACT | RD_RDLE;
else
port_info->rx_desc_cur->rd0 = RD_RACT;
+
+ flush_cache_wback(port_info->rx_desc_cur,
+ sizeof(struct rx_desc_s));
+
/* Point to the next descriptor */
port_info->rx_desc_cur++;
if (port_info->rx_desc_cur >=
@@ -181,27 +187,27 @@ static int sh_eth_reset(struct sh_eth_dev *eth)
static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
{
int port = eth->port, i, ret = 0;
- u32 tmp_addr;
+ u32 alloc_desc_size = NUM_TX_DESC * sizeof(struct tx_desc_s);
struct sh_eth_info *port_info = &eth->port_info[port];
struct tx_desc_s *cur_tx_desc;
/*
- * Allocate tx descriptors. They must be TX_DESC_SIZE bytes aligned
+ * Allocate rx descriptors. They must be aligned to size of struct
+ * tx_desc_s.
*/
- port_info->tx_desc_malloc = malloc(NUM_TX_DESC *
- sizeof(struct tx_desc_s) +
- TX_DESC_SIZE - 1);
- if (!port_info->tx_desc_malloc) {
- printf(SHETHER_NAME ": malloc failed\n");
+ port_info->tx_desc_alloc =
+ memalign(sizeof(struct tx_desc_s), alloc_desc_size);
+ if (!port_info->tx_desc_alloc) {
+ printf(SHETHER_NAME ": memalign failed\n");
ret = -ENOMEM;
goto err;
}
- tmp_addr = (u32) (((int)port_info->tx_desc_malloc + TX_DESC_SIZE - 1) &
- ~(TX_DESC_SIZE - 1));
- flush_cache_wback(tmp_addr, NUM_TX_DESC * sizeof(struct tx_desc_s));
+ flush_cache_wback((u32)port_info->tx_desc_alloc, alloc_desc_size);
+
/* Make sure we use a P2 address (non-cacheable) */
- port_info->tx_desc_base = (struct tx_desc_s *)ADDR_TO_P2(tmp_addr);
+ port_info->tx_desc_base =
+ (struct tx_desc_s *)ADDR_TO_P2((u32)port_info->tx_desc_alloc);
port_info->tx_desc_cur = port_info->tx_desc_base;
/* Initialize all descriptors */
@@ -232,47 +238,44 @@ err:
static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
{
int port = eth->port, i , ret = 0;
+ u32 alloc_desc_size = NUM_RX_DESC * sizeof(struct rx_desc_s);
struct sh_eth_info *port_info = &eth->port_info[port];
struct rx_desc_s *cur_rx_desc;
- u32 tmp_addr;
u8 *rx_buf;
/*
- * Allocate rx descriptors. They must be RX_DESC_SIZE bytes aligned
+ * Allocate rx descriptors. They must be aligned to size of struct
+ * rx_desc_s.
*/
- port_info->rx_desc_malloc = malloc(NUM_RX_DESC *
- sizeof(struct rx_desc_s) +
- RX_DESC_SIZE - 1);
- if (!port_info->rx_desc_malloc) {
- printf(SHETHER_NAME ": malloc failed\n");
+ port_info->rx_desc_alloc =
+ memalign(sizeof(struct rx_desc_s), alloc_desc_size);
+ if (!port_info->rx_desc_alloc) {
+ printf(SHETHER_NAME ": memalign failed\n");
ret = -ENOMEM;
goto err;
}
- tmp_addr = (u32) (((int)port_info->rx_desc_malloc + RX_DESC_SIZE - 1) &
- ~(RX_DESC_SIZE - 1));
- flush_cache_wback(tmp_addr, NUM_RX_DESC * sizeof(struct rx_desc_s));
+ flush_cache_wback(port_info->rx_desc_alloc, alloc_desc_size);
+
/* Make sure we use a P2 address (non-cacheable) */
- port_info->rx_desc_base = (struct rx_desc_s *)ADDR_TO_P2(tmp_addr);
+ port_info->rx_desc_base =
+ (struct rx_desc_s *)ADDR_TO_P2((u32)port_info->rx_desc_alloc);
port_info->rx_desc_cur = port_info->rx_desc_base;
/*
- * Allocate rx data buffers. They must be 32 bytes aligned and in
- * P2 area
+ * Allocate rx data buffers. They must be RX_BUF_ALIGNE_SIZE bytes
+ * aligned and in P2 area.
*/
- port_info->rx_buf_malloc = malloc(
- NUM_RX_DESC * MAX_BUF_SIZE + RX_BUF_ALIGNE_SIZE - 1);
- if (!port_info->rx_buf_malloc) {
- printf(SHETHER_NAME ": malloc failed\n");
+ port_info->rx_buf_alloc =
+ memalign(RX_BUF_ALIGNE_SIZE, NUM_RX_DESC * MAX_BUF_SIZE);
+ if (!port_info->rx_buf_alloc) {
+ printf(SHETHER_NAME ": alloc failed\n");
ret = -ENOMEM;
- goto err_buf_malloc;
+ goto err_buf_alloc;
}
- tmp_addr = (u32)(((int)port_info->rx_buf_malloc
- + (RX_BUF_ALIGNE_SIZE - 1)) &
- ~(RX_BUF_ALIGNE_SIZE - 1));
- port_info->rx_buf_base = (u8 *)ADDR_TO_P2(tmp_addr);
+ port_info->rx_buf_base = (u8 *)ADDR_TO_P2((u32)port_info->rx_buf_alloc);
/* Initialize all descriptors */
for (cur_rx_desc = port_info->rx_desc_base,
@@ -297,9 +300,9 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
return ret;
-err_buf_malloc:
- free(port_info->rx_desc_malloc);
- port_info->rx_desc_malloc = NULL;
+err_buf_alloc:
+ free(port_info->rx_desc_alloc);
+ port_info->rx_desc_alloc = NULL;
err:
return ret;
@@ -310,9 +313,9 @@ static void sh_eth_tx_desc_free(struct sh_eth_dev *eth)
int port = eth->port;
struct sh_eth_info *port_info = &eth->port_info[port];
- if (port_info->tx_desc_malloc) {
- free(port_info->tx_desc_malloc);
- port_info->tx_desc_malloc = NULL;
+ if (port_info->tx_desc_alloc) {
+ free(port_info->tx_desc_alloc);
+ port_info->tx_desc_alloc = NULL;
}
}
@@ -321,14 +324,14 @@ static void sh_eth_rx_desc_free(struct sh_eth_dev *eth)
int port = eth->port;
struct sh_eth_info *port_info = &eth->port_info[port];
- if (port_info->rx_desc_malloc) {
- free(port_info->rx_desc_malloc);
- port_info->rx_desc_malloc = NULL;
+ if (port_info->rx_desc_alloc) {
+ free(port_info->rx_desc_alloc);
+ port_info->rx_desc_alloc = NULL;
}
- if (port_info->rx_buf_malloc) {
- free(port_info->rx_buf_malloc);
- port_info->rx_buf_malloc = NULL;
+ if (port_info->rx_buf_alloc) {
+ free(port_info->rx_buf_alloc);
+ port_info->rx_buf_alloc = NULL;
}
}
@@ -414,7 +417,7 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
#if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740)
sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII);
#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
- defined(CONFIG_R8A7794)
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR);
#endif
/* Configure phy */
@@ -440,7 +443,8 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
#elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
sh_eth_write(eth, 1, RTRATE);
#elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) || \
- defined(CONFIG_R8A7791) || defined(CONFIG_R8A7794)
+ defined(CONFIG_R8A7791) || defined(CONFIG_R8A7793) || \
+ defined(CONFIG_R8A7794)
val = ECMR_RTM;
#endif
} else if (phy->speed == 10) {
diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h
index e325a39aac..5cb520c63e 100644
--- a/drivers/net/sh_eth.h
+++ b/drivers/net/sh_eth.h
@@ -51,8 +51,6 @@
/* The size of the tx descriptor is determined by how much padding is used.
4, 20, or 52 bytes of padding can be used */
#define TX_DESC_PADDING (CONFIG_SH_ETHER_ALIGNE_SIZE - 12)
-/* same as CONFIG_SH_ETHER_ALIGNE_SIZE */
-#define TX_DESC_SIZE (12 + TX_DESC_PADDING)
/* Tx descriptor. We always use 3 bytes of padding */
struct tx_desc_s {
@@ -68,8 +66,6 @@ struct tx_desc_s {
/* The size of the rx descriptor is determined by how much padding is used.
4, 20, or 52 bytes of padding can be used */
#define RX_DESC_PADDING (CONFIG_SH_ETHER_ALIGNE_SIZE - 12)
-/* same as CONFIG_SH_ETHER_ALIGNE_SIZE */
-#define RX_DESC_SIZE (12 + RX_DESC_PADDING)
/* aligned cache line size */
#define RX_BUF_ALIGNE_SIZE (CONFIG_SH_ETHER_ALIGNE_SIZE > 32 ? 64 : 32)
@@ -82,13 +78,13 @@ struct rx_desc_s {
};
struct sh_eth_info {
- struct tx_desc_s *tx_desc_malloc;
+ struct tx_desc_s *tx_desc_alloc;
struct tx_desc_s *tx_desc_base;
struct tx_desc_s *tx_desc_cur;
- struct rx_desc_s *rx_desc_malloc;
+ struct rx_desc_s *rx_desc_alloc;
struct rx_desc_s *rx_desc_base;
struct rx_desc_s *rx_desc_cur;
- u8 *rx_buf_malloc;
+ u8 *rx_buf_alloc;
u8 *rx_buf_base;
u8 mac_addr[6];
u8 phy_addr;
@@ -359,7 +355,7 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
#define SH_ETH_TYPE_GETHER
#define BASE_IO_ADDR 0xE9A00000
#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
- defined(CONFIG_R8A7794)
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
#define SH_ETH_TYPE_ETHER
#define BASE_IO_ADDR 0xEE700200
#elif defined(CONFIG_R7S72100)
@@ -571,7 +567,7 @@ enum FELIC_MODE_BIT {
#ifdef CONFIG_CPU_SH7724
ECMR_RTM = 0x00000010,
#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
- defined(CONFIG_R8A7794)
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
ECMR_RTM = 0x00000004,
#endif
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index b097c1a56f..5959672370 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -187,6 +187,7 @@ static int smc911x_send(struct eth_device *dev, void *packet, int length)
static void smc911x_halt(struct eth_device *dev)
{
smc911x_reset(dev);
+ smc911x_handle_mac_address(dev);
}
static int smc911x_rx(struct eth_device *dev)
diff --git a/drivers/net/uli526x.c b/drivers/net/uli526x.c
index 538f11e3eb..9526faa4af 100644
--- a/drivers/net/uli526x.c
+++ b/drivers/net/uli526x.c
@@ -548,7 +548,7 @@ static int uli526x_rx_packet(struct eth_device *dev)
rdes0 = le32_to_cpu(rxptr->rdes0);
#ifdef RX_DEBUG
- printf("%s(): rxptr->rdes0=%x:%x\n", __FUNCTION__, rxptr->rdes0);
+ printf("%s(): rxptr->rdes0=%x\n", __FUNCTION__, rxptr->rdes0);
#endif
if (!(rdes0 & 0x80000000)) { /* packet owner check */
if ((rdes0 & 0x300) != 0x300) {
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 28859f3161..60c333e2c0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -572,7 +572,7 @@ const char * pci_class_str(u8 class)
}
#endif /* CONFIG_CMD_PCI || CONFIG_PCI_SCAN_SHOW */
-int __pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
+__weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
{
/*
* Check if pci device should be skipped in configuration
@@ -591,19 +591,15 @@ int __pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
return 0;
}
-int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
- __attribute__((weak, alias("__pci_skip_dev")));
#ifdef CONFIG_PCI_SCAN_SHOW
-int __pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
+__weak int pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
{
if (dev == PCI_BDF(hose->first_busno, 0, 0))
return 0;
return 1;
}
-int pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
- __attribute__((weak, alias("__pci_print_dev")));
#endif /* CONFIG_PCI_SCAN_SHOW */
int pci_hose_scan_bus(struct pci_controller *hose, int bus)
diff --git a/drivers/power/power_spi.c b/drivers/power/power_spi.c
index fb455a0061..1e554461f3 100644
--- a/drivers/power/power_spi.c
+++ b/drivers/power/power_spi.c
@@ -17,27 +17,14 @@
static struct spi_slave *slave;
-void pmic_spi_free(struct spi_slave *slave)
-{
- if (slave)
- spi_free_slave(slave);
-}
-
-struct spi_slave *pmic_spi_probe(struct pmic *p)
-{
- return spi_setup_slave(p->bus,
- p->hw.spi.cs,
- p->hw.spi.clk,
- p->hw.spi.mode);
-}
-
static u32 pmic_reg(struct pmic *p, u32 reg, u32 *val, u32 write)
{
u32 pmic_tx, pmic_rx;
u32 tmp;
if (!slave) {
- slave = pmic_spi_probe(p);
+ slave = spi_setup_slave(p->bus, p->hw.spi.cs, p->hw.spi.clk,
+ p->hw.spi.mode);
if (!slave)
return -1;
@@ -54,25 +41,25 @@ static u32 pmic_reg(struct pmic *p, u32 reg, u32 *val, u32 write)
tmp = cpu_to_be32(pmic_tx);
if (spi_xfer(slave, pmic_spi_bitlen, &tmp, &pmic_rx,
- pmic_spi_flags)) {
- spi_release_bus(slave);
- return -1;
- }
+ pmic_spi_flags))
+ goto err;
if (write) {
pmic_tx = p->hw.spi.prepare_tx(reg, val, 0);
tmp = cpu_to_be32(pmic_tx);
if (spi_xfer(slave, pmic_spi_bitlen, &tmp, &pmic_rx,
- pmic_spi_flags)) {
- spi_release_bus(slave);
- return -1;
- }
+ pmic_spi_flags))
+ goto err;
}
spi_release_bus(slave);
*val = cpu_to_be32(pmic_rx);
return 0;
+
+err:
+ spi_release_bus(slave);
+ return -1;
}
int pmic_reg_write(struct pmic *p, u32 reg, u32 val)
diff --git a/drivers/power/twl4030.c b/drivers/power/twl4030.c
index 3e50310464..e578ae6342 100644
--- a/drivers/power/twl4030.c
+++ b/drivers/power/twl4030.c
@@ -98,4 +98,10 @@ void twl4030_power_mmc_init(void)
TWL4030_PM_RECEIVER_VMMC1_VSEL_32,
TWL4030_PM_RECEIVER_VMMC1_DEV_GRP,
TWL4030_PM_RECEIVER_DEV_GRP_P1);
+
+ /* Set VMMC2 to 3.15 Volts */
+ twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VMMC2_DEDICATED,
+ TWL4030_PM_RECEIVER_VMMC2_VSEL_32,
+ TWL4030_PM_RECEIVER_VMMC2_DEV_GRP,
+ TWL4030_PM_RECEIVER_DEV_GRP_P1);
}
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index e69de29bb2..a0b6e02b54 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -0,0 +1,12 @@
+config DM_SERIAL
+ bool "Enable Driver Model for serial drivers"
+ depends on DM
+ help
+ If you want to use driver model for serial drivers, say Y.
+ To use legacy serial drivers, say N.
+
+config UNIPHIER_SERIAL
+ bool "UniPhier on-chip UART support"
+ depends on ARCH_UNIPHIER && DM_SERIAL
+ help
+ Support for the on-chip UARTs on the Panasonic UniPhier platform.
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 17c56ea66e..8c84942761 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_UART) += altera_uart.o
obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o
obj-$(CONFIG_ARM_DCC) += arm_dcc.o
obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
+obj-$(CONFIG_DW_SERIAL) += serial_dw.o
obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
obj-$(CONFIG_MCFUART) += mcfuart.o
obj-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o
@@ -41,6 +42,8 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
obj-$(CONFIG_TEGRA_SERIAL) += serial_tegra.o
obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
+obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
+obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 63a9ef6844..8f051914f5 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -61,13 +61,13 @@ static void ns16550_writeb(NS16550_t port, int offset, int value)
unsigned char *addr;
offset *= 1 << plat->reg_shift;
- addr = plat->base + offset;
+ addr = map_sysmem(plat->base, 0) + offset;
/*
* As far as we know it doesn't make sense to support selection of
* these options at run-time, so use the existing CONFIG options.
*/
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
- outb(value, addr);
+ outb(value, (ulong)addr);
#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
out_le32(addr, value);
#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
@@ -85,9 +85,9 @@ static int ns16550_readb(NS16550_t port, int offset)
unsigned char *addr;
offset *= 1 << plat->reg_shift;
- addr = plat->base + offset;
+ addr = map_sysmem(plat->base, 0) + offset;
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
- return inb(addr);
+ return inb((ulong)addr);
#elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
return in_le32(addr);
#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
@@ -253,7 +253,7 @@ static int ns16550_serial_getc(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
- if (!serial_in(&com_port->lsr) & UART_LSR_DR)
+ if (!(serial_in(&com_port->lsr) & UART_LSR_DR))
return -EAGAIN;
return serial_in(&com_port->rbr);
@@ -276,14 +276,15 @@ int ns16550_serial_probe(struct udevice *dev)
{
struct NS16550 *const com_port = dev_get_priv(dev);
+ com_port->plat = dev_get_platdata(dev);
NS16550_init(com_port, -1);
return 0;
}
+#ifdef CONFIG_OF_CONTROL
int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
{
- struct NS16550 *const com_port = dev_get_priv(dev);
struct ns16550_platdata *plat = dev->platdata;
fdt_addr_t addr;
@@ -291,13 +292,13 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
- plat->base = (unsigned char *)addr;
+ plat->base = addr;
plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"reg-shift", 1);
- com_port->plat = plat;
return 0;
}
+#endif
const struct dm_serial_ops ns16550_serial_ops = {
.putc = ns16550_serial_putc,
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 1a75950d19..71f1a5cb91 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -11,9 +11,12 @@
#include <os.h>
#include <serial.h>
#include <stdio_dev.h>
+#include <watchdog.h>
#include <dm/lists.h>
#include <dm/device-internal.h>
+#include <ns16550.h>
+
DECLARE_GLOBAL_DATA_PTR;
/* The currently-selected console serial device */
@@ -47,13 +50,22 @@ static void serial_find_console_or_panic(void)
}
#endif
/*
+ * Try to use CONFIG_CONS_INDEX if available (it is numbered from 1!).
+ *
* Failing that, get the device with sequence number 0, or in extremis
* just the first serial device we can find. But we insist on having
* a console (even if it is silent).
*/
- if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) &&
+#ifdef CONFIG_CONS_INDEX
+#define INDEX (CONFIG_CONS_INDEX - 1)
+#else
+#define INDEX 0
+#endif
+ if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) &&
+ uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) &&
(uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev))
panic("No serial driver found");
+#undef INDEX
}
/* Called prior to relocation */
@@ -71,62 +83,74 @@ void serial_initialize(void)
serial_find_console_or_panic();
}
-static void serial_putc_dev(struct udevice *dev, char ch)
+static void _serial_putc(struct udevice *dev, char ch)
{
- struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+ struct dm_serial_ops *ops = serial_get_ops(dev);
int err;
do {
- err = ops->putc(cur_dev, ch);
+ err = ops->putc(dev, ch);
} while (err == -EAGAIN);
if (ch == '\n')
- serial_putc('\r');
+ _serial_putc(dev, '\r');
}
-void serial_putc(char ch)
+static void _serial_puts(struct udevice *dev, const char *str)
{
- serial_putc_dev(cur_dev, ch);
+ while (*str)
+ _serial_putc(dev, *str++);
}
-void serial_setbrg(void)
+static int _serial_getc(struct udevice *dev)
{
- struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+ int err;
- if (ops->setbrg)
- ops->setbrg(cur_dev, gd->baudrate);
-}
+ do {
+ err = ops->getc(dev);
+ if (err == -EAGAIN)
+ WATCHDOG_RESET();
+ } while (err == -EAGAIN);
-void serial_puts(const char *str)
-{
- while (*str)
- serial_putc(*str++);
+ return err >= 0 ? err : 0;
}
-int serial_tstc(void)
+static int _serial_tstc(struct udevice *dev)
{
- struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+ struct dm_serial_ops *ops = serial_get_ops(dev);
if (ops->pending)
- return ops->pending(cur_dev, true);
+ return ops->pending(dev, true);
return 1;
}
-static int serial_getc_dev(struct udevice *dev)
+void serial_putc(char ch)
{
- struct dm_serial_ops *ops = serial_get_ops(dev);
- int err;
-
- do {
- err = ops->getc(dev);
- } while (err == -EAGAIN);
+ _serial_putc(cur_dev, ch);
+}
- return err >= 0 ? err : 0;
+void serial_puts(const char *str)
+{
+ _serial_puts(cur_dev, str);
}
int serial_getc(void)
{
- return serial_getc_dev(cur_dev);
+ return _serial_getc(cur_dev);
+}
+
+int serial_tstc(void)
+{
+ return _serial_tstc(cur_dev);
+}
+
+void serial_setbrg(void)
+{
+ struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+
+ if (ops->setbrg)
+ ops->setbrg(cur_dev, gd->baudrate);
}
void serial_stdio_init(void)
@@ -135,33 +159,22 @@ void serial_stdio_init(void)
static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
{
- struct udevice *dev = sdev->priv;
-
- serial_putc_dev(dev, ch);
+ _serial_putc(sdev->priv, ch);
}
void serial_stub_puts(struct stdio_dev *sdev, const char *str)
{
- while (*str)
- serial_stub_putc(sdev, *str++);
+ _serial_puts(sdev->priv, str);
}
int serial_stub_getc(struct stdio_dev *sdev)
{
- struct udevice *dev = sdev->priv;
-
- return serial_getc_dev(dev);
+ return _serial_getc(sdev->priv);
}
int serial_stub_tstc(struct stdio_dev *sdev)
{
- struct udevice *dev = sdev->priv;
- struct dm_serial_ops *ops = serial_get_ops(dev);
-
- if (ops->pending)
- return ops->pending(dev, true);
-
- return 1;
+ return _serial_tstc(sdev->priv);
}
static int serial_post_probe(struct udevice *dev)
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index 82fbbd92e2..95c992a5a3 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -109,55 +109,54 @@ U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
void name(void) \
__attribute__((weak, alias("serial_null")));
-serial_initfunc(mpc8xx_serial_initialize);
-serial_initfunc(ns16550_serial_initialize);
-serial_initfunc(pxa_serial_initialize);
-serial_initfunc(s3c24xx_serial_initialize);
-serial_initfunc(s5p_serial_initialize);
-serial_initfunc(zynq_serial_initialize);
-serial_initfunc(bfin_serial_initialize);
-serial_initfunc(bfin_jtag_initialize);
-serial_initfunc(mpc512x_serial_initialize);
-serial_initfunc(uartlite_serial_initialize);
-serial_initfunc(au1x00_serial_initialize);
-serial_initfunc(asc_serial_initialize);
-serial_initfunc(jz_serial_initialize);
-serial_initfunc(mpc5xx_serial_initialize);
-serial_initfunc(mpc8260_scc_serial_initialize);
-serial_initfunc(mpc8260_smc_serial_initialize);
-serial_initfunc(mpc85xx_serial_initialize);
-serial_initfunc(iop480_serial_initialize);
-serial_initfunc(leon2_serial_initialize);
-serial_initfunc(leon3_serial_initialize);
-serial_initfunc(marvell_serial_initialize);
+serial_initfunc(altera_jtag_serial_initialize);
+serial_initfunc(altera_serial_initialize);
serial_initfunc(amirix_serial_initialize);
+serial_initfunc(arc_serial_initialize);
+serial_initfunc(arm_dcc_initialize);
+serial_initfunc(asc_serial_initialize);
+serial_initfunc(atmel_serial_initialize);
+serial_initfunc(au1x00_serial_initialize);
+serial_initfunc(bfin_jtag_initialize);
+serial_initfunc(bfin_serial_initialize);
serial_initfunc(bmw_serial_initialize);
+serial_initfunc(clps7111_serial_initialize);
serial_initfunc(cogent_serial_initialize);
serial_initfunc(cpci750_serial_initialize);
serial_initfunc(evb64260_serial_initialize);
-serial_initfunc(ml2_serial_initialize);
-serial_initfunc(sconsole_serial_initialize);
-serial_initfunc(p3mx_serial_initialize);
-serial_initfunc(altera_jtag_serial_initialize);
-serial_initfunc(altera_serial_initialize);
-serial_initfunc(atmel_serial_initialize);
-serial_initfunc(lpc32xx_serial_initialize);
-serial_initfunc(mcf_serial_initialize);
-serial_initfunc(oc_serial_initialize);
-serial_initfunc(sandbox_serial_initialize);
-serial_initfunc(clps7111_serial_initialize);
serial_initfunc(imx_serial_initialize);
+serial_initfunc(iop480_serial_initialize);
+serial_initfunc(jz_serial_initialize);
serial_initfunc(ks8695_serial_initialize);
+serial_initfunc(leon2_serial_initialize);
+serial_initfunc(leon3_serial_initialize);
serial_initfunc(lh7a40x_serial_initialize);
+serial_initfunc(lpc32xx_serial_initialize);
+serial_initfunc(marvell_serial_initialize);
serial_initfunc(max3100_serial_initialize);
+serial_initfunc(mcf_serial_initialize);
+serial_initfunc(ml2_serial_initialize);
+serial_initfunc(mpc512x_serial_initialize);
+serial_initfunc(mpc5xx_serial_initialize);
+serial_initfunc(mpc8260_scc_serial_initialize);
+serial_initfunc(mpc8260_smc_serial_initialize);
+serial_initfunc(mpc85xx_serial_initialize);
+serial_initfunc(mpc8xx_serial_initialize);
serial_initfunc(mxc_serial_initialize);
+serial_initfunc(mxs_auart_initialize);
+serial_initfunc(ns16550_serial_initialize);
+serial_initfunc(oc_serial_initialize);
+serial_initfunc(p3mx_serial_initialize);
serial_initfunc(pl01x_serial_initialize);
+serial_initfunc(pxa_serial_initialize);
+serial_initfunc(s3c24xx_serial_initialize);
+serial_initfunc(s5p_serial_initialize);
serial_initfunc(sa1100_serial_initialize);
+serial_initfunc(sandbox_serial_initialize);
+serial_initfunc(sconsole_serial_initialize);
serial_initfunc(sh_serial_initialize);
-serial_initfunc(arm_dcc_initialize);
-serial_initfunc(mxs_auart_initialize);
-serial_initfunc(arc_serial_initialize);
-serial_initfunc(uniphier_serial_initialize);
+serial_initfunc(uartlite_serial_initialize);
+serial_initfunc(zynq_serial_initialize);
/**
* serial_register() - Register serial driver with serial driver core
@@ -203,81 +202,80 @@ void serial_register(struct serial_device *dev)
*/
void serial_initialize(void)
{
- mpc8xx_serial_initialize();
- ns16550_serial_initialize();
- pxa_serial_initialize();
- s3c24xx_serial_initialize();
- s5p_serial_initialize();
- mpc512x_serial_initialize();
- bfin_serial_initialize();
- bfin_jtag_initialize();
- uartlite_serial_initialize();
- zynq_serial_initialize();
- au1x00_serial_initialize();
- asc_serial_initialize();
- jz_serial_initialize();
- mpc5xx_serial_initialize();
- mpc8260_scc_serial_initialize();
- mpc8260_smc_serial_initialize();
- mpc85xx_serial_initialize();
- iop480_serial_initialize();
- leon2_serial_initialize();
- leon3_serial_initialize();
- marvell_serial_initialize();
+ altera_jtag_serial_initialize();
+ altera_serial_initialize();
amirix_serial_initialize();
+ arc_serial_initialize();
+ arm_dcc_initialize();
+ asc_serial_initialize();
+ atmel_serial_initialize();
+ au1x00_serial_initialize();
+ bfin_jtag_initialize();
+ bfin_serial_initialize();
bmw_serial_initialize();
+ clps7111_serial_initialize();
cogent_serial_initialize();
cpci750_serial_initialize();
evb64260_serial_initialize();
- ml2_serial_initialize();
- sconsole_serial_initialize();
- p3mx_serial_initialize();
- altera_jtag_serial_initialize();
- altera_serial_initialize();
- atmel_serial_initialize();
- lpc32xx_serial_initialize();
- mcf_serial_initialize();
- oc_serial_initialize();
- sandbox_serial_initialize();
- clps7111_serial_initialize();
imx_serial_initialize();
+ iop480_serial_initialize();
+ jz_serial_initialize();
ks8695_serial_initialize();
+ leon2_serial_initialize();
+ leon3_serial_initialize();
lh7a40x_serial_initialize();
+ lpc32xx_serial_initialize();
+ marvell_serial_initialize();
max3100_serial_initialize();
+ mcf_serial_initialize();
+ ml2_serial_initialize();
+ mpc512x_serial_initialize();
+ mpc5xx_serial_initialize();
+ mpc8260_scc_serial_initialize();
+ mpc8260_smc_serial_initialize();
+ mpc85xx_serial_initialize();
+ mpc8xx_serial_initialize();
mxc_serial_initialize();
+ mxs_auart_initialize();
+ ns16550_serial_initialize();
+ oc_serial_initialize();
+ p3mx_serial_initialize();
pl01x_serial_initialize();
+ pxa_serial_initialize();
+ s3c24xx_serial_initialize();
+ s5p_serial_initialize();
sa1100_serial_initialize();
+ sandbox_serial_initialize();
+ sconsole_serial_initialize();
sh_serial_initialize();
- arm_dcc_initialize();
- mxs_auart_initialize();
- arc_serial_initialize();
- uniphier_serial_initialize();
+ uartlite_serial_initialize();
+ zynq_serial_initialize();
serial_assign(default_serial_console()->name);
}
-int serial_stub_start(struct stdio_dev *sdev)
+static int serial_stub_start(struct stdio_dev *sdev)
{
struct serial_device *dev = sdev->priv;
return dev->start();
}
-int serial_stub_stop(struct stdio_dev *sdev)
+static int serial_stub_stop(struct stdio_dev *sdev)
{
struct serial_device *dev = sdev->priv;
return dev->stop();
}
-void serial_stub_putc(struct stdio_dev *sdev, const char ch)
+static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
{
struct serial_device *dev = sdev->priv;
dev->putc(ch);
}
-void serial_stub_puts(struct stdio_dev *sdev, const char *str)
+static void serial_stub_puts(struct stdio_dev *sdev, const char *str)
{
struct serial_device *dev = sdev->priv;
diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c
new file mode 100644
index 0000000000..5c6a76c59c
--- /dev/null
+++ b/drivers/serial/serial_coreboot.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+
+static const struct udevice_id coreboot_serial_ids[] = {
+ { .compatible = "coreboot-uart" },
+ { }
+};
+
+static int coreboot_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct ns16550_platdata *plat = dev_get_platdata(dev);
+ int ret;
+
+ ret = ns16550_serial_ofdata_to_platdata(dev);
+ if (ret)
+ return ret;
+ plat->clock = 1843200;
+
+ return 0;
+}
+U_BOOT_DRIVER(serial_ns16550) = {
+ .name = "serial_coreboot",
+ .id = UCLASS_SERIAL,
+ .of_match = coreboot_serial_ids,
+ .ofdata_to_platdata = coreboot_serial_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+ .priv_auto_alloc_size = sizeof(struct NS16550),
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+};
diff --git a/drivers/serial/serial_dw.c b/drivers/serial/serial_dw.c
new file mode 100644
index 0000000000..a348f2956a
--- /dev/null
+++ b/drivers/serial/serial_dw.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+
+static const struct udevice_id dw_serial_ids[] = {
+ { .compatible = "snps,dw-apb-uart" },
+ { }
+};
+
+static int dw_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct ns16550_platdata *plat = dev_get_platdata(dev);
+ int ret;
+
+ ret = ns16550_serial_ofdata_to_platdata(dev);
+ if (ret)
+ return ret;
+ plat->clock = CONFIG_SYS_NS16550_CLK;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(serial_ns16550) = {
+ .name = "serial_dw",
+ .id = UCLASS_SERIAL,
+ .of_match = dw_serial_ids,
+ .ofdata_to_platdata = dw_serial_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+ .priv_auto_alloc_size = sizeof(struct NS16550),
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+};
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index 9ce24f9f93..d6cf1d874a 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -7,10 +7,10 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
-#include <serial_mxc.h>
#include <watchdog.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
+#include <dm/platform_data/serial_mxc.h>
#include <serial.h>
#include <linux/compiler.h>
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 632da4cf70..799ef6a667 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -119,8 +119,7 @@ static NS16550_t serial_ports[6] = {
.puts = eserial##port##_puts, \
}
-void
-_serial_putc(const char c,const int port)
+static void _serial_putc(const char c, const int port)
{
if (c == '\n')
NS16550_putc(PORT, '\r');
@@ -128,35 +127,29 @@ _serial_putc(const char c,const int port)
NS16550_putc(PORT, c);
}
-void
-_serial_putc_raw(const char c,const int port)
+static void _serial_putc_raw(const char c, const int port)
{
NS16550_putc(PORT, c);
}
-void
-_serial_puts (const char *s,const int port)
+static void _serial_puts(const char *s, const int port)
{
while (*s) {
- _serial_putc (*s++,port);
+ _serial_putc(*s++, port);
}
}
-
-int
-_serial_getc(const int port)
+static int _serial_getc(const int port)
{
return NS16550_getc(PORT);
}
-int
-_serial_tstc(const int port)
+static int _serial_tstc(const int port)
{
return NS16550_tstc(PORT);
}
-void
-_serial_setbrg (const int port)
+static void _serial_setbrg(const int port)
{
int clock_divisor;
diff --git a/drivers/serial/serial_omap.c b/drivers/serial/serial_omap.c
new file mode 100644
index 0000000000..265fe007a0
--- /dev/null
+++ b/drivers/serial/serial_omap.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <ns16550.h>
+#include <serial.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_OF_CONTROL
+static const struct udevice_id omap_serial_ids[] = {
+ { .compatible = "ti,omap3-uart" },
+ { }
+};
+
+static int omap_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct ns16550_platdata *plat = dev_get_platdata(dev);
+ int ret;
+
+ ret = ns16550_serial_ofdata_to_platdata(dev);
+ if (ret)
+ return ret;
+ plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "clock-frequency", -1);
+ plat->reg_shift = 2;
+
+ return 0;
+}
+#endif
+
+U_BOOT_DRIVER(serial_omap_ns16550) = {
+ .name = "serial_omap",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(omap_serial_ids),
+ .ofdata_to_platdata = of_match_ptr(omap_serial_ofdata_to_platdata),
+ .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+ .priv_auto_alloc_size = sizeof(struct NS16550),
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index e6313ad3d3..38dda91021 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -17,7 +17,7 @@
#include <watchdog.h>
#include <asm/io.h>
#include <serial.h>
-#include <serial_pl01x.h>
+#include <dm/platform_data/serial_pl01x.h>
#include <linux/compiler.h>
#include "serial_pl01x_internal.h"
diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c
index c07f4c9b47..7afc5044a8 100644
--- a/drivers/serial/serial_s3c24x0.c
+++ b/drivers/serial/serial_s3c24x0.c
@@ -69,7 +69,7 @@ DECLARE_GLOBAL_DATA_PTR;
static int hwflow;
#endif
-void _serial_setbrg(const int dev_index)
+static void _serial_setbrg(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
unsigned int reg = 0;
@@ -131,7 +131,7 @@ static int serial_init_dev(const int dev_index)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int _serial_getc(const int dev_index)
+static int _serial_getc(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
@@ -181,7 +181,7 @@ void enable_putc(void)
/*
* Output a single byte to the serial port.
*/
-void _serial_putc(const char c, const int dev_index)
+static void _serial_putc(const char c, const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
#ifdef CONFIG_MODEM_SUPPORT
@@ -212,7 +212,7 @@ static inline void serial_putc_dev(unsigned int dev_index, const char c)
/*
* Test whether a character is in the RX buffer
*/
-int _serial_tstc(const int dev_index)
+static int _serial_tstc(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
@@ -224,7 +224,7 @@ static inline int serial_tstc_dev(unsigned int dev_index)
return _serial_tstc(dev_index);
}
-void _serial_puts(const char *s, const int dev_index)
+static void _serial_puts(const char *s, const int dev_index)
{
while (*s) {
_serial_putc(*s++, dev_index);
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 144a925394..7c1f271376 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -122,7 +122,7 @@ static void handle_error(void)
sci_out(&sh_sci, SCLSR, 0x00);
}
-void serial_raw_putc(const char c)
+static void serial_raw_putc(const char c)
{
while (1) {
/* Tx fifo is empty */
@@ -152,7 +152,7 @@ static int sh_serial_tstc(void)
}
-int serial_getc_check(void)
+static int serial_getc_check(void)
{
unsigned short status;
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h
index fe8cde4ded..53406e5855 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -227,7 +227,7 @@ struct uart_port {
# define SCIF_ORER 0x0001 /* Overrun error bit */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
- defined(CONFIG_R8A7794)
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
# define SCIF_ORER 0x0001
# define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0, */
#else
@@ -304,7 +304,8 @@ struct uart_port {
/* SH7763 SCIF2 support */
# define SCIF2_RFDC_MASK 0x001f
# define SCIF2_TXROOM_MAX 16
-#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791)
+#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
# define SCIF_RFDC_MASK 0x003f
#else
@@ -589,7 +590,7 @@ SCIF_FNS(SCSPTR, 0, 0, 0, 0)
SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
#endif
#if defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
- defined(CONFIG_R8A7794)
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
SCIF_FNS(DL, 0, 0, 0x30, 16)
SCIF_FNS(CKS, 0, 0, 0x34, 16)
#endif
@@ -734,7 +735,8 @@ static inline int scbrr_calc(struct uart_port port, int bps, int clk)
#define SCBRR_VALUE(bps, clk) scbrr_calc(sh_sci, bps, clk)
#elif defined(__H8300H__) || defined(__H8300S__)
#define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1)
-#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791)
+#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
#define DL_VALUE(bps, clk) (clk / bps / 16) /* External Clock */
#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) /* Internal Clock */
#else /* Generic SH */
diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c
index f8c9d921e2..3f3d415213 100644
--- a/drivers/serial/serial_uniphier.c
+++ b/drivers/serial/serial_uniphier.c
@@ -2,14 +2,14 @@
* Copyright (C) 2012-2014 Panasonic Corporation
* Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
*
- * Based on serial_ns16550.c
- * (C) Copyright 2000
- * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
- *
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <dm/device.h>
+#include <dm/platform_data/serial-uniphier.h>
#include <serial.h>
#define UART_REG(x) \
@@ -48,157 +48,115 @@ struct uniphier_serial {
#define UART_LSR_DR 0x01 /* Data ready */
#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
-DECLARE_GLOBAL_DATA_PTR;
+struct uniphier_serial_private_data {
+ struct uniphier_serial __iomem *membase;
+};
+
+#define uniphier_serial_port(dev) \
+ ((struct uniphier_serial_private_data *)dev_get_priv(dev))->membase
-static void uniphier_serial_init(struct uniphier_serial *port)
+static int uniphier_serial_setbrg(struct udevice *dev, int baudrate)
{
+ struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
+ struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
const unsigned int mode_x_div = 16;
unsigned int divisor;
writeb(UART_LCR_WLS_8, &port->lcr);
- divisor = DIV_ROUND_CLOSEST(CONFIG_SYS_UNIPHIER_UART_CLK,
- mode_x_div * gd->baudrate);
+ divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate);
writew(divisor, &port->dlr);
-}
-static void uniphier_serial_setbrg(struct uniphier_serial *port)
-{
- uniphier_serial_init(port);
+ return 0;
}
-static int uniphier_serial_tstc(struct uniphier_serial *port)
+static int uniphier_serial_getc(struct udevice *dev)
{
- return (readb(&port->lsr) & UART_LSR_DR) != 0;
-}
+ struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
-static int uniphier_serial_getc(struct uniphier_serial *port)
-{
- while (!uniphier_serial_tstc(port))
- ;
+ if (!(readb(&port->lsr) & UART_LSR_DR))
+ return -EAGAIN;
return readb(&port->rbr);
}
-static void uniphier_serial_putc(struct uniphier_serial *port, const char c)
+static int uniphier_serial_putc(struct udevice *dev, const char c)
{
- if (c == '\n')
- uniphier_serial_putc(port, '\r');
+ struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
- while (!(readb(&port->lsr) & UART_LSR_THRE))
- ;
+ if (!(readb(&port->lsr) & UART_LSR_THRE))
+ return -EAGAIN;
writeb(c, &port->thr);
+
+ return 0;
}
-static struct uniphier_serial *serial_ports[4] = {
-#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE0
- (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE0,
-#else
- NULL,
-#endif
-#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE1
- (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE1,
-#else
- NULL,
-#endif
-#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE2
- (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE2,
-#else
- NULL,
-#endif
-#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE3
- (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE3,
-#else
- NULL,
-#endif
-};
+static int uniphier_serial_pending(struct udevice *dev, bool input)
+{
+ struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
-/* Multi serial device functions */
-#define DECLARE_ESERIAL_FUNCTIONS(port) \
- static int eserial##port##_init(void) \
- { \
- uniphier_serial_init(serial_ports[port]); \
- return 0 ; \
- } \
- static void eserial##port##_setbrg(void) \
- { \
- uniphier_serial_setbrg(serial_ports[port]); \
- } \
- static int eserial##port##_getc(void) \
- { \
- return uniphier_serial_getc(serial_ports[port]); \
- } \
- static int eserial##port##_tstc(void) \
- { \
- return uniphier_serial_tstc(serial_ports[port]); \
- } \
- static void eserial##port##_putc(const char c) \
- { \
- uniphier_serial_putc(serial_ports[port], c); \
- }
-
-/* Serial device descriptor */
-#define INIT_ESERIAL_STRUCTURE(port, __name) { \
- .name = __name, \
- .start = eserial##port##_init, \
- .stop = NULL, \
- .setbrg = eserial##port##_setbrg, \
- .getc = eserial##port##_getc, \
- .tstc = eserial##port##_tstc, \
- .putc = eserial##port##_putc, \
- .puts = default_serial_puts, \
+ if (input)
+ return readb(&port->lsr) & UART_LSR_DR;
+ else
+ return !(readb(&port->lsr) & UART_LSR_THRE);
}
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
-DECLARE_ESERIAL_FUNCTIONS(0);
-struct serial_device uniphier_serial0_device =
- INIT_ESERIAL_STRUCTURE(0, "ttyS0");
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
-DECLARE_ESERIAL_FUNCTIONS(1);
-struct serial_device uniphier_serial1_device =
- INIT_ESERIAL_STRUCTURE(1, "ttyS1");
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
-DECLARE_ESERIAL_FUNCTIONS(2);
-struct serial_device uniphier_serial2_device =
- INIT_ESERIAL_STRUCTURE(2, "ttyS2");
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
-DECLARE_ESERIAL_FUNCTIONS(3);
-struct serial_device uniphier_serial3_device =
- INIT_ESERIAL_STRUCTURE(3, "ttyS3");
-#endif
+static int uniphier_serial_probe(struct udevice *dev)
+{
+ struct uniphier_serial_private_data *priv = dev_get_priv(dev);
+ struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
+
+ priv->membase = map_sysmem(plat->base, sizeof(struct uniphier_serial));
+
+ if (!priv->membase)
+ return -ENOMEM;
+
+ return 0;
+}
-__weak struct serial_device *default_serial_console(void)
+static int uniphier_serial_remove(struct udevice *dev)
{
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
- return &uniphier_serial0_device;
-#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
- return &uniphier_serial1_device;
-#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
- return &uniphier_serial2_device;
-#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
- return &uniphier_serial3_device;
-#else
-#error "No uniphier serial ports configured."
-#endif
+ unmap_sysmem(uniphier_serial_port(dev));
+
+ return 0;
}
-void uniphier_serial_initialize(void)
+#ifdef CONFIG_OF_CONTROL
+static const struct udevice_id uniphier_uart_of_match = {
+ { .compatible = "panasonic,uniphier-uart"},
+ {},
+};
+
+static int uniphier_serial_ofdata_to_platdata(struct udevice *dev)
{
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
- serial_register(&uniphier_serial0_device);
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
- serial_register(&uniphier_serial1_device);
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
- serial_register(&uniphier_serial2_device);
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
- serial_register(&uniphier_serial3_device);
-#endif
+ /*
+ * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com)
+ *
+ * Implement conversion code from DTB to platform data
+ * when supporting CONFIG_OF_CONTROL on UniPhir platform.
+ */
}
+#endif
+
+static const struct dm_serial_ops uniphier_serial_ops = {
+ .setbrg = uniphier_serial_setbrg,
+ .getc = uniphier_serial_getc,
+ .putc = uniphier_serial_putc,
+ .pending = uniphier_serial_pending,
+};
+
+U_BOOT_DRIVER(uniphier_serial) = {
+ .name = DRIVER_NAME,
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(uniphier_uart_of_match),
+ .ofdata_to_platdata = of_match_ptr(uniphier_serial_ofdata_to_platdata),
+ .probe = uniphier_serial_probe,
+ .remove = uniphier_serial_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_serial_private_data),
+ .platdata_auto_alloc_size =
+ sizeof(struct uniphier_serial_platform_data),
+ .ops = &uniphier_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
new file mode 100644
index 0000000000..3d4baa51d6
--- /dev/null
+++ b/drivers/soc/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the U-boot SOC specific device drivers.
+#
+
+obj-$(CONFIG_ARCH_KEYSTONE) += keystone/
diff --git a/drivers/soc/keystone/Makefile b/drivers/soc/keystone/Makefile
new file mode 100644
index 0000000000..c000ecac76
--- /dev/null
+++ b/drivers/soc/keystone/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o
diff --git a/drivers/soc/keystone/keystone_serdes.c b/drivers/soc/keystone/keystone_serdes.c
new file mode 100644
index 0000000000..dd5eac9bb3
--- /dev/null
+++ b/drivers/soc/keystone/keystone_serdes.c
@@ -0,0 +1,210 @@
+/*
+ * TI serdes driver for keystone2.
+ *
+ * (C) Copyright 2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <asm/ti-common/keystone_serdes.h>
+
+#define SERDES_CMU_REGS(x) (0x0000 + (0x0c00 * (x)))
+#define SERDES_LANE_REGS(x) (0x0200 + (0x200 * (x)))
+#define SERDES_COMLANE_REGS 0x0a00
+#define SERDES_WIZ_REGS 0x1fc0
+
+#define SERDES_CMU_REG_000(x) (SERDES_CMU_REGS(x) + 0x000)
+#define SERDES_CMU_REG_010(x) (SERDES_CMU_REGS(x) + 0x010)
+#define SERDES_COMLANE_REG_000 (SERDES_COMLANE_REGS + 0x000)
+#define SERDES_LANE_REG_000(x) (SERDES_LANE_REGS(x) + 0x000)
+#define SERDES_LANE_REG_028(x) (SERDES_LANE_REGS(x) + 0x028)
+#define SERDES_LANE_CTL_STATUS_REG(x) (SERDES_WIZ_REGS + 0x0020 + (4 * (x)))
+#define SERDES_PLL_CTL_REG (SERDES_WIZ_REGS + 0x0034)
+
+#define SERDES_RESET BIT(28)
+#define SERDES_LANE_RESET BIT(29)
+#define SERDES_LANE_LOOPBACK BIT(30)
+#define SERDES_LANE_EN_VAL(x, y, z) (x[y] | (z << 26) | (z << 10))
+
+#define SERDES_CMU_CFG_NUM 5
+#define SERDES_COMLANE_CFG_NUM 10
+#define SERDES_LANE_CFG_NUM 10
+
+struct serdes_cfg {
+ u32 ofs;
+ u32 val;
+ u32 mask;
+};
+
+struct cfg_entry {
+ enum ks2_serdes_clock clk;
+ enum ks2_serdes_rate rate;
+ struct serdes_cfg cmu[SERDES_CMU_CFG_NUM];
+ struct serdes_cfg comlane[SERDES_COMLANE_CFG_NUM];
+ struct serdes_cfg lane[SERDES_LANE_CFG_NUM];
+};
+
+/* SERDES PHY lane enable configuration value, indexed by PHY interface */
+static u32 serdes_cfg_lane_enable[] = {
+ 0xf000f0c0, /* SGMII */
+ 0xf0e9f038, /* PCSR */
+};
+
+/* SERDES PHY PLL enable configuration value, indexed by PHY interface */
+static u32 serdes_cfg_pll_enable[] = {
+ 0xe0000000, /* SGMII */
+ 0xee000000, /* PCSR */
+};
+
+/**
+ * Array to hold all possible serdes configurations.
+ * Combination for 5 clock settings and 6 baud rates.
+ */
+static struct cfg_entry cfgs[] = {
+ {
+ .clk = SERDES_CLOCK_156P25M,
+ .rate = SERDES_RATE_5G,
+ .cmu = {
+ {0x0000, 0x00800000, 0xffff0000},
+ {0x0014, 0x00008282, 0x0000ffff},
+ {0x0060, 0x00142438, 0x00ffffff},
+ {0x0064, 0x00c3c700, 0x00ffff00},
+ {0x0078, 0x0000c000, 0x0000ff00}
+ },
+ .comlane = {
+ {0x0a00, 0x00000800, 0x0000ff00},
+ {0x0a08, 0x38a20000, 0xffff0000},
+ {0x0a30, 0x008a8a00, 0x00ffff00},
+ {0x0a84, 0x00000600, 0x0000ff00},
+ {0x0a94, 0x10000000, 0xff000000},
+ {0x0aa0, 0x81000000, 0xff000000},
+ {0x0abc, 0xff000000, 0xff000000},
+ {0x0ac0, 0x0000008b, 0x000000ff},
+ {0x0b08, 0x583f0000, 0xffff0000},
+ {0x0b0c, 0x0000004e, 0x000000ff}
+ },
+ .lane = {
+ {0x0004, 0x38000080, 0xff0000ff},
+ {0x0008, 0x00000000, 0x000000ff},
+ {0x000c, 0x02000000, 0xff000000},
+ {0x0010, 0x1b000000, 0xff000000},
+ {0x0014, 0x00006fb8, 0x0000ffff},
+ {0x0018, 0x758000e4, 0xffff00ff},
+ {0x00ac, 0x00004400, 0x0000ff00},
+ {0x002c, 0x00100800, 0x00ffff00},
+ {0x0080, 0x00820082, 0x00ff00ff},
+ {0x0084, 0x1d0f0385, 0xffffffff}
+ },
+ },
+};
+
+static inline void ks2_serdes_rmw(u32 addr, u32 value, u32 mask)
+{
+ writel(((readl(addr) & (~mask)) | (value & mask)), addr);
+}
+
+static void ks2_serdes_cfg_setup(u32 base, struct serdes_cfg *cfg, u32 size)
+{
+ u32 i;
+
+ for (i = 0; i < size; i++)
+ ks2_serdes_rmw(base + cfg[i].ofs, cfg[i].val, cfg[i].mask);
+}
+
+static void ks2_serdes_lane_config(u32 base, struct serdes_cfg *cfg_lane,
+ u32 size, u32 lane)
+{
+ u32 i;
+
+ for (i = 0; i < size; i++)
+ ks2_serdes_rmw(base + cfg_lane[i].ofs + SERDES_LANE_REGS(lane),
+ cfg_lane[i].val, cfg_lane[i].mask);
+}
+
+static int ks2_serdes_init_cfg(u32 base, struct cfg_entry *cfg, u32 num_lanes)
+{
+ u32 i;
+
+ ks2_serdes_cfg_setup(base, cfg->cmu, SERDES_CMU_CFG_NUM);
+ ks2_serdes_cfg_setup(base, cfg->comlane, SERDES_COMLANE_CFG_NUM);
+
+ for (i = 0; i < num_lanes; i++)
+ ks2_serdes_lane_config(base, cfg->lane, SERDES_LANE_CFG_NUM, i);
+
+ return 0;
+}
+
+static void ks2_serdes_cmu_comlane_enable(u32 base, struct ks2_serdes *serdes)
+{
+ /* Bring SerDes out of Reset */
+ ks2_serdes_rmw(base + SERDES_CMU_REG_010(0), 0x0, SERDES_RESET);
+ if (serdes->intf == SERDES_PHY_PCSR)
+ ks2_serdes_rmw(base + SERDES_CMU_REG_010(1), 0x0, SERDES_RESET);
+
+ /* Enable CMU and COMLANE */
+ ks2_serdes_rmw(base + SERDES_CMU_REG_000(0), 0x03, 0x000000ff);
+ if (serdes->intf == SERDES_PHY_PCSR)
+ ks2_serdes_rmw(base + SERDES_CMU_REG_000(1), 0x03, 0x000000ff);
+
+ ks2_serdes_rmw(base + SERDES_COMLANE_REG_000, 0x5f, 0x000000ff);
+}
+
+static void ks2_serdes_pll_enable(u32 base, struct ks2_serdes *serdes)
+{
+ writel(serdes_cfg_pll_enable[serdes->intf],
+ base + SERDES_PLL_CTL_REG);
+}
+
+static void ks2_serdes_lane_reset(u32 base, u32 reset, u32 lane)
+{
+ if (reset)
+ ks2_serdes_rmw(base + SERDES_LANE_REG_028(lane),
+ 0x1, SERDES_LANE_RESET);
+ else
+ ks2_serdes_rmw(base + SERDES_LANE_REG_028(lane),
+ 0x0, SERDES_LANE_RESET);
+}
+
+static void ks2_serdes_lane_enable(u32 base,
+ struct ks2_serdes *serdes, u32 lane)
+{
+ /* Bring lane out of reset */
+ ks2_serdes_lane_reset(base, 0, lane);
+
+ writel(SERDES_LANE_EN_VAL(serdes_cfg_lane_enable, serdes->intf,
+ serdes->rate_mode),
+ base + SERDES_LANE_CTL_STATUS_REG(lane));
+
+ /* Set NES bit if Loopback Enabled */
+ if (serdes->loopback)
+ ks2_serdes_rmw(base + SERDES_LANE_REG_000(lane),
+ 0x1, SERDES_LANE_LOOPBACK);
+}
+
+int ks2_serdes_init(u32 base, struct ks2_serdes *serdes, u32 num_lanes)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(cfgs); i++)
+ if (serdes->clk == cfgs[i].clk && serdes->rate == cfgs[i].rate)
+ break;
+
+ if (i >= ARRAY_SIZE(cfgs)) {
+ puts("Cannot find keystone SerDes configuration");
+ return -EINVAL;
+ }
+
+ ks2_serdes_init_cfg(base, &cfgs[i], num_lanes);
+
+ ks2_serdes_cmu_comlane_enable(base, serdes);
+ for (i = 0; i < num_lanes; i++)
+ ks2_serdes_lane_enable(base, serdes, i);
+
+ ks2_serdes_pll_enable(base, serdes);
+
+ return ret;
+}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index e69de29bb2..e1678e63e6 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -0,0 +1,6 @@
+config DM_SPI
+ bool "Enable Driver Model for SPI drivers"
+ depends on DM
+ help
+ If you want to use driver model for SPI drivers, say Y.
+ To use legacy SPI drivers, say N.
diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c
index 5accbb5c22..a4d03d97cf 100644
--- a/drivers/spi/altera_spi.c
+++ b/drivers/spi/altera_spi.c
@@ -12,58 +12,62 @@
#include <malloc.h>
#include <spi.h>
-#define ALTERA_SPI_RXDATA 0
-#define ALTERA_SPI_TXDATA 4
-#define ALTERA_SPI_STATUS 8
-#define ALTERA_SPI_CONTROL 12
-#define ALTERA_SPI_SLAVE_SEL 20
-
-#define ALTERA_SPI_STATUS_ROE_MSK (0x8)
-#define ALTERA_SPI_STATUS_TOE_MSK (0x10)
-#define ALTERA_SPI_STATUS_TMT_MSK (0x20)
-#define ALTERA_SPI_STATUS_TRDY_MSK (0x40)
-#define ALTERA_SPI_STATUS_RRDY_MSK (0x80)
-#define ALTERA_SPI_STATUS_E_MSK (0x100)
-
-#define ALTERA_SPI_CONTROL_IROE_MSK (0x8)
-#define ALTERA_SPI_CONTROL_ITOE_MSK (0x10)
-#define ALTERA_SPI_CONTROL_ITRDY_MSK (0x40)
-#define ALTERA_SPI_CONTROL_IRRDY_MSK (0x80)
-#define ALTERA_SPI_CONTROL_IE_MSK (0x100)
-#define ALTERA_SPI_CONTROL_SSO_MSK (0x400)
+#ifndef CONFIG_ALTERA_SPI_IDLE_VAL
+#define CONFIG_ALTERA_SPI_IDLE_VAL 0xff
+#endif
#ifndef CONFIG_SYS_ALTERA_SPI_LIST
#define CONFIG_SYS_ALTERA_SPI_LIST { CONFIG_SYS_SPI_BASE }
#endif
+struct altera_spi_regs {
+ u32 rxdata;
+ u32 txdata;
+ u32 status;
+ u32 control;
+ u32 _reserved;
+ u32 slave_sel;
+};
+
+#define ALTERA_SPI_STATUS_ROE_MSK (1 << 3)
+#define ALTERA_SPI_STATUS_TOE_MSK (1 << 4)
+#define ALTERA_SPI_STATUS_TMT_MSK (1 << 5)
+#define ALTERA_SPI_STATUS_TRDY_MSK (1 << 6)
+#define ALTERA_SPI_STATUS_RRDY_MSK (1 << 7)
+#define ALTERA_SPI_STATUS_E_MSK (1 << 8)
+
+#define ALTERA_SPI_CONTROL_IROE_MSK (1 << 3)
+#define ALTERA_SPI_CONTROL_ITOE_MSK (1 << 4)
+#define ALTERA_SPI_CONTROL_ITRDY_MSK (1 << 6)
+#define ALTERA_SPI_CONTROL_IRRDY_MSK (1 << 7)
+#define ALTERA_SPI_CONTROL_IE_MSK (1 << 8)
+#define ALTERA_SPI_CONTROL_SSO_MSK (1 << 10)
+
static ulong altera_spi_base_list[] = CONFIG_SYS_ALTERA_SPI_LIST;
struct altera_spi_slave {
- struct spi_slave slave;
- ulong base;
+ struct spi_slave slave;
+ struct altera_spi_regs *regs;
};
#define to_altera_spi_slave(s) container_of(s, struct altera_spi_slave, slave)
-__attribute__((weak))
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+__weak int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
return bus < ARRAY_SIZE(altera_spi_base_list) && cs < 32;
}
-__attribute__((weak))
-void spi_cs_activate(struct spi_slave *slave)
+__weak void spi_cs_activate(struct spi_slave *slave)
{
struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
- writel(1 << slave->cs, altspi->base + ALTERA_SPI_SLAVE_SEL);
- writel(ALTERA_SPI_CONTROL_SSO_MSK, altspi->base + ALTERA_SPI_CONTROL);
+ writel(1 << slave->cs, &altspi->regs->slave_sel);
+ writel(ALTERA_SPI_CONTROL_SSO_MSK, &altspi->regs->control);
}
-__attribute__((weak))
-void spi_cs_deactivate(struct spi_slave *slave)
+__weak void spi_cs_deactivate(struct spi_slave *slave)
{
struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
- writel(0, altspi->base + ALTERA_SPI_CONTROL);
- writel(0, altspi->base + ALTERA_SPI_SLAVE_SEL);
+ writel(0, &altspi->regs->control);
+ writel(0, &altspi->regs->slave_sel);
}
void spi_init(void)
@@ -87,9 +91,8 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (!altspi)
return NULL;
- altspi->base = altera_spi_base_list[bus];
- debug("%s: bus:%i cs:%i base:%lx\n", __func__,
- bus, cs, altspi->base);
+ altspi->regs = (struct altera_spi_regs *)altera_spi_base_list[bus];
+ debug("%s: bus:%i cs:%i base:%p\n", __func__, bus, cs, altspi->regs);
return &altspi->slave;
}
@@ -105,8 +108,8 @@ int spi_claim_bus(struct spi_slave *slave)
struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
- writel(0, altspi->base + ALTERA_SPI_CONTROL);
- writel(0, altspi->base + ALTERA_SPI_SLAVE_SEL);
+ writel(0, &altspi->regs->control);
+ writel(0, &altspi->regs->slave_sel);
return 0;
}
@@ -115,24 +118,22 @@ void spi_release_bus(struct spi_slave *slave)
struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
- writel(0, altspi->base + ALTERA_SPI_SLAVE_SEL);
+ writel(0, &altspi->regs->slave_sel);
}
-#ifndef CONFIG_ALTERA_SPI_IDLE_VAL
-# define CONFIG_ALTERA_SPI_IDLE_VAL 0xff
-#endif
-
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
void *din, unsigned long flags)
{
struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
/* assume spi core configured to do 8 bit transfers */
- uint bytes = bitlen / 8;
- const uchar *txp = dout;
- uchar *rxp = din;
+ unsigned int bytes = bitlen / 8;
+ const unsigned char *txp = dout;
+ unsigned char *rxp = din;
+ uint32_t reg, data, start;
debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
- slave->bus, slave->cs, bitlen, bytes, flags);
+ slave->bus, slave->cs, bitlen, bytes, flags);
+
if (bitlen == 0)
goto done;
@@ -142,25 +143,40 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
}
/* empty read buffer */
- if (readl(altspi->base + ALTERA_SPI_STATUS) &
- ALTERA_SPI_STATUS_RRDY_MSK)
- readl(altspi->base + ALTERA_SPI_RXDATA);
+ if (readl(&altspi->regs->status) & ALTERA_SPI_STATUS_RRDY_MSK)
+ readl(&altspi->regs->rxdata);
+
if (flags & SPI_XFER_BEGIN)
spi_cs_activate(slave);
while (bytes--) {
- uchar d = txp ? *txp++ : CONFIG_ALTERA_SPI_IDLE_VAL;
- debug("%s: tx:%x ", __func__, d);
- writel(d, altspi->base + ALTERA_SPI_TXDATA);
- while (!(readl(altspi->base + ALTERA_SPI_STATUS) &
- ALTERA_SPI_STATUS_RRDY_MSK))
- ;
- d = readl(altspi->base + ALTERA_SPI_RXDATA);
+ if (txp)
+ data = *txp++;
+ else
+ data = CONFIG_ALTERA_SPI_IDLE_VAL;
+
+ debug("%s: tx:%x ", __func__, data);
+ writel(data, &altspi->regs->txdata);
+
+ start = get_timer(0);
+ while (1) {
+ reg = readl(&altspi->regs->status);
+ if (reg & ALTERA_SPI_STATUS_RRDY_MSK)
+ break;
+ if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+ printf("%s: Transmission timed out!\n", __func__);
+ goto done;
+ }
+ }
+
+ data = readl(&altspi->regs->rxdata);
if (rxp)
- *rxp++ = d;
- debug("rx:%x\n", d);
+ *rxp++ = data & 0xff;
+
+ debug("rx:%x\n", data);
}
- done:
+
+done:
if (flags & SPI_XFER_END)
spi_cs_deactivate(slave);
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index 026f680d80..23f2ba6223 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -12,6 +12,7 @@
#include <asm/gpio.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
+#include <asm/imx-common/spi.h>
#ifdef CONFIG_MX27
/* i.MX27 has a completely wrong register layout and register definitions in the
@@ -48,6 +49,8 @@ struct mxc_spi_slave {
#endif
int gpio;
int ss_pol;
+ unsigned int max_hz;
+ unsigned int mode;
};
static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave)
@@ -82,12 +85,13 @@ u32 get_cspi_div(u32 div)
}
#ifdef MXC_CSPI
-static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
- unsigned int max_hz, unsigned int mode)
+static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs)
{
unsigned int ctrl_reg;
u32 clk_src;
u32 div;
+ unsigned int max_hz = mxcs->max_hz;
+ unsigned int mode = mxcs->mode;
clk_src = mxc_get_clock(MXC_CSPI_CLK);
@@ -119,19 +123,15 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
#endif
#ifdef MXC_ECSPI
-static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
- unsigned int max_hz, unsigned int mode)
+static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs)
{
u32 clk_src = mxc_get_clock(MXC_CSPI_CLK);
s32 reg_ctrl, reg_config;
u32 ss_pol = 0, sclkpol = 0, sclkpha = 0, sclkctl = 0;
u32 pre_div = 0, post_div = 0;
struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
-
- if (max_hz == 0) {
- printf("Error: desired clock is 0\n");
- return -1;
- }
+ unsigned int max_hz = mxcs->max_hz;
+ unsigned int mode = mxcs->mode;
/*
* Reset SPI and set all CSs to master mode, if toggling
@@ -168,9 +168,6 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_POSTDIV(0x0F)) |
MXC_CSPICTRL_POSTDIV(post_div);
- /* We need to disable SPI before changing registers */
- reg_ctrl &= ~MXC_CSPICTRL_EN;
-
if (mode & SPI_CS_HIGH)
ss_pol = 1;
@@ -411,6 +408,11 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (bus >= ARRAY_SIZE(spi_bases))
return NULL;
+ if (max_hz == 0) {
+ printf("Error: desired clock is 0\n");
+ return NULL;
+ }
+
mxcs = spi_alloc_slave(struct mxc_spi_slave, bus, cs);
if (!mxcs) {
puts("mxc_spi: SPI Slave not allocated !\n");
@@ -426,13 +428,9 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
}
mxcs->base = spi_bases[bus];
+ mxcs->max_hz = max_hz;
+ mxcs->mode = mode;
- ret = spi_cfg_mxc(mxcs, cs, max_hz, mode);
- if (ret) {
- printf("mxc_spi: cannot setup SPI controller\n");
- free(mxcs);
- return NULL;
- }
return &mxcs->slave;
}
@@ -445,12 +443,17 @@ void spi_free_slave(struct spi_slave *slave)
int spi_claim_bus(struct spi_slave *slave)
{
+ int ret;
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
reg_write(&regs->rxdata, 1);
udelay(1);
- reg_write(&regs->ctrl, mxcs->ctrl_reg);
+ ret = spi_cfg_mxc(mxcs, slave->cs);
+ if (ret) {
+ printf("mxc_spi: cannot setup SPI controller\n");
+ return ret;
+ }
reg_write(&regs->period, MXC_CSPIPERIOD_32KHZ);
reg_write(&regs->intr, 0);
diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c
index 6557055e02..11811094ed 100644
--- a/drivers/usb/eth/asix.c
+++ b/drivers/usb/eth/asix.c
@@ -580,6 +580,7 @@ static const struct asix_dongle asix_dongles[] = {
{ 0x2001, 0x3c05, FLAG_TYPE_AX88772 },
/* ASIX 88772B */
{ 0x0b95, 0x772b, FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC },
+ { 0x0b95, 0x7e2b, FLAG_TYPE_AX88772B },
{ 0x0000, 0x0000, FLAG_NONE } /* END - Do not remove */
};
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index c4f5157a84..1c3592914d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -43,5 +43,9 @@ obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o
# xhci
obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
+obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o
obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
+
+# designware
+obj-$(CONFIG_USB_DWC2) += dwc2.o
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
new file mode 100644
index 0000000000..2a5bbf5ac0
--- /dev/null
+++ b/drivers/usb/host/dwc2.c
@@ -0,0 +1,1053 @@
+/*
+ * Copyright (C) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <usb.h>
+#include <malloc.h>
+#include <usbroothubdes.h>
+#include <asm/io.h>
+
+#include "dwc2.h"
+
+/* Use only HC channel 0. */
+#define DWC2_HC_CHANNEL 0
+
+#define DWC2_STATUS_BUF_SIZE 64
+#define DWC2_DATA_BUF_SIZE (64 * 1024)
+
+/* We need doubleword-aligned buffers for DMA transfers */
+DEFINE_ALIGN_BUFFER(uint8_t, aligned_buffer, DWC2_DATA_BUF_SIZE, 8);
+DEFINE_ALIGN_BUFFER(uint8_t, status_buffer, DWC2_STATUS_BUF_SIZE, 8);
+
+#define MAX_DEVICE 16
+#define MAX_ENDPOINT 16
+static int bulk_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+static int control_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+
+static int root_hub_devnum;
+
+static struct dwc2_core_regs *regs =
+ (struct dwc2_core_regs *)CONFIG_USB_DWC2_REG_ADDR;
+
+/*
+ * DWC2 IP interface
+ */
+static int wait_for_bit(void *reg, const uint32_t mask, bool set)
+{
+ unsigned int timeout = 1000000;
+ uint32_t val;
+
+ while (--timeout) {
+ val = readl(reg);
+ if (!set)
+ val = ~val;
+
+ if ((val & mask) == mask)
+ return 0;
+
+ udelay(1);
+ }
+
+ debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n",
+ __func__, reg, mask, set);
+
+ return -ETIMEDOUT;
+}
+
+/*
+ * Initializes the FSLSPClkSel field of the HCFG register
+ * depending on the PHY type.
+ */
+static void init_fslspclksel(struct dwc2_core_regs *regs)
+{
+ uint32_t phyclk;
+
+#if (CONFIG_DWC2_PHY_TYPE == DWC2_PHY_TYPE_FS)
+ phyclk = DWC2_HCFG_FSLSPCLKSEL_48_MHZ; /* Full speed PHY */
+#else
+ /* High speed PHY running at full speed or high speed */
+ phyclk = DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ;
+#endif
+
+#ifdef CONFIG_DWC2_ULPI_FS_LS
+ uint32_t hwcfg2 = readl(&regs->ghwcfg2);
+ uint32_t hval = (ghwcfg2 & DWC2_HWCFG2_HS_PHY_TYPE_MASK) >>
+ DWC2_HWCFG2_HS_PHY_TYPE_OFFSET;
+ uint32_t fval = (ghwcfg2 & DWC2_HWCFG2_FS_PHY_TYPE_MASK) >>
+ DWC2_HWCFG2_FS_PHY_TYPE_OFFSET;
+
+ if (hval == 2 && fval == 1)
+ phyclk = DWC2_HCFG_FSLSPCLKSEL_48_MHZ; /* Full speed PHY */
+#endif
+
+ clrsetbits_le32(&regs->host_regs.hcfg,
+ DWC2_HCFG_FSLSPCLKSEL_MASK,
+ phyclk << DWC2_HCFG_FSLSPCLKSEL_OFFSET);
+}
+
+/*
+ * Flush a Tx FIFO.
+ *
+ * @param regs Programming view of DWC_otg controller.
+ * @param num Tx FIFO to flush.
+ */
+static void dwc_otg_flush_tx_fifo(struct dwc2_core_regs *regs, const int num)
+{
+ int ret;
+
+ writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET),
+ &regs->grstctl);
+ ret = wait_for_bit(&regs->grstctl, DWC2_GRSTCTL_TXFFLSH, 0);
+ if (ret)
+ printf("%s: Timeout!\n", __func__);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/*
+ * Flush Rx FIFO.
+ *
+ * @param regs Programming view of DWC_otg controller.
+ */
+static void dwc_otg_flush_rx_fifo(struct dwc2_core_regs *regs)
+{
+ int ret;
+
+ writel(DWC2_GRSTCTL_RXFFLSH, &regs->grstctl);
+ ret = wait_for_bit(&regs->grstctl, DWC2_GRSTCTL_RXFFLSH, 0);
+ if (ret)
+ printf("%s: Timeout!\n", __func__);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/*
+ * Do core a soft reset of the core. Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+static void dwc_otg_core_reset(struct dwc2_core_regs *regs)
+{
+ int ret;
+
+ /* Wait for AHB master IDLE state. */
+ ret = wait_for_bit(&regs->grstctl, DWC2_GRSTCTL_AHBIDLE, 1);
+ if (ret)
+ printf("%s: Timeout!\n", __func__);
+
+ /* Core Soft Reset */
+ writel(DWC2_GRSTCTL_CSFTRST, &regs->grstctl);
+ ret = wait_for_bit(&regs->grstctl, DWC2_GRSTCTL_CSFTRST, 0);
+ if (ret)
+ printf("%s: Timeout!\n", __func__);
+
+ /*
+ * Wait for core to come out of reset.
+ * NOTE: This long sleep is _very_ important, otherwise the core will
+ * not stay in host mode after a connector ID change!
+ */
+ mdelay(100);
+}
+
+/*
+ * This function initializes the DWC_otg controller registers for
+ * host mode.
+ *
+ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
+ * request queues. Host channels are reset to ensure that they are ready for
+ * performing transfers.
+ *
+ * @param regs Programming view of DWC_otg controller
+ *
+ */
+static void dwc_otg_core_host_init(struct dwc2_core_regs *regs)
+{
+ uint32_t nptxfifosize = 0;
+ uint32_t ptxfifosize = 0;
+ uint32_t hprt0 = 0;
+ int i, ret, num_channels;
+
+ /* Restart the Phy Clock */
+ writel(0, &regs->pcgcctl);
+
+ /* Initialize Host Configuration Register */
+ init_fslspclksel(regs);
+#ifdef CONFIG_DWC2_DFLT_SPEED_FULL
+ setbits_le32(&regs->host_regs.hcfg, DWC2_HCFG_FSLSSUPP);
+#endif
+
+ /* Configure data FIFO sizes */
+#ifdef CONFIG_DWC2_ENABLE_DYNAMIC_FIFO
+ if (readl(&regs->ghwcfg2) & DWC2_HWCFG2_DYNAMIC_FIFO) {
+ /* Rx FIFO */
+ writel(CONFIG_DWC2_HOST_RX_FIFO_SIZE, &regs->grxfsiz);
+
+ /* Non-periodic Tx FIFO */
+ nptxfifosize |= CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE <<
+ DWC2_FIFOSIZE_DEPTH_OFFSET;
+ nptxfifosize |= CONFIG_DWC2_HOST_RX_FIFO_SIZE <<
+ DWC2_FIFOSIZE_STARTADDR_OFFSET;
+ writel(nptxfifosize, &regs->gnptxfsiz);
+
+ /* Periodic Tx FIFO */
+ ptxfifosize |= CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE <<
+ DWC2_FIFOSIZE_DEPTH_OFFSET;
+ ptxfifosize |= (CONFIG_DWC2_HOST_RX_FIFO_SIZE +
+ CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE) <<
+ DWC2_FIFOSIZE_STARTADDR_OFFSET;
+ writel(ptxfifosize, &regs->hptxfsiz);
+ }
+#endif
+
+ /* Clear Host Set HNP Enable in the OTG Control Register */
+ clrbits_le32(&regs->gotgctl, DWC2_GOTGCTL_HSTSETHNPEN);
+
+ /* Make sure the FIFOs are flushed. */
+ dwc_otg_flush_tx_fifo(regs, 0x10); /* All Tx FIFOs */
+ dwc_otg_flush_rx_fifo(regs);
+
+ /* Flush out any leftover queued requests. */
+ num_channels = readl(&regs->ghwcfg2);
+ num_channels &= DWC2_HWCFG2_NUM_HOST_CHAN_MASK;
+ num_channels >>= DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET;
+ num_channels += 1;
+
+ for (i = 0; i < num_channels; i++)
+ clrsetbits_le32(&regs->hc_regs[i].hcchar,
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_EPDIR,
+ DWC2_HCCHAR_CHDIS);
+
+ /* Halt all channels to put them into a known state. */
+ for (i = 0; i < num_channels; i++) {
+ clrsetbits_le32(&regs->hc_regs[i].hcchar,
+ DWC2_HCCHAR_EPDIR,
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS);
+ ret = wait_for_bit(&regs->hc_regs[i].hcchar,
+ DWC2_HCCHAR_CHEN, 0);
+ if (ret)
+ printf("%s: Timeout!\n", __func__);
+ }
+
+ /* Turn on the vbus power. */
+ if (readl(&regs->gintsts) & DWC2_GINTSTS_CURMODE_HOST) {
+ hprt0 = readl(&regs->hprt0);
+ hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET);
+ hprt0 &= ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG);
+ if (!(hprt0 & DWC2_HPRT0_PRTPWR)) {
+ hprt0 |= DWC2_HPRT0_PRTPWR;
+ writel(hprt0, &regs->hprt0);
+ }
+ }
+}
+
+/*
+ * This function initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation.
+ *
+ * @param regs Programming view of the DWC_otg controller
+ */
+static void dwc_otg_core_init(struct dwc2_core_regs *regs)
+{
+ uint32_t ahbcfg = 0;
+ uint32_t usbcfg = 0;
+ uint8_t brst_sz = CONFIG_DWC2_DMA_BURST_SIZE;
+
+ /* Common Initialization */
+ usbcfg = readl(&regs->gusbcfg);
+
+ /* Program the ULPI External VBUS bit if needed */
+#ifdef CONFIG_DWC2_PHY_ULPI_EXT_VBUS
+ usbcfg |= DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV;
+#else
+ usbcfg &= ~DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV;
+#endif
+
+ /* Set external TS Dline pulsing */
+#ifdef CONFIG_DWC2_TS_DLINE
+ usbcfg |= DWC2_GUSBCFG_TERM_SEL_DL_PULSE;
+#else
+ usbcfg &= ~DWC2_GUSBCFG_TERM_SEL_DL_PULSE;
+#endif
+ writel(usbcfg, &regs->gusbcfg);
+
+ /* Reset the Controller */
+ dwc_otg_core_reset(regs);
+
+ /*
+ * This programming sequence needs to happen in FS mode before
+ * any other programming occurs
+ */
+#if defined(CONFIG_DWC2_DFLT_SPEED_FULL) && \
+ (CONFIG_DWC2_PHY_TYPE == DWC2_PHY_TYPE_FS)
+ /* If FS mode with FS PHY */
+ setbits_le32(&regs->gusbcfg, DWC2_GUSBCFG_PHYSEL);
+
+ /* Reset after a PHY select */
+ dwc_otg_core_reset(regs);
+
+ /*
+ * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.
+ * Also do this on HNP Dev/Host mode switches (done in dev_init
+ * and host_init).
+ */
+ if (readl(&regs->gintsts) & DWC2_GINTSTS_CURMODE_HOST)
+ init_fslspclksel(regs);
+
+#ifdef CONFIG_DWC2_I2C_ENABLE
+ /* Program GUSBCFG.OtgUtmifsSel to I2C */
+ setbits_le32(&regs->gusbcfg, DWC2_GUSBCFG_OTGUTMIFSSEL);
+
+ /* Program GI2CCTL.I2CEn */
+ clrsetbits_le32(&regs->gi2cctl, DWC2_GI2CCTL_I2CEN |
+ DWC2_GI2CCTL_I2CDEVADDR_MASK,
+ 1 << DWC2_GI2CCTL_I2CDEVADDR_OFFSET);
+ setbits_le32(&regs->gi2cctl, DWC2_GI2CCTL_I2CEN);
+#endif
+
+#else
+ /* High speed PHY. */
+
+ /*
+ * HS PHY parameters. These parameters are preserved during
+ * soft reset so only program the first time. Do a soft reset
+ * immediately after setting phyif.
+ */
+ usbcfg &= ~(DWC2_GUSBCFG_ULPI_UTMI_SEL | DWC2_GUSBCFG_PHYIF);
+ usbcfg |= CONFIG_DWC2_PHY_TYPE << DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET;
+
+ if (usbcfg & DWC2_GUSBCFG_ULPI_UTMI_SEL) { /* ULPI interface */
+#ifdef CONFIG_DWC2_PHY_ULPI_DDR
+ usbcfg |= DWC2_GUSBCFG_DDRSEL;
+#else
+ usbcfg &= ~DWC2_GUSBCFG_DDRSEL;
+#endif
+ } else { /* UTMI+ interface */
+#if (CONFIG_DWC2_UTMI_PHY_WIDTH == 16)
+ usbcfg |= DWC2_GUSBCFG_PHYIF;
+#endif
+ }
+
+ writel(usbcfg, &regs->gusbcfg);
+
+ /* Reset after setting the PHY parameters */
+ dwc_otg_core_reset(regs);
+#endif
+
+ usbcfg = readl(&regs->gusbcfg);
+ usbcfg &= ~(DWC2_GUSBCFG_ULPI_FSLS | DWC2_GUSBCFG_ULPI_CLK_SUS_M);
+#ifdef CONFIG_DWC2_ULPI_FS_LS
+ uint32_t hwcfg2 = readl(&regs->ghwcfg2);
+ uint32_t hval = (ghwcfg2 & DWC2_HWCFG2_HS_PHY_TYPE_MASK) >>
+ DWC2_HWCFG2_HS_PHY_TYPE_OFFSET;
+ uint32_t fval = (ghwcfg2 & DWC2_HWCFG2_FS_PHY_TYPE_MASK) >>
+ DWC2_HWCFG2_FS_PHY_TYPE_OFFSET;
+ if (hval == 2 && fval == 1) {
+ usbcfg |= DWC2_GUSBCFG_ULPI_FSLS;
+ usbcfg |= DWC2_GUSBCFG_ULPI_CLK_SUS_M;
+ }
+#endif
+ writel(usbcfg, &regs->gusbcfg);
+
+ /* Program the GAHBCFG Register. */
+ switch (readl(&regs->ghwcfg2) & DWC2_HWCFG2_ARCHITECTURE_MASK) {
+ case DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY:
+ break;
+ case DWC2_HWCFG2_ARCHITECTURE_EXT_DMA:
+ while (brst_sz > 1) {
+ ahbcfg |= ahbcfg + (1 << DWC2_GAHBCFG_HBURSTLEN_OFFSET);
+ ahbcfg &= DWC2_GAHBCFG_HBURSTLEN_MASK;
+ brst_sz >>= 1;
+ }
+
+#ifdef CONFIG_DWC2_DMA_ENABLE
+ ahbcfg |= DWC2_GAHBCFG_DMAENABLE;
+#endif
+ break;
+
+ case DWC2_HWCFG2_ARCHITECTURE_INT_DMA:
+ ahbcfg |= DWC2_GAHBCFG_HBURSTLEN_INCR4;
+#ifdef CONFIG_DWC2_DMA_ENABLE
+ ahbcfg |= DWC2_GAHBCFG_DMAENABLE;
+#endif
+ break;
+ }
+
+ writel(ahbcfg, &regs->gahbcfg);
+
+ /* Program the GUSBCFG register for HNP/SRP. */
+ setbits_le32(&regs->gusbcfg, DWC2_GUSBCFG_HNPCAP | DWC2_GUSBCFG_SRPCAP);
+
+#ifdef CONFIG_DWC2_IC_USB_CAP
+ setbits_le32(&regs->gusbcfg, DWC2_GUSBCFG_IC_USB_CAP);
+#endif
+}
+
+/*
+ * Prepares a host channel for transferring packets to/from a specific
+ * endpoint. The HCCHARn register is set up with the characteristics specified
+ * in _hc. Host channel interrupts that may need to be serviced while this
+ * transfer is in progress are enabled.
+ *
+ * @param regs Programming view of DWC_otg controller
+ * @param hc Information needed to initialize the host channel
+ */
+static void dwc_otg_hc_init(struct dwc2_core_regs *regs, uint8_t hc_num,
+ uint8_t dev_addr, uint8_t ep_num, uint8_t ep_is_in,
+ uint8_t ep_type, uint16_t max_packet)
+{
+ struct dwc2_hc_regs *hc_regs = &regs->hc_regs[hc_num];
+ const uint32_t hcchar = (dev_addr << DWC2_HCCHAR_DEVADDR_OFFSET) |
+ (ep_num << DWC2_HCCHAR_EPNUM_OFFSET) |
+ (ep_is_in << DWC2_HCCHAR_EPDIR_OFFSET) |
+ (ep_type << DWC2_HCCHAR_EPTYPE_OFFSET) |
+ (max_packet << DWC2_HCCHAR_MPS_OFFSET);
+
+ /* Clear old interrupt conditions for this host channel. */
+ writel(0x3fff, &hc_regs->hcint);
+
+ /*
+ * Program the HCCHARn register with the endpoint characteristics
+ * for the current transfer.
+ */
+ writel(hcchar, &hc_regs->hcchar);
+
+ /* Program the HCSPLIT register for SPLITs */
+ writel(0, &hc_regs->hcsplt);
+}
+
+/*
+ * DWC2 to USB API interface
+ */
+/* Direction: In ; Request: Status */
+static int dwc_otg_submit_rh_msg_in_status(struct usb_device *dev, void *buffer,
+ int txlen, struct devrequest *cmd)
+{
+ uint32_t hprt0 = 0;
+ uint32_t port_status = 0;
+ uint32_t port_change = 0;
+ int len = 0;
+ int stat = 0;
+
+ switch (cmd->requesttype & ~USB_DIR_IN) {
+ case 0:
+ *(uint16_t *)buffer = cpu_to_le16(1);
+ len = 2;
+ break;
+ case USB_RECIP_INTERFACE:
+ case USB_RECIP_ENDPOINT:
+ *(uint16_t *)buffer = cpu_to_le16(0);
+ len = 2;
+ break;
+ case USB_TYPE_CLASS:
+ *(uint32_t *)buffer = cpu_to_le32(0);
+ len = 4;
+ break;
+ case USB_RECIP_OTHER | USB_TYPE_CLASS:
+ hprt0 = readl(&regs->hprt0);
+ if (hprt0 & DWC2_HPRT0_PRTCONNSTS)
+ port_status |= USB_PORT_STAT_CONNECTION;
+ if (hprt0 & DWC2_HPRT0_PRTENA)
+ port_status |= USB_PORT_STAT_ENABLE;
+ if (hprt0 & DWC2_HPRT0_PRTSUSP)
+ port_status |= USB_PORT_STAT_SUSPEND;
+ if (hprt0 & DWC2_HPRT0_PRTOVRCURRACT)
+ port_status |= USB_PORT_STAT_OVERCURRENT;
+ if (hprt0 & DWC2_HPRT0_PRTRST)
+ port_status |= USB_PORT_STAT_RESET;
+ if (hprt0 & DWC2_HPRT0_PRTPWR)
+ port_status |= USB_PORT_STAT_POWER;
+
+ port_status |= USB_PORT_STAT_HIGH_SPEED;
+
+ if (hprt0 & DWC2_HPRT0_PRTENCHNG)
+ port_change |= USB_PORT_STAT_C_ENABLE;
+ if (hprt0 & DWC2_HPRT0_PRTCONNDET)
+ port_change |= USB_PORT_STAT_C_CONNECTION;
+ if (hprt0 & DWC2_HPRT0_PRTOVRCURRCHNG)
+ port_change |= USB_PORT_STAT_C_OVERCURRENT;
+
+ *(uint32_t *)buffer = cpu_to_le32(port_status |
+ (port_change << 16));
+ len = 4;
+ break;
+ default:
+ puts("unsupported root hub command\n");
+ stat = USB_ST_STALLED;
+ }
+
+ dev->act_len = min(len, txlen);
+ dev->status = stat;
+
+ return stat;
+}
+
+/* Direction: In ; Request: Descriptor */
+static int dwc_otg_submit_rh_msg_in_descriptor(struct usb_device *dev,
+ void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ unsigned char data[32];
+ uint32_t dsc;
+ int len = 0;
+ int stat = 0;
+ uint16_t wValue = cpu_to_le16(cmd->value);
+ uint16_t wLength = cpu_to_le16(cmd->length);
+
+ switch (cmd->requesttype & ~USB_DIR_IN) {
+ case 0:
+ switch (wValue & 0xff00) {
+ case 0x0100: /* device descriptor */
+ len = min3(txlen, sizeof(root_hub_dev_des), wLength);
+ memcpy(buffer, root_hub_dev_des, len);
+ break;
+ case 0x0200: /* configuration descriptor */
+ len = min3(txlen, sizeof(root_hub_config_des), wLength);
+ memcpy(buffer, root_hub_config_des, len);
+ break;
+ case 0x0300: /* string descriptors */
+ switch (wValue & 0xff) {
+ case 0x00:
+ len = min3(txlen, sizeof(root_hub_str_index0),
+ wLength);
+ memcpy(buffer, root_hub_str_index0, len);
+ break;
+ case 0x01:
+ len = min3(txlen, sizeof(root_hub_str_index1),
+ wLength);
+ memcpy(buffer, root_hub_str_index1, len);
+ break;
+ }
+ break;
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case USB_TYPE_CLASS:
+ /* Root port config, set 1 port and nothing else. */
+ dsc = 0x00000001;
+
+ data[0] = 9; /* min length; */
+ data[1] = 0x29;
+ data[2] = dsc & RH_A_NDP;
+ data[3] = 0;
+ if (dsc & RH_A_PSM)
+ data[3] |= 0x1;
+ if (dsc & RH_A_NOCP)
+ data[3] |= 0x10;
+ else if (dsc & RH_A_OCPM)
+ data[3] |= 0x8;
+
+ /* corresponds to data[4-7] */
+ data[5] = (dsc & RH_A_POTPGT) >> 24;
+ data[7] = dsc & RH_B_DR;
+ if (data[2] < 7) {
+ data[8] = 0xff;
+ } else {
+ data[0] += 2;
+ data[8] = (dsc & RH_B_DR) >> 8;
+ data[9] = 0xff;
+ data[10] = data[9];
+ }
+
+ len = min3(txlen, data[0], wLength);
+ memcpy(buffer, data, len);
+ break;
+ default:
+ puts("unsupported root hub command\n");
+ stat = USB_ST_STALLED;
+ }
+
+ dev->act_len = min(len, txlen);
+ dev->status = stat;
+
+ return stat;
+}
+
+/* Direction: In ; Request: Configuration */
+static int dwc_otg_submit_rh_msg_in_configuration(struct usb_device *dev,
+ void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ int len = 0;
+ int stat = 0;
+
+ switch (cmd->requesttype & ~USB_DIR_IN) {
+ case 0:
+ *(uint8_t *)buffer = 0x01;
+ len = 1;
+ break;
+ default:
+ puts("unsupported root hub command\n");
+ stat = USB_ST_STALLED;
+ }
+
+ dev->act_len = min(len, txlen);
+ dev->status = stat;
+
+ return stat;
+}
+
+/* Direction: In */
+static int dwc_otg_submit_rh_msg_in(struct usb_device *dev,
+ void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ switch (cmd->request) {
+ case USB_REQ_GET_STATUS:
+ return dwc_otg_submit_rh_msg_in_status(dev, buffer,
+ txlen, cmd);
+ case USB_REQ_GET_DESCRIPTOR:
+ return dwc_otg_submit_rh_msg_in_descriptor(dev, buffer,
+ txlen, cmd);
+ case USB_REQ_GET_CONFIGURATION:
+ return dwc_otg_submit_rh_msg_in_configuration(dev, buffer,
+ txlen, cmd);
+ default:
+ puts("unsupported root hub command\n");
+ return USB_ST_STALLED;
+ }
+}
+
+/* Direction: Out */
+static int dwc_otg_submit_rh_msg_out(struct usb_device *dev,
+ void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ int len = 0;
+ int stat = 0;
+ uint16_t bmrtype_breq = cmd->requesttype | (cmd->request << 8);
+ uint16_t wValue = cpu_to_le16(cmd->value);
+
+ switch (bmrtype_breq & ~USB_DIR_IN) {
+ case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_ENDPOINT:
+ case (USB_REQ_CLEAR_FEATURE << 8) | USB_TYPE_CLASS:
+ break;
+
+ case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
+ switch (wValue) {
+ case USB_PORT_FEAT_C_CONNECTION:
+ setbits_le32(&regs->hprt0, DWC2_HPRT0_PRTCONNDET);
+ break;
+ }
+ break;
+
+ case (USB_REQ_SET_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
+ switch (wValue) {
+ case USB_PORT_FEAT_SUSPEND:
+ break;
+
+ case USB_PORT_FEAT_RESET:
+ clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
+ DWC2_HPRT0_PRTCONNDET |
+ DWC2_HPRT0_PRTENCHNG |
+ DWC2_HPRT0_PRTOVRCURRCHNG,
+ DWC2_HPRT0_PRTRST);
+ mdelay(50);
+ clrbits_le32(&regs->hprt0, DWC2_HPRT0_PRTRST);
+ break;
+
+ case USB_PORT_FEAT_POWER:
+ clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
+ DWC2_HPRT0_PRTCONNDET |
+ DWC2_HPRT0_PRTENCHNG |
+ DWC2_HPRT0_PRTOVRCURRCHNG,
+ DWC2_HPRT0_PRTRST);
+ break;
+
+ case USB_PORT_FEAT_ENABLE:
+ break;
+ }
+ break;
+ case (USB_REQ_SET_ADDRESS << 8):
+ root_hub_devnum = wValue;
+ break;
+ case (USB_REQ_SET_CONFIGURATION << 8):
+ break;
+ default:
+ puts("unsupported root hub command\n");
+ stat = USB_ST_STALLED;
+ }
+
+ len = min(len, txlen);
+
+ dev->act_len = len;
+ dev->status = stat;
+
+ return stat;
+}
+
+static int dwc_otg_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ int stat = 0;
+
+ if (usb_pipeint(pipe)) {
+ puts("Root-Hub submit IRQ: NOT implemented\n");
+ return 0;
+ }
+
+ if (cmd->requesttype & USB_DIR_IN)
+ stat = dwc_otg_submit_rh_msg_in(dev, buffer, txlen, cmd);
+ else
+ stat = dwc_otg_submit_rh_msg_out(dev, buffer, txlen, cmd);
+
+ mdelay(1);
+
+ return stat;
+}
+
+/* U-Boot USB transmission interface */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len)
+{
+ int devnum = usb_pipedevice(pipe);
+ int ep = usb_pipeendpoint(pipe);
+ int max = usb_maxpacket(dev, pipe);
+ int done = 0;
+ uint32_t hctsiz, sub, tmp;
+ struct dwc2_hc_regs *hc_regs = &regs->hc_regs[DWC2_HC_CHANNEL];
+ uint32_t hcint;
+ uint32_t xfer_len;
+ uint32_t num_packets;
+ int stop_transfer = 0;
+ unsigned int timeout = 1000000;
+
+ if (devnum == root_hub_devnum) {
+ dev->status = 0;
+ return -EINVAL;
+ }
+
+ if (len > DWC2_DATA_BUF_SIZE) {
+ printf("%s: %d is more then available buffer size (%d)\n",
+ __func__, len, DWC2_DATA_BUF_SIZE);
+ dev->status = 0;
+ dev->act_len = 0;
+ return -EINVAL;
+ }
+
+ while ((done < len) && !stop_transfer) {
+ /* Initialize channel */
+ dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, devnum, ep,
+ usb_pipein(pipe), DWC2_HCCHAR_EPTYPE_BULK, max);
+
+ xfer_len = len - done;
+ /* Make sure that xfer_len is a multiple of max packet size. */
+ if (xfer_len > CONFIG_DWC2_MAX_TRANSFER_SIZE)
+ xfer_len = CONFIG_DWC2_MAX_TRANSFER_SIZE - max + 1;
+
+ if (xfer_len > 0) {
+ num_packets = (xfer_len + max - 1) / max;
+ if (num_packets > CONFIG_DWC2_MAX_PACKET_COUNT) {
+ num_packets = CONFIG_DWC2_MAX_PACKET_COUNT;
+ xfer_len = num_packets * max;
+ }
+ } else {
+ num_packets = 1;
+ }
+
+ if (usb_pipein(pipe))
+ xfer_len = num_packets * max;
+
+ writel((xfer_len << DWC2_HCTSIZ_XFERSIZE_OFFSET) |
+ (num_packets << DWC2_HCTSIZ_PKTCNT_OFFSET) |
+ (bulk_data_toggle[devnum][ep] <<
+ DWC2_HCTSIZ_PID_OFFSET),
+ &hc_regs->hctsiz);
+
+ memcpy(aligned_buffer, (char *)buffer + done, len - done);
+ writel((uint32_t)aligned_buffer, &hc_regs->hcdma);
+
+ /* Set host channel enable after all other setup is complete. */
+ clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK |
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS,
+ (1 << DWC2_HCCHAR_MULTICNT_OFFSET) |
+ DWC2_HCCHAR_CHEN);
+
+ while (1) {
+ hcint = readl(&hc_regs->hcint);
+
+ if (!(hcint & DWC2_HCINT_CHHLTD))
+ continue;
+
+ if (hcint & DWC2_HCINT_XFERCOMP) {
+ hctsiz = readl(&hc_regs->hctsiz);
+ done += xfer_len;
+
+ sub = hctsiz & DWC2_HCTSIZ_XFERSIZE_MASK;
+ sub >>= DWC2_HCTSIZ_XFERSIZE_OFFSET;
+
+ if (usb_pipein(pipe)) {
+ done -= sub;
+ if (hctsiz & DWC2_HCTSIZ_XFERSIZE_MASK)
+ stop_transfer = 1;
+ }
+
+ tmp = hctsiz & DWC2_HCTSIZ_PID_MASK;
+ tmp >>= DWC2_HCTSIZ_PID_OFFSET;
+ if (tmp == DWC2_HC_PID_DATA1) {
+ bulk_data_toggle[devnum][ep] =
+ DWC2_HC_PID_DATA1;
+ } else {
+ bulk_data_toggle[devnum][ep] =
+ DWC2_HC_PID_DATA0;
+ }
+ break;
+ }
+
+ if (hcint & DWC2_HCINT_STALL) {
+ puts("DWC OTG: Channel halted\n");
+ bulk_data_toggle[devnum][ep] =
+ DWC2_HC_PID_DATA0;
+
+ stop_transfer = 1;
+ break;
+ }
+
+ if (!--timeout) {
+ printf("%s: Timeout!\n", __func__);
+ break;
+ }
+ }
+ }
+
+ if (done && usb_pipein(pipe))
+ memcpy(buffer, aligned_buffer, done);
+
+ writel(0, &hc_regs->hcintmsk);
+ writel(0xFFFFFFFF, &hc_regs->hcint);
+
+ dev->status = 0;
+ dev->act_len = done;
+
+ return 0;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, struct devrequest *setup)
+{
+ struct dwc2_hc_regs *hc_regs = &regs->hc_regs[DWC2_HC_CHANNEL];
+ int done = 0;
+ int devnum = usb_pipedevice(pipe);
+ int ep = usb_pipeendpoint(pipe);
+ int max = usb_maxpacket(dev, pipe);
+ uint32_t hctsiz = 0, sub, tmp, ret;
+ uint32_t hcint;
+ const uint32_t hcint_comp_hlt_ack = DWC2_HCINT_XFERCOMP |
+ DWC2_HCINT_CHHLTD | DWC2_HCINT_ACK;
+ unsigned int timeout = 1000000;
+
+ /* For CONTROL endpoint pid should start with DATA1 */
+ int status_direction;
+
+ if (devnum == root_hub_devnum) {
+ dev->status = 0;
+ dev->speed = USB_SPEED_HIGH;
+ return dwc_otg_submit_rh_msg(dev, pipe, buffer, len, setup);
+ }
+
+ if (len > DWC2_DATA_BUF_SIZE) {
+ printf("%s: %d is more then available buffer size(%d)\n",
+ __func__, len, DWC2_DATA_BUF_SIZE);
+ dev->status = 0;
+ dev->act_len = 0;
+ return -EINVAL;
+ }
+
+ /* Initialize channel, OUT for setup buffer */
+ dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, devnum, ep, 0,
+ DWC2_HCCHAR_EPTYPE_CONTROL, max);
+
+ /* SETUP stage */
+ writel((8 << DWC2_HCTSIZ_XFERSIZE_OFFSET) |
+ (1 << DWC2_HCTSIZ_PKTCNT_OFFSET) |
+ (DWC2_HC_PID_SETUP << DWC2_HCTSIZ_PID_OFFSET),
+ &hc_regs->hctsiz);
+
+ writel((uint32_t)setup, &hc_regs->hcdma);
+
+ /* Set host channel enable after all other setup is complete. */
+ clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK |
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS,
+ (1 << DWC2_HCCHAR_MULTICNT_OFFSET) | DWC2_HCCHAR_CHEN);
+
+ ret = wait_for_bit(&hc_regs->hcint, DWC2_HCINT_CHHLTD, 1);
+ if (ret)
+ printf("%s: Timeout!\n", __func__);
+
+ hcint = readl(&hc_regs->hcint);
+
+ if (!(hcint & DWC2_HCINT_CHHLTD) || !(hcint & DWC2_HCINT_XFERCOMP)) {
+ printf("%s: Error (HCINT=%08x)\n", __func__, hcint);
+ dev->status = 0;
+ dev->act_len = 0;
+ return -EINVAL;
+ }
+
+ /* Clear interrupts */
+ writel(0, &hc_regs->hcintmsk);
+ writel(0xFFFFFFFF, &hc_regs->hcint);
+
+ if (buffer) {
+ /* DATA stage */
+ dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, devnum, ep,
+ usb_pipein(pipe),
+ DWC2_HCCHAR_EPTYPE_CONTROL, max);
+
+ /* TODO: check if len < 64 */
+ control_data_toggle[devnum][ep] = DWC2_HC_PID_DATA1;
+ writel((len << DWC2_HCTSIZ_XFERSIZE_OFFSET) |
+ (1 << DWC2_HCTSIZ_PKTCNT_OFFSET) |
+ (control_data_toggle[devnum][ep] <<
+ DWC2_HCTSIZ_PID_OFFSET),
+ &hc_regs->hctsiz);
+
+ writel((uint32_t)buffer, &hc_regs->hcdma);
+
+ /* Set host channel enable after all other setup is complete */
+ clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK |
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS,
+ (1 << DWC2_HCCHAR_MULTICNT_OFFSET) |
+ DWC2_HCCHAR_CHEN);
+
+ while (1) {
+ hcint = readl(&hc_regs->hcint);
+ if (!(hcint & DWC2_HCINT_CHHLTD))
+ continue;
+
+ if (hcint & DWC2_HCINT_XFERCOMP) {
+ hctsiz = readl(&hc_regs->hctsiz);
+ done = len;
+
+ sub = hctsiz & DWC2_HCTSIZ_XFERSIZE_MASK;
+ sub >>= DWC2_HCTSIZ_XFERSIZE_OFFSET;
+
+ if (usb_pipein(pipe))
+ done -= sub;
+ }
+
+ if (hcint & DWC2_HCINT_ACK) {
+ tmp = hctsiz & DWC2_HCTSIZ_PID_MASK;
+ tmp >>= DWC2_HCTSIZ_PID_OFFSET;
+ if (tmp == DWC2_HC_PID_DATA0) {
+ control_data_toggle[devnum][ep] =
+ DWC2_HC_PID_DATA0;
+ } else {
+ control_data_toggle[devnum][ep] =
+ DWC2_HC_PID_DATA1;
+ }
+ }
+
+ if (hcint != hcint_comp_hlt_ack) {
+ printf("%s: Error (HCINT=%08x)\n",
+ __func__, hcint);
+ goto out;
+ }
+
+ if (!--timeout) {
+ printf("%s: Timeout!\n", __func__);
+ goto out;
+ }
+
+ break;
+ }
+ } /* End of DATA stage */
+
+ /* STATUS stage */
+ if ((len == 0) || usb_pipeout(pipe))
+ status_direction = 1;
+ else
+ status_direction = 0;
+
+ dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, devnum, ep,
+ status_direction, DWC2_HCCHAR_EPTYPE_CONTROL, max);
+
+ writel((1 << DWC2_HCTSIZ_PKTCNT_OFFSET) |
+ (DWC2_HC_PID_DATA1 << DWC2_HCTSIZ_PID_OFFSET),
+ &hc_regs->hctsiz);
+
+ writel((uint32_t)status_buffer, &hc_regs->hcdma);
+
+ /* Set host channel enable after all other setup is complete. */
+ clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK |
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS,
+ (1 << DWC2_HCCHAR_MULTICNT_OFFSET) | DWC2_HCCHAR_CHEN);
+
+ while (1) {
+ hcint = readl(&hc_regs->hcint);
+ if (hcint & DWC2_HCINT_CHHLTD)
+ break;
+ }
+
+ if (hcint != hcint_comp_hlt_ack)
+ printf("%s: Error (HCINT=%08x)\n", __func__, hcint);
+
+out:
+ dev->act_len = done;
+ dev->status = 0;
+
+ return done;
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, int interval)
+{
+ printf("dev = %p pipe = %#lx buf = %p size = %d int = %d\n",
+ dev, pipe, buffer, len, interval);
+ return -ENOSYS;
+}
+
+/* U-Boot USB control interface */
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+{
+ uint32_t snpsid;
+ int i, j;
+
+ root_hub_devnum = 0;
+
+ snpsid = readl(&regs->gsnpsid);
+ printf("Core Release: %x.%03x\n", snpsid >> 12 & 0xf, snpsid & 0xfff);
+
+ if ((snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_2xx) {
+ printf("SNPSID invalid (not DWC2 OTG device): %08x\n", snpsid);
+ return -ENODEV;
+ }
+
+ dwc_otg_core_init(regs);
+ dwc_otg_core_host_init(regs);
+
+ clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
+ DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG |
+ DWC2_HPRT0_PRTOVRCURRCHNG,
+ DWC2_HPRT0_PRTRST);
+ mdelay(50);
+ clrbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET |
+ DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG |
+ DWC2_HPRT0_PRTRST);
+
+ for (i = 0; i < MAX_DEVICE; i++) {
+ for (j = 0; j < MAX_ENDPOINT; j++) {
+ control_data_toggle[i][j] = DWC2_HC_PID_DATA1;
+ bulk_data_toggle[i][j] = DWC2_HC_PID_DATA0;
+ }
+ }
+
+ return 0;
+}
+
+int usb_lowlevel_stop(int index)
+{
+ /* Put everything in reset. */
+ clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
+ DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG |
+ DWC2_HPRT0_PRTOVRCURRCHNG,
+ DWC2_HPRT0_PRTRST);
+ return 0;
+}
diff --git a/drivers/usb/host/dwc2.h b/drivers/usb/host/dwc2.h
new file mode 100644
index 0000000000..ba08fd554f
--- /dev/null
+++ b/drivers/usb/host/dwc2.h
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __DWC2_H__
+#define __DWC2_H__
+
+struct dwc2_hc_regs {
+ u32 hcchar; /* 0x00 */
+ u32 hcsplt;
+ u32 hcint;
+ u32 hcintmsk;
+ u32 hctsiz; /* 0x10 */
+ u32 hcdma;
+ u32 reserved;
+ u32 hcdmab;
+};
+
+struct dwc2_host_regs {
+ u32 hcfg; /* 0x00 */
+ u32 hfir;
+ u32 hfnum;
+ u32 _pad_0x40c;
+ u32 hptxsts; /* 0x10 */
+ u32 haint;
+ u32 haintmsk;
+ u32 hflbaddr;
+};
+
+struct dwc2_core_regs {
+ u32 gotgctl; /* 0x000 */
+ u32 gotgint;
+ u32 gahbcfg;
+ u32 gusbcfg;
+ u32 grstctl; /* 0x010 */
+ u32 gintsts;
+ u32 gintmsk;
+ u32 grxstsr;
+ u32 grxstsp; /* 0x020 */
+ u32 grxfsiz;
+ u32 gnptxfsiz;
+ u32 gnptxsts;
+ u32 gi2cctl; /* 0x030 */
+ u32 gpvndctl;
+ u32 ggpio;
+ u32 guid;
+ u32 gsnpsid; /* 0x040 */
+ u32 ghwcfg1;
+ u32 ghwcfg2;
+ u32 ghwcfg3;
+ u32 ghwcfg4; /* 0x050 */
+ u32 glpmcfg;
+ u32 _pad_0x58_0x9c[42];
+ u32 hptxfsiz; /* 0x100 */
+ u32 dptxfsiz_dieptxf[15];
+ u32 _pad_0x140_0x3fc[176];
+ struct dwc2_host_regs host_regs; /* 0x400 */
+ u32 _pad_0x420_0x43c[8];
+ u32 hprt0; /* 0x440 */
+ u32 _pad_0x444_0x4fc[47];
+ struct dwc2_hc_regs hc_regs[16]; /* 0x500 */
+ u32 _pad_0x700_0xe00[448];
+ u32 pcgcctl; /* 0xe00 */
+};
+
+#define DWC2_GOTGCTL_SESREQSCS (1 << 0)
+#define DWC2_GOTGCTL_SESREQSCS_OFFSET 0
+#define DWC2_GOTGCTL_SESREQ (1 << 1)
+#define DWC2_GOTGCTL_SESREQ_OFFSET 1
+#define DWC2_GOTGCTL_HSTNEGSCS (1 << 8)
+#define DWC2_GOTGCTL_HSTNEGSCS_OFFSET 8
+#define DWC2_GOTGCTL_HNPREQ (1 << 9)
+#define DWC2_GOTGCTL_HNPREQ_OFFSET 9
+#define DWC2_GOTGCTL_HSTSETHNPEN (1 << 10)
+#define DWC2_GOTGCTL_HSTSETHNPEN_OFFSET 10
+#define DWC2_GOTGCTL_DEVHNPEN (1 << 11)
+#define DWC2_GOTGCTL_DEVHNPEN_OFFSET 11
+#define DWC2_GOTGCTL_CONIDSTS (1 << 16)
+#define DWC2_GOTGCTL_CONIDSTS_OFFSET 16
+#define DWC2_GOTGCTL_DBNCTIME (1 << 17)
+#define DWC2_GOTGCTL_DBNCTIME_OFFSET 17
+#define DWC2_GOTGCTL_ASESVLD (1 << 18)
+#define DWC2_GOTGCTL_ASESVLD_OFFSET 18
+#define DWC2_GOTGCTL_BSESVLD (1 << 19)
+#define DWC2_GOTGCTL_BSESVLD_OFFSET 19
+#define DWC2_GOTGCTL_OTGVER (1 << 20)
+#define DWC2_GOTGCTL_OTGVER_OFFSET 20
+#define DWC2_GOTGINT_SESENDDET (1 << 2)
+#define DWC2_GOTGINT_SESENDDET_OFFSET 2
+#define DWC2_GOTGINT_SESREQSUCSTSCHNG (1 << 8)
+#define DWC2_GOTGINT_SESREQSUCSTSCHNG_OFFSET 8
+#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG (1 << 9)
+#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG_OFFSET 9
+#define DWC2_GOTGINT_RESERVER10_16_MASK (0x7F << 10)
+#define DWC2_GOTGINT_RESERVER10_16_OFFSET 10
+#define DWC2_GOTGINT_HSTNEGDET (1 << 17)
+#define DWC2_GOTGINT_HSTNEGDET_OFFSET 17
+#define DWC2_GOTGINT_ADEVTOUTCHNG (1 << 18)
+#define DWC2_GOTGINT_ADEVTOUTCHNG_OFFSET 18
+#define DWC2_GOTGINT_DEBDONE (1 << 19)
+#define DWC2_GOTGINT_DEBDONE_OFFSET 19
+#define DWC2_GAHBCFG_GLBLINTRMSK (1 << 0)
+#define DWC2_GAHBCFG_GLBLINTRMSK_OFFSET 0
+#define DWC2_GAHBCFG_HBURSTLEN_SINGLE (0 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_INCR (1 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_INCR4 (3 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_INCR8 (5 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_INCR16 (7 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_MASK (0xF << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_OFFSET 1
+#define DWC2_GAHBCFG_DMAENABLE (1 << 5)
+#define DWC2_GAHBCFG_DMAENABLE_OFFSET 5
+#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL (1 << 7)
+#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL_OFFSET 7
+#define DWC2_GAHBCFG_PTXFEMPLVL (1 << 8)
+#define DWC2_GAHBCFG_PTXFEMPLVL_OFFSET 8
+#define DWC2_GUSBCFG_TOUTCAL_MASK (0x7 << 0)
+#define DWC2_GUSBCFG_TOUTCAL_OFFSET 0
+#define DWC2_GUSBCFG_PHYIF (1 << 3)
+#define DWC2_GUSBCFG_PHYIF_OFFSET 3
+#define DWC2_GUSBCFG_ULPI_UTMI_SEL (1 << 4)
+#define DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET 4
+#define DWC2_GUSBCFG_FSINTF (1 << 5)
+#define DWC2_GUSBCFG_FSINTF_OFFSET 5
+#define DWC2_GUSBCFG_PHYSEL (1 << 6)
+#define DWC2_GUSBCFG_PHYSEL_OFFSET 6
+#define DWC2_GUSBCFG_DDRSEL (1 << 7)
+#define DWC2_GUSBCFG_DDRSEL_OFFSET 7
+#define DWC2_GUSBCFG_SRPCAP (1 << 8)
+#define DWC2_GUSBCFG_SRPCAP_OFFSET 8
+#define DWC2_GUSBCFG_HNPCAP (1 << 9)
+#define DWC2_GUSBCFG_HNPCAP_OFFSET 9
+#define DWC2_GUSBCFG_USBTRDTIM_MASK (0xF << 10)
+#define DWC2_GUSBCFG_USBTRDTIM_OFFSET 10
+#define DWC2_GUSBCFG_NPTXFRWNDEN (1 << 14)
+#define DWC2_GUSBCFG_NPTXFRWNDEN_OFFSET 14
+#define DWC2_GUSBCFG_PHYLPWRCLKSEL (1 << 15)
+#define DWC2_GUSBCFG_PHYLPWRCLKSEL_OFFSET 15
+#define DWC2_GUSBCFG_OTGUTMIFSSEL (1 << 16)
+#define DWC2_GUSBCFG_OTGUTMIFSSEL_OFFSET 16
+#define DWC2_GUSBCFG_ULPI_FSLS (1 << 17)
+#define DWC2_GUSBCFG_ULPI_FSLS_OFFSET 17
+#define DWC2_GUSBCFG_ULPI_AUTO_RES (1 << 18)
+#define DWC2_GUSBCFG_ULPI_AUTO_RES_OFFSET 18
+#define DWC2_GUSBCFG_ULPI_CLK_SUS_M (1 << 19)
+#define DWC2_GUSBCFG_ULPI_CLK_SUS_M_OFFSET 19
+#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV (1 << 20)
+#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV_OFFSET 20
+#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR (1 << 21)
+#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR_OFFSET 21
+#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE (1 << 22)
+#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE_OFFSET 22
+#define DWC2_GUSBCFG_IC_USB_CAP (1 << 26)
+#define DWC2_GUSBCFG_IC_USB_CAP_OFFSET 26
+#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE (1 << 27)
+#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE_OFFSET 27
+#define DWC2_GUSBCFG_TX_END_DELAY (1 << 28)
+#define DWC2_GUSBCFG_TX_END_DELAY_OFFSET 28
+#define DWC2_GUSBCFG_FORCEHOSTMODE (1 << 29)
+#define DWC2_GUSBCFG_FORCEHOSTMODE_OFFSET 29
+#define DWC2_GUSBCFG_FORCEDEVMODE (1 << 30)
+#define DWC2_GUSBCFG_FORCEDEVMODE_OFFSET 30
+#define DWC2_GLPMCTL_LPM_CAP_EN (1 << 0)
+#define DWC2_GLPMCTL_LPM_CAP_EN_OFFSET 0
+#define DWC2_GLPMCTL_APPL_RESP (1 << 1)
+#define DWC2_GLPMCTL_APPL_RESP_OFFSET 1
+#define DWC2_GLPMCTL_HIRD_MASK (0xF << 2)
+#define DWC2_GLPMCTL_HIRD_OFFSET 2
+#define DWC2_GLPMCTL_REM_WKUP_EN (1 << 6)
+#define DWC2_GLPMCTL_REM_WKUP_EN_OFFSET 6
+#define DWC2_GLPMCTL_EN_UTMI_SLEEP (1 << 7)
+#define DWC2_GLPMCTL_EN_UTMI_SLEEP_OFFSET 7
+#define DWC2_GLPMCTL_HIRD_THRES_MASK (0x1F << 8)
+#define DWC2_GLPMCTL_HIRD_THRES_OFFSET 8
+#define DWC2_GLPMCTL_LPM_RESP_MASK (0x3 << 13)
+#define DWC2_GLPMCTL_LPM_RESP_OFFSET 13
+#define DWC2_GLPMCTL_PRT_SLEEP_STS (1 << 15)
+#define DWC2_GLPMCTL_PRT_SLEEP_STS_OFFSET 15
+#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK (1 << 16)
+#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK_OFFSET 16
+#define DWC2_GLPMCTL_LPM_CHAN_INDEX_MASK (0xF << 17)
+#define DWC2_GLPMCTL_LPM_CHAN_INDEX_OFFSET 17
+#define DWC2_GLPMCTL_RETRY_COUNT_MASK (0x7 << 21)
+#define DWC2_GLPMCTL_RETRY_COUNT_OFFSET 21
+#define DWC2_GLPMCTL_SEND_LPM (1 << 24)
+#define DWC2_GLPMCTL_SEND_LPM_OFFSET 24
+#define DWC2_GLPMCTL_RETRY_COUNT_STS_MASK (0x7 << 25)
+#define DWC2_GLPMCTL_RETRY_COUNT_STS_OFFSET 25
+#define DWC2_GLPMCTL_HSIC_CONNECT (1 << 30)
+#define DWC2_GLPMCTL_HSIC_CONNECT_OFFSET 30
+#define DWC2_GLPMCTL_INV_SEL_HSIC (1 << 31)
+#define DWC2_GLPMCTL_INV_SEL_HSIC_OFFSET 31
+#define DWC2_GRSTCTL_CSFTRST (1 << 0)
+#define DWC2_GRSTCTL_CSFTRST_OFFSET 0
+#define DWC2_GRSTCTL_HSFTRST (1 << 1)
+#define DWC2_GRSTCTL_HSFTRST_OFFSET 1
+#define DWC2_GRSTCTL_HSTFRM (1 << 2)
+#define DWC2_GRSTCTL_HSTFRM_OFFSET 2
+#define DWC2_GRSTCTL_INTKNQFLSH (1 << 3)
+#define DWC2_GRSTCTL_INTKNQFLSH_OFFSET 3
+#define DWC2_GRSTCTL_RXFFLSH (1 << 4)
+#define DWC2_GRSTCTL_RXFFLSH_OFFSET 4
+#define DWC2_GRSTCTL_TXFFLSH (1 << 5)
+#define DWC2_GRSTCTL_TXFFLSH_OFFSET 5
+#define DWC2_GRSTCTL_TXFNUM_MASK (0x1F << 6)
+#define DWC2_GRSTCTL_TXFNUM_OFFSET 6
+#define DWC2_GRSTCTL_DMAREQ (1 << 30)
+#define DWC2_GRSTCTL_DMAREQ_OFFSET 30
+#define DWC2_GRSTCTL_AHBIDLE (1 << 31)
+#define DWC2_GRSTCTL_AHBIDLE_OFFSET 31
+#define DWC2_GINTMSK_MODEMISMATCH (1 << 1)
+#define DWC2_GINTMSK_MODEMISMATCH_OFFSET 1
+#define DWC2_GINTMSK_OTGINTR (1 << 2)
+#define DWC2_GINTMSK_OTGINTR_OFFSET 2
+#define DWC2_GINTMSK_SOFINTR (1 << 3)
+#define DWC2_GINTMSK_SOFINTR_OFFSET 3
+#define DWC2_GINTMSK_RXSTSQLVL (1 << 4)
+#define DWC2_GINTMSK_RXSTSQLVL_OFFSET 4
+#define DWC2_GINTMSK_NPTXFEMPTY (1 << 5)
+#define DWC2_GINTMSK_NPTXFEMPTY_OFFSET 5
+#define DWC2_GINTMSK_GINNAKEFF (1 << 6)
+#define DWC2_GINTMSK_GINNAKEFF_OFFSET 6
+#define DWC2_GINTMSK_GOUTNAKEFF (1 << 7)
+#define DWC2_GINTMSK_GOUTNAKEFF_OFFSET 7
+#define DWC2_GINTMSK_I2CINTR (1 << 9)
+#define DWC2_GINTMSK_I2CINTR_OFFSET 9
+#define DWC2_GINTMSK_ERLYSUSPEND (1 << 10)
+#define DWC2_GINTMSK_ERLYSUSPEND_OFFSET 10
+#define DWC2_GINTMSK_USBSUSPEND (1 << 11)
+#define DWC2_GINTMSK_USBSUSPEND_OFFSET 11
+#define DWC2_GINTMSK_USBRESET (1 << 12)
+#define DWC2_GINTMSK_USBRESET_OFFSET 12
+#define DWC2_GINTMSK_ENUMDONE (1 << 13)
+#define DWC2_GINTMSK_ENUMDONE_OFFSET 13
+#define DWC2_GINTMSK_ISOOUTDROP (1 << 14)
+#define DWC2_GINTMSK_ISOOUTDROP_OFFSET 14
+#define DWC2_GINTMSK_EOPFRAME (1 << 15)
+#define DWC2_GINTMSK_EOPFRAME_OFFSET 15
+#define DWC2_GINTMSK_EPMISMATCH (1 << 17)
+#define DWC2_GINTMSK_EPMISMATCH_OFFSET 17
+#define DWC2_GINTMSK_INEPINTR (1 << 18)
+#define DWC2_GINTMSK_INEPINTR_OFFSET 18
+#define DWC2_GINTMSK_OUTEPINTR (1 << 19)
+#define DWC2_GINTMSK_OUTEPINTR_OFFSET 19
+#define DWC2_GINTMSK_INCOMPLISOIN (1 << 20)
+#define DWC2_GINTMSK_INCOMPLISOIN_OFFSET 20
+#define DWC2_GINTMSK_INCOMPLISOOUT (1 << 21)
+#define DWC2_GINTMSK_INCOMPLISOOUT_OFFSET 21
+#define DWC2_GINTMSK_PORTINTR (1 << 24)
+#define DWC2_GINTMSK_PORTINTR_OFFSET 24
+#define DWC2_GINTMSK_HCINTR (1 << 25)
+#define DWC2_GINTMSK_HCINTR_OFFSET 25
+#define DWC2_GINTMSK_PTXFEMPTY (1 << 26)
+#define DWC2_GINTMSK_PTXFEMPTY_OFFSET 26
+#define DWC2_GINTMSK_LPMTRANRCVD (1 << 27)
+#define DWC2_GINTMSK_LPMTRANRCVD_OFFSET 27
+#define DWC2_GINTMSK_CONIDSTSCHNG (1 << 28)
+#define DWC2_GINTMSK_CONIDSTSCHNG_OFFSET 28
+#define DWC2_GINTMSK_DISCONNECT (1 << 29)
+#define DWC2_GINTMSK_DISCONNECT_OFFSET 29
+#define DWC2_GINTMSK_SESSREQINTR (1 << 30)
+#define DWC2_GINTMSK_SESSREQINTR_OFFSET 30
+#define DWC2_GINTMSK_WKUPINTR (1 << 31)
+#define DWC2_GINTMSK_WKUPINTR_OFFSET 31
+#define DWC2_GINTSTS_CURMODE_DEVICE (0 << 0)
+#define DWC2_GINTSTS_CURMODE_HOST (1 << 0)
+#define DWC2_GINTSTS_CURMODE (1 << 0)
+#define DWC2_GINTSTS_CURMODE_OFFSET 0
+#define DWC2_GINTSTS_MODEMISMATCH (1 << 1)
+#define DWC2_GINTSTS_MODEMISMATCH_OFFSET 1
+#define DWC2_GINTSTS_OTGINTR (1 << 2)
+#define DWC2_GINTSTS_OTGINTR_OFFSET 2
+#define DWC2_GINTSTS_SOFINTR (1 << 3)
+#define DWC2_GINTSTS_SOFINTR_OFFSET 3
+#define DWC2_GINTSTS_RXSTSQLVL (1 << 4)
+#define DWC2_GINTSTS_RXSTSQLVL_OFFSET 4
+#define DWC2_GINTSTS_NPTXFEMPTY (1 << 5)
+#define DWC2_GINTSTS_NPTXFEMPTY_OFFSET 5
+#define DWC2_GINTSTS_GINNAKEFF (1 << 6)
+#define DWC2_GINTSTS_GINNAKEFF_OFFSET 6
+#define DWC2_GINTSTS_GOUTNAKEFF (1 << 7)
+#define DWC2_GINTSTS_GOUTNAKEFF_OFFSET 7
+#define DWC2_GINTSTS_I2CINTR (1 << 9)
+#define DWC2_GINTSTS_I2CINTR_OFFSET 9
+#define DWC2_GINTSTS_ERLYSUSPEND (1 << 10)
+#define DWC2_GINTSTS_ERLYSUSPEND_OFFSET 10
+#define DWC2_GINTSTS_USBSUSPEND (1 << 11)
+#define DWC2_GINTSTS_USBSUSPEND_OFFSET 11
+#define DWC2_GINTSTS_USBRESET (1 << 12)
+#define DWC2_GINTSTS_USBRESET_OFFSET 12
+#define DWC2_GINTSTS_ENUMDONE (1 << 13)
+#define DWC2_GINTSTS_ENUMDONE_OFFSET 13
+#define DWC2_GINTSTS_ISOOUTDROP (1 << 14)
+#define DWC2_GINTSTS_ISOOUTDROP_OFFSET 14
+#define DWC2_GINTSTS_EOPFRAME (1 << 15)
+#define DWC2_GINTSTS_EOPFRAME_OFFSET 15
+#define DWC2_GINTSTS_INTOKENRX (1 << 16)
+#define DWC2_GINTSTS_INTOKENRX_OFFSET 16
+#define DWC2_GINTSTS_EPMISMATCH (1 << 17)
+#define DWC2_GINTSTS_EPMISMATCH_OFFSET 17
+#define DWC2_GINTSTS_INEPINT (1 << 18)
+#define DWC2_GINTSTS_INEPINT_OFFSET 18
+#define DWC2_GINTSTS_OUTEPINTR (1 << 19)
+#define DWC2_GINTSTS_OUTEPINTR_OFFSET 19
+#define DWC2_GINTSTS_INCOMPLISOIN (1 << 20)
+#define DWC2_GINTSTS_INCOMPLISOIN_OFFSET 20
+#define DWC2_GINTSTS_INCOMPLISOOUT (1 << 21)
+#define DWC2_GINTSTS_INCOMPLISOOUT_OFFSET 21
+#define DWC2_GINTSTS_PORTINTR (1 << 24)
+#define DWC2_GINTSTS_PORTINTR_OFFSET 24
+#define DWC2_GINTSTS_HCINTR (1 << 25)
+#define DWC2_GINTSTS_HCINTR_OFFSET 25
+#define DWC2_GINTSTS_PTXFEMPTY (1 << 26)
+#define DWC2_GINTSTS_PTXFEMPTY_OFFSET 26
+#define DWC2_GINTSTS_LPMTRANRCVD (1 << 27)
+#define DWC2_GINTSTS_LPMTRANRCVD_OFFSET 27
+#define DWC2_GINTSTS_CONIDSTSCHNG (1 << 28)
+#define DWC2_GINTSTS_CONIDSTSCHNG_OFFSET 28
+#define DWC2_GINTSTS_DISCONNECT (1 << 29)
+#define DWC2_GINTSTS_DISCONNECT_OFFSET 29
+#define DWC2_GINTSTS_SESSREQINTR (1 << 30)
+#define DWC2_GINTSTS_SESSREQINTR_OFFSET 30
+#define DWC2_GINTSTS_WKUPINTR (1 << 31)
+#define DWC2_GINTSTS_WKUPINTR_OFFSET 31
+#define DWC2_GRXSTS_EPNUM_MASK (0xF << 0)
+#define DWC2_GRXSTS_EPNUM_OFFSET 0
+#define DWC2_GRXSTS_BCNT_MASK (0x7FF << 4)
+#define DWC2_GRXSTS_BCNT_OFFSET 4
+#define DWC2_GRXSTS_DPID_MASK (0x3 << 15)
+#define DWC2_GRXSTS_DPID_OFFSET 15
+#define DWC2_GRXSTS_PKTSTS_MASK (0xF << 17)
+#define DWC2_GRXSTS_PKTSTS_OFFSET 17
+#define DWC2_GRXSTS_FN_MASK (0xF << 21)
+#define DWC2_GRXSTS_FN_OFFSET 21
+#define DWC2_FIFOSIZE_STARTADDR_MASK (0xFFFF << 0)
+#define DWC2_FIFOSIZE_STARTADDR_OFFSET 0
+#define DWC2_FIFOSIZE_DEPTH_MASK (0xFFFF << 16)
+#define DWC2_FIFOSIZE_DEPTH_OFFSET 16
+#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_MASK (0xFFFF << 0)
+#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_OFFSET 0
+#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_MASK (0xFF << 16)
+#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_OFFSET 16
+#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE (1 << 24)
+#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE_OFFSET 24
+#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_MASK (0x3 << 25)
+#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_OFFSET 25
+#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_MASK (0xF << 27)
+#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_OFFSET 27
+#define DWC2_DTXFSTS_TXFSPCAVAIL_MASK (0xFFFF << 0)
+#define DWC2_DTXFSTS_TXFSPCAVAIL_OFFSET 0
+#define DWC2_GI2CCTL_RWDATA_MASK (0xFF << 0)
+#define DWC2_GI2CCTL_RWDATA_OFFSET 0
+#define DWC2_GI2CCTL_REGADDR_MASK (0xFF << 8)
+#define DWC2_GI2CCTL_REGADDR_OFFSET 8
+#define DWC2_GI2CCTL_ADDR_MASK (0x7F << 16)
+#define DWC2_GI2CCTL_ADDR_OFFSET 16
+#define DWC2_GI2CCTL_I2CEN (1 << 23)
+#define DWC2_GI2CCTL_I2CEN_OFFSET 23
+#define DWC2_GI2CCTL_ACK (1 << 24)
+#define DWC2_GI2CCTL_ACK_OFFSET 24
+#define DWC2_GI2CCTL_I2CSUSPCTL (1 << 25)
+#define DWC2_GI2CCTL_I2CSUSPCTL_OFFSET 25
+#define DWC2_GI2CCTL_I2CDEVADDR_MASK (0x3 << 26)
+#define DWC2_GI2CCTL_I2CDEVADDR_OFFSET 26
+#define DWC2_GI2CCTL_RW (1 << 30)
+#define DWC2_GI2CCTL_RW_OFFSET 30
+#define DWC2_GI2CCTL_BSYDNE (1 << 31)
+#define DWC2_GI2CCTL_BSYDNE_OFFSET 31
+#define DWC2_HWCFG1_EP_DIR0_MASK (0x3 << 0)
+#define DWC2_HWCFG1_EP_DIR0_OFFSET 0
+#define DWC2_HWCFG1_EP_DIR1_MASK (0x3 << 2)
+#define DWC2_HWCFG1_EP_DIR1_OFFSET 2
+#define DWC2_HWCFG1_EP_DIR2_MASK (0x3 << 4)
+#define DWC2_HWCFG1_EP_DIR2_OFFSET 4
+#define DWC2_HWCFG1_EP_DIR3_MASK (0x3 << 6)
+#define DWC2_HWCFG1_EP_DIR3_OFFSET 6
+#define DWC2_HWCFG1_EP_DIR4_MASK (0x3 << 8)
+#define DWC2_HWCFG1_EP_DIR4_OFFSET 8
+#define DWC2_HWCFG1_EP_DIR5_MASK (0x3 << 10)
+#define DWC2_HWCFG1_EP_DIR5_OFFSET 10
+#define DWC2_HWCFG1_EP_DIR6_MASK (0x3 << 12)
+#define DWC2_HWCFG1_EP_DIR6_OFFSET 12
+#define DWC2_HWCFG1_EP_DIR7_MASK (0x3 << 14)
+#define DWC2_HWCFG1_EP_DIR7_OFFSET 14
+#define DWC2_HWCFG1_EP_DIR8_MASK (0x3 << 16)
+#define DWC2_HWCFG1_EP_DIR8_OFFSET 16
+#define DWC2_HWCFG1_EP_DIR9_MASK (0x3 << 18)
+#define DWC2_HWCFG1_EP_DIR9_OFFSET 18
+#define DWC2_HWCFG1_EP_DIR10_MASK (0x3 << 20)
+#define DWC2_HWCFG1_EP_DIR10_OFFSET 20
+#define DWC2_HWCFG1_EP_DIR11_MASK (0x3 << 22)
+#define DWC2_HWCFG1_EP_DIR11_OFFSET 22
+#define DWC2_HWCFG1_EP_DIR12_MASK (0x3 << 24)
+#define DWC2_HWCFG1_EP_DIR12_OFFSET 24
+#define DWC2_HWCFG1_EP_DIR13_MASK (0x3 << 26)
+#define DWC2_HWCFG1_EP_DIR13_OFFSET 26
+#define DWC2_HWCFG1_EP_DIR14_MASK (0x3 << 28)
+#define DWC2_HWCFG1_EP_DIR14_OFFSET 28
+#define DWC2_HWCFG1_EP_DIR15_MASK (0x3 << 30)
+#define DWC2_HWCFG1_EP_DIR15_OFFSET 30
+#define DWC2_HWCFG2_OP_MODE_MASK (0x7 << 0)
+#define DWC2_HWCFG2_OP_MODE_OFFSET 0
+#define DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY (0x0 << 3)
+#define DWC2_HWCFG2_ARCHITECTURE_EXT_DMA (0x1 << 3)
+#define DWC2_HWCFG2_ARCHITECTURE_INT_DMA (0x2 << 3)
+#define DWC2_HWCFG2_ARCHITECTURE_MASK (0x3 << 3)
+#define DWC2_HWCFG2_ARCHITECTURE_OFFSET 3
+#define DWC2_HWCFG2_POINT2POINT (1 << 5)
+#define DWC2_HWCFG2_POINT2POINT_OFFSET 5
+#define DWC2_HWCFG2_HS_PHY_TYPE_MASK (0x3 << 6)
+#define DWC2_HWCFG2_HS_PHY_TYPE_OFFSET 6
+#define DWC2_HWCFG2_FS_PHY_TYPE_MASK (0x3 << 8)
+#define DWC2_HWCFG2_FS_PHY_TYPE_OFFSET 8
+#define DWC2_HWCFG2_NUM_DEV_EP_MASK (0xF << 10)
+#define DWC2_HWCFG2_NUM_DEV_EP_OFFSET 10
+#define DWC2_HWCFG2_NUM_HOST_CHAN_MASK (0xF << 14)
+#define DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET 14
+#define DWC2_HWCFG2_PERIO_EP_SUPPORTED (1 << 18)
+#define DWC2_HWCFG2_PERIO_EP_SUPPORTED_OFFSET 18
+#define DWC2_HWCFG2_DYNAMIC_FIFO (1 << 19)
+#define DWC2_HWCFG2_DYNAMIC_FIFO_OFFSET 19
+#define DWC2_HWCFG2_MULTI_PROC_INT (1 << 20)
+#define DWC2_HWCFG2_MULTI_PROC_INT_OFFSET 20
+#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22)
+#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_OFFSET 22
+#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24)
+#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_OFFSET 24
+#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1F << 26)
+#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_OFFSET 26
+#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xF << 0)
+#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_OFFSET 0
+#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4)
+#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_OFFSET 4
+#define DWC2_HWCFG3_OTG_FUNC (1 << 7)
+#define DWC2_HWCFG3_OTG_FUNC_OFFSET 7
+#define DWC2_HWCFG3_I2C (1 << 8)
+#define DWC2_HWCFG3_I2C_OFFSET 8
+#define DWC2_HWCFG3_VENDOR_CTRL_IF (1 << 9)
+#define DWC2_HWCFG3_VENDOR_CTRL_IF_OFFSET 9
+#define DWC2_HWCFG3_OPTIONAL_FEATURES (1 << 10)
+#define DWC2_HWCFG3_OPTIONAL_FEATURES_OFFSET 10
+#define DWC2_HWCFG3_SYNCH_RESET_TYPE (1 << 11)
+#define DWC2_HWCFG3_SYNCH_RESET_TYPE_OFFSET 11
+#define DWC2_HWCFG3_OTG_ENABLE_IC_USB (1 << 12)
+#define DWC2_HWCFG3_OTG_ENABLE_IC_USB_OFFSET 12
+#define DWC2_HWCFG3_OTG_ENABLE_HSIC (1 << 13)
+#define DWC2_HWCFG3_OTG_ENABLE_HSIC_OFFSET 13
+#define DWC2_HWCFG3_OTG_LPM_EN (1 << 15)
+#define DWC2_HWCFG3_OTG_LPM_EN_OFFSET 15
+#define DWC2_HWCFG3_DFIFO_DEPTH_MASK (0xFFFF << 16)
+#define DWC2_HWCFG3_DFIFO_DEPTH_OFFSET 16
+#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xF << 0)
+#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_OFFSET 0
+#define DWC2_HWCFG4_POWER_OPTIMIZ (1 << 4)
+#define DWC2_HWCFG4_POWER_OPTIMIZ_OFFSET 4
+#define DWC2_HWCFG4_MIN_AHB_FREQ_MASK (0x1FF << 5)
+#define DWC2_HWCFG4_MIN_AHB_FREQ_OFFSET 5
+#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14)
+#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_OFFSET 14
+#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xF << 16)
+#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_OFFSET 16
+#define DWC2_HWCFG4_IDDIG_FILT_EN (1 << 20)
+#define DWC2_HWCFG4_IDDIG_FILT_EN_OFFSET 20
+#define DWC2_HWCFG4_VBUS_VALID_FILT_EN (1 << 21)
+#define DWC2_HWCFG4_VBUS_VALID_FILT_EN_OFFSET 21
+#define DWC2_HWCFG4_A_VALID_FILT_EN (1 << 22)
+#define DWC2_HWCFG4_A_VALID_FILT_EN_OFFSET 22
+#define DWC2_HWCFG4_B_VALID_FILT_EN (1 << 23)
+#define DWC2_HWCFG4_B_VALID_FILT_EN_OFFSET 23
+#define DWC2_HWCFG4_SESSION_END_FILT_EN (1 << 24)
+#define DWC2_HWCFG4_SESSION_END_FILT_EN_OFFSET 24
+#define DWC2_HWCFG4_DED_FIFO_EN (1 << 25)
+#define DWC2_HWCFG4_DED_FIFO_EN_OFFSET 25
+#define DWC2_HWCFG4_NUM_IN_EPS_MASK (0xF << 26)
+#define DWC2_HWCFG4_NUM_IN_EPS_OFFSET 26
+#define DWC2_HWCFG4_DESC_DMA (1 << 30)
+#define DWC2_HWCFG4_DESC_DMA_OFFSET 30
+#define DWC2_HWCFG4_DESC_DMA_DYN (1 << 31)
+#define DWC2_HWCFG4_DESC_DMA_DYN_OFFSET 31
+#define DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ 0
+#define DWC2_HCFG_FSLSPCLKSEL_48_MHZ 1
+#define DWC2_HCFG_FSLSPCLKSEL_6_MHZ 2
+#define DWC2_HCFG_FSLSPCLKSEL_MASK (0x3 << 0)
+#define DWC2_HCFG_FSLSPCLKSEL_OFFSET 0
+#define DWC2_HCFG_FSLSSUPP (1 << 2)
+#define DWC2_HCFG_FSLSSUPP_OFFSET 2
+#define DWC2_HCFG_DESCDMA (1 << 23)
+#define DWC2_HCFG_DESCDMA_OFFSET 23
+#define DWC2_HCFG_FRLISTEN_MASK (0x3 << 24)
+#define DWC2_HCFG_FRLISTEN_OFFSET 24
+#define DWC2_HCFG_PERSCHEDENA (1 << 26)
+#define DWC2_HCFG_PERSCHEDENA_OFFSET 26
+#define DWC2_HCFG_PERSCHEDSTAT (1 << 27)
+#define DWC2_HCFG_PERSCHEDSTAT_OFFSET 27
+#define DWC2_HFIR_FRINT_MASK (0xFFFF << 0)
+#define DWC2_HFIR_FRINT_OFFSET 0
+#define DWC2_HFNUM_FRNUM_MASK (0xFFFF << 0)
+#define DWC2_HFNUM_FRNUM_OFFSET 0
+#define DWC2_HFNUM_FRREM_MASK (0xFFFF << 16)
+#define DWC2_HFNUM_FRREM_OFFSET 16
+#define DWC2_HPTXSTS_PTXFSPCAVAIL_MASK (0xFFFF << 0)
+#define DWC2_HPTXSTS_PTXFSPCAVAIL_OFFSET 0
+#define DWC2_HPTXSTS_PTXQSPCAVAIL_MASK (0xFF << 16)
+#define DWC2_HPTXSTS_PTXQSPCAVAIL_OFFSET 16
+#define DWC2_HPTXSTS_PTXQTOP_TERMINATE (1 << 24)
+#define DWC2_HPTXSTS_PTXQTOP_TERMINATE_OFFSET 24
+#define DWC2_HPTXSTS_PTXQTOP_TOKEN_MASK (0x3 << 25)
+#define DWC2_HPTXSTS_PTXQTOP_TOKEN_OFFSET 25
+#define DWC2_HPTXSTS_PTXQTOP_CHNUM_MASK (0xF << 27)
+#define DWC2_HPTXSTS_PTXQTOP_CHNUM_OFFSET 27
+#define DWC2_HPTXSTS_PTXQTOP_ODD (1 << 31)
+#define DWC2_HPTXSTS_PTXQTOP_ODD_OFFSET 31
+#define DWC2_HPRT0_PRTCONNSTS (1 << 0)
+#define DWC2_HPRT0_PRTCONNSTS_OFFSET 0
+#define DWC2_HPRT0_PRTCONNDET (1 << 1)
+#define DWC2_HPRT0_PRTCONNDET_OFFSET 1
+#define DWC2_HPRT0_PRTENA (1 << 2)
+#define DWC2_HPRT0_PRTENA_OFFSET 2
+#define DWC2_HPRT0_PRTENCHNG (1 << 3)
+#define DWC2_HPRT0_PRTENCHNG_OFFSET 3
+#define DWC2_HPRT0_PRTOVRCURRACT (1 << 4)
+#define DWC2_HPRT0_PRTOVRCURRACT_OFFSET 4
+#define DWC2_HPRT0_PRTOVRCURRCHNG (1 << 5)
+#define DWC2_HPRT0_PRTOVRCURRCHNG_OFFSET 5
+#define DWC2_HPRT0_PRTRES (1 << 6)
+#define DWC2_HPRT0_PRTRES_OFFSET 6
+#define DWC2_HPRT0_PRTSUSP (1 << 7)
+#define DWC2_HPRT0_PRTSUSP_OFFSET 7
+#define DWC2_HPRT0_PRTRST (1 << 8)
+#define DWC2_HPRT0_PRTRST_OFFSET 8
+#define DWC2_HPRT0_PRTLNSTS_MASK (0x3 << 10)
+#define DWC2_HPRT0_PRTLNSTS_OFFSET 10
+#define DWC2_HPRT0_PRTPWR (1 << 12)
+#define DWC2_HPRT0_PRTPWR_OFFSET 12
+#define DWC2_HPRT0_PRTTSTCTL_MASK (0xF << 13)
+#define DWC2_HPRT0_PRTTSTCTL_OFFSET 13
+#define DWC2_HPRT0_PRTSPD_MASK (0x3 << 17)
+#define DWC2_HPRT0_PRTSPD_OFFSET 17
+#define DWC2_HAINT_CH0 (1 << 0)
+#define DWC2_HAINT_CH0_OFFSET 0
+#define DWC2_HAINT_CH1 (1 << 1)
+#define DWC2_HAINT_CH1_OFFSET 1
+#define DWC2_HAINT_CH2 (1 << 2)
+#define DWC2_HAINT_CH2_OFFSET 2
+#define DWC2_HAINT_CH3 (1 << 3)
+#define DWC2_HAINT_CH3_OFFSET 3
+#define DWC2_HAINT_CH4 (1 << 4)
+#define DWC2_HAINT_CH4_OFFSET 4
+#define DWC2_HAINT_CH5 (1 << 5)
+#define DWC2_HAINT_CH5_OFFSET 5
+#define DWC2_HAINT_CH6 (1 << 6)
+#define DWC2_HAINT_CH6_OFFSET 6
+#define DWC2_HAINT_CH7 (1 << 7)
+#define DWC2_HAINT_CH7_OFFSET 7
+#define DWC2_HAINT_CH8 (1 << 8)
+#define DWC2_HAINT_CH8_OFFSET 8
+#define DWC2_HAINT_CH9 (1 << 9)
+#define DWC2_HAINT_CH9_OFFSET 9
+#define DWC2_HAINT_CH10 (1 << 10)
+#define DWC2_HAINT_CH10_OFFSET 10
+#define DWC2_HAINT_CH11 (1 << 11)
+#define DWC2_HAINT_CH11_OFFSET 11
+#define DWC2_HAINT_CH12 (1 << 12)
+#define DWC2_HAINT_CH12_OFFSET 12
+#define DWC2_HAINT_CH13 (1 << 13)
+#define DWC2_HAINT_CH13_OFFSET 13
+#define DWC2_HAINT_CH14 (1 << 14)
+#define DWC2_HAINT_CH14_OFFSET 14
+#define DWC2_HAINT_CH15 (1 << 15)
+#define DWC2_HAINT_CH15_OFFSET 15
+#define DWC2_HAINT_CHINT_MASK 0xffff
+#define DWC2_HAINT_CHINT_OFFSET 0
+#define DWC2_HAINTMSK_CH0 (1 << 0)
+#define DWC2_HAINTMSK_CH0_OFFSET 0
+#define DWC2_HAINTMSK_CH1 (1 << 1)
+#define DWC2_HAINTMSK_CH1_OFFSET 1
+#define DWC2_HAINTMSK_CH2 (1 << 2)
+#define DWC2_HAINTMSK_CH2_OFFSET 2
+#define DWC2_HAINTMSK_CH3 (1 << 3)
+#define DWC2_HAINTMSK_CH3_OFFSET 3
+#define DWC2_HAINTMSK_CH4 (1 << 4)
+#define DWC2_HAINTMSK_CH4_OFFSET 4
+#define DWC2_HAINTMSK_CH5 (1 << 5)
+#define DWC2_HAINTMSK_CH5_OFFSET 5
+#define DWC2_HAINTMSK_CH6 (1 << 6)
+#define DWC2_HAINTMSK_CH6_OFFSET 6
+#define DWC2_HAINTMSK_CH7 (1 << 7)
+#define DWC2_HAINTMSK_CH7_OFFSET 7
+#define DWC2_HAINTMSK_CH8 (1 << 8)
+#define DWC2_HAINTMSK_CH8_OFFSET 8
+#define DWC2_HAINTMSK_CH9 (1 << 9)
+#define DWC2_HAINTMSK_CH9_OFFSET 9
+#define DWC2_HAINTMSK_CH10 (1 << 10)
+#define DWC2_HAINTMSK_CH10_OFFSET 10
+#define DWC2_HAINTMSK_CH11 (1 << 11)
+#define DWC2_HAINTMSK_CH11_OFFSET 11
+#define DWC2_HAINTMSK_CH12 (1 << 12)
+#define DWC2_HAINTMSK_CH12_OFFSET 12
+#define DWC2_HAINTMSK_CH13 (1 << 13)
+#define DWC2_HAINTMSK_CH13_OFFSET 13
+#define DWC2_HAINTMSK_CH14 (1 << 14)
+#define DWC2_HAINTMSK_CH14_OFFSET 14
+#define DWC2_HAINTMSK_CH15 (1 << 15)
+#define DWC2_HAINTMSK_CH15_OFFSET 15
+#define DWC2_HAINTMSK_CHINT_MASK 0xffff
+#define DWC2_HAINTMSK_CHINT_OFFSET 0
+#define DWC2_HCCHAR_MPS_MASK (0x7FF << 0)
+#define DWC2_HCCHAR_MPS_OFFSET 0
+#define DWC2_HCCHAR_EPNUM_MASK (0xF << 11)
+#define DWC2_HCCHAR_EPNUM_OFFSET 11
+#define DWC2_HCCHAR_EPDIR (1 << 15)
+#define DWC2_HCCHAR_EPDIR_OFFSET 15
+#define DWC2_HCCHAR_LSPDDEV (1 << 17)
+#define DWC2_HCCHAR_LSPDDEV_OFFSET 17
+#define DWC2_HCCHAR_EPTYPE_CONTROL 0
+#define DWC2_HCCHAR_EPTYPE_ISOC 1
+#define DWC2_HCCHAR_EPTYPE_BULK 2
+#define DWC2_HCCHAR_EPTYPE_INTR 3
+#define DWC2_HCCHAR_EPTYPE_MASK (0x3 << 18)
+#define DWC2_HCCHAR_EPTYPE_OFFSET 18
+#define DWC2_HCCHAR_MULTICNT_MASK (0x3 << 20)
+#define DWC2_HCCHAR_MULTICNT_OFFSET 20
+#define DWC2_HCCHAR_DEVADDR_MASK (0x7F << 22)
+#define DWC2_HCCHAR_DEVADDR_OFFSET 22
+#define DWC2_HCCHAR_ODDFRM (1 << 29)
+#define DWC2_HCCHAR_ODDFRM_OFFSET 29
+#define DWC2_HCCHAR_CHDIS (1 << 30)
+#define DWC2_HCCHAR_CHDIS_OFFSET 30
+#define DWC2_HCCHAR_CHEN (1 << 31)
+#define DWC2_HCCHAR_CHEN_OFFSET 31
+#define DWC2_HCSPLT_PRTADDR_MASK (0x7F << 0)
+#define DWC2_HCSPLT_PRTADDR_OFFSET 0
+#define DWC2_HCSPLT_HUBADDR_MASK (0x7F << 7)
+#define DWC2_HCSPLT_HUBADDR_OFFSET 7
+#define DWC2_HCSPLT_XACTPOS_MASK (0x3 << 14)
+#define DWC2_HCSPLT_XACTPOS_OFFSET 14
+#define DWC2_HCSPLT_COMPSPLT (1 << 16)
+#define DWC2_HCSPLT_COMPSPLT_OFFSET 16
+#define DWC2_HCSPLT_SPLTENA (1 << 31)
+#define DWC2_HCSPLT_SPLTENA_OFFSET 31
+#define DWC2_HCINT_XFERCOMP (1 << 0)
+#define DWC2_HCINT_XFERCOMP_OFFSET 0
+#define DWC2_HCINT_CHHLTD (1 << 1)
+#define DWC2_HCINT_CHHLTD_OFFSET 1
+#define DWC2_HCINT_AHBERR (1 << 2)
+#define DWC2_HCINT_AHBERR_OFFSET 2
+#define DWC2_HCINT_STALL (1 << 3)
+#define DWC2_HCINT_STALL_OFFSET 3
+#define DWC2_HCINT_NAK (1 << 4)
+#define DWC2_HCINT_NAK_OFFSET 4
+#define DWC2_HCINT_ACK (1 << 5)
+#define DWC2_HCINT_ACK_OFFSET 5
+#define DWC2_HCINT_NYET (1 << 6)
+#define DWC2_HCINT_NYET_OFFSET 6
+#define DWC2_HCINT_XACTERR (1 << 7)
+#define DWC2_HCINT_XACTERR_OFFSET 7
+#define DWC2_HCINT_BBLERR (1 << 8)
+#define DWC2_HCINT_BBLERR_OFFSET 8
+#define DWC2_HCINT_FRMOVRUN (1 << 9)
+#define DWC2_HCINT_FRMOVRUN_OFFSET 9
+#define DWC2_HCINT_DATATGLERR (1 << 10)
+#define DWC2_HCINT_DATATGLERR_OFFSET 10
+#define DWC2_HCINT_BNA (1 << 11)
+#define DWC2_HCINT_BNA_OFFSET 11
+#define DWC2_HCINT_XCS_XACT (1 << 12)
+#define DWC2_HCINT_XCS_XACT_OFFSET 12
+#define DWC2_HCINT_FRM_LIST_ROLL (1 << 13)
+#define DWC2_HCINT_FRM_LIST_ROLL_OFFSET 13
+#define DWC2_HCINTMSK_XFERCOMPL (1 << 0)
+#define DWC2_HCINTMSK_XFERCOMPL_OFFSET 0
+#define DWC2_HCINTMSK_CHHLTD (1 << 1)
+#define DWC2_HCINTMSK_CHHLTD_OFFSET 1
+#define DWC2_HCINTMSK_AHBERR (1 << 2)
+#define DWC2_HCINTMSK_AHBERR_OFFSET 2
+#define DWC2_HCINTMSK_STALL (1 << 3)
+#define DWC2_HCINTMSK_STALL_OFFSET 3
+#define DWC2_HCINTMSK_NAK (1 << 4)
+#define DWC2_HCINTMSK_NAK_OFFSET 4
+#define DWC2_HCINTMSK_ACK (1 << 5)
+#define DWC2_HCINTMSK_ACK_OFFSET 5
+#define DWC2_HCINTMSK_NYET (1 << 6)
+#define DWC2_HCINTMSK_NYET_OFFSET 6
+#define DWC2_HCINTMSK_XACTERR (1 << 7)
+#define DWC2_HCINTMSK_XACTERR_OFFSET 7
+#define DWC2_HCINTMSK_BBLERR (1 << 8)
+#define DWC2_HCINTMSK_BBLERR_OFFSET 8
+#define DWC2_HCINTMSK_FRMOVRUN (1 << 9)
+#define DWC2_HCINTMSK_FRMOVRUN_OFFSET 9
+#define DWC2_HCINTMSK_DATATGLERR (1 << 10)
+#define DWC2_HCINTMSK_DATATGLERR_OFFSET 10
+#define DWC2_HCINTMSK_BNA (1 << 11)
+#define DWC2_HCINTMSK_BNA_OFFSET 11
+#define DWC2_HCINTMSK_XCS_XACT (1 << 12)
+#define DWC2_HCINTMSK_XCS_XACT_OFFSET 12
+#define DWC2_HCINTMSK_FRM_LIST_ROLL (1 << 13)
+#define DWC2_HCINTMSK_FRM_LIST_ROLL_OFFSET 13
+#define DWC2_HCTSIZ_XFERSIZE_MASK 0x7ffff
+#define DWC2_HCTSIZ_XFERSIZE_OFFSET 0
+#define DWC2_HCTSIZ_SCHINFO_MASK 0xff
+#define DWC2_HCTSIZ_SCHINFO_OFFSET 0
+#define DWC2_HCTSIZ_NTD_MASK (0xff << 8)
+#define DWC2_HCTSIZ_NTD_OFFSET 8
+#define DWC2_HCTSIZ_PKTCNT_MASK (0x3ff << 19)
+#define DWC2_HCTSIZ_PKTCNT_OFFSET 19
+#define DWC2_HCTSIZ_PID_MASK (0x3 << 29)
+#define DWC2_HCTSIZ_PID_OFFSET 29
+#define DWC2_HCTSIZ_DOPNG (1 << 31)
+#define DWC2_HCTSIZ_DOPNG_OFFSET 31
+#define DWC2_HCDMA_CTD_MASK (0xFF << 3)
+#define DWC2_HCDMA_CTD_OFFSET 3
+#define DWC2_HCDMA_DMA_ADDR_MASK (0x1FFFFF << 11)
+#define DWC2_HCDMA_DMA_ADDR_OFFSET 11
+#define DWC2_PCGCCTL_STOPPCLK (1 << 0)
+#define DWC2_PCGCCTL_STOPPCLK_OFFSET 0
+#define DWC2_PCGCCTL_GATEHCLK (1 << 1)
+#define DWC2_PCGCCTL_GATEHCLK_OFFSET 1
+#define DWC2_PCGCCTL_PWRCLMP (1 << 2)
+#define DWC2_PCGCCTL_PWRCLMP_OFFSET 2
+#define DWC2_PCGCCTL_RSTPDWNMODULE (1 << 3)
+#define DWC2_PCGCCTL_RSTPDWNMODULE_OFFSET 3
+#define DWC2_PCGCCTL_PHYSUSPENDED (1 << 4)
+#define DWC2_PCGCCTL_PHYSUSPENDED_OFFSET 4
+#define DWC2_PCGCCTL_ENBL_SLEEP_GATING (1 << 5)
+#define DWC2_PCGCCTL_ENBL_SLEEP_GATING_OFFSET 5
+#define DWC2_PCGCCTL_PHY_IN_SLEEP (1 << 6)
+#define DWC2_PCGCCTL_PHY_IN_SLEEP_OFFSET 6
+#define DWC2_PCGCCTL_DEEP_SLEEP (1 << 7)
+#define DWC2_PCGCCTL_DEEP_SLEEP_OFFSET 7
+#define DWC2_SNPSID_DEVID_VER_2xx (0x4f542 << 12)
+#define DWC2_SNPSID_DEVID_MASK (0xfffff << 12)
+#define DWC2_SNPSID_DEVID_OFFSET 12
+
+/* Host controller specific */
+#define DWC2_HC_PID_DATA0 0
+#define DWC2_HC_PID_DATA2 1
+#define DWC2_HC_PID_DATA1 2
+#define DWC2_HC_PID_MDATA 3
+#define DWC2_HC_PID_SETUP 3
+
+/* roothub.a masks */
+#define RH_A_NDP (0xff << 0) /* number of downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* over current protection mode */
+#define RH_A_NOCP (1 << 12) /* no over current protection */
+#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
+
+/* roothub.b masks */
+#define RH_B_DR 0x0000ffff /* device removable flags */
+#define RH_B_PPCM 0xffff0000 /* port power control mask */
+
+/* Default driver configuration */
+#define CONFIG_DWC2_DMA_ENABLE
+#define CONFIG_DWC2_DMA_BURST_SIZE 32 /* DMA burst len */
+#undef CONFIG_DWC2_DFLT_SPEED_FULL /* Do not force DWC2 to FS */
+#define CONFIG_DWC2_ENABLE_DYNAMIC_FIFO /* Runtime FIFO size detect */
+#define CONFIG_DWC2_MAX_CHANNELS 16 /* Max # of EPs */
+#define CONFIG_DWC2_HOST_RX_FIFO_SIZE (516 + CONFIG_DWC2_MAX_CHANNELS)
+#define CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE 0x100 /* nPeriodic TX FIFO */
+#define CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE 0x200 /* Periodic TX FIFO */
+#define CONFIG_DWC2_MAX_TRANSFER_SIZE 65535
+#define CONFIG_DWC2_MAX_PACKET_COUNT 511
+
+#define DWC2_PHY_TYPE_FS 0
+#define DWC2_PHY_TYPE_UTMI 1
+#define DWC2_PHY_TYPE_ULPI 2
+#define CONFIG_DWC2_PHY_TYPE DWC2_PHY_TYPE_UTMI /* PHY type */
+#define CONFIG_DWC2_UTMI_WIDTH 8 /* UTMI bus width (8/16) */
+
+#undef CONFIG_DWC2_PHY_ULPI_DDR /* ULPI PHY uses DDR mode */
+#define CONFIG_DWC2_PHY_ULPI_EXT_VBUS /* ULPI PHY controls VBUS */
+#undef CONFIG_DWC2_I2C_ENABLE /* Enable I2C */
+#undef CONFIG_DWC2_ULPI_FS_LS /* ULPI is FS/LS */
+#undef CONFIG_DWC2_TS_DLINE /* External DLine pulsing */
+#undef CONFIG_DWC2_THR_CTL /* Threshold control */
+#define CONFIG_DWC2_TX_THR_LENGTH 64
+#undef CONFIG_DWC2_IC_USB_CAP /* IC Cap */
+
+#endif /* __DWC2_H__ */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 6323c50837..c671c72cb1 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -119,15 +119,12 @@ static struct descriptor {
#define ehci_is_TDI() (0)
#endif
-int __ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg)
+__weak int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg)
{
return PORTSC_PSPD(reg);
}
-int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg)
- __attribute__((weak, alias("__ehci_get_port_speed")));
-
-void __ehci_set_usbmode(int index)
+__weak void ehci_set_usbmode(int index)
{
uint32_t tmp;
uint32_t *reg_ptr;
@@ -141,17 +138,11 @@ void __ehci_set_usbmode(int index)
ehci_writel(reg_ptr, tmp);
}
-void ehci_set_usbmode(int index)
- __attribute__((weak, alias("__ehci_set_usbmode")));
-
-void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
+__weak void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
{
mdelay(50);
}
-void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
- __attribute__((weak, alias("__ehci_powerup_fixup")));
-
static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
{
uint32_t result;
@@ -1106,6 +1097,7 @@ submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
}
struct int_queue {
+ int elementsize;
struct QH *first;
struct QH *current;
struct QH *last;
@@ -1163,6 +1155,23 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
struct int_queue *result = NULL;
int i;
+ /*
+ * Interrupt transfers requiring several transactions are not supported
+ * because bInterval is ignored.
+ *
+ * Also, ehci_submit_async() relies on wMaxPacketSize being a power of 2
+ * <= PKT_ALIGN if several qTDs are required, while the USB
+ * specification does not constrain this for interrupt transfers. That
+ * means that ehci_submit_async() would support interrupt transfers
+ * requiring several transactions only as long as the transfer size does
+ * not require more than a single qTD.
+ */
+ if (elementsize > usb_maxpacket(dev, pipe)) {
+ printf("%s: xfers requiring several transactions are not supported.\n",
+ __func__);
+ return NULL;
+ }
+
debug("Enter create_int_queue\n");
if (usb_pipetype(pipe) != PIPE_INTERRUPT) {
debug("non-interrupt pipe (type=%lu)", usb_pipetype(pipe));
@@ -1183,6 +1192,7 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
debug("ehci intr queue: out of memory\n");
goto fail1;
}
+ result->elementsize = elementsize;
result->first = memalign(USB_DMA_MINALIGN,
sizeof(struct QH) * queuesize);
if (!result->first) {
@@ -1258,9 +1268,11 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
ALIGN_END_ADDR(struct qTD, result->tds,
queuesize));
- if (disable_periodic(ctrl) < 0) {
- debug("FATAL: periodic should never fail, but did");
- goto fail3;
+ if (ctrl->periodic_schedules > 0) {
+ if (disable_periodic(ctrl) < 0) {
+ debug("FATAL: periodic should never fail, but did");
+ goto fail3;
+ }
}
/* hook up to periodic list */
@@ -1317,6 +1329,11 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
queue->current++;
else
queue->current = NULL;
+
+ invalidate_dcache_range((uint32_t)cur->buffer,
+ ALIGN_END_ADDR(char, cur->buffer,
+ queue->elementsize));
+
debug("Exit poll_int_queue with completed intr transfer. token is %x at %p (first at %p)\n",
hc32_to_cpu(cur_td->qt_token), cur, queue->first);
return cur->buffer;
@@ -1382,24 +1399,9 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
dev, pipe, buffer, length, interval);
- /*
- * Interrupt transfers requiring several transactions are not supported
- * because bInterval is ignored.
- *
- * Also, ehci_submit_async() relies on wMaxPacketSize being a power of 2
- * <= PKT_ALIGN if several qTDs are required, while the USB
- * specification does not constrain this for interrupt transfers. That
- * means that ehci_submit_async() would support interrupt transfers
- * requiring several transactions only as long as the transfer size does
- * not require more than a single qTD.
- */
- if (length > usb_maxpacket(dev, pipe)) {
- printf("%s: Interrupt transfers requiring several "
- "transactions are not supported.\n", __func__);
- return -1;
- }
-
queue = create_int_queue(dev, pipe, 1, length, buffer);
+ if (!queue)
+ return -1;
timeout = get_timer(0) + USB_TIMEOUT_MS(pipe);
while ((backbuffer = poll_int_queue(dev, queue)) == NULL)
@@ -1415,9 +1417,6 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
return -EINVAL;
}
- invalidate_dcache_range((uint32_t)buffer,
- ALIGN_END_ADDR(char, buffer, length));
-
ret = destroy_int_queue(dev, queue);
if (ret < 0)
return ret;
diff --git a/drivers/usb/host/ehci-rmobile.c b/drivers/usb/host/ehci-rmobile.c
index 0d1a726d35..b4330876f8 100644
--- a/drivers/usb/host/ehci-rmobile.c
+++ b/drivers/usb/host/ehci-rmobile.c
@@ -22,12 +22,8 @@ static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = {
0xEE0A0000, /* USB1 */
0xEE0C0000, /* USB2 */
};
-#elif defined(CONFIG_R8A7791)
-static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = {
- 0xEE080000, /* USB0 (EHCI) */
- 0xEE0C0000, /* USB1 */
-};
-#elif defined(CONFIG_R8A7794)
+#elif defined(CONFIG_R8A7791) || defined(CONFIG_R8A7793) || \
+ defined(CONFIG_R8A7794)
static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = {
0xEE080000, /* USB0 (EHCI) */
0xEE0C0000, /* USB1 */
diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c
index 23617b7adc..4befd57454 100644
--- a/drivers/usb/host/ehci-sunxi.c
+++ b/drivers/usb/host/ehci-sunxi.c
@@ -105,7 +105,7 @@ static void sunxi_usb_phy_init(struct sunxi_ehci_hcd *sunxi_ehci)
usb_phy_write(sunxi_ehci, 0x20, 0x14, 5);
/* threshold adjustment disconnect */
-#ifdef CONFIG_SUN4I
+#ifdef CONFIG_MACH_SUN4I
usb_phy_write(sunxi_ehci, 0x2a, 3, 2);
#else
usb_phy_write(sunxi_ehci, 0x2a, 2, 2);
@@ -163,11 +163,16 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
{
struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
struct sunxi_ehci_hcd *sunxi_ehci = &sunxi_echi_hcd[index];
+ int err;
/* enable common PHY only once */
if (index == 0)
setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
+ err = gpio_request(sunxi_ehci->gpio_vbus, "ehci_vbus");
+ if (err)
+ return err;
+
sunxi_ehci_enable(sunxi_ehci);
*hccr = get_io_base(sunxi_ehci->id);
@@ -188,9 +193,14 @@ int ehci_hcd_stop(int index)
{
struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
struct sunxi_ehci_hcd *sunxi_ehci = &sunxi_echi_hcd[index];
+ int err;
sunxi_ehci_disable(sunxi_ehci);
+ err = gpio_free(sunxi_ehci->gpio_vbus);
+ if (err)
+ return err;
+
/* disable common PHY only once, for the last enabled hcd */
if (enabled_hcd_count == 1)
clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
diff --git a/drivers/usb/host/xhci-keystone.c b/drivers/usb/host/xhci-keystone.c
new file mode 100644
index 0000000000..05d338f261
--- /dev/null
+++ b/drivers/usb/host/xhci-keystone.c
@@ -0,0 +1,329 @@
+/*
+ * USB 3.0 DRD Controller
+ *
+ * (C) Copyright 2012-2014
+ * Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <usb.h>
+#include <asm/arch/psc_defs.h>
+#include <asm/io.h>
+#include <linux/usb/dwc3.h>
+#include <asm/arch/xhci-keystone.h>
+#include <asm-generic/errno.h>
+#include <linux/list.h>
+#include "xhci.h"
+
+struct kdwc3_irq_regs {
+ u32 revision; /* 0x000 */
+ u32 rsvd0[3];
+ u32 sysconfig; /* 0x010 */
+ u32 rsvd1[1];
+ u32 irq_eoi;
+ u32 rsvd2[1];
+ struct {
+ u32 raw_status;
+ u32 status;
+ u32 enable_set;
+ u32 enable_clr;
+ } irqs[16];
+};
+
+struct keystone_xhci {
+ struct xhci_hccr *hcd;
+ struct dwc3 *dwc3_reg;
+ struct xhci_hcor *hcor;
+ struct kdwc3_irq_regs *usbss;
+ struct keystone_xhci_phy *phy;
+};
+
+struct keystone_xhci keystone;
+
+static void keystone_xhci_phy_set(struct keystone_xhci_phy *phy)
+{
+ u32 val;
+
+ /*
+ * VBUSVLDEXTSEL has a default value of 1 in BootCfg but shouldn't.
+ * It should always be cleared because our USB PHY has an onchip VBUS
+ * analog comparator.
+ */
+ val = readl(&phy->phy_clock);
+ /* quit selecting the vbusvldextsel by default! */
+ val &= ~USB3_PHY_OTG_VBUSVLDECTSEL;
+ writel(val, &phy->phy_clock);
+}
+
+static void keystone_xhci_phy_unset(struct keystone_xhci_phy *phy)
+{
+ u32 val;
+
+ /* Disable the PHY REFCLK clock gate */
+ val = readl(&phy->phy_clock);
+ val &= ~USB3_PHY_REF_SSP_EN;
+ writel(val, &phy->phy_clock);
+}
+
+static void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode)
+{
+ clrsetbits_le32(&dwc3_reg->g_ctl,
+ DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG),
+ DWC3_GCTL_PRTCAPDIR(mode));
+}
+
+static void dwc3_core_soft_reset(struct dwc3 *dwc3_reg)
+{
+ /* Before Resetting PHY, put Core in Reset */
+ setbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET);
+
+ /* Assert USB3 PHY reset */
+ setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST);
+
+ /* Assert USB2 PHY reset */
+ setbits_le32(&dwc3_reg->g_usb2phycfg[0], DWC3_GUSB2PHYCFG_PHYSOFTRST);
+
+ mdelay(100);
+
+ /* Clear USB3 PHY reset */
+ clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST);
+
+ /* Clear USB2 PHY reset */
+ clrbits_le32(&dwc3_reg->g_usb2phycfg[0], DWC3_GUSB2PHYCFG_PHYSOFTRST);
+
+ /* After PHYs are stable we can take Core out of reset state */
+ clrbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET);
+}
+
+static int dwc3_core_init(struct dwc3 *dwc3_reg)
+{
+ u32 revision, val;
+ unsigned long t_rst;
+ unsigned int dwc3_hwparams1;
+
+ revision = readl(&dwc3_reg->g_snpsid);
+ /* This should read as U3 followed by revision number */
+ if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) {
+ puts("this is not a DesignWare USB3 DRD Core\n");
+ return -EINVAL;
+ }
+
+ /* issue device SoftReset too */
+ writel(DWC3_DCTL_CSFTRST, &dwc3_reg->d_ctl);
+
+ t_rst = get_timer(0);
+ do {
+ val = readl(&dwc3_reg->d_ctl);
+ if (!(val & DWC3_DCTL_CSFTRST))
+ break;
+ WATCHDOG_RESET();
+ } while (get_timer(t_rst) < 500);
+
+ if (val & DWC3_DCTL_CSFTRST) {
+ debug("Reset timed out\n");
+ return -2;
+ }
+
+ dwc3_core_soft_reset(dwc3_reg);
+
+ dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1);
+
+ val = readl(&dwc3_reg->g_ctl);
+ val &= ~DWC3_GCTL_SCALEDOWN_MASK;
+ val &= ~DWC3_GCTL_DISSCRAMBLE;
+ switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) {
+ case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
+ val &= ~DWC3_GCTL_DSBLCLKGTNG;
+ break;
+ default:
+ printf("No power optimization available\n");
+ }
+
+ /*
+ * WORKAROUND: DWC3 revisions <1.90a have a bug
+ * where the device can fail to connect at SuperSpeed
+ * and falls back to high-speed mode which causes
+ * the device to enter a Connect/Disconnect loop
+ */
+ if ((revision & DWC3_REVISION_MASK) < 0x190a)
+ val |= DWC3_GCTL_U2RSTECN;
+
+ writel(val, &dwc3_reg->g_ctl);
+
+ return 0;
+}
+
+static int keystone_xhci_core_init(struct dwc3 *dwc3_reg)
+{
+ int ret;
+
+ ret = dwc3_core_init(dwc3_reg);
+ if (ret) {
+ debug("failed to initialize core\n");
+ return -EINVAL;
+ }
+
+ /* We are hard-coding DWC3 core to Host Mode */
+ dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
+
+ return 0;
+}
+
+int xhci_hcd_init(int index,
+ struct xhci_hccr **ret_hccr, struct xhci_hcor **ret_hcor)
+{
+ u32 val;
+ int ret;
+ struct xhci_hccr *hcd;
+ struct xhci_hcor *hcor;
+ struct kdwc3_irq_regs *usbss;
+ struct keystone_xhci_phy *phy;
+
+ usbss = (struct kdwc3_irq_regs *)CONFIG_USB_SS_BASE;
+ phy = (struct keystone_xhci_phy *)CONFIG_DEV_USB_PHY_BASE;
+
+ /* Enable the PHY REFCLK clock gate with phy_ref_ssp_en = 1 */
+ val = readl(&(phy->phy_clock));
+ val |= USB3_PHY_REF_SSP_EN;
+ writel(val, &phy->phy_clock);
+
+ mdelay(100);
+
+ /* Release USB from reset */
+ ret = psc_enable_module(KS2_LPSC_USB);
+ if (ret) {
+ puts("Cannot enable USB module");
+ return -1;
+ }
+
+ mdelay(100);
+
+ /* Initialize usb phy */
+ keystone_xhci_phy_set(phy);
+
+ /* soft reset usbss */
+ writel(1, &usbss->sysconfig);
+ while (readl(&usbss->sysconfig) & 1)
+ ;
+
+ val = readl(&usbss->revision);
+ debug("usbss revision %x\n", val);
+
+ /* Initialize usb core */
+ hcd = (struct xhci_hccr *)CONFIG_USB_HOST_XHCI_BASE;
+ keystone.dwc3_reg = (struct dwc3 *)(CONFIG_USB_HOST_XHCI_BASE +
+ DWC3_REG_OFFSET);
+
+ keystone_xhci_core_init(keystone.dwc3_reg);
+
+ /* set register addresses */
+ hcor = (struct xhci_hcor *)((uint32_t)hcd +
+ HC_LENGTH(readl(&hcd->cr_capbase)));
+
+ debug("Keystone2-xhci: init hccr %08x and hcor %08x hc_length %d\n",
+ (u32)hcd, (u32)hcor,
+ (u32)HC_LENGTH(xhci_readl(&hcd->cr_capbase)));
+
+ keystone.usbss = usbss;
+ keystone.phy = phy;
+ keystone.hcd = hcd;
+ keystone.hcor = hcor;
+
+ *ret_hccr = hcd;
+ *ret_hcor = hcor;
+
+ return 0;
+}
+
+static int keystone_xhci_phy_suspend(void)
+{
+ int loop_cnt = 0;
+ struct xhci_hcor *hcor;
+ uint32_t *portsc_1 = NULL;
+ uint32_t *portsc_2 = NULL;
+ u32 val, usb2_pls, usb3_pls, event_q;
+ struct dwc3 *dwc3_reg = keystone.dwc3_reg;
+
+ /* set register addresses */
+ hcor = keystone.hcor;
+
+ /* Bypass Scrambling and Set Shorter Training sequence for simulation */
+ val = DWC3_GCTL_PWRDNSCALE(0x4b0) | DWC3_GCTL_PRTCAPDIR(0x2);
+ writel(val, &dwc3_reg->g_ctl);
+
+ /* GUSB2PHYCFG */
+ val = readl(&dwc3_reg->g_usb2phycfg[0]);
+
+ /* assert bit 6 (SusPhy) */
+ val |= DWC3_GUSB2PHYCFG_SUSPHY;
+ writel(val, &dwc3_reg->g_usb2phycfg[0]);
+
+ /* GUSB3PIPECTL */
+ val = readl(&dwc3_reg->g_usb3pipectl[0]);
+
+ /*
+ * assert bit 29 to allow PHY to go to suspend when idle
+ * and cause the USB3 SS PHY to enter suspend mode
+ */
+ val |= (BIT(29) | DWC3_GUSB3PIPECTL_SUSPHY);
+ writel(val, &dwc3_reg->g_usb3pipectl[0]);
+
+ /*
+ * Steps necessary to allow controller to suspend even when
+ * VBUS is HIGH:
+ * - Init DCFG[2:0] (DevSpd) to: 1=FS
+ * - Init GEVNTADR0 to point to an eventQ
+ * - Init GEVNTSIZ0 to 0x0100 to specify the size of the eventQ
+ * - Init DCTL::Run_nStop = 1
+ */
+ writel(0x00020001, &dwc3_reg->d_cfg);
+ /* TODO: local2global( (Uint32) eventQ )? */
+ writel((u32)&event_q, &dwc3_reg->g_evnt_buf[0].g_evntadrlo);
+ writel(0, &dwc3_reg->g_evnt_buf[0].g_evntadrhi);
+ writel(0x4, &dwc3_reg->g_evnt_buf[0].g_evntsiz);
+ /* Run */
+ writel(DWC3_DCTL_RUN_STOP, &dwc3_reg->d_ctl);
+
+ mdelay(100);
+
+ /* Wait for USB2 & USB3 PORTSC::PortLinkState to indicate suspend */
+ portsc_1 = (uint32_t *)(&hcor->portregs[0].or_portsc);
+ portsc_2 = (uint32_t *)(&hcor->portregs[1].or_portsc);
+ usb2_pls = 0;
+ usb3_pls = 0;
+ do {
+ ++loop_cnt;
+ usb2_pls = (readl(portsc_1) & PORT_PLS_MASK) >> 5;
+ usb3_pls = (readl(portsc_2) & PORT_PLS_MASK) >> 5;
+ } while (((usb2_pls != 0x4) || (usb3_pls != 0x4)) && loop_cnt < 1000);
+
+ if (usb2_pls != 0x4 || usb3_pls != 0x4) {
+ debug("USB suspend failed - PLS USB2=%02x, USB3=%02x\n",
+ usb2_pls, usb3_pls);
+ return -1;
+ }
+
+ debug("USB2 and USB3 PLS - Disabled, loop_cnt=%d\n", loop_cnt);
+ return 0;
+}
+
+void xhci_hcd_stop(int index)
+{
+ /* Disable USB */
+ if (keystone_xhci_phy_suspend())
+ return;
+
+ if (psc_disable_module(KS2_LPSC_USB)) {
+ debug("PSC disable module USB failed!\n");
+ return;
+ }
+
+ /* Disable PHY */
+ keystone_xhci_phy_unset(keystone.phy);
+
+/* memset(&keystone, 0, sizeof(struct keystone_xhci)); */
+ debug("xhci_hcd_stop OK.\n");
+}
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index 9231927879..6aa50cb4f9 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -944,7 +944,7 @@ static void parse_putc(const char c)
CURSOR_SET;
}
-void video_putc(struct stdio_dev *dev, const char c)
+static void video_putc(struct stdio_dev *dev, const char c)
{
#ifdef CONFIG_CFB_CONSOLE_ANSI
int i;
@@ -1158,7 +1158,7 @@ void video_putc(struct stdio_dev *dev, const char c)
flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
}
-void video_puts(struct stdio_dev *dev, const char *s)
+static void video_puts(struct stdio_dev *dev, const char *s)
{
int count = strlen(s);
@@ -1171,14 +1171,11 @@ void video_puts(struct stdio_dev *dev, const char *s)
* video_set_lut() if they do not support 8 bpp format.
* Implement weak default function instead.
*/
-void __video_set_lut(unsigned int index, unsigned char r,
+__weak void video_set_lut(unsigned int index, unsigned char r,
unsigned char g, unsigned char b)
{
}
-void video_set_lut(unsigned int, unsigned char, unsigned char, unsigned char)
- __attribute__ ((weak, alias("__video_set_lut")));
-
#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
#define FILL_8BIT_332RGB(r,g,b) { \
@@ -2240,15 +2237,12 @@ static int video_init(void)
* Implement a weak default function for boards that optionally
* need to skip the video initialization.
*/
-int __board_video_skip(void)
+__weak int board_video_skip(void)
{
/* As default, don't skip test */
return 0;
}
-int board_video_skip(void)
- __attribute__ ((weak, alias("__board_video_skip")));
-
int drv_video_init(void)
{
int skip_dev_init;
diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c
index 180a3b4149..be35b982ac 100644
--- a/drivers/video/exynos_fb.c
+++ b/drivers/video/exynos_fb.c
@@ -58,54 +58,38 @@ static void exynos_lcd_init(vidinfo_t *vid)
lcd_set_flush_dcache(1);
}
-void __exynos_cfg_lcd_gpio(void)
+__weak void exynos_cfg_lcd_gpio(void)
{
}
-void exynos_cfg_lcd_gpio(void)
- __attribute__((weak, alias("__exynos_cfg_lcd_gpio")));
-void __exynos_backlight_on(unsigned int onoff)
+__weak void exynos_backlight_on(unsigned int onoff)
{
}
-void exynos_backlight_on(unsigned int onoff)
- __attribute__((weak, alias("__exynos_cfg_lcd_gpio")));
-void __exynos_reset_lcd(void)
+__weak void exynos_reset_lcd(void)
{
}
-void exynos_reset_lcd(void)
- __attribute__((weak, alias("__exynos_reset_lcd")));
-void __exynos_lcd_power_on(void)
+__weak void exynos_lcd_power_on(void)
{
}
-void exynos_lcd_power_on(void)
- __attribute__((weak, alias("__exynos_lcd_power_on")));
-void __exynos_cfg_ldo(void)
+__weak void exynos_cfg_ldo(void)
{
}
-void exynos_cfg_ldo(void)
- __attribute__((weak, alias("__exynos_cfg_ldo")));
-void __exynos_enable_ldo(unsigned int onoff)
+__weak void exynos_enable_ldo(unsigned int onoff)
{
}
-void exynos_enable_ldo(unsigned int onoff)
- __attribute__((weak, alias("__exynos_enable_ldo")));
-void __exynos_backlight_reset(void)
+__weak void exynos_backlight_reset(void)
{
}
-void exynos_backlight_reset(void)
- __attribute__((weak, alias("__exynos_backlight_reset")));
-int __exynos_lcd_misc_init(vidinfo_t *vid)
+__weak int exynos_lcd_misc_init(vidinfo_t *vid)
{
return 0;
}
-int exynos_lcd_misc_init(vidinfo_t *vid)
- __attribute__((weak, alias("__exynos_lcd_misc_init")));
static void lcd_panel_on(vidinfo_t *vid)
{
diff --git a/drivers/video/ipu_common.c b/drivers/video/ipu_common.c
index 8d4e925478..5873531953 100644
--- a/drivers/video/ipu_common.c
+++ b/drivers/video/ipu_common.c
@@ -379,7 +379,7 @@ static struct clk pixel_clk[] = {
/*
* This function resets IPU
*/
-void ipu_reset(void)
+static void ipu_reset(void)
{
u32 *reg;
u32 value;
diff --git a/drivers/video/ipu_disp.c b/drivers/video/ipu_disp.c
index 48fee992a1..4faeafb635 100644
--- a/drivers/video/ipu_disp.c
+++ b/drivers/video/ipu_disp.c
@@ -377,7 +377,7 @@ static struct dp_csc_param_t dp_csc_array[CSC_NUM][CSC_NUM] = {
static enum csc_type_t fg_csc_type = CSC_NONE, bg_csc_type = CSC_NONE;
static int color_key_4rgb = 1;
-void ipu_dp_csc_setup(int dp, struct dp_csc_param_t dp_csc_param,
+static void ipu_dp_csc_setup(int dp, struct dp_csc_param_t dp_csc_param,
unsigned char srm_mode_update)
{
u32 reg;
@@ -605,17 +605,6 @@ void ipu_dc_uninit(int dc_chan)
}
}
-int ipu_chan_is_interlaced(ipu_channel_t channel)
-{
- if (channel == MEM_DC_SYNC)
- return !!(__raw_readl(DC_WR_CH_CONF_1) &
- DC_WR_CH_CONF_FIELD_MODE);
- else if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC))
- return !!(__raw_readl(DC_WR_CH_CONF_5) &
- DC_WR_CH_CONF_FIELD_MODE);
- return 0;
-}
-
void ipu_dp_dc_enable(ipu_channel_t channel)
{
int di;
@@ -782,7 +771,7 @@ void ipu_init_dc_mappings(void)
ipu_dc_map_config(4, 2, 21, 0xFC);
}
-int ipu_pixfmt_to_map(uint32_t fmt)
+static int ipu_pixfmt_to_map(uint32_t fmt)
{
switch (fmt) {
case IPU_PIX_FMT_GENERIC:
diff --git a/drivers/video/mxc_ipuv3_fb.c b/drivers/video/mxc_ipuv3_fb.c
index b20c19c426..1fa95314fc 100644
--- a/drivers/video/mxc_ipuv3_fb.c
+++ b/drivers/video/mxc_ipuv3_fb.c
@@ -36,7 +36,7 @@ static struct fb_videomode const *gmode;
static uint8_t gdisp;
static uint32_t gpixfmt;
-void fb_videomode_to_var(struct fb_var_screeninfo *var,
+static void fb_videomode_to_var(struct fb_var_screeninfo *var,
const struct fb_videomode *mode)
{
var->xres = mode->xres;
OpenPOWER on IntegriCloud