From c1ff6d8872401dd421a329440debba8fb91ecf2b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 13 Feb 2012 09:05:16 +0100 Subject: PXA: Remove PXA PCMCIA support Say good bye to some ancient, very broken and unused code. Signed-off-by: Marek Vasut --- drivers/pcmcia/Makefile | 1 - drivers/pcmcia/pxa_pcmcia.c | 93 --------------------------------------------- 2 files changed, 94 deletions(-) delete mode 100644 drivers/pcmcia/pxa_pcmcia.c (limited to 'drivers') diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 03495087dc9..aa477d4f933 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -27,7 +27,6 @@ LIB := $(obj)libpcmcia.o COBJS-$(CONFIG_I82365) += i82365.o COBJS-$(CONFIG_8xx) += mpc8xx_pcmcia.o -COBJS-$(CONFIG_PXA_PCMCIA) += pxa_pcmcia.o COBJS-y += rpx_pcmcia.o COBJS-$(CONFIG_IDE_TI_CARDBUS) += ti_pci1410a.o COBJS-y += tqm8xx_pcmcia.o diff --git a/drivers/pcmcia/pxa_pcmcia.c b/drivers/pcmcia/pxa_pcmcia.c deleted file mode 100644 index d06ab746c8a..00000000000 --- a/drivers/pcmcia/pxa_pcmcia.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include -#include -#include - -static inline void msWait(unsigned msVal) -{ - udelay(msVal*1000); -} - -int pcmcia_on (void) -{ - unsigned int reg_arr[] = { - 0x48000028, CONFIG_SYS_MCMEM0_VAL, - 0x4800002c, CONFIG_SYS_MCMEM1_VAL, - 0x48000030, CONFIG_SYS_MCATT0_VAL, - 0x48000034, CONFIG_SYS_MCATT1_VAL, - 0x48000038, CONFIG_SYS_MCIO0_VAL, - 0x4800003c, CONFIG_SYS_MCIO1_VAL, - - 0, 0 - }; - int i, rc; - -#ifdef CONFIG_EXADRON1 - int cardDetect; - volatile unsigned int *v_pBCRReg = - (volatile unsigned int *) 0x08000000; -#endif - - debug ("%s\n", __FUNCTION__); - - i = 0; - while (reg_arr[i]) { - (*(volatile unsigned int *) reg_arr[i]) |= reg_arr[i + 1]; - i += 2; - } - udelay (1000); - - debug ("%s: programmed mem controller \n", __FUNCTION__); - -#ifdef CONFIG_EXADRON1 - -/*define useful BCR masks */ -#define BCR_CF_INIT_VAL 0x00007230 -#define BCR_CF_PWRON_BUSOFF_RESETOFF_VAL 0x00007231 -#define BCR_CF_PWRON_BUSOFF_RESETON_VAL 0x00007233 -#define BCR_CF_PWRON_BUSON_RESETON_VAL 0x00007213 -#define BCR_CF_PWRON_BUSON_RESETOFF_VAL 0x00007211 - - /* we see from the GPIO bit if the card is present */ - cardDetect = !(GPLR0 & GPIO_bit (14)); - - if (cardDetect) { - printf ("No PCMCIA card found!\n"); - } - - /* reset the card via the BCR line */ - *v_pBCRReg = (unsigned) BCR_CF_INIT_VAL; - msWait (500); - - *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSOFF_RESETOFF_VAL; - msWait (500); - - *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSOFF_RESETON_VAL; - msWait (500); - - *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSON_RESETON_VAL; - msWait (500); - - *v_pBCRReg = (unsigned) BCR_CF_PWRON_BUSON_RESETOFF_VAL; - msWait (1500); - - /* enable address bus */ - GPCR1 = 0x01; - /* and the first CF slot */ - MECR = 0x00000002; - -#endif /* EXADRON 1 */ - - rc = check_ide_device (0); /* use just slot 0 */ - - return rc; -} - -#if defined(CONFIG_CMD_PCMCIA) -int pcmcia_off (void) -{ - return 0; -} -#endif -- cgit v1.3.1 From 3f467529cad0789b6dcc44f5ebc595c3e47341ce Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Wed, 8 Feb 2012 22:33:25 +0000 Subject: usb/ehci: Add USB support for the MX6Q Currently, only USB Host 1 is supported. Cc: Remy Bohmer Signed-off-by: Wolfgang Grandegger --- arch/arm/cpu/armv7/mx6/clock.c | 13 ++ arch/arm/include/asm/arch-mx6/clock.h | 1 + arch/arm/include/asm/arch-mx6/imx-regs.h | 3 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-mx6.c | 205 +++++++++++++++++++++++++++++++ 5 files changed, 223 insertions(+) create mode 100644 drivers/usb/host/ehci-mx6.c (limited to 'drivers') diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index fa3a1248079..ef98563ff76 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -36,6 +36,19 @@ enum pll_clocks { struct imx_ccm_reg *imx_ccm = (struct imx_ccm_reg *)CCM_BASE_ADDR; +void enable_usboh3_clk(unsigned char enable) +{ + u32 reg; + + reg = __raw_readl(&imx_ccm->CCGR6); + if (enable) + reg |= MXC_CCM_CCGR_CG_MASK << MXC_CCM_CCGR0_CG0_OFFSET; + else + reg &= ~(MXC_CCM_CCGR_CG_MASK << MXC_CCM_CCGR0_CG0_OFFSET); + __raw_writel(reg, &imx_ccm->CCGR6); + +} + static u32 decode_pll(enum pll_clocks pll, u32 infreq) { u32 div; diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 636458f8a07..613809bdd67 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -46,5 +46,6 @@ enum mxc_clock { u32 imx_get_uartclk(void); u32 imx_get_fecclk(void); unsigned int mxc_get_clock(enum mxc_clock clk); +void enable_usboh3_clk(unsigned char enable); #endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h index 6b7589b78a3..6a200bb8655 100644 --- a/arch/arm/include/asm/arch-mx6/imx-regs.h +++ b/arch/arm/include/asm/arch-mx6/imx-regs.h @@ -111,6 +111,9 @@ #define KPP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x38000) #define WDOG1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x3C000) #define WDOG2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x40000) +#define ANATOP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x48000) +#define USB_PHY0_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x49000) +#define USB_PHY1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4a000) #define CCM_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x44000) #define ANATOP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x48000) #define SNVS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4C000) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 5fdc97b8c86..53ad70af23c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -44,6 +44,7 @@ endif COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o COBJS-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o +COBJS-$(CONFIG_USB_EHCI_MX6) += ehci-mx6.o COBJS-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c new file mode 100644 index 00000000000..b7bf49d6a4b --- /dev/null +++ b/drivers/usb/host/ehci-mx6.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ehci.h" +#include "ehci-core.h" + +#define USB_OTGREGS_OFFSET 0x000 +#define USB_H1REGS_OFFSET 0x200 +#define USB_H2REGS_OFFSET 0x400 +#define USB_H3REGS_OFFSET 0x600 +#define USB_OTHERREGS_OFFSET 0x800 + +#define USB_H1_CTRL_OFFSET 0x04 + +#define USBPHY_CTRL 0x00000030 +#define USBPHY_CTRL_SET 0x00000034 +#define USBPHY_CTRL_CLR 0x00000038 +#define USBPHY_CTRL_TOG 0x0000003c + +#define USBPHY_PWD 0x00000000 +#define USBPHY_CTRL_SFTRST 0x80000000 +#define USBPHY_CTRL_CLKGATE 0x40000000 +#define USBPHY_CTRL_ENUTMILEVEL3 0x00008000 +#define USBPHY_CTRL_ENUTMILEVEL2 0x00004000 + +#define ANADIG_USB2_CHRG_DETECT 0x00000210 +#define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 +#define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 + +#define ANADIG_USB2_PLL_480_CTRL 0x00000020 +#define ANADIG_USB2_PLL_480_CTRL_SET 0x00000024 +#define ANADIG_USB2_PLL_480_CTRL_CLR 0x00000028 +#define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 +#define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 +#define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 +#define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 + + +#define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ +#define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ + +/* USBCMD */ +#define UH1_USBCMD_OFFSET 0x140 +#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ +#define UCMD_RESET (1 << 1) /* controller reset */ + +static void usbh1_internal_phy_clock_gate(int on) +{ + void __iomem *phy_reg = (void __iomem *)USB_PHY1_BASE_ADDR; + + phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; + __raw_writel(USBPHY_CTRL_CLKGATE, phy_reg); +} + +static void usbh1_power_config(void) +{ + void __iomem *anatop_base = (void __iomem *)ANATOP_BASE_ADDR; + + /* + * Some phy and power's special controls for host1 + * 1. The external charger detector needs to be disabled + * or the signal at DP will be poor + * 2. The PLL's power and output to usb for host 1 + * is totally controlled by IC, so the Software only needs + * to enable them at initializtion. + */ + __raw_writel(ANADIG_USB2_CHRG_DETECT_EN_B | + ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, + anatop_base + ANADIG_USB2_CHRG_DETECT); + + __raw_writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, + anatop_base + ANADIG_USB2_PLL_480_CTRL_CLR); + + __raw_writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | + ANADIG_USB2_PLL_480_CTRL_POWER | + ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, + anatop_base + ANADIG_USB2_PLL_480_CTRL_SET); +} + +static int usbh1_phy_enable(void) +{ + void __iomem *phy_reg = (void __iomem *)USB_PHY1_BASE_ADDR; + void __iomem *phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); + void __iomem *usb_cmd = (void __iomem *)(USBOH3_USB_BASE_ADDR + + USB_H1REGS_OFFSET + + UH1_USBCMD_OFFSET); + u32 val; + + /* Stop then Reset */ + val = __raw_readl(usb_cmd); + val &= ~UCMD_RUN_STOP; + __raw_writel(val, usb_cmd); + while (__raw_readl(usb_cmd) & UCMD_RUN_STOP) + ; + + val = __raw_readl(usb_cmd); + val |= UCMD_RESET; + __raw_writel(val, usb_cmd); + while (__raw_readl(usb_cmd) & UCMD_RESET) + ; + + /* Reset USBPHY module */ + val = __raw_readl(phy_ctrl); + val |= USBPHY_CTRL_SFTRST; + __raw_writel(val, phy_ctrl); + udelay(10); + + /* Remove CLKGATE and SFTRST */ + val = __raw_readl(phy_ctrl); + val &= ~(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); + __raw_writel(val, phy_ctrl); + udelay(10); + + /* Power up the PHY */ + __raw_writel(0, phy_reg + USBPHY_PWD); + /* enable FS/LS device */ + val = __raw_readl(phy_reg + USBPHY_CTRL); + val |= (USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); + __raw_writel(val, phy_reg + USBPHY_CTRL); + + return 0; +} + +static void usbh1_oc_config(void) +{ + void __iomem *usb_base = (void __iomem *)USBOH3_USB_BASE_ADDR; + void __iomem *usbother_base = usb_base + USB_OTHERREGS_OFFSET; + u32 val; + + val = __raw_readl(usbother_base + USB_H1_CTRL_OFFSET); +#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 + /* mx6qarm2 seems to required a different setting*/ + val &= ~UCTRL_OVER_CUR_POL; +#else + val |= UCTRL_OVER_CUR_POL; +#endif + __raw_writel(val, usbother_base + USB_H1_CTRL_OFFSET); + + val = __raw_readl(usbother_base + USB_H1_CTRL_OFFSET); + val |= UCTRL_OVER_CUR_DIS; + __raw_writel(val, usbother_base + USB_H1_CTRL_OFFSET); +} + +int ehci_hcd_init(void) +{ + struct usb_ehci *ehci; + + enable_usboh3_clk(1); + mdelay(1); + + /* Do board specific initialization */ + board_ehci_hcd_init(CONFIG_MXC_USB_PORT); + +#if CONFIG_MXC_USB_PORT == 1 + /* USB Host 1 */ + usbh1_power_config(); + usbh1_oc_config(); + usbh1_internal_phy_clock_gate(1); + usbh1_phy_enable(); +#else +#error "MXC USB port not yet supported" +#endif + + ehci = (struct usb_ehci *)(USBOH3_USB_BASE_ADDR + + (0x200 * CONFIG_MXC_USB_PORT)); + hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); + hcor = (struct ehci_hcor *)((uint32_t)hccr + + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); + setbits_le32(&ehci->usbmode, CM_HOST); + + __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); + setbits_le32(&ehci->portsc, USB_EN); + + mdelay(10); + + return 0; +} + +int ehci_hcd_stop(void) +{ + return 0; +} -- cgit v1.3.1 From b228e14e9653fe4ead0f39a7a879d1a50e61321a Mon Sep 17 00:00:00 2001 From: Robert Delien Date: Sun, 26 Feb 2012 12:15:05 +0000 Subject: Renamed mx28_register to mx28_register_32 to prepare for mx28_register_8 This patch renames mx28_register to mx28_register_32 in order to prepare for the introduction of an 8-bit register, mx28_register_8. Signed-off-by: Robert Delien Acked-by: Marek Vasut Tested-by: Marek Vasut --- arch/arm/cpu/arm926ejs/mx28/clock.c | 4 +- arch/arm/cpu/arm926ejs/mx28/iomux.c | 6 +- arch/arm/cpu/arm926ejs/mx28/mx28.c | 6 +- arch/arm/include/asm/arch-mx28/regs-apbh.h | 254 +++++++++++++------------- arch/arm/include/asm/arch-mx28/regs-bch.h | 42 ++--- arch/arm/include/asm/arch-mx28/regs-clkctrl.h | 58 +++--- arch/arm/include/asm/arch-mx28/regs-common.h | 12 +- arch/arm/include/asm/arch-mx28/regs-gpmi.h | 26 +-- arch/arm/include/asm/arch-mx28/regs-i2c.h | 28 +-- arch/arm/include/asm/arch-mx28/regs-ocotp.h | 86 ++++----- arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 168 ++++++++--------- arch/arm/include/asm/arch-mx28/regs-power.h | 28 +-- arch/arm/include/asm/arch-mx28/regs-rtc.h | 28 +-- arch/arm/include/asm/arch-mx28/regs-ssp.h | 40 ++-- arch/arm/include/asm/arch-mx28/regs-timrot.h | 38 ++-- arch/arm/include/asm/arch-mx28/regs-usbphy.h | 20 +- arch/arm/include/asm/arch-mx28/sys_proto.h | 10 +- drivers/gpio/mxs_gpio.c | 16 +- drivers/usb/host/ehci-mxs.c | 8 +- 19 files changed, 441 insertions(+), 437 deletions(-) (limited to 'drivers') diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c index f698506007d..9d3a018bf2d 100644 --- a/arch/arm/cpu/arm926ejs/mx28/clock.c +++ b/arch/arm/cpu/arm926ejs/mx28/clock.c @@ -223,7 +223,7 @@ void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal) return; clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + - (ssp * sizeof(struct mx28_register)); + (ssp * sizeof(struct mx28_register_32)); clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE); while (readl(clkreg) & CLKCTRL_SSP_CLKGATE) @@ -272,7 +272,7 @@ static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp) return XTAL_FREQ_KHZ; clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + - (ssp * sizeof(struct mx28_register)); + (ssp * sizeof(struct mx28_register_32)); tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK; diff --git a/arch/arm/cpu/arm926ejs/mx28/iomux.c b/arch/arm/cpu/arm926ejs/mx28/iomux.c index 9ea411f22ad..12916b6d606 100644 --- a/arch/arm/cpu/arm926ejs/mx28/iomux.c +++ b/arch/arm/cpu/arm926ejs/mx28/iomux.c @@ -43,7 +43,7 @@ int mxs_iomux_setup_pad(iomux_cfg_t pad) { u32 reg, ofs, bp, bm; void *iomux_base = (void *)MXS_PINCTRL_BASE; - struct mx28_register *mxs_reg; + struct mx28_register_32 *mxs_reg; /* muxsel */ ofs = 0x100; @@ -70,7 +70,7 @@ int mxs_iomux_setup_pad(iomux_cfg_t pad) /* vol */ if (PAD_VOL_VALID(pad)) { bp = PAD_PIN(pad) % 8 * 4 + 2; - mxs_reg = (struct mx28_register *)(iomux_base + ofs); + mxs_reg = (struct mx28_register_32 *)(iomux_base + ofs); if (PAD_VOL(pad)) writel(1 << bp, &mxs_reg->reg_set); else @@ -82,7 +82,7 @@ int mxs_iomux_setup_pad(iomux_cfg_t pad) ofs = PULL_OFFSET; ofs += PAD_BANK(pad) * 0x10; bp = PAD_PIN(pad); - mxs_reg = (struct mx28_register *)(iomux_base + ofs); + mxs_reg = (struct mx28_register_32 *)(iomux_base + ofs); if (PAD_PULL(pad)) writel(1 << bp, &mxs_reg->reg_set); else diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c index b235091c25a..9bfd83bab97 100644 --- a/arch/arm/cpu/arm926ejs/mx28/mx28.c +++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c @@ -63,7 +63,7 @@ void reset_cpu(ulong ignored) ; } -int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout) +int mx28_wait_mask_set(struct mx28_register_32 *reg, uint32_t mask, int timeout) { while (--timeout) { if ((readl(®->reg) & mask) == mask) @@ -74,7 +74,7 @@ int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout) return !timeout; } -int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout) +int mx28_wait_mask_clr(struct mx28_register_32 *reg, uint32_t mask, int timeout) { while (--timeout) { if ((readl(®->reg) & mask) == 0) @@ -85,7 +85,7 @@ int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout) return !timeout; } -int mx28_reset_block(struct mx28_register *reg) +int mx28_reset_block(struct mx28_register_32 *reg) { /* Clear SFTRST */ writel(MX28_BLOCK_SFTRST, ®->reg_clr); diff --git a/arch/arm/include/asm/arch-mx28/regs-apbh.h b/arch/arm/include/asm/arch-mx28/regs-apbh.h index a7fa1ec1ca4..91d7bc8400b 100644 --- a/arch/arm/include/asm/arch-mx28/regs-apbh.h +++ b/arch/arm/include/asm/arch-mx28/regs-apbh.h @@ -30,142 +30,142 @@ #ifndef __ASSEMBLY__ struct mx28_apbh_regs { - mx28_reg(hw_apbh_ctrl0) - mx28_reg(hw_apbh_ctrl1) - mx28_reg(hw_apbh_ctrl2) - mx28_reg(hw_apbh_channel_ctrl) - mx28_reg(hw_apbh_devsel) - mx28_reg(hw_apbh_dma_burst_size) - mx28_reg(hw_apbh_debug) + mx28_reg_32(hw_apbh_ctrl0) + mx28_reg_32(hw_apbh_ctrl1) + mx28_reg_32(hw_apbh_ctrl2) + mx28_reg_32(hw_apbh_channel_ctrl) + mx28_reg_32(hw_apbh_devsel) + mx28_reg_32(hw_apbh_dma_burst_size) + mx28_reg_32(hw_apbh_debug) uint32_t reserved[36]; union { struct { - mx28_reg(hw_apbh_ch_curcmdar) - mx28_reg(hw_apbh_ch_nxtcmdar) - mx28_reg(hw_apbh_ch_cmd) - mx28_reg(hw_apbh_ch_bar) - mx28_reg(hw_apbh_ch_sema) - mx28_reg(hw_apbh_ch_debug1) - mx28_reg(hw_apbh_ch_debug2) + mx28_reg_32(hw_apbh_ch_curcmdar) + mx28_reg_32(hw_apbh_ch_nxtcmdar) + mx28_reg_32(hw_apbh_ch_cmd) + mx28_reg_32(hw_apbh_ch_bar) + mx28_reg_32(hw_apbh_ch_sema) + mx28_reg_32(hw_apbh_ch_debug1) + mx28_reg_32(hw_apbh_ch_debug2) } ch[16]; struct { - mx28_reg(hw_apbh_ch0_curcmdar) - mx28_reg(hw_apbh_ch0_nxtcmdar) - mx28_reg(hw_apbh_ch0_cmd) - mx28_reg(hw_apbh_ch0_bar) - mx28_reg(hw_apbh_ch0_sema) - mx28_reg(hw_apbh_ch0_debug1) - mx28_reg(hw_apbh_ch0_debug2) - mx28_reg(hw_apbh_ch1_curcmdar) - mx28_reg(hw_apbh_ch1_nxtcmdar) - mx28_reg(hw_apbh_ch1_cmd) - mx28_reg(hw_apbh_ch1_bar) - mx28_reg(hw_apbh_ch1_sema) - mx28_reg(hw_apbh_ch1_debug1) - mx28_reg(hw_apbh_ch1_debug2) - mx28_reg(hw_apbh_ch2_curcmdar) - mx28_reg(hw_apbh_ch2_nxtcmdar) - mx28_reg(hw_apbh_ch2_cmd) - mx28_reg(hw_apbh_ch2_bar) - mx28_reg(hw_apbh_ch2_sema) - mx28_reg(hw_apbh_ch2_debug1) - mx28_reg(hw_apbh_ch2_debug2) - mx28_reg(hw_apbh_ch3_curcmdar) - mx28_reg(hw_apbh_ch3_nxtcmdar) - mx28_reg(hw_apbh_ch3_cmd) - mx28_reg(hw_apbh_ch3_bar) - mx28_reg(hw_apbh_ch3_sema) - mx28_reg(hw_apbh_ch3_debug1) - mx28_reg(hw_apbh_ch3_debug2) - mx28_reg(hw_apbh_ch4_curcmdar) - mx28_reg(hw_apbh_ch4_nxtcmdar) - mx28_reg(hw_apbh_ch4_cmd) - mx28_reg(hw_apbh_ch4_bar) - mx28_reg(hw_apbh_ch4_sema) - mx28_reg(hw_apbh_ch4_debug1) - mx28_reg(hw_apbh_ch4_debug2) - mx28_reg(hw_apbh_ch5_curcmdar) - mx28_reg(hw_apbh_ch5_nxtcmdar) - mx28_reg(hw_apbh_ch5_cmd) - mx28_reg(hw_apbh_ch5_bar) - mx28_reg(hw_apbh_ch5_sema) - mx28_reg(hw_apbh_ch5_debug1) - mx28_reg(hw_apbh_ch5_debug2) - mx28_reg(hw_apbh_ch6_curcmdar) - mx28_reg(hw_apbh_ch6_nxtcmdar) - mx28_reg(hw_apbh_ch6_cmd) - mx28_reg(hw_apbh_ch6_bar) - mx28_reg(hw_apbh_ch6_sema) - mx28_reg(hw_apbh_ch6_debug1) - mx28_reg(hw_apbh_ch6_debug2) - mx28_reg(hw_apbh_ch7_curcmdar) - mx28_reg(hw_apbh_ch7_nxtcmdar) - mx28_reg(hw_apbh_ch7_cmd) - mx28_reg(hw_apbh_ch7_bar) - mx28_reg(hw_apbh_ch7_sema) - mx28_reg(hw_apbh_ch7_debug1) - mx28_reg(hw_apbh_ch7_debug2) - mx28_reg(hw_apbh_ch8_curcmdar) - mx28_reg(hw_apbh_ch8_nxtcmdar) - mx28_reg(hw_apbh_ch8_cmd) - mx28_reg(hw_apbh_ch8_bar) - mx28_reg(hw_apbh_ch8_sema) - mx28_reg(hw_apbh_ch8_debug1) - mx28_reg(hw_apbh_ch8_debug2) - mx28_reg(hw_apbh_ch9_curcmdar) - mx28_reg(hw_apbh_ch9_nxtcmdar) - mx28_reg(hw_apbh_ch9_cmd) - mx28_reg(hw_apbh_ch9_bar) - mx28_reg(hw_apbh_ch9_sema) - mx28_reg(hw_apbh_ch9_debug1) - mx28_reg(hw_apbh_ch9_debug2) - mx28_reg(hw_apbh_ch10_curcmdar) - mx28_reg(hw_apbh_ch10_nxtcmdar) - mx28_reg(hw_apbh_ch10_cmd) - mx28_reg(hw_apbh_ch10_bar) - mx28_reg(hw_apbh_ch10_sema) - mx28_reg(hw_apbh_ch10_debug1) - mx28_reg(hw_apbh_ch10_debug2) - mx28_reg(hw_apbh_ch11_curcmdar) - mx28_reg(hw_apbh_ch11_nxtcmdar) - mx28_reg(hw_apbh_ch11_cmd) - mx28_reg(hw_apbh_ch11_bar) - mx28_reg(hw_apbh_ch11_sema) - mx28_reg(hw_apbh_ch11_debug1) - mx28_reg(hw_apbh_ch11_debug2) - mx28_reg(hw_apbh_ch12_curcmdar) - mx28_reg(hw_apbh_ch12_nxtcmdar) - mx28_reg(hw_apbh_ch12_cmd) - mx28_reg(hw_apbh_ch12_bar) - mx28_reg(hw_apbh_ch12_sema) - mx28_reg(hw_apbh_ch12_debug1) - mx28_reg(hw_apbh_ch12_debug2) - mx28_reg(hw_apbh_ch13_curcmdar) - mx28_reg(hw_apbh_ch13_nxtcmdar) - mx28_reg(hw_apbh_ch13_cmd) - mx28_reg(hw_apbh_ch13_bar) - mx28_reg(hw_apbh_ch13_sema) - mx28_reg(hw_apbh_ch13_debug1) - mx28_reg(hw_apbh_ch13_debug2) - mx28_reg(hw_apbh_ch14_curcmdar) - mx28_reg(hw_apbh_ch14_nxtcmdar) - mx28_reg(hw_apbh_ch14_cmd) - mx28_reg(hw_apbh_ch14_bar) - mx28_reg(hw_apbh_ch14_sema) - mx28_reg(hw_apbh_ch14_debug1) - mx28_reg(hw_apbh_ch14_debug2) - mx28_reg(hw_apbh_ch15_curcmdar) - mx28_reg(hw_apbh_ch15_nxtcmdar) - mx28_reg(hw_apbh_ch15_cmd) - mx28_reg(hw_apbh_ch15_bar) - mx28_reg(hw_apbh_ch15_sema) - mx28_reg(hw_apbh_ch15_debug1) - mx28_reg(hw_apbh_ch15_debug2) + mx28_reg_32(hw_apbh_ch0_curcmdar) + mx28_reg_32(hw_apbh_ch0_nxtcmdar) + mx28_reg_32(hw_apbh_ch0_cmd) + mx28_reg_32(hw_apbh_ch0_bar) + mx28_reg_32(hw_apbh_ch0_sema) + mx28_reg_32(hw_apbh_ch0_debug1) + mx28_reg_32(hw_apbh_ch0_debug2) + mx28_reg_32(hw_apbh_ch1_curcmdar) + mx28_reg_32(hw_apbh_ch1_nxtcmdar) + mx28_reg_32(hw_apbh_ch1_cmd) + mx28_reg_32(hw_apbh_ch1_bar) + mx28_reg_32(hw_apbh_ch1_sema) + mx28_reg_32(hw_apbh_ch1_debug1) + mx28_reg_32(hw_apbh_ch1_debug2) + mx28_reg_32(hw_apbh_ch2_curcmdar) + mx28_reg_32(hw_apbh_ch2_nxtcmdar) + mx28_reg_32(hw_apbh_ch2_cmd) + mx28_reg_32(hw_apbh_ch2_bar) + mx28_reg_32(hw_apbh_ch2_sema) + mx28_reg_32(hw_apbh_ch2_debug1) + mx28_reg_32(hw_apbh_ch2_debug2) + mx28_reg_32(hw_apbh_ch3_curcmdar) + mx28_reg_32(hw_apbh_ch3_nxtcmdar) + mx28_reg_32(hw_apbh_ch3_cmd) + mx28_reg_32(hw_apbh_ch3_bar) + mx28_reg_32(hw_apbh_ch3_sema) + mx28_reg_32(hw_apbh_ch3_debug1) + mx28_reg_32(hw_apbh_ch3_debug2) + mx28_reg_32(hw_apbh_ch4_curcmdar) + mx28_reg_32(hw_apbh_ch4_nxtcmdar) + mx28_reg_32(hw_apbh_ch4_cmd) + mx28_reg_32(hw_apbh_ch4_bar) + mx28_reg_32(hw_apbh_ch4_sema) + mx28_reg_32(hw_apbh_ch4_debug1) + mx28_reg_32(hw_apbh_ch4_debug2) + mx28_reg_32(hw_apbh_ch5_curcmdar) + mx28_reg_32(hw_apbh_ch5_nxtcmdar) + mx28_reg_32(hw_apbh_ch5_cmd) + mx28_reg_32(hw_apbh_ch5_bar) + mx28_reg_32(hw_apbh_ch5_sema) + mx28_reg_32(hw_apbh_ch5_debug1) + mx28_reg_32(hw_apbh_ch5_debug2) + mx28_reg_32(hw_apbh_ch6_curcmdar) + mx28_reg_32(hw_apbh_ch6_nxtcmdar) + mx28_reg_32(hw_apbh_ch6_cmd) + mx28_reg_32(hw_apbh_ch6_bar) + mx28_reg_32(hw_apbh_ch6_sema) + mx28_reg_32(hw_apbh_ch6_debug1) + mx28_reg_32(hw_apbh_ch6_debug2) + mx28_reg_32(hw_apbh_ch7_curcmdar) + mx28_reg_32(hw_apbh_ch7_nxtcmdar) + mx28_reg_32(hw_apbh_ch7_cmd) + mx28_reg_32(hw_apbh_ch7_bar) + mx28_reg_32(hw_apbh_ch7_sema) + mx28_reg_32(hw_apbh_ch7_debug1) + mx28_reg_32(hw_apbh_ch7_debug2) + mx28_reg_32(hw_apbh_ch8_curcmdar) + mx28_reg_32(hw_apbh_ch8_nxtcmdar) + mx28_reg_32(hw_apbh_ch8_cmd) + mx28_reg_32(hw_apbh_ch8_bar) + mx28_reg_32(hw_apbh_ch8_sema) + mx28_reg_32(hw_apbh_ch8_debug1) + mx28_reg_32(hw_apbh_ch8_debug2) + mx28_reg_32(hw_apbh_ch9_curcmdar) + mx28_reg_32(hw_apbh_ch9_nxtcmdar) + mx28_reg_32(hw_apbh_ch9_cmd) + mx28_reg_32(hw_apbh_ch9_bar) + mx28_reg_32(hw_apbh_ch9_sema) + mx28_reg_32(hw_apbh_ch9_debug1) + mx28_reg_32(hw_apbh_ch9_debug2) + mx28_reg_32(hw_apbh_ch10_curcmdar) + mx28_reg_32(hw_apbh_ch10_nxtcmdar) + mx28_reg_32(hw_apbh_ch10_cmd) + mx28_reg_32(hw_apbh_ch10_bar) + mx28_reg_32(hw_apbh_ch10_sema) + mx28_reg_32(hw_apbh_ch10_debug1) + mx28_reg_32(hw_apbh_ch10_debug2) + mx28_reg_32(hw_apbh_ch11_curcmdar) + mx28_reg_32(hw_apbh_ch11_nxtcmdar) + mx28_reg_32(hw_apbh_ch11_cmd) + mx28_reg_32(hw_apbh_ch11_bar) + mx28_reg_32(hw_apbh_ch11_sema) + mx28_reg_32(hw_apbh_ch11_debug1) + mx28_reg_32(hw_apbh_ch11_debug2) + mx28_reg_32(hw_apbh_ch12_curcmdar) + mx28_reg_32(hw_apbh_ch12_nxtcmdar) + mx28_reg_32(hw_apbh_ch12_cmd) + mx28_reg_32(hw_apbh_ch12_bar) + mx28_reg_32(hw_apbh_ch12_sema) + mx28_reg_32(hw_apbh_ch12_debug1) + mx28_reg_32(hw_apbh_ch12_debug2) + mx28_reg_32(hw_apbh_ch13_curcmdar) + mx28_reg_32(hw_apbh_ch13_nxtcmdar) + mx28_reg_32(hw_apbh_ch13_cmd) + mx28_reg_32(hw_apbh_ch13_bar) + mx28_reg_32(hw_apbh_ch13_sema) + mx28_reg_32(hw_apbh_ch13_debug1) + mx28_reg_32(hw_apbh_ch13_debug2) + mx28_reg_32(hw_apbh_ch14_curcmdar) + mx28_reg_32(hw_apbh_ch14_nxtcmdar) + mx28_reg_32(hw_apbh_ch14_cmd) + mx28_reg_32(hw_apbh_ch14_bar) + mx28_reg_32(hw_apbh_ch14_sema) + mx28_reg_32(hw_apbh_ch14_debug1) + mx28_reg_32(hw_apbh_ch14_debug2) + mx28_reg_32(hw_apbh_ch15_curcmdar) + mx28_reg_32(hw_apbh_ch15_nxtcmdar) + mx28_reg_32(hw_apbh_ch15_cmd) + mx28_reg_32(hw_apbh_ch15_bar) + mx28_reg_32(hw_apbh_ch15_sema) + mx28_reg_32(hw_apbh_ch15_debug1) + mx28_reg_32(hw_apbh_ch15_debug2) }; }; - mx28_reg(hw_apbh_version) + mx28_reg_32(hw_apbh_version) }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-bch.h b/arch/arm/include/asm/arch-mx28/regs-bch.h index cac04709dab..9243bdd1c03 100644 --- a/arch/arm/include/asm/arch-mx28/regs-bch.h +++ b/arch/arm/include/asm/arch-mx28/regs-bch.h @@ -30,30 +30,30 @@ #ifndef __ASSEMBLY__ struct mx28_bch_regs { - mx28_reg(hw_bch_ctrl) - mx28_reg(hw_bch_status0) - mx28_reg(hw_bch_mode) - mx28_reg(hw_bch_encodeptr) - mx28_reg(hw_bch_dataptr) - mx28_reg(hw_bch_metaptr) + mx28_reg_32(hw_bch_ctrl) + mx28_reg_32(hw_bch_status0) + mx28_reg_32(hw_bch_mode) + mx28_reg_32(hw_bch_encodeptr) + mx28_reg_32(hw_bch_dataptr) + mx28_reg_32(hw_bch_metaptr) uint32_t reserved[4]; - mx28_reg(hw_bch_layoutselect) - mx28_reg(hw_bch_flash0layout0) - mx28_reg(hw_bch_flash0layout1) - mx28_reg(hw_bch_flash1layout0) - mx28_reg(hw_bch_flash1layout1) - mx28_reg(hw_bch_flash2layout0) - mx28_reg(hw_bch_flash2layout1) - mx28_reg(hw_bch_flash3layout0) - mx28_reg(hw_bch_flash3layout1) - mx28_reg(hw_bch_dbgkesread) - mx28_reg(hw_bch_dbgcsferead) - mx28_reg(hw_bch_dbgsyndegread) - mx28_reg(hw_bch_dbgahbmread) - mx28_reg(hw_bch_blockname) - mx28_reg(hw_bch_version) + mx28_reg_32(hw_bch_layoutselect) + mx28_reg_32(hw_bch_flash0layout0) + mx28_reg_32(hw_bch_flash0layout1) + mx28_reg_32(hw_bch_flash1layout0) + mx28_reg_32(hw_bch_flash1layout1) + mx28_reg_32(hw_bch_flash2layout0) + mx28_reg_32(hw_bch_flash2layout1) + mx28_reg_32(hw_bch_flash3layout0) + mx28_reg_32(hw_bch_flash3layout1) + mx28_reg_32(hw_bch_dbgkesread) + mx28_reg_32(hw_bch_dbgcsferead) + mx28_reg_32(hw_bch_dbgsyndegread) + mx28_reg_32(hw_bch_dbgahbmread) + mx28_reg_32(hw_bch_blockname) + mx28_reg_32(hw_bch_version) }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h index 93d0397ef71..8e666ee8ae9 100644 --- a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h +++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h @@ -30,38 +30,38 @@ #ifndef __ASSEMBLY__ struct mx28_clkctrl_regs { - mx28_reg(hw_clkctrl_pll0ctrl0) /* 0x00 */ - mx28_reg(hw_clkctrl_pll0ctrl1) /* 0x10 */ - mx28_reg(hw_clkctrl_pll1ctrl0) /* 0x20 */ - mx28_reg(hw_clkctrl_pll1ctrl1) /* 0x30 */ - mx28_reg(hw_clkctrl_pll2ctrl0) /* 0x40 */ - mx28_reg(hw_clkctrl_cpu) /* 0x50 */ - mx28_reg(hw_clkctrl_hbus) /* 0x60 */ - mx28_reg(hw_clkctrl_xbus) /* 0x70 */ - mx28_reg(hw_clkctrl_xtal) /* 0x80 */ - mx28_reg(hw_clkctrl_ssp0) /* 0x90 */ - mx28_reg(hw_clkctrl_ssp1) /* 0xa0 */ - mx28_reg(hw_clkctrl_ssp2) /* 0xb0 */ - mx28_reg(hw_clkctrl_ssp3) /* 0xc0 */ - mx28_reg(hw_clkctrl_gpmi) /* 0xd0 */ - mx28_reg(hw_clkctrl_spdif) /* 0xe0 */ - mx28_reg(hw_clkctrl_emi) /* 0xf0 */ - mx28_reg(hw_clkctrl_saif0) /* 0x100 */ - mx28_reg(hw_clkctrl_saif1) /* 0x110 */ - mx28_reg(hw_clkctrl_lcdif) /* 0x120 */ - mx28_reg(hw_clkctrl_etm) /* 0x130 */ - mx28_reg(hw_clkctrl_enet) /* 0x140 */ - mx28_reg(hw_clkctrl_hsadc) /* 0x150 */ - mx28_reg(hw_clkctrl_flexcan) /* 0x160 */ + mx28_reg_32(hw_clkctrl_pll0ctrl0) /* 0x00 */ + mx28_reg_32(hw_clkctrl_pll0ctrl1) /* 0x10 */ + mx28_reg_32(hw_clkctrl_pll1ctrl0) /* 0x20 */ + mx28_reg_32(hw_clkctrl_pll1ctrl1) /* 0x30 */ + mx28_reg_32(hw_clkctrl_pll2ctrl0) /* 0x40 */ + mx28_reg_32(hw_clkctrl_cpu) /* 0x50 */ + mx28_reg_32(hw_clkctrl_hbus) /* 0x60 */ + mx28_reg_32(hw_clkctrl_xbus) /* 0x70 */ + mx28_reg_32(hw_clkctrl_xtal) /* 0x80 */ + mx28_reg_32(hw_clkctrl_ssp0) /* 0x90 */ + mx28_reg_32(hw_clkctrl_ssp1) /* 0xa0 */ + mx28_reg_32(hw_clkctrl_ssp2) /* 0xb0 */ + mx28_reg_32(hw_clkctrl_ssp3) /* 0xc0 */ + mx28_reg_32(hw_clkctrl_gpmi) /* 0xd0 */ + mx28_reg_32(hw_clkctrl_spdif) /* 0xe0 */ + mx28_reg_32(hw_clkctrl_emi) /* 0xf0 */ + mx28_reg_32(hw_clkctrl_saif0) /* 0x100 */ + mx28_reg_32(hw_clkctrl_saif1) /* 0x110 */ + mx28_reg_32(hw_clkctrl_lcdif) /* 0x120 */ + mx28_reg_32(hw_clkctrl_etm) /* 0x130 */ + mx28_reg_32(hw_clkctrl_enet) /* 0x140 */ + mx28_reg_32(hw_clkctrl_hsadc) /* 0x150 */ + mx28_reg_32(hw_clkctrl_flexcan) /* 0x160 */ uint32_t reserved[16]; - mx28_reg(hw_clkctrl_frac0) /* 0x1b0 */ - mx28_reg(hw_clkctrl_frac1) /* 0x1c0 */ - mx28_reg(hw_clkctrl_clkseq) /* 0x1d0 */ - mx28_reg(hw_clkctrl_reset) /* 0x1e0 */ - mx28_reg(hw_clkctrl_status) /* 0x1f0 */ - mx28_reg(hw_clkctrl_version) /* 0x200 */ + mx28_reg_32(hw_clkctrl_frac0) /* 0x1b0 */ + mx28_reg_32(hw_clkctrl_frac1) /* 0x1c0 */ + mx28_reg_32(hw_clkctrl_clkseq) /* 0x1d0 */ + mx28_reg_32(hw_clkctrl_reset) /* 0x1e0 */ + mx28_reg_32(hw_clkctrl_status) /* 0x1f0 */ + mx28_reg_32(hw_clkctrl_version) /* 0x200 */ }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-common.h b/arch/arm/include/asm/arch-mx28/regs-common.h index efe975b4bb2..75cc9a67b61 100644 --- a/arch/arm/include/asm/arch-mx28/regs-common.h +++ b/arch/arm/include/asm/arch-mx28/regs-common.h @@ -47,20 +47,20 @@ * */ -#define __mx28_reg(name) \ +#define __mx28_reg_32(name) \ uint32_t name; \ uint32_t name##_set; \ uint32_t name##_clr; \ uint32_t name##_tog; -struct mx28_register { - __mx28_reg(reg) +struct mx28_register_32 { + __mx28_reg_32(reg) }; -#define mx28_reg(name) \ +#define mx28_reg_32(name) \ union { \ - struct { __mx28_reg(name) }; \ - struct mx28_register name##_reg; \ + struct { __mx28_reg_32(name) }; \ + struct mx28_register_32 name##_reg; \ }; #endif /* __MX28_REGS_COMMON_H__ */ diff --git a/arch/arm/include/asm/arch-mx28/regs-gpmi.h b/arch/arm/include/asm/arch-mx28/regs-gpmi.h index 00967938f5a..1b487f46c64 100644 --- a/arch/arm/include/asm/arch-mx28/regs-gpmi.h +++ b/arch/arm/include/asm/arch-mx28/regs-gpmi.h @@ -30,22 +30,22 @@ #ifndef __ASSEMBLY__ struct mx28_gpmi_regs { - mx28_reg(hw_gpmi_ctrl0) - mx28_reg(hw_gpmi_compare) - mx28_reg(hw_gpmi_eccctrl) - mx28_reg(hw_gpmi_ecccount) - mx28_reg(hw_gpmi_payload) - mx28_reg(hw_gpmi_auxiliary) - mx28_reg(hw_gpmi_ctrl1) - mx28_reg(hw_gpmi_timing0) - mx28_reg(hw_gpmi_timing1) + mx28_reg_32(hw_gpmi_ctrl0) + mx28_reg_32(hw_gpmi_compare) + mx28_reg_32(hw_gpmi_eccctrl) + mx28_reg_32(hw_gpmi_ecccount) + mx28_reg_32(hw_gpmi_payload) + mx28_reg_32(hw_gpmi_auxiliary) + mx28_reg_32(hw_gpmi_ctrl1) + mx28_reg_32(hw_gpmi_timing0) + mx28_reg_32(hw_gpmi_timing1) uint32_t reserved[4]; - mx28_reg(hw_gpmi_data) - mx28_reg(hw_gpmi_stat) - mx28_reg(hw_gpmi_debug) - mx28_reg(hw_gpmi_version) + mx28_reg_32(hw_gpmi_data) + mx28_reg_32(hw_gpmi_stat) + mx28_reg_32(hw_gpmi_debug) + mx28_reg_32(hw_gpmi_version) }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-i2c.h b/arch/arm/include/asm/arch-mx28/regs-i2c.h index 30e0ed7433f..2e2e81453d8 100644 --- a/arch/arm/include/asm/arch-mx28/regs-i2c.h +++ b/arch/arm/include/asm/arch-mx28/regs-i2c.h @@ -27,20 +27,20 @@ #ifndef __ASSEMBLY__ struct mx28_i2c_regs { - mx28_reg(hw_i2c_ctrl0) - mx28_reg(hw_i2c_timing0) - mx28_reg(hw_i2c_timing1) - mx28_reg(hw_i2c_timing2) - mx28_reg(hw_i2c_ctrl1) - mx28_reg(hw_i2c_stat) - mx28_reg(hw_i2c_queuectrl) - mx28_reg(hw_i2c_queuestat) - mx28_reg(hw_i2c_queuecmd) - mx28_reg(hw_i2c_queuedata) - mx28_reg(hw_i2c_data) - mx28_reg(hw_i2c_debug0) - mx28_reg(hw_i2c_debug1) - mx28_reg(hw_i2c_version) + mx28_reg_32(hw_i2c_ctrl0) + mx28_reg_32(hw_i2c_timing0) + mx28_reg_32(hw_i2c_timing1) + mx28_reg_32(hw_i2c_timing2) + mx28_reg_32(hw_i2c_ctrl1) + mx28_reg_32(hw_i2c_stat) + mx28_reg_32(hw_i2c_queuectrl) + mx28_reg_32(hw_i2c_queuestat) + mx28_reg_32(hw_i2c_queuecmd) + mx28_reg_32(hw_i2c_queuedata) + mx28_reg_32(hw_i2c_data) + mx28_reg_32(hw_i2c_debug0) + mx28_reg_32(hw_i2c_debug1) + mx28_reg_32(hw_i2c_version) }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-ocotp.h b/arch/arm/include/asm/arch-mx28/regs-ocotp.h index ea2fd7b167f..27380355192 100644 --- a/arch/arm/include/asm/arch-mx28/regs-ocotp.h +++ b/arch/arm/include/asm/arch-mx28/regs-ocotp.h @@ -30,49 +30,49 @@ #ifndef __ASSEMBLY__ struct mx28_ocotp_regs { - mx28_reg(hw_ocotp_ctrl) /* 0x0 */ - mx28_reg(hw_ocotp_data) /* 0x10 */ - mx28_reg(hw_ocotp_cust0) /* 0x20 */ - mx28_reg(hw_ocotp_cust1) /* 0x30 */ - mx28_reg(hw_ocotp_cust2) /* 0x40 */ - mx28_reg(hw_ocotp_cust3) /* 0x50 */ - mx28_reg(hw_ocotp_crypto0) /* 0x60 */ - mx28_reg(hw_ocotp_crypto1) /* 0x70 */ - mx28_reg(hw_ocotp_crypto2) /* 0x80 */ - mx28_reg(hw_ocotp_crypto3) /* 0x90 */ - mx28_reg(hw_ocotp_hwcap0) /* 0xa0 */ - mx28_reg(hw_ocotp_hwcap1) /* 0xb0 */ - mx28_reg(hw_ocotp_hwcap2) /* 0xc0 */ - mx28_reg(hw_ocotp_hwcap3) /* 0xd0 */ - mx28_reg(hw_ocotp_hwcap4) /* 0xe0 */ - mx28_reg(hw_ocotp_hwcap5) /* 0xf0 */ - mx28_reg(hw_ocotp_swcap) /* 0x100 */ - mx28_reg(hw_ocotp_custcap) /* 0x110 */ - mx28_reg(hw_ocotp_lock) /* 0x120 */ - mx28_reg(hw_ocotp_ops0) /* 0x130 */ - mx28_reg(hw_ocotp_ops1) /* 0x140 */ - mx28_reg(hw_ocotp_ops2) /* 0x150 */ - mx28_reg(hw_ocotp_ops3) /* 0x160 */ - mx28_reg(hw_ocotp_un0) /* 0x170 */ - mx28_reg(hw_ocotp_un1) /* 0x180 */ - mx28_reg(hw_ocotp_un2) /* 0x190 */ - mx28_reg(hw_ocotp_rom0) /* 0x1a0 */ - mx28_reg(hw_ocotp_rom1) /* 0x1b0 */ - mx28_reg(hw_ocotp_rom2) /* 0x1c0 */ - mx28_reg(hw_ocotp_rom3) /* 0x1d0 */ - mx28_reg(hw_ocotp_rom4) /* 0x1e0 */ - mx28_reg(hw_ocotp_rom5) /* 0x1f0 */ - mx28_reg(hw_ocotp_rom6) /* 0x200 */ - mx28_reg(hw_ocotp_rom7) /* 0x210 */ - mx28_reg(hw_ocotp_srk0) /* 0x220 */ - mx28_reg(hw_ocotp_srk1) /* 0x230 */ - mx28_reg(hw_ocotp_srk2) /* 0x240 */ - mx28_reg(hw_ocotp_srk3) /* 0x250 */ - mx28_reg(hw_ocotp_srk4) /* 0x260 */ - mx28_reg(hw_ocotp_srk5) /* 0x270 */ - mx28_reg(hw_ocotp_srk6) /* 0x280 */ - mx28_reg(hw_ocotp_srk7) /* 0x290 */ - mx28_reg(hw_ocotp_version) /* 0x2a0 */ + mx28_reg_32(hw_ocotp_ctrl) /* 0x0 */ + mx28_reg_32(hw_ocotp_data) /* 0x10 */ + mx28_reg_32(hw_ocotp_cust0) /* 0x20 */ + mx28_reg_32(hw_ocotp_cust1) /* 0x30 */ + mx28_reg_32(hw_ocotp_cust2) /* 0x40 */ + mx28_reg_32(hw_ocotp_cust3) /* 0x50 */ + mx28_reg_32(hw_ocotp_crypto0) /* 0x60 */ + mx28_reg_32(hw_ocotp_crypto1) /* 0x70 */ + mx28_reg_32(hw_ocotp_crypto2) /* 0x80 */ + mx28_reg_32(hw_ocotp_crypto3) /* 0x90 */ + mx28_reg_32(hw_ocotp_hwcap0) /* 0xa0 */ + mx28_reg_32(hw_ocotp_hwcap1) /* 0xb0 */ + mx28_reg_32(hw_ocotp_hwcap2) /* 0xc0 */ + mx28_reg_32(hw_ocotp_hwcap3) /* 0xd0 */ + mx28_reg_32(hw_ocotp_hwcap4) /* 0xe0 */ + mx28_reg_32(hw_ocotp_hwcap5) /* 0xf0 */ + mx28_reg_32(hw_ocotp_swcap) /* 0x100 */ + mx28_reg_32(hw_ocotp_custcap) /* 0x110 */ + mx28_reg_32(hw_ocotp_lock) /* 0x120 */ + mx28_reg_32(hw_ocotp_ops0) /* 0x130 */ + mx28_reg_32(hw_ocotp_ops1) /* 0x140 */ + mx28_reg_32(hw_ocotp_ops2) /* 0x150 */ + mx28_reg_32(hw_ocotp_ops3) /* 0x160 */ + mx28_reg_32(hw_ocotp_un0) /* 0x170 */ + mx28_reg_32(hw_ocotp_un1) /* 0x180 */ + mx28_reg_32(hw_ocotp_un2) /* 0x190 */ + mx28_reg_32(hw_ocotp_rom0) /* 0x1a0 */ + mx28_reg_32(hw_ocotp_rom1) /* 0x1b0 */ + mx28_reg_32(hw_ocotp_rom2) /* 0x1c0 */ + mx28_reg_32(hw_ocotp_rom3) /* 0x1d0 */ + mx28_reg_32(hw_ocotp_rom4) /* 0x1e0 */ + mx28_reg_32(hw_ocotp_rom5) /* 0x1f0 */ + mx28_reg_32(hw_ocotp_rom6) /* 0x200 */ + mx28_reg_32(hw_ocotp_rom7) /* 0x210 */ + mx28_reg_32(hw_ocotp_srk0) /* 0x220 */ + mx28_reg_32(hw_ocotp_srk1) /* 0x230 */ + mx28_reg_32(hw_ocotp_srk2) /* 0x240 */ + mx28_reg_32(hw_ocotp_srk3) /* 0x250 */ + mx28_reg_32(hw_ocotp_srk4) /* 0x260 */ + mx28_reg_32(hw_ocotp_srk5) /* 0x270 */ + mx28_reg_32(hw_ocotp_srk6) /* 0x280 */ + mx28_reg_32(hw_ocotp_srk7) /* 0x290 */ + mx28_reg_32(hw_ocotp_version) /* 0x2a0 */ }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-pinctrl.h b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h index 73739cad54d..80dcdf66197 100644 --- a/arch/arm/include/asm/arch-mx28/regs-pinctrl.h +++ b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h @@ -30,129 +30,129 @@ #ifndef __ASSEMBLY__ struct mx28_pinctrl_regs { - mx28_reg(hw_pinctrl_ctrl) /* 0x0 */ + mx28_reg_32(hw_pinctrl_ctrl) /* 0x0 */ uint32_t reserved1[60]; - mx28_reg(hw_pinctrl_muxsel0) /* 0x100 */ - mx28_reg(hw_pinctrl_muxsel1) /* 0x110 */ - mx28_reg(hw_pinctrl_muxsel2) /* 0x120 */ - mx28_reg(hw_pinctrl_muxsel3) /* 0x130 */ - mx28_reg(hw_pinctrl_muxsel4) /* 0x140 */ - mx28_reg(hw_pinctrl_muxsel5) /* 0x150 */ - mx28_reg(hw_pinctrl_muxsel6) /* 0x160 */ - mx28_reg(hw_pinctrl_muxsel7) /* 0x170 */ - mx28_reg(hw_pinctrl_muxsel8) /* 0x180 */ - mx28_reg(hw_pinctrl_muxsel9) /* 0x190 */ - mx28_reg(hw_pinctrl_muxsel10) /* 0x1a0 */ - mx28_reg(hw_pinctrl_muxsel11) /* 0x1b0 */ - mx28_reg(hw_pinctrl_muxsel12) /* 0x1c0 */ - mx28_reg(hw_pinctrl_muxsel13) /* 0x1d0 */ + mx28_reg_32(hw_pinctrl_muxsel0) /* 0x100 */ + mx28_reg_32(hw_pinctrl_muxsel1) /* 0x110 */ + mx28_reg_32(hw_pinctrl_muxsel2) /* 0x120 */ + mx28_reg_32(hw_pinctrl_muxsel3) /* 0x130 */ + mx28_reg_32(hw_pinctrl_muxsel4) /* 0x140 */ + mx28_reg_32(hw_pinctrl_muxsel5) /* 0x150 */ + mx28_reg_32(hw_pinctrl_muxsel6) /* 0x160 */ + mx28_reg_32(hw_pinctrl_muxsel7) /* 0x170 */ + mx28_reg_32(hw_pinctrl_muxsel8) /* 0x180 */ + mx28_reg_32(hw_pinctrl_muxsel9) /* 0x190 */ + mx28_reg_32(hw_pinctrl_muxsel10) /* 0x1a0 */ + mx28_reg_32(hw_pinctrl_muxsel11) /* 0x1b0 */ + mx28_reg_32(hw_pinctrl_muxsel12) /* 0x1c0 */ + mx28_reg_32(hw_pinctrl_muxsel13) /* 0x1d0 */ uint32_t reserved2[72]; - mx28_reg(hw_pinctrl_drive0) /* 0x300 */ - mx28_reg(hw_pinctrl_drive1) /* 0x310 */ - mx28_reg(hw_pinctrl_drive2) /* 0x320 */ - mx28_reg(hw_pinctrl_drive3) /* 0x330 */ - mx28_reg(hw_pinctrl_drive4) /* 0x340 */ - mx28_reg(hw_pinctrl_drive5) /* 0x350 */ - mx28_reg(hw_pinctrl_drive6) /* 0x360 */ - mx28_reg(hw_pinctrl_drive7) /* 0x370 */ - mx28_reg(hw_pinctrl_drive8) /* 0x380 */ - mx28_reg(hw_pinctrl_drive9) /* 0x390 */ - mx28_reg(hw_pinctrl_drive10) /* 0x3a0 */ - mx28_reg(hw_pinctrl_drive11) /* 0x3b0 */ - mx28_reg(hw_pinctrl_drive12) /* 0x3c0 */ - mx28_reg(hw_pinctrl_drive13) /* 0x3d0 */ - mx28_reg(hw_pinctrl_drive14) /* 0x3e0 */ - mx28_reg(hw_pinctrl_drive15) /* 0x3f0 */ - mx28_reg(hw_pinctrl_drive16) /* 0x400 */ - mx28_reg(hw_pinctrl_drive17) /* 0x410 */ - mx28_reg(hw_pinctrl_drive18) /* 0x420 */ - mx28_reg(hw_pinctrl_drive19) /* 0x430 */ + mx28_reg_32(hw_pinctrl_drive0) /* 0x300 */ + mx28_reg_32(hw_pinctrl_drive1) /* 0x310 */ + mx28_reg_32(hw_pinctrl_drive2) /* 0x320 */ + mx28_reg_32(hw_pinctrl_drive3) /* 0x330 */ + mx28_reg_32(hw_pinctrl_drive4) /* 0x340 */ + mx28_reg_32(hw_pinctrl_drive5) /* 0x350 */ + mx28_reg_32(hw_pinctrl_drive6) /* 0x360 */ + mx28_reg_32(hw_pinctrl_drive7) /* 0x370 */ + mx28_reg_32(hw_pinctrl_drive8) /* 0x380 */ + mx28_reg_32(hw_pinctrl_drive9) /* 0x390 */ + mx28_reg_32(hw_pinctrl_drive10) /* 0x3a0 */ + mx28_reg_32(hw_pinctrl_drive11) /* 0x3b0 */ + mx28_reg_32(hw_pinctrl_drive12) /* 0x3c0 */ + mx28_reg_32(hw_pinctrl_drive13) /* 0x3d0 */ + mx28_reg_32(hw_pinctrl_drive14) /* 0x3e0 */ + mx28_reg_32(hw_pinctrl_drive15) /* 0x3f0 */ + mx28_reg_32(hw_pinctrl_drive16) /* 0x400 */ + mx28_reg_32(hw_pinctrl_drive17) /* 0x410 */ + mx28_reg_32(hw_pinctrl_drive18) /* 0x420 */ + mx28_reg_32(hw_pinctrl_drive19) /* 0x430 */ uint32_t reserved3[112]; - mx28_reg(hw_pinctrl_pull0) /* 0x600 */ - mx28_reg(hw_pinctrl_pull1) /* 0x610 */ - mx28_reg(hw_pinctrl_pull2) /* 0x620 */ - mx28_reg(hw_pinctrl_pull3) /* 0x630 */ - mx28_reg(hw_pinctrl_pull4) /* 0x640 */ - mx28_reg(hw_pinctrl_pull5) /* 0x650 */ - mx28_reg(hw_pinctrl_pull6) /* 0x660 */ + mx28_reg_32(hw_pinctrl_pull0) /* 0x600 */ + mx28_reg_32(hw_pinctrl_pull1) /* 0x610 */ + mx28_reg_32(hw_pinctrl_pull2) /* 0x620 */ + mx28_reg_32(hw_pinctrl_pull3) /* 0x630 */ + mx28_reg_32(hw_pinctrl_pull4) /* 0x640 */ + mx28_reg_32(hw_pinctrl_pull5) /* 0x650 */ + mx28_reg_32(hw_pinctrl_pull6) /* 0x660 */ uint32_t reserved4[36]; - mx28_reg(hw_pinctrl_dout0) /* 0x700 */ - mx28_reg(hw_pinctrl_dout1) /* 0x710 */ - mx28_reg(hw_pinctrl_dout2) /* 0x720 */ - mx28_reg(hw_pinctrl_dout3) /* 0x730 */ - mx28_reg(hw_pinctrl_dout4) /* 0x740 */ + mx28_reg_32(hw_pinctrl_dout0) /* 0x700 */ + mx28_reg_32(hw_pinctrl_dout1) /* 0x710 */ + mx28_reg_32(hw_pinctrl_dout2) /* 0x720 */ + mx28_reg_32(hw_pinctrl_dout3) /* 0x730 */ + mx28_reg_32(hw_pinctrl_dout4) /* 0x740 */ uint32_t reserved5[108]; - mx28_reg(hw_pinctrl_din0) /* 0x900 */ - mx28_reg(hw_pinctrl_din1) /* 0x910 */ - mx28_reg(hw_pinctrl_din2) /* 0x920 */ - mx28_reg(hw_pinctrl_din3) /* 0x930 */ - mx28_reg(hw_pinctrl_din4) /* 0x940 */ + mx28_reg_32(hw_pinctrl_din0) /* 0x900 */ + mx28_reg_32(hw_pinctrl_din1) /* 0x910 */ + mx28_reg_32(hw_pinctrl_din2) /* 0x920 */ + mx28_reg_32(hw_pinctrl_din3) /* 0x930 */ + mx28_reg_32(hw_pinctrl_din4) /* 0x940 */ uint32_t reserved6[108]; - mx28_reg(hw_pinctrl_doe0) /* 0xb00 */ - mx28_reg(hw_pinctrl_doe1) /* 0xb10 */ - mx28_reg(hw_pinctrl_doe2) /* 0xb20 */ - mx28_reg(hw_pinctrl_doe3) /* 0xb30 */ - mx28_reg(hw_pinctrl_doe4) /* 0xb40 */ + mx28_reg_32(hw_pinctrl_doe0) /* 0xb00 */ + mx28_reg_32(hw_pinctrl_doe1) /* 0xb10 */ + mx28_reg_32(hw_pinctrl_doe2) /* 0xb20 */ + mx28_reg_32(hw_pinctrl_doe3) /* 0xb30 */ + mx28_reg_32(hw_pinctrl_doe4) /* 0xb40 */ uint32_t reserved7[300]; - mx28_reg(hw_pinctrl_pin2irq0) /* 0x1000 */ - mx28_reg(hw_pinctrl_pin2irq1) /* 0x1010 */ - mx28_reg(hw_pinctrl_pin2irq2) /* 0x1020 */ - mx28_reg(hw_pinctrl_pin2irq3) /* 0x1030 */ - mx28_reg(hw_pinctrl_pin2irq4) /* 0x1040 */ + mx28_reg_32(hw_pinctrl_pin2irq0) /* 0x1000 */ + mx28_reg_32(hw_pinctrl_pin2irq1) /* 0x1010 */ + mx28_reg_32(hw_pinctrl_pin2irq2) /* 0x1020 */ + mx28_reg_32(hw_pinctrl_pin2irq3) /* 0x1030 */ + mx28_reg_32(hw_pinctrl_pin2irq4) /* 0x1040 */ uint32_t reserved8[44]; - mx28_reg(hw_pinctrl_irqen0) /* 0x1100 */ - mx28_reg(hw_pinctrl_irqen1) /* 0x1110 */ - mx28_reg(hw_pinctrl_irqen2) /* 0x1120 */ - mx28_reg(hw_pinctrl_irqen3) /* 0x1130 */ - mx28_reg(hw_pinctrl_irqen4) /* 0x1140 */ + mx28_reg_32(hw_pinctrl_irqen0) /* 0x1100 */ + mx28_reg_32(hw_pinctrl_irqen1) /* 0x1110 */ + mx28_reg_32(hw_pinctrl_irqen2) /* 0x1120 */ + mx28_reg_32(hw_pinctrl_irqen3) /* 0x1130 */ + mx28_reg_32(hw_pinctrl_irqen4) /* 0x1140 */ uint32_t reserved9[44]; - mx28_reg(hw_pinctrl_irqlevel0) /* 0x1200 */ - mx28_reg(hw_pinctrl_irqlevel1) /* 0x1210 */ - mx28_reg(hw_pinctrl_irqlevel2) /* 0x1220 */ - mx28_reg(hw_pinctrl_irqlevel3) /* 0x1230 */ - mx28_reg(hw_pinctrl_irqlevel4) /* 0x1240 */ + mx28_reg_32(hw_pinctrl_irqlevel0) /* 0x1200 */ + mx28_reg_32(hw_pinctrl_irqlevel1) /* 0x1210 */ + mx28_reg_32(hw_pinctrl_irqlevel2) /* 0x1220 */ + mx28_reg_32(hw_pinctrl_irqlevel3) /* 0x1230 */ + mx28_reg_32(hw_pinctrl_irqlevel4) /* 0x1240 */ uint32_t reserved10[44]; - mx28_reg(hw_pinctrl_irqpol0) /* 0x1300 */ - mx28_reg(hw_pinctrl_irqpol1) /* 0x1310 */ - mx28_reg(hw_pinctrl_irqpol2) /* 0x1320 */ - mx28_reg(hw_pinctrl_irqpol3) /* 0x1330 */ - mx28_reg(hw_pinctrl_irqpol4) /* 0x1340 */ + mx28_reg_32(hw_pinctrl_irqpol0) /* 0x1300 */ + mx28_reg_32(hw_pinctrl_irqpol1) /* 0x1310 */ + mx28_reg_32(hw_pinctrl_irqpol2) /* 0x1320 */ + mx28_reg_32(hw_pinctrl_irqpol3) /* 0x1330 */ + mx28_reg_32(hw_pinctrl_irqpol4) /* 0x1340 */ uint32_t reserved11[44]; - mx28_reg(hw_pinctrl_irqstat0) /* 0x1400 */ - mx28_reg(hw_pinctrl_irqstat1) /* 0x1410 */ - mx28_reg(hw_pinctrl_irqstat2) /* 0x1420 */ - mx28_reg(hw_pinctrl_irqstat3) /* 0x1430 */ - mx28_reg(hw_pinctrl_irqstat4) /* 0x1440 */ + mx28_reg_32(hw_pinctrl_irqstat0) /* 0x1400 */ + mx28_reg_32(hw_pinctrl_irqstat1) /* 0x1410 */ + mx28_reg_32(hw_pinctrl_irqstat2) /* 0x1420 */ + mx28_reg_32(hw_pinctrl_irqstat3) /* 0x1430 */ + mx28_reg_32(hw_pinctrl_irqstat4) /* 0x1440 */ uint32_t reserved12[380]; - mx28_reg(hw_pinctrl_emi_odt_ctrl) /* 0x1a40 */ + mx28_reg_32(hw_pinctrl_emi_odt_ctrl) /* 0x1a40 */ uint32_t reserved13[76]; - mx28_reg(hw_pinctrl_emi_ds_ctrl) /* 0x1b80 */ + mx28_reg_32(hw_pinctrl_emi_ds_ctrl) /* 0x1b80 */ }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-power.h b/arch/arm/include/asm/arch-mx28/regs-power.h index 9da63adc2ec..8eadc6d5528 100644 --- a/arch/arm/include/asm/arch-mx28/regs-power.h +++ b/arch/arm/include/asm/arch-mx28/regs-power.h @@ -26,10 +26,10 @@ #ifndef __ASSEMBLY__ struct mx28_power_regs { - mx28_reg(hw_power_ctrl) - mx28_reg(hw_power_5vctrl) - mx28_reg(hw_power_minpwr) - mx28_reg(hw_power_charge) + mx28_reg_32(hw_power_ctrl) + mx28_reg_32(hw_power_5vctrl) + mx28_reg_32(hw_power_minpwr) + mx28_reg_32(hw_power_charge) uint32_t hw_power_vdddctrl; uint32_t reserved_vddd[3]; uint32_t hw_power_vddactrl; @@ -44,23 +44,23 @@ struct mx28_power_regs { uint32_t reserved_misc[3]; uint32_t hw_power_dclimits; uint32_t reserved_dclimits[3]; - mx28_reg(hw_power_loopctrl) + mx28_reg_32(hw_power_loopctrl) uint32_t hw_power_sts; uint32_t reserved_sts[3]; - mx28_reg(hw_power_speed) + mx28_reg_32(hw_power_speed) uint32_t hw_power_battmonitor; uint32_t reserved_battmonitor[3]; uint32_t reserved[4]; - mx28_reg(hw_power_reset) - mx28_reg(hw_power_debug) - mx28_reg(hw_power_thermal) - mx28_reg(hw_power_usb1ctrl) - mx28_reg(hw_power_special) - mx28_reg(hw_power_version) - mx28_reg(hw_power_anaclkctrl) - mx28_reg(hw_power_refctrl) + mx28_reg_32(hw_power_reset) + mx28_reg_32(hw_power_debug) + mx28_reg_32(hw_power_thermal) + mx28_reg_32(hw_power_usb1ctrl) + mx28_reg_32(hw_power_special) + mx28_reg_32(hw_power_version) + mx28_reg_32(hw_power_anaclkctrl) + mx28_reg_32(hw_power_refctrl) }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-rtc.h b/arch/arm/include/asm/arch-mx28/regs-rtc.h index fe2fda96559..e605a03953b 100644 --- a/arch/arm/include/asm/arch-mx28/regs-rtc.h +++ b/arch/arm/include/asm/arch-mx28/regs-rtc.h @@ -27,20 +27,20 @@ #ifndef __ASSEMBLY__ struct mx28_rtc_regs { - mx28_reg(hw_rtc_ctrl) - mx28_reg(hw_rtc_stat) - mx28_reg(hw_rtc_milliseconds) - mx28_reg(hw_rtc_seconds) - mx28_reg(hw_rtc_rtc_alarm) - mx28_reg(hw_rtc_watchdog) - mx28_reg(hw_rtc_persistent0) - mx28_reg(hw_rtc_persistent1) - mx28_reg(hw_rtc_persistent2) - mx28_reg(hw_rtc_persistent3) - mx28_reg(hw_rtc_persistent4) - mx28_reg(hw_rtc_persistent5) - mx28_reg(hw_rtc_debug) - mx28_reg(hw_rtc_version) + mx28_reg_32(hw_rtc_ctrl) + mx28_reg_32(hw_rtc_stat) + mx28_reg_32(hw_rtc_milliseconds) + mx28_reg_32(hw_rtc_seconds) + mx28_reg_32(hw_rtc_rtc_alarm) + mx28_reg_32(hw_rtc_watchdog) + mx28_reg_32(hw_rtc_persistent0) + mx28_reg_32(hw_rtc_persistent1) + mx28_reg_32(hw_rtc_persistent2) + mx28_reg_32(hw_rtc_persistent3) + mx28_reg_32(hw_rtc_persistent4) + mx28_reg_32(hw_rtc_persistent5) + mx28_reg_32(hw_rtc_debug) + mx28_reg_32(hw_rtc_version) }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-ssp.h b/arch/arm/include/asm/arch-mx28/regs-ssp.h index ab3870c149c..be71d489477 100644 --- a/arch/arm/include/asm/arch-mx28/regs-ssp.h +++ b/arch/arm/include/asm/arch-mx28/regs-ssp.h @@ -29,26 +29,26 @@ #ifndef __ASSEMBLY__ struct mx28_ssp_regs { - mx28_reg(hw_ssp_ctrl0) - mx28_reg(hw_ssp_cmd0) - mx28_reg(hw_ssp_cmd1) - mx28_reg(hw_ssp_xfer_size) - mx28_reg(hw_ssp_block_size) - mx28_reg(hw_ssp_compref) - mx28_reg(hw_ssp_compmask) - mx28_reg(hw_ssp_timing) - mx28_reg(hw_ssp_ctrl1) - mx28_reg(hw_ssp_data) - mx28_reg(hw_ssp_sdresp0) - mx28_reg(hw_ssp_sdresp1) - mx28_reg(hw_ssp_sdresp2) - mx28_reg(hw_ssp_sdresp3) - mx28_reg(hw_ssp_ddr_ctrl) - mx28_reg(hw_ssp_dll_ctrl) - mx28_reg(hw_ssp_status) - mx28_reg(hw_ssp_dll_sts) - mx28_reg(hw_ssp_debug) - mx28_reg(hw_ssp_version) + mx28_reg_32(hw_ssp_ctrl0) + mx28_reg_32(hw_ssp_cmd0) + mx28_reg_32(hw_ssp_cmd1) + mx28_reg_32(hw_ssp_xfer_size) + mx28_reg_32(hw_ssp_block_size) + mx28_reg_32(hw_ssp_compref) + mx28_reg_32(hw_ssp_compmask) + mx28_reg_32(hw_ssp_timing) + mx28_reg_32(hw_ssp_ctrl1) + mx28_reg_32(hw_ssp_data) + mx28_reg_32(hw_ssp_sdresp0) + mx28_reg_32(hw_ssp_sdresp1) + mx28_reg_32(hw_ssp_sdresp2) + mx28_reg_32(hw_ssp_sdresp3) + mx28_reg_32(hw_ssp_ddr_ctrl) + mx28_reg_32(hw_ssp_dll_ctrl) + mx28_reg_32(hw_ssp_status) + mx28_reg_32(hw_ssp_dll_sts) + mx28_reg_32(hw_ssp_debug) + mx28_reg_32(hw_ssp_version) }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-timrot.h b/arch/arm/include/asm/arch-mx28/regs-timrot.h index 1b941cf2898..3e8dfe782fd 100644 --- a/arch/arm/include/asm/arch-mx28/regs-timrot.h +++ b/arch/arm/include/asm/arch-mx28/regs-timrot.h @@ -29,25 +29,25 @@ #ifndef __ASSEMBLY__ struct mx28_timrot_regs { - mx28_reg(hw_timrot_rotctrl) - mx28_reg(hw_timrot_rotcount) - mx28_reg(hw_timrot_timctrl0) - mx28_reg(hw_timrot_running_count0) - mx28_reg(hw_timrot_fixed_count0) - mx28_reg(hw_timrot_match_count0) - mx28_reg(hw_timrot_timctrl1) - mx28_reg(hw_timrot_running_count1) - mx28_reg(hw_timrot_fixed_count1) - mx28_reg(hw_timrot_match_count1) - mx28_reg(hw_timrot_timctrl2) - mx28_reg(hw_timrot_running_count2) - mx28_reg(hw_timrot_fixed_count2) - mx28_reg(hw_timrot_match_count2) - mx28_reg(hw_timrot_timctrl3) - mx28_reg(hw_timrot_running_count3) - mx28_reg(hw_timrot_fixed_count3) - mx28_reg(hw_timrot_match_count3) - mx28_reg(hw_timrot_version) + mx28_reg_32(hw_timrot_rotctrl) + mx28_reg_32(hw_timrot_rotcount) + mx28_reg_32(hw_timrot_timctrl0) + mx28_reg_32(hw_timrot_running_count0) + mx28_reg_32(hw_timrot_fixed_count0) + mx28_reg_32(hw_timrot_match_count0) + mx28_reg_32(hw_timrot_timctrl1) + mx28_reg_32(hw_timrot_running_count1) + mx28_reg_32(hw_timrot_fixed_count1) + mx28_reg_32(hw_timrot_match_count1) + mx28_reg_32(hw_timrot_timctrl2) + mx28_reg_32(hw_timrot_running_count2) + mx28_reg_32(hw_timrot_fixed_count2) + mx28_reg_32(hw_timrot_match_count2) + mx28_reg_32(hw_timrot_timctrl3) + mx28_reg_32(hw_timrot_running_count3) + mx28_reg_32(hw_timrot_fixed_count3) + mx28_reg_32(hw_timrot_match_count3) + mx28_reg_32(hw_timrot_version) }; #endif diff --git a/arch/arm/include/asm/arch-mx28/regs-usbphy.h b/arch/arm/include/asm/arch-mx28/regs-usbphy.h index e823e1997db..0291d815c6a 100644 --- a/arch/arm/include/asm/arch-mx28/regs-usbphy.h +++ b/arch/arm/include/asm/arch-mx28/regs-usbphy.h @@ -24,16 +24,16 @@ #define __REGS_USBPHY_H__ struct mx28_usbphy_regs { - mx28_reg(hw_usbphy_pwd) - mx28_reg(hw_usbphy_tx) - mx28_reg(hw_usbphy_rx) - mx28_reg(hw_usbphy_ctrl) - mx28_reg(hw_usbphy_status) - mx28_reg(hw_usbphy_debug) - mx28_reg(hw_usbphy_debug0_status) - mx28_reg(hw_usbphy_debug1) - mx28_reg(hw_usbphy_version) - mx28_reg(hw_usbphy_ip) + mx28_reg_32(hw_usbphy_pwd) + mx28_reg_32(hw_usbphy_tx) + mx28_reg_32(hw_usbphy_rx) + mx28_reg_32(hw_usbphy_ctrl) + mx28_reg_32(hw_usbphy_status) + mx28_reg_32(hw_usbphy_debug) + mx28_reg_32(hw_usbphy_debug0_status) + mx28_reg_32(hw_usbphy_debug1) + mx28_reg_32(hw_usbphy_version) + mx28_reg_32(hw_usbphy_ip) }; #define USBPHY_PWD_RXPWDRX (1 << 20) diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h index f10149477ad..15d8de31ee9 100644 --- a/arch/arm/include/asm/arch-mx28/sys_proto.h +++ b/arch/arm/include/asm/arch-mx28/sys_proto.h @@ -23,9 +23,13 @@ #ifndef __MX28_H__ #define __MX28_H__ -int mx28_reset_block(struct mx28_register *reg); -int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout); -int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout); +int mx28_reset_block(struct mx28_register_32 *reg); +int mx28_wait_mask_set(struct mx28_register_32 *reg, + uint32_t mask, + int timeout); +int mx28_wait_mask_clr(struct mx28_register_32 *reg, + uint32_t mask, + int timeout); int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int)); diff --git a/drivers/gpio/mxs_gpio.c b/drivers/gpio/mxs_gpio.c index 0365812c0a6..38dbc81b451 100644 --- a/drivers/gpio/mxs_gpio.c +++ b/drivers/gpio/mxs_gpio.c @@ -73,8 +73,8 @@ int gpio_get_value(unsigned gpio) { uint32_t bank = PAD_BANK(gpio); uint32_t offset = PINCTRL_DIN(bank); - struct mx28_register *reg = - (struct mx28_register *)(MXS_PINCTRL_BASE + offset); + struct mx28_register_32 *reg = + (struct mx28_register_32 *)(MXS_PINCTRL_BASE + offset); return (readl(®->reg) >> PAD_PIN(gpio)) & 1; } @@ -83,8 +83,8 @@ void gpio_set_value(unsigned gpio, int value) { uint32_t bank = PAD_BANK(gpio); uint32_t offset = PINCTRL_DOUT(bank); - struct mx28_register *reg = - (struct mx28_register *)(MXS_PINCTRL_BASE + offset); + struct mx28_register_32 *reg = + (struct mx28_register_32 *)(MXS_PINCTRL_BASE + offset); if (value) writel(1 << PAD_PIN(gpio), ®->reg_set); @@ -96,8 +96,8 @@ int gpio_direction_input(unsigned gpio) { uint32_t bank = PAD_BANK(gpio); uint32_t offset = PINCTRL_DOE(bank); - struct mx28_register *reg = - (struct mx28_register *)(MXS_PINCTRL_BASE + offset); + struct mx28_register_32 *reg = + (struct mx28_register_32 *)(MXS_PINCTRL_BASE + offset); writel(1 << PAD_PIN(gpio), ®->reg_clr); @@ -108,8 +108,8 @@ int gpio_direction_output(unsigned gpio, int value) { uint32_t bank = PAD_BANK(gpio); uint32_t offset = PINCTRL_DOE(bank); - struct mx28_register *reg = - (struct mx28_register *)(MXS_PINCTRL_BASE + offset); + struct mx28_register_32 *reg = + (struct mx28_register_32 *)(MXS_PINCTRL_BASE + offset); writel(1 << PAD_PIN(gpio), ®->reg_set); diff --git a/drivers/usb/host/ehci-mxs.c b/drivers/usb/host/ehci-mxs.c index c795f23bd7f..e1bd37ec8d5 100644 --- a/drivers/usb/host/ehci-mxs.c +++ b/drivers/usb/host/ehci-mxs.c @@ -75,8 +75,8 @@ int ehci_hcd_init(void) int ret; uint32_t usb_base, cap_base; - struct mx28_register *digctl_ctrl = - (struct mx28_register *)HW_DIGCTL_CTRL; + struct mx28_register_32 *digctl_ctrl = + (struct mx28_register_32 *)HW_DIGCTL_CTRL; struct mx28_clkctrl_regs *clkctrl_regs = (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE; @@ -119,8 +119,8 @@ int ehci_hcd_stop(void) { int ret; uint32_t tmp; - struct mx28_register *digctl_ctrl = - (struct mx28_register *)HW_DIGCTL_CTRL; + struct mx28_register_32 *digctl_ctrl = + (struct mx28_register_32 *)HW_DIGCTL_CTRL; struct mx28_clkctrl_regs *clkctrl_regs = (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE; -- cgit v1.3.1 From a22429d2bfaa16588635a02958ebcd06114dd697 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 16 Mar 2012 11:32:09 +0000 Subject: pmic_i2c: Return error in case of invalid pmic_i2c_tx_num Return error in case of invalid pmic_i2c_tx_num. Signed-off-by: Fabio Estevam Acked-by: Marek Vasut Acked-by: Lukasz Majewski Acked-by: Stefano Babic --- drivers/misc/pmic_i2c.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/pmic_i2c.c b/drivers/misc/pmic_i2c.c index ad55d6447e3..95a3365b9fc 100644 --- a/drivers/misc/pmic_i2c.c +++ b/drivers/misc/pmic_i2c.c @@ -47,6 +47,9 @@ int pmic_reg_write(struct pmic *p, u32 reg, u32 val) case 1: buf[0] = val & 0xff; break; + default: + printf("%s: invalid tx_num: %d", __func__, pmic_i2c_tx_num); + return -1; } if (i2c_write(pmic_i2c_addr, reg, 1, buf, pmic_i2c_tx_num)) @@ -73,6 +76,9 @@ int pmic_reg_read(struct pmic *p, u32 reg, u32 *val) case 1: ret_val = buf[0]; break; + default: + printf("%s: invalid tx_num: %d", __func__, pmic_i2c_tx_num); + return -1; } memcpy(val, &ret_val, sizeof(ret_val)); -- cgit v1.3.1 From d9fb6a4c7e61d735eec2936a8dc3877f83e61d24 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 18 Mar 2012 17:23:35 +0000 Subject: mxs_spi: Return proper timeout error Instead of returning -1, it is preferred to return -ETIMEDOUT in case of timeouts. Signed-off-by: Fabio Estevam Acked-by: Marek Vasut --- drivers/spi/mxs_spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c index adb9ca8ec8f..4e6f14ee072 100644 --- a/drivers/spi/mxs_spi.c +++ b/drivers/spi/mxs_spi.c @@ -162,7 +162,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, if (mx28_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg, SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) { printf("MXS SPI: Timeout waiting for start\n"); - return -1; + return -ETIMEDOUT; } if (tx) @@ -174,7 +174,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_status_reg, SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) { printf("MXS SPI: Timeout waiting for data\n"); - return -1; + return -ETIMEDOUT; } *rx = readl(&ssp_regs->hw_ssp_data); @@ -184,7 +184,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg, SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) { printf("MXS SPI: Timeout waiting for finish\n"); - return -1; + return -ETIMEDOUT; } } -- cgit v1.3.1 From 522b2a02e6569970e18f539577f4fd6ce81bbc42 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 19 Mar 2012 12:36:10 +0000 Subject: USB: ehci-mx6: Add proper IO accessors Add proper IO accessors for mx6 usb registers. Signed-off-by: Fabio Estevam Acked-by: Stefano Babic Acked-by: Marek Vasut Acked-by: Jason Liu --- drivers/usb/host/ehci-mx6.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index b7bf49d6a4b..5dec673c8ef 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -46,13 +46,9 @@ #define USBPHY_CTRL_ENUTMILEVEL3 0x00008000 #define USBPHY_CTRL_ENUTMILEVEL2 0x00004000 -#define ANADIG_USB2_CHRG_DETECT 0x00000210 #define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 #define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 -#define ANADIG_USB2_PLL_480_CTRL 0x00000020 -#define ANADIG_USB2_PLL_480_CTRL_SET 0x00000024 -#define ANADIG_USB2_PLL_480_CTRL_CLR 0x00000028 #define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 #define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 #define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 @@ -77,8 +73,7 @@ static void usbh1_internal_phy_clock_gate(int on) static void usbh1_power_config(void) { - void __iomem *anatop_base = (void __iomem *)ANATOP_BASE_ADDR; - + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; /* * Some phy and power's special controls for host1 * 1. The external charger detector needs to be disabled @@ -89,15 +84,15 @@ static void usbh1_power_config(void) */ __raw_writel(ANADIG_USB2_CHRG_DETECT_EN_B | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, - anatop_base + ANADIG_USB2_CHRG_DETECT); + &anatop->usb2_chrg_detect); __raw_writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, - anatop_base + ANADIG_USB2_PLL_480_CTRL_CLR); + &anatop->usb2_pll_480_ctrl); __raw_writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | ANADIG_USB2_PLL_480_CTRL_POWER | ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, - anatop_base + ANADIG_USB2_PLL_480_CTRL_SET); + &anatop->usb2_pll_480_ctrl_set); } static int usbh1_phy_enable(void) -- cgit v1.3.1 From f7dad8f12164d08577b42492ae8d350a002e9d99 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Wed, 21 Mar 2012 23:56:17 +0000 Subject: NAND: TI: fix warnings in omap_gpmc.c The following warnings are reported for boards using SOFT ECC. omap_gpmc.c:33:30: warning: 'hw_nand_oob' defined but not used omap_gpmc.c:78:13: warning: 'omap_hwecc_init' defined but not used omap_gpmc.c:116:12: warning: 'omap_correct_data' defined but not used omap_gpmc.c:182:12: warning: 'omap_calculate_ecc' defined but not used omap_gpmc.c:208:13: warning: 'omap_enable_hwecc' defined but not used Signed-off-by: Stefano Babic Cc: Tom Rini Cc: Scott Wood --- drivers/mtd/nand/omap_gpmc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index 1dfe074e1e1..ca868efb9f2 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -27,10 +27,12 @@ #include #include #include +#include #include static uint8_t cs; -static struct nand_ecclayout hw_nand_oob = GPMC_NAND_HW_ECC_LAYOUT; +static __maybe_unused struct nand_ecclayout hw_nand_oob = + GPMC_NAND_HW_ECC_LAYOUT; /* * omap_nand_hwcontrol - Set the address pointers corretly for the @@ -75,7 +77,7 @@ int omap_spl_dev_ready(struct mtd_info *mtd) * @mtd: MTD device structure * */ -static void omap_hwecc_init(struct nand_chip *chip) +static void __maybe_unused omap_hwecc_init(struct nand_chip *chip) { /* * Init ECC Control Register @@ -113,7 +115,7 @@ static uint32_t gen_true_ecc(uint8_t *ecc_buf) * * @return 0 if data is OK or corrected, else returns -1 */ -static int omap_correct_data(struct mtd_info *mtd, uint8_t *dat, +static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc) { uint32_t orig_ecc, new_ecc, res, hm; @@ -179,8 +181,8 @@ static int omap_correct_data(struct mtd_info *mtd, uint8_t *dat, * @dat: unused * @ecc_code: ecc_code buffer */ -static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, - uint8_t *ecc_code) +static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd, + const uint8_t *dat, uint8_t *ecc_code) { u_int32_t val; @@ -205,7 +207,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, * @mtd: MTD device structure * @mode: Read/Write mode */ -static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode) +static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode) { struct nand_chip *chip = mtd->priv; uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1; -- cgit v1.3.1 From 61712bcad48d2874fbd9e2dc90255f0885b716b0 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Mon, 19 Mar 2012 03:37:40 +0000 Subject: twl4030: fix potential power supply handling issues twl4030_pmrecv_vsel_cfg currently first sets up device group (effectively enabling the supply), and only then sets vsel (selects voltage). This could lead to wrong voltage for a short time, or even long time if second i2c write fails. Fix this by writing vsel first and device group after that. Also introduce error checking to not enable the supply if we failed to set the voltage, and start logging errors as power supply problems are usually important. Signed-off-by: Grazvydas Ignotas --- drivers/power/twl4030.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/power/twl4030.c b/drivers/power/twl4030.c index 4a4ddeb91ff..36b2144947a 100644 --- a/drivers/power/twl4030.c +++ b/drivers/power/twl4030.c @@ -65,13 +65,23 @@ void twl4030_power_reset_init(void) void twl4030_pmrecv_vsel_cfg(u8 vsel_reg, u8 vsel_val, u8 dev_grp, u8 dev_grp_sel) { - /* Select the Device Group */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, dev_grp_sel, - dev_grp); + int ret; /* Select the Voltage */ - twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, vsel_val, + ret = twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, vsel_val, vsel_reg); + if (ret != 0) { + printf("Could could not write vsel to reg %02x (%d)\n", + vsel_reg, ret); + return; + } + + /* Select the Device Group (enable the supply if dev_grp_sel != 0) */ + ret = twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, dev_grp_sel, + dev_grp); + if (ret != 0) + printf("Could could not write grp_sel to reg %02x (%d)\n", + dev_grp, ret); } void twl4030_power_init(void) -- cgit v1.3.1 From 08b5ab073d4eb389ffd622f71094cf1c70253c00 Mon Sep 17 00:00:00 2001 From: jacopo mondi Date: Wed, 2 Mar 2011 05:13:22 +0000 Subject: omap3_spi: receive transmit mode Implementation of receive-transmit mode for omap3 MCSPI. Introduces full duplex communication, needed by some spi devices (such as enc28j60). Signed-off-by: jacopo mondi --- drivers/spi/omap3_spi.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++--- drivers/spi/omap3_spi.h | 2 ++ 2 files changed, 65 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index af12c0e590b..9346c0b5b4a 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -297,6 +297,65 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, u8 *rxp, return 0; } +/*McSPI Transmit Receive Mode*/ +int omap3_spi_txrx(struct spi_slave *slave, + unsigned int len, const u8 *txp, u8 *rxp, unsigned long flags) +{ + struct omap3_spi_slave *ds = to_omap3_spi(slave); + int timeout = SPI_WAIT_TIMEOUT; + int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf); + int irqstatus = readl(&ds->regs->irqstatus); + int i=0; + + /*Enable SPI channel*/ + if (flags & SPI_XFER_BEGIN) + writel(OMAP3_MCSPI_CHCTRL_EN, + &ds->regs->channel[ds->slave.cs].chctrl); + + /*set TRANSMIT-RECEIVE Mode*/ + chconf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK; + chconf |= OMAP3_MCSPI_CHCONF_FORCE; + writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); + + /*Shift in and out 1 byte at time*/ + for (i=0; i < len; i++){ + /* Write: wait for TX empty (TXS == 1)*/ + irqstatus |= (1<< (4*(ds->slave.bus))); + while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & + OMAP3_MCSPI_CHSTAT_TXS)) { + if (--timeout <= 0) { + printf("SPI TXS timed out, status=0x%08x\n", + readl(&ds->regs->channel[ds->slave.cs].chstat)); + return -1; + } + } + /* Write the data */ + writel(txp[i], &ds->regs->channel[ds->slave.cs].tx); + + /*Read: wait for RX containing data (RXS == 1)*/ + while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) & + OMAP3_MCSPI_CHSTAT_RXS)) { + if (--timeout <= 0) { + printf("SPI RXS timed out, status=0x%08x\n", + readl(&ds->regs->channel[ds->slave.cs].chstat)); + return -1; + } + } + /* Read the data */ + rxp[i] = readl(&ds->regs->channel[ds->slave.cs].rx); + } + + /*if transfer must be terminated disable the channel*/ + if (flags & SPI_XFER_END) { + chconf &= ~OMAP3_MCSPI_CHCONF_FORCE; + writel(chconf, &ds->regs->channel[ds->slave.cs].chconf); + + writel(0, &ds->regs->channel[ds->slave.cs].chctrl); + } + + return 0; +} + int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { @@ -329,10 +388,11 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, } ret = 0; } else { - if (dout != NULL) + if (dout != NULL && din != NULL) + ret = omap3_spi_txrx(slave, len, txp, rxp, flags); + else if (dout != NULL) ret = omap3_spi_write(slave, len, txp, flags); - - if (din != NULL) + else if (din != NULL) ret = omap3_spi_read(slave, len, rxp, flags); } return ret; diff --git a/drivers/spi/omap3_spi.h b/drivers/spi/omap3_spi.h index b8e3a4c44c4..0ac801cb251 100644 --- a/drivers/spi/omap3_spi.h +++ b/drivers/spi/omap3_spi.h @@ -109,6 +109,8 @@ static inline struct omap3_spi_slave *to_omap3_spi(struct spi_slave *slave) return container_of(slave, struct omap3_spi_slave, slave); } +int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, const u8 *txp, + u8 *rxp, unsigned long flags); int omap3_spi_write(struct spi_slave *slave, unsigned int len, const u8 *txp, unsigned long flags); int omap3_spi_read(struct spi_slave *slave, unsigned int len, u8 *rxp, -- cgit v1.3.1 From d821ad4a618fe2a1a23aa66b8be3559de6e484fa Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 1 Feb 2012 12:58:49 +0000 Subject: net: calxedaxgmac: fix build due to missing __aligned definition Include linux/compiler.h to fix build error due to missing __aligned definition. Signed-off-by: Rob Herring --- drivers/net/calxedaxgmac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/calxedaxgmac.c b/drivers/net/calxedaxgmac.c index 01b2eeeaeed..00e26c2adc2 100644 --- a/drivers/net/calxedaxgmac.c +++ b/drivers/net/calxedaxgmac.c @@ -16,6 +16,7 @@ */ #include #include +#include #include #include -- cgit v1.3.1 From c3dfe7077630aa5f81d499c08964005d204c2b3b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 15 Mar 2012 18:33:18 +0000 Subject: i.MX28: Add cache support into the APBH DMA driver The desc_append() now flushes descriptors into RAM. Signed-off-by: Marek Vasut Cc: Stefano Babic --- drivers/dma/apbh_dma.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c index e85f5fe6d21..c086629b0a9 100644 --- a/drivers/dma/apbh_dma.c +++ b/drivers/dma/apbh_dma.c @@ -93,6 +93,21 @@ static int mxs_dma_read_semaphore(int channel) return tmp; } +#ifndef CONFIG_SYS_DCACHE_OFF +void mxs_dma_flush_desc(struct mxs_dma_desc *desc) +{ + uint32_t addr; + uint32_t size; + + addr = (uint32_t)desc; + size = roundup(sizeof(struct mxs_dma_desc), MXS_DMA_ALIGNMENT); + + flush_dcache_range(addr, addr + size); +} +#else +inline void mxs_dma_flush_desc(struct mxs_dma_desc *desc) {} +#endif + /* * Enable a DMA channel. * @@ -329,8 +344,10 @@ static int mxs_dma_release(int channel) struct mxs_dma_desc *mxs_dma_desc_alloc(void) { struct mxs_dma_desc *pdesc; + uint32_t size; - pdesc = memalign(MXS_DMA_ALIGNMENT, sizeof(struct mxs_dma_desc)); + size = roundup(sizeof(struct mxs_dma_desc), MXS_DMA_ALIGNMENT); + pdesc = memalign(MXS_DMA_ALIGNMENT, size); if (pdesc == NULL) return NULL; @@ -415,12 +432,16 @@ int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc) last->cmd.next = mxs_dma_cmd_address(pdesc); last->cmd.data |= MXS_DMA_DESC_CHAIN; + + mxs_dma_flush_desc(last); } pdesc->flags |= MXS_DMA_DESC_READY; if (pdesc->flags & MXS_DMA_DESC_FIRST) pchan->pending_num++; list_add_tail(&pdesc->node, &pchan->active); + mxs_dma_flush_desc(pdesc); + return ret; } -- cgit v1.3.1 From 6b9408edd3f6af6e91bcc0eebd4aedc0aca28934 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 15 Mar 2012 18:33:19 +0000 Subject: i.MX28: Add cache support to MXS NAND driver Signed-off-by: Marek Vasut Cc: Stefano Babic --- drivers/mtd/nand/mxs_nand.c | 53 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index ce2a3268732..4b1297a2fdc 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -50,6 +50,7 @@ struct mxs_nand_info { int cur_chip; uint32_t cmd_queue_len; + uint32_t data_buf_size; uint8_t *cmd_buf; uint8_t *data_buf; @@ -73,6 +74,36 @@ struct mxs_nand_info { struct nand_ecclayout fake_ecc_layout; +/* + * Cache management functions + */ +#ifndef CONFIG_SYS_DCACHE_OFF +static void mxs_nand_flush_data_buf(struct mxs_nand_info *info) +{ + uint32_t addr = (uint32_t)info->data_buf; + + flush_dcache_range(addr, addr + info->data_buf_size); +} + +static void mxs_nand_inval_data_buf(struct mxs_nand_info *info) +{ + uint32_t addr = (uint32_t)info->data_buf; + + invalidate_dcache_range(addr, addr + info->data_buf_size); +} + +static void mxs_nand_flush_cmd_buf(struct mxs_nand_info *info) +{ + uint32_t addr = (uint32_t)info->cmd_buf; + + flush_dcache_range(addr, addr + MXS_NAND_COMMAND_BUFFER_SIZE); +} +#else +static inline void mxs_nand_flush_data_buf(struct mxs_nand_info *info) {} +static inline void mxs_nand_inval_data_buf(struct mxs_nand_info *info) {} +static inline void mxs_nand_flush_cmd_buf(struct mxs_nand_info *info) {} +#endif + static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info) { struct mxs_dma_desc *desc; @@ -286,6 +317,9 @@ static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) mxs_dma_desc_append(channel, d); + /* Flush caches */ + mxs_nand_flush_cmd_buf(nand_info); + /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) @@ -435,6 +469,9 @@ static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length) goto rtn; } + /* Invalidate caches */ + mxs_nand_inval_data_buf(nand_info); + memcpy(buf, nand_info->data_buf, length); rtn: @@ -484,6 +521,9 @@ static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, mxs_dma_desc_append(channel, d); + /* Flush caches */ + mxs_nand_flush_data_buf(nand_info); + /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) @@ -600,6 +640,9 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, goto rtn; } + /* Invalidate caches */ + mxs_nand_inval_data_buf(nand_info); + /* Read DMA completed, now do the mark swapping. */ mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); @@ -687,6 +730,9 @@ static void mxs_nand_ecc_write_page(struct mtd_info *mtd, mxs_dma_desc_append(channel, d); + /* Flush caches */ + mxs_nand_flush_data_buf(nand_info); + /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) { @@ -978,18 +1024,19 @@ int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info) uint8_t *buf; const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE; + nand_info->data_buf_size = roundup(size, MXS_DMA_ALIGNMENT); + /* DMA buffers */ - buf = memalign(MXS_DMA_ALIGNMENT, size); + buf = memalign(MXS_DMA_ALIGNMENT, nand_info->data_buf_size); if (!buf) { printf("MXS NAND: Error allocating DMA buffers\n"); return -ENOMEM; } - memset(buf, 0, size); + memset(buf, 0, nand_info->data_buf_size); nand_info->data_buf = buf; nand_info->oob_buf = buf + NAND_MAX_PAGESIZE; - /* Command buffers */ nand_info->cmd_buf = memalign(MXS_DMA_ALIGNMENT, MXS_NAND_COMMAND_BUFFER_SIZE); -- cgit v1.3.1 From 8635ff9e999071cbfaef50ec4d631e60e8de23d3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 15 Mar 2012 18:41:35 +0000 Subject: MMC: Implement generic bounce buffer This implements generic bounce buffer at the end of MMC command submission chain. Therefore if unaligned data are passed, they are copied. This stuff should be pushed down into the MMC subsystem to squash all places generating these unaligned data. Signed-off-by: Marek Vasut Cc: Andy Fleming --- drivers/mmc/mmc.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 49c3349f55f..74e5fea6671 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -47,10 +47,105 @@ int __board_mmc_getcd(struct mmc *mmc) { int board_mmc_getcd(struct mmc *mmc)__attribute__((weak, alias("__board_mmc_getcd"))); +#ifdef CONFIG_MMC_BOUNCE_BUFFER +static int mmc_bounce_need_bounce(struct mmc_data *orig) +{ + ulong addr, len; + + if (orig->flags & MMC_DATA_READ) + addr = (ulong)orig->dest; + else + addr = (ulong)orig->src; + + if (addr % ARCH_DMA_MINALIGN) { + debug("MMC: Unaligned data destination address %08lx!\n", addr); + return 1; + } + + len = (ulong)(orig->blocksize * orig->blocks); + if (len % ARCH_DMA_MINALIGN) { + debug("MMC: Unaligned data destination length %08lx!\n", len); + return 1; + } + + return 0; +} + +static int mmc_bounce_buffer_start(struct mmc_data *backup, + struct mmc_data *orig) +{ + ulong origlen, len; + void *buffer; + + if (!orig) + return 0; + + if (!mmc_bounce_need_bounce(orig)) + return 0; + + memcpy(backup, orig, sizeof(struct mmc_data)); + + origlen = orig->blocksize * orig->blocks; + len = roundup(origlen, ARCH_DMA_MINALIGN); + buffer = memalign(ARCH_DMA_MINALIGN, len); + if (!buffer) { + puts("MMC: Error allocating MMC bounce buffer!\n"); + return 1; + } + + if (orig->flags & MMC_DATA_READ) { + orig->dest = buffer; + } else { + memcpy(buffer, orig->src, origlen); + orig->src = buffer; + } + + return 0; +} + +static void mmc_bounce_buffer_stop(struct mmc_data *backup, + struct mmc_data *orig) +{ + ulong len; + + if (!orig) + return; + + if (!mmc_bounce_need_bounce(backup)) + return; + + if (backup->flags & MMC_DATA_READ) { + len = backup->blocksize * backup->blocks; + memcpy(backup->dest, orig->dest, len); + free(orig->dest); + orig->dest = backup->dest; + } else { + free((void *)orig->src); + orig->src = backup->src; + } + + return; + +} +#else +static inline int mmc_bounce_buffer_start(struct mmc_data *backup, + struct mmc_data *orig) { } +static inline void mmc_bounce_buffer_stop(struct mmc_data *backup, + struct mmc_data *orig) { } +#endif + int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { -#ifdef CONFIG_MMC_TRACE + struct mmc_data backup; int ret; + + memset(&backup, 0, sizeof(backup)); + + ret = mmc_bounce_buffer_start(&backup, data); + if (ret) + return ret; + +#ifdef CONFIG_MMC_TRACE int i; u8 *ptr; @@ -99,10 +194,11 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) printf("\t\tERROR MMC rsp not supported\n"); break; } - return ret; #else - return mmc->send_cmd(mmc, cmd, data); + ret = mmc->send_cmd(mmc, cmd, data); #endif + mmc_bounce_buffer_stop(&backup, data); + return ret; } int mmc_send_status(struct mmc *mmc, int timeout) -- cgit v1.3.1 From 3687c4155af6ad502ca216a123cff852917dd364 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 15 Mar 2012 18:33:21 +0000 Subject: i.MX28: Do data transfers via DMA in MMC driver This utilizes the newly introduced bounce buffers in the MMC layer. Signed-off-by: Marek Vasut Cc: Stefano Babic Cc: Andy Fleming Cc: Fabio Estevam --- drivers/mmc/mxsmmc.c | 70 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 5f87a1efd6c..e8bad9dc751 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -41,6 +41,7 @@ #include #include #include +#include struct mxsmmc_priv { int id; @@ -49,6 +50,7 @@ struct mxsmmc_priv { uint32_t *clkctrl_ssp; uint32_t buswidth; int (*mmc_is_wp)(int); + struct mxs_dma_desc *desc; }; #define MXSMMC_MAX_TIMEOUT 10000 @@ -64,8 +66,7 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) struct mx28_ssp_regs *ssp_regs = priv->regs; uint32_t reg; int timeout; - uint32_t data_count; - uint32_t *data_ptr; + uint32_t data_count, cache_data_count; uint32_t ctrl0; debug("MMC%d: CMD%d\n", mmc->block_dev.dev, cmd->cmdidx); @@ -183,40 +184,41 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) if (!data) return 0; - /* Process the data */ data_count = data->blocksize * data->blocks; - timeout = MXSMMC_MAX_TIMEOUT; + + if (data_count % ARCH_DMA_MINALIGN) + cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN); + else + cache_data_count = data_count; + if (data->flags & MMC_DATA_READ) { - data_ptr = (uint32_t *)data->dest; - while (data_count && --timeout) { - reg = readl(&ssp_regs->hw_ssp_status); - if (!(reg & SSP_STATUS_FIFO_EMPTY)) { - *data_ptr++ = readl(&ssp_regs->hw_ssp_data); - data_count -= 4; - timeout = MXSMMC_MAX_TIMEOUT; - } else - udelay(1000); - } + priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_WRITE; + priv->desc->cmd.address = (dma_addr_t)data->dest; } else { - data_ptr = (uint32_t *)data->src; - timeout *= 100; - while (data_count && --timeout) { - reg = readl(&ssp_regs->hw_ssp_status); - if (!(reg & SSP_STATUS_FIFO_FULL)) { - writel(*data_ptr++, &ssp_regs->hw_ssp_data); - data_count -= 4; - timeout = MXSMMC_MAX_TIMEOUT; - } else - udelay(1000); - } + priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ; + priv->desc->cmd.address = (dma_addr_t)data->src; + + /* Flush data to DRAM so DMA can pick them up */ + flush_dcache_range((uint32_t)priv->desc->cmd.address, + (uint32_t)(priv->desc->cmd.address + cache_data_count)); } - if (!timeout) { - printf("MMC%d: Data timeout with command %d (status 0x%08x)!\n", - mmc->block_dev.dev, cmd->cmdidx, reg); + priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM | + (data_count << MXS_DMA_DESC_BYTES_OFFSET); + + + mxs_dma_desc_append(MXS_DMA_CHANNEL_AHB_APBH_SSP0, priv->desc); + if (mxs_dma_go(MXS_DMA_CHANNEL_AHB_APBH_SSP0)) { + printf("MMC%d: DMA transfer failed\n", mmc->block_dev.dev); return COMM_ERR; } + /* The data arrived into DRAM, invalidate cache over them */ + if (data->flags & MMC_DATA_READ) { + invalidate_dcache_range((uint32_t)priv->desc->cmd.address, + (uint32_t)(priv->desc->cmd.address + cache_data_count)); + } + /* Check data errors */ reg = readl(&ssp_regs->hw_ssp_status); if (reg & @@ -270,7 +272,8 @@ static int mxsmmc_init(struct mmc *mmc) /* 8 bits word length in MMC mode */ clrsetbits_le32(&ssp_regs->hw_ssp_ctrl1, SSP_CTRL1_SSP_MODE_MASK | SSP_CTRL1_WORD_LENGTH_MASK, - SSP_CTRL1_SSP_MODE_SD_MMC | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS); + SSP_CTRL1_SSP_MODE_SD_MMC | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS | + SSP_CTRL1_DMA_ENABLE); /* Set initial bit clock 400 KHz */ mx28_set_ssp_busclock(priv->id, 400); @@ -300,6 +303,13 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int)) return -ENOMEM; } + priv->desc = mxs_dma_desc_alloc(); + if (!priv->desc) { + free(priv); + free(mmc); + return -ENOMEM; + } + priv->mmc_is_wp = wp; priv->id = id; switch (id) { @@ -345,7 +355,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int)) */ mmc->f_min = 400000; mmc->f_max = mxc_get_clock(MXC_SSP0_CLK + id) * 1000 / 2; - mmc->b_max = 0; + mmc->b_max = 0x40; mmc_register(mmc); return 0; -- cgit v1.3.1 From 5c1ad3e6f8ae578bbe30e09652f1531e9bc22031 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Thu, 15 Mar 2012 18:33:25 +0000 Subject: net: fec_mxc: allow use with cache enabled Ensure that transmit and receive buffers are cache-line aligned. Invalidate cache for each packet as received, update receive buffer descriptors one cache line at a time, flush cache before transmitting. Original patch by Marek: http://lists.denx.de/pipermail/u-boot/2012-February/117695.html Signed-off-by: Eric Nelson Acked-by: Marek Vasut Tested-by: Marek Vasut --- drivers/net/fec_mxc.c | 277 ++++++++++++++++++++++++++++++++++---------------- drivers/net/fec_mxc.h | 19 +--- 2 files changed, 192 insertions(+), 104 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 1fdd071e385..d8db9f0c6e8 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -38,16 +38,28 @@ DECLARE_GLOBAL_DATA_PTR; #error "CONFIG_MII has to be defined!" #endif -#ifndef CONFIG_FEC_XCV_TYPE -#define CONFIG_FEC_XCV_TYPE MII100 +#ifndef CONFIG_FEC_XCV_TYPE +#define CONFIG_FEC_XCV_TYPE MII100 #endif /* * The i.MX28 operates with packets in big endian. We need to swap them before * sending and after receiving. */ -#ifdef CONFIG_MX28 -#define CONFIG_FEC_MXC_SWAP_PACKET +#ifdef CONFIG_MX28 +#define CONFIG_FEC_MXC_SWAP_PACKET +#endif + +#define RXDESC_PER_CACHELINE (ARCH_DMA_MINALIGN/sizeof(struct fec_bd)) + +/* Check various alignment issues at compile time */ +#if ((ARCH_DMA_MINALIGN < 16) || (ARCH_DMA_MINALIGN % 16 != 0)) +#error "ARCH_DMA_MINALIGN must be multiple of 16!" +#endif + +#if ((PKTALIGN < ARCH_DMA_MINALIGN) || \ + (PKTALIGN % ARCH_DMA_MINALIGN != 0)) +#error "PKTALIGN must be multiple of ARCH_DMA_MINALIGN!" #endif #undef DEBUG @@ -59,7 +71,7 @@ struct nbuf { uint8_t head[16]; /**< MAC header(6 + 6 + 2) + 2(aligned) */ }; -#ifdef CONFIG_FEC_MXC_SWAP_PACKET +#ifdef CONFIG_FEC_MXC_SWAP_PACKET static void swap_packet(uint32_t *packet, int length) { int i; @@ -259,43 +271,52 @@ static int fec_tx_task_disable(struct fec_priv *fec) * Initialize receive task's buffer descriptors * @param[in] fec all we know about the device yet * @param[in] count receive buffer count to be allocated - * @param[in] size size of each receive buffer + * @param[in] dsize desired size of each receive buffer * @return 0 on success * * For this task we need additional memory for the data buffers. And each * data buffer requires some alignment. Thy must be aligned to a specific - * boundary each (DB_DATA_ALIGNMENT). + * boundary each. */ -static int fec_rbd_init(struct fec_priv *fec, int count, int size) +static int fec_rbd_init(struct fec_priv *fec, int count, int dsize) { - int ix; - uint32_t p = 0; - - /* reserve data memory and consider alignment */ - if (fec->rdb_ptr == NULL) - fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT); - p = (uint32_t)fec->rdb_ptr; - if (!p) { - puts("fec_mxc: not enough malloc memory\n"); - return -ENOMEM; - } - memset((void *)p, 0, size * count + DB_DATA_ALIGNMENT); - p += DB_DATA_ALIGNMENT-1; - p &= ~(DB_DATA_ALIGNMENT-1); - - for (ix = 0; ix < count; ix++) { - writel(p, &fec->rbd_base[ix].data_pointer); - p += size; - writew(FEC_RBD_EMPTY, &fec->rbd_base[ix].status); - writew(0, &fec->rbd_base[ix].data_length); - } + uint32_t size; + int i; + /* - * mark the last RBD to close the ring + * Allocate memory for the buffers. This allocation respects the + * alignment */ - writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &fec->rbd_base[ix - 1].status); + size = roundup(dsize, ARCH_DMA_MINALIGN); + for (i = 0; i < count; i++) { + uint32_t data_ptr = readl(&fec->rbd_base[i].data_pointer); + if (data_ptr == 0) { + uint8_t *data = memalign(ARCH_DMA_MINALIGN, + size); + if (!data) { + printf("%s: error allocating rxbuf %d\n", + __func__, i); + goto err; + } + writel((uint32_t)data, &fec->rbd_base[i].data_pointer); + } /* needs allocation */ + writew(FEC_RBD_EMPTY, &fec->rbd_base[i].status); + writew(0, &fec->rbd_base[i].data_length); + } + + /* Mark the last RBD to close the ring. */ + writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &fec->rbd_base[i - 1].status); fec->rbd_index = 0; return 0; + +err: + for (; i >= 0; i--) { + uint32_t data_ptr = readl(&fec->rbd_base[i].data_pointer); + free((void *)data_ptr); + } + + return -ENOMEM; } /** @@ -312,9 +333,13 @@ static int fec_rbd_init(struct fec_priv *fec, int count, int size) */ static void fec_tbd_init(struct fec_priv *fec) { + unsigned addr = (unsigned)fec->tbd_base; + unsigned size = roundup(2 * sizeof(struct fec_bd), + ARCH_DMA_MINALIGN); writew(0x0000, &fec->tbd_base[0].status); writew(FEC_TBD_WRAP, &fec->tbd_base[1].status); fec->tbd_index = 0; + flush_dcache_range(addr, addr+size); } /** @@ -324,16 +349,10 @@ static void fec_tbd_init(struct fec_priv *fec) */ static void fec_rbd_clean(int last, struct fec_bd *pRbd) { - /* - * Reset buffer descriptor as empty - */ + unsigned short flags = FEC_RBD_EMPTY; if (last) - writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &pRbd->status); - else - writew(FEC_RBD_EMPTY, &pRbd->status); - /* - * no data in it - */ + flags |= FEC_RBD_WRAP; + writew(flags, &pRbd->status); writew(0, &pRbd->data_length); } @@ -387,12 +406,25 @@ static int fec_open(struct eth_device *edev) { struct fec_priv *fec = (struct fec_priv *)edev->priv; int speed; + uint32_t addr, size; + int i; debug("fec_open: fec_open(dev)\n"); /* full-duplex, heartbeat disabled */ writel(1 << 2, &fec->eth->x_cntrl); fec->rbd_index = 0; + /* Invalidate all descriptors */ + for (i = 0; i < FEC_RBD_NUM - 1; i++) + fec_rbd_clean(0, &fec->rbd_base[i]); + fec_rbd_clean(1, &fec->rbd_base[i]); + + /* Flush the descriptors into RAM */ + size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), + ARCH_DMA_MINALIGN); + addr = (uint32_t)fec->rbd_base; + flush_dcache_range(addr, addr + size); + #ifdef FEC_QUIRK_ENET_MAC /* Enable ENET HW endian SWAP */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_DBSWAP, @@ -478,38 +510,55 @@ static int fec_open(struct eth_device *edev) static int fec_init(struct eth_device *dev, bd_t* bd) { - uint32_t base; struct fec_priv *fec = (struct fec_priv *)dev->priv; uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; uint32_t rcntrl; - int i; + uint32_t size; + int i, ret; /* Initialize MAC address */ fec_set_hwaddr(dev); /* - * reserve memory for both buffer descriptor chains at once - * Datasheet forces the startaddress of each chain is 16 byte - * aligned + * Allocate transmit descriptors, there are two in total. This + * allocation respects cache alignment. */ - if (fec->base_ptr == NULL) - fec->base_ptr = malloc((2 + FEC_RBD_NUM) * - sizeof(struct fec_bd) + DB_ALIGNMENT); - base = (uint32_t)fec->base_ptr; - if (!base) { - puts("fec_mxc: not enough malloc memory\n"); - return -ENOMEM; + if (!fec->tbd_base) { + size = roundup(2 * sizeof(struct fec_bd), + ARCH_DMA_MINALIGN); + fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size); + if (!fec->tbd_base) { + ret = -ENOMEM; + goto err1; + } + memset(fec->tbd_base, 0, size); + fec_tbd_init(fec); + flush_dcache_range((unsigned)fec->tbd_base, size); } - memset((void *)base, 0, (2 + FEC_RBD_NUM) * - sizeof(struct fec_bd) + DB_ALIGNMENT); - base += (DB_ALIGNMENT-1); - base &= ~(DB_ALIGNMENT-1); - - fec->rbd_base = (struct fec_bd *)base; - base += FEC_RBD_NUM * sizeof(struct fec_bd); - - fec->tbd_base = (struct fec_bd *)base; + /* + * Allocate receive descriptors. This allocation respects cache + * alignment. + */ + if (!fec->rbd_base) { + size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), + ARCH_DMA_MINALIGN); + fec->rbd_base = memalign(ARCH_DMA_MINALIGN, size); + if (!fec->rbd_base) { + ret = -ENOMEM; + goto err2; + } + memset(fec->rbd_base, 0, size); + /* + * Initialize RxBD ring + */ + if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) { + ret = -ENOMEM; + goto err3; + } + flush_dcache_range((unsigned)fec->rbd_base, + (unsigned)fec->rbd_base + size); + } /* * Set interrupt mask register @@ -566,23 +615,19 @@ static int fec_init(struct eth_device *dev, bd_t* bd) writel((uint32_t)fec->tbd_base, &fec->eth->etdsr); writel((uint32_t)fec->rbd_base, &fec->eth->erdsr); - /* - * Initialize RxBD/TxBD rings - */ - if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) { - free(fec->base_ptr); - fec->base_ptr = NULL; - return -ENOMEM; - } - fec_tbd_init(fec); - - #ifndef CONFIG_PHYLIB if (fec->xcv_type != SEVENWIRE) miiphy_restart_aneg(dev); #endif fec_open(dev); return 0; + +err3: + free(fec->rbd_base); +err2: + free(fec->tbd_base); +err1: + return ret; } /** @@ -631,9 +676,11 @@ static void fec_halt(struct eth_device *dev) * @param[in] length Data count in bytes * @return 0 on success */ -static int fec_send(struct eth_device *dev, volatile void* packet, int length) +static int fec_send(struct eth_device *dev, volatile void *packet, int length) { unsigned int status; + uint32_t size; + uint32_t addr; /* * This routine transmits one frame. This routine only accepts @@ -650,15 +697,21 @@ static int fec_send(struct eth_device *dev, volatile void* packet, int length) } /* - * Setup the transmit buffer - * Note: We are always using the first buffer for transmission, - * the second will be empty and only used to stop the DMA engine + * Setup the transmit buffer. We are always using the first buffer for + * transmission, the second will be empty and only used to stop the DMA + * engine. We also flush the packet to RAM here to avoid cache trouble. */ -#ifdef CONFIG_FEC_MXC_SWAP_PACKET +#ifdef CONFIG_FEC_MXC_SWAP_PACKET swap_packet((uint32_t *)packet, length); #endif + + addr = (uint32_t)packet; + size = roundup(length, ARCH_DMA_MINALIGN); + flush_dcache_range(addr, addr + size); + writew(length, &fec->tbd_base[fec->tbd_index].data_length); - writel((uint32_t)packet, &fec->tbd_base[fec->tbd_index].data_pointer); + writel(addr, &fec->tbd_base[fec->tbd_index].data_pointer); + /* * update BD's status now * This block: @@ -671,17 +724,31 @@ static int fec_send(struct eth_device *dev, volatile void* packet, int length) status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY; writew(status, &fec->tbd_base[fec->tbd_index].status); + /* + * Flush data cache. This code flushes both TX descriptors to RAM. + * After this code, the descriptors will be safely in RAM and we + * can start DMA. + */ + size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN); + addr = (uint32_t)fec->tbd_base; + flush_dcache_range(addr, addr + size); + /* * Enable SmartDMA transmit task */ fec_tx_task_enable(fec); /* - * wait until frame is sent . + * Wait until frame is sent. On each turn of the wait cycle, we must + * invalidate data cache to see what's really in RAM. Also, we need + * barrier here. */ + invalidate_dcache_range(addr, addr + size); while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) { udelay(1); + invalidate_dcache_range(addr, addr + size); } + debug("fec_send: status 0x%x index %d\n", readw(&fec->tbd_base[fec->tbd_index].status), fec->tbd_index); @@ -707,6 +774,8 @@ static int fec_recv(struct eth_device *dev) int frame_length, len = 0; struct nbuf *frame; uint16_t bd_status; + uint32_t addr, size; + int i; uchar buff[FEC_MAX_PKT_SIZE]; /* @@ -737,8 +806,23 @@ static int fec_recv(struct eth_device *dev) } /* - * ensure reading the right buffer status + * Read the buffer status. Before the status can be read, the data cache + * must be invalidated, because the data in RAM might have been changed + * by DMA. The descriptors are properly aligned to cachelines so there's + * no need to worry they'd overlap. + * + * WARNING: By invalidating the descriptor here, we also invalidate + * the descriptors surrounding this one. Therefore we can NOT change the + * contents of this descriptor nor the surrounding ones. The problem is + * that in order to mark the descriptor as processed, we need to change + * the descriptor. The solution is to mark the whole cache line when all + * descriptors in the cache line are processed. */ + addr = (uint32_t)rbd; + addr &= ~(ARCH_DMA_MINALIGN - 1); + size = roundup(sizeof(struct fec_bd), ARCH_DMA_MINALIGN); + invalidate_dcache_range(addr, addr + size); + bd_status = readw(&rbd->status); debug("fec_recv: status 0x%x\n", bd_status); @@ -750,10 +834,17 @@ static int fec_recv(struct eth_device *dev) */ frame = (struct nbuf *)readl(&rbd->data_pointer); frame_length = readw(&rbd->data_length) - 4; + /* + * Invalidate data cache over the buffer + */ + addr = (uint32_t)frame; + size = roundup(frame_length, ARCH_DMA_MINALIGN); + invalidate_dcache_range(addr, addr + size); + /* * Fill the buffer and pass it to upper layers */ -#ifdef CONFIG_FEC_MXC_SWAP_PACKET +#ifdef CONFIG_FEC_MXC_SWAP_PACKET swap_packet((uint32_t *)frame->data, frame_length); #endif memcpy(buff, frame->data, frame_length); @@ -765,11 +856,25 @@ static int fec_recv(struct eth_device *dev) (ulong)rbd->data_pointer, bd_status); } + /* - * free the current buffer, restart the engine - * and move forward to the next buffer + * Free the current buffer, restart the engine and move forward + * to the next buffer. Here we check if the whole cacheline of + * descriptors was already processed and if so, we mark it free + * as whole. */ - fec_rbd_clean(fec->rbd_index == (FEC_RBD_NUM - 1) ? 1 : 0, rbd); + size = RXDESC_PER_CACHELINE - 1; + if ((fec->rbd_index & size) == size) { + i = fec->rbd_index - size; + addr = (uint32_t)&fec->rbd_base[i]; + for (; i <= fec->rbd_index ; i++) { + fec_rbd_clean(i == (FEC_RBD_NUM - 1), + &fec->rbd_base[i]); + } + flush_dcache_range(addr, + addr + ARCH_DMA_MINALIGN); + } + fec_rx_task_enable(fec); fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM; } @@ -866,7 +971,7 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr) bus->read = fec_phy_read; bus->write = fec_phy_write; sprintf(bus->name, edev->name); -#ifdef CONFIG_MX28 +#ifdef CONFIG_MX28 /* * The i.MX28 has two ethernet interfaces, but they are not equal. * Only the first one can access the MDIO bus. @@ -901,7 +1006,7 @@ err1: return ret; } -#ifndef CONFIG_FEC_MXC_MULTI +#ifndef CONFIG_FEC_MXC_MULTI int fecmxc_initialize(bd_t *bd) { int lout = 1; diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 2eb78037fcb..852b2e07e71 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -233,22 +233,6 @@ struct ethernet_regs { #define MIIGSK_ENR_EN (1 << 1) #endif -/** - * @brief Descriptor buffer alignment - * - * i.MX27 requires a 16 byte alignment (but for the first element only) - */ -#define DB_ALIGNMENT 16 - -/** - * @brief Data buffer alignment - * - * i.MX27 requires a four byte alignment for transmit and 16 bits - * alignment for receive so take 16 - * Note: Valid for member data_pointer in struct buffer_descriptor - */ -#define DB_DATA_ALIGNMENT 16 - /** * @brief Receive & Transmit Buffer Descriptor definitions * @@ -282,8 +266,7 @@ struct fec_priv { struct fec_bd *tbd_base; /* TBD ring */ int tbd_index; /* next transmit BD to write */ bd_t *bd; - void *rdb_ptr; - void *base_ptr; + uint8_t *tdb_ptr; int dev_id; int phy_id; struct mii_dev *bus; -- cgit v1.3.1 From 9ab4ce223c1d991e92e15c9aa0f522d61072155d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 27 Feb 2012 10:52:47 +0000 Subject: usb: Add support for txfifo threshold CONFIG_USB_EHCI_TXFIFO_THRESH enables setting of the txfilltuning field in the EHCI controller on reset. Signed-off-by: Simon Glass Acked-by: Remy Bohmer Signed-off-by: Tom Warren --- README | 3 +++ drivers/usb/host/ehci-hcd.c | 7 +++++++ drivers/usb/host/ehci.h | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/README b/README index 5452813449d..d4799e222f5 100644 --- a/README +++ b/README @@ -1125,6 +1125,9 @@ The following options need to be configured: May be defined to allow interrupt polling instead of using asynchronous interrupts + CONFIG_USB_EHCI_TXFIFO_THRESH enables setting of the + txfilltuning field in the EHCI controller on reset. + - USB Device: Define the below if you wish to use the USB console. Once firmware is rebuilt from a serial console issue the diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index ef5afc22b04..b6422d7d7aa 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -255,6 +255,13 @@ static int ehci_reset(void) #endif ehci_writel(reg_ptr, tmp); } + +#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH + cmd = ehci_readl(&hcor->or_txfilltuning); + cmd &= ~TXFIFO_THRESH(0x3f); + cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH); + ehci_writel(&hcor->or_txfilltuning, cmd); +#endif out: return ret; } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 3d0ad0c8521..cc00ce428b8 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -80,7 +80,11 @@ struct ehci_hcor { uint32_t or_ctrldssegment; uint32_t or_periodiclistbase; uint32_t or_asynclistaddr; - uint32_t _reserved_[9]; + uint32_t _reserved_0_; + uint32_t or_burstsize; + uint32_t or_txfilltuning; +#define TXFIFO_THRESH(p) ((p & 0x3f) << 16) + uint32_t _reserved_1_[6]; uint32_t or_configflag; #define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS]; -- cgit v1.3.1 From 87f938c9f7372f587a43fe7babcb171ee0a0672f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 27 Feb 2012 10:52:49 +0000 Subject: tegra: usb: Add support for Tegra USB peripheral This adds basic support for the Tegra2 USB controller. Board files should call board_usb_init() to set things up. Configuration is performed through the FDT, with aliases used to set the order of the ports, like this fragment: aliases { /* This defines the order of our USB ports */ usb0 = "/usb@0xc5008000"; usb1 = "/usb@0xc5000000"; }; drivers/usb/host files ONLY: Acked-by: Remy Bohmer Signed-off-by: Simon Glass Signed-off-by: Tom Warren --- arch/arm/cpu/armv7/tegra2/Makefile | 4 +- arch/arm/cpu/armv7/tegra2/usb.c | 460 ++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-tegra2/tegra2.h | 2 + arch/arm/include/asm/arch-tegra2/usb.h | 252 ++++++++++++++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-tegra.c | 62 ++++ include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 8 files changed, 782 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/tegra2/usb.c create mode 100644 arch/arm/include/asm/arch-tegra2/usb.h create mode 100644 drivers/usb/host/ehci-tegra.c (limited to 'drivers') diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile index f668a818fbf..e9ac6c9a710 100644 --- a/arch/arm/cpu/armv7/tegra2/Makefile +++ b/arch/arm/cpu/armv7/tegra2/Makefile @@ -33,8 +33,10 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o SOBJS := lowlevel_init.o -COBJS := ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o +COBJS-y := ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o +COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o +COBJS := $(COBJS-y) SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) diff --git a/arch/arm/cpu/armv7/tegra2/usb.c b/arch/arm/cpu/armv7/tegra2/usb.c new file mode 100644 index 00000000000..c80de7f6a37 --- /dev/null +++ b/arch/arm/cpu/armv7/tegra2/usb.c @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010,2011 NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + USB_PORTS_MAX = 4, /* Maximum ports we allow */ +}; + +/* Parameters we need for USB */ +enum { + PARAM_DIVN, /* PLL FEEDBACK DIVIDer */ + PARAM_DIVM, /* PLL INPUT DIVIDER */ + PARAM_DIVP, /* POST DIVIDER (2^N) */ + PARAM_CPCON, /* BASE PLLC CHARGE Pump setup ctrl */ + PARAM_LFCON, /* BASE PLLC LOOP FILter setup ctrl */ + PARAM_ENABLE_DELAY_COUNT, /* PLL-U Enable Delay Count */ + PARAM_STABLE_COUNT, /* PLL-U STABLE count */ + PARAM_ACTIVE_DELAY_COUNT, /* PLL-U Active delay count */ + PARAM_XTAL_FREQ_COUNT, /* PLL-U XTAL frequency count */ + PARAM_DEBOUNCE_A_TIME, /* 10MS DELAY for BIAS_DEBOUNCE_A */ + PARAM_BIAS_TIME, /* 20US DELAY AFter bias cell op */ + + PARAM_COUNT +}; + +/* Possible port types (dual role mode) */ +enum dr_mode { + DR_MODE_NONE = 0, + DR_MODE_HOST, /* supports host operation */ + DR_MODE_DEVICE, /* supports device operation */ + DR_MODE_OTG, /* supports both */ +}; + +/* Information about a USB port */ +struct fdt_usb { + struct usb_ctlr *reg; /* address of registers in physical memory */ + unsigned utmi:1; /* 1 if port has external tranceiver, else 0 */ + unsigned enabled:1; /* 1 to enable, 0 to disable */ + unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ + enum dr_mode dr_mode; /* dual role mode */ + enum periph_id periph_id;/* peripheral id */ + struct fdt_gpio_state vbus_gpio; /* GPIO for vbus enable */ +}; + +static struct fdt_usb port[USB_PORTS_MAX]; /* List of valid USB ports */ +static unsigned port_count; /* Number of available ports */ +static int port_current; /* Current port (-1 = none) */ + +/* + * This table has USB timing parameters for each Oscillator frequency we + * support. There are four sets of values: + * + * 1. PLLU configuration information (reference clock is osc/clk_m and + * PLLU-FOs are fixed at 12MHz/60MHz/480MHz). + * + * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz + * ---------------------------------------------------------------------- + * DIVN 960 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) + * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) + * Filter frequency (MHz) 1 4.8 6 2 + * CPCON 1100b 0011b 1100b 1100b + * LFCON0 0 0 0 0 + * + * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: + * + * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz + * --------------------------------------------------------------------------- + * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) + * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) + * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) + * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) + * + * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and + * SessEnd. Each of these signals have their own debouncer and for each of + * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or + * BIAS_DEBOUNCE_B). + * + * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows: + * 0xffff -> No debouncing at all + * ms = *1000 / (1/19.2MHz) / 4 + * + * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have: + * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0 + * + * We need to use only DebounceA for BOOTROM. We don't need the DebounceB + * values, so we can keep those to default. + * + * 4. The 20 microsecond delay after bias cell operation. + */ +static const unsigned usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { + /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ + { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, + { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, + { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, + { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } +}; + +/* UTMIP Idle Wait Delay */ +static const u8 utmip_idle_wait_delay = 17; + +/* UTMIP Elastic limit */ +static const u8 utmip_elastic_limit = 16; + +/* UTMIP High Speed Sync Start Delay */ +static const u8 utmip_hs_sync_start_delay = 9; + +/* Put the port into host mode (this only works for OTG ports) */ +static void set_host_mode(struct fdt_usb *config) +{ + if (config->dr_mode == DR_MODE_OTG) { + /* Check whether remote host from USB1 is driving VBus */ + if (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS) + return; + + /* + * If not driving, we set the GPIO to enable VBUS. We assume + * that the pinmux is set up correctly for this. + */ + if (fdt_gpio_isvalid(&config->vbus_gpio)) { + fdtdec_setup_gpio(&config->vbus_gpio); + gpio_direction_output(config->vbus_gpio.gpio, 1); + debug("set_host_mode: GPIO %d high\n", + config->vbus_gpio.gpio); + } + } +} + +void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) +{ + /* Reset the USB controller with 2us delay */ + reset_periph(config->periph_id, 2); + + /* + * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under + * base address + */ + if (config->has_legacy_mode) + setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE); + + /* Put UTMIP1/3 in reset */ + setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); + + /* Enable the UTMIP PHY */ + if (config->utmi) + setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB); + + /* + * TODO: where do we take the USB1 out of reset? The old code would + * take USB3 out of reset, but not USB1. This code doesn't do either. + */ +} + +/* set up the USB controller with the parameters provided */ +static int init_usb_controller(struct fdt_usb *config, + struct usb_ctlr *usbctlr, const u32 timing[]) +{ + u32 val; + int loop_count; + + clock_enable(config->periph_id); + + /* Reset the usb controller */ + usbf_reset_controller(config, usbctlr); + + /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */ + clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); + + /* Follow the crystal clock disable by >100ns delay */ + udelay(1); + + /* + * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP + * mux must be switched to actually use a_sess_vld threshold. + */ + if (fdt_gpio_isvalid(&config->vbus_gpio)) { + clrsetbits_le32(&usbctlr->usb1_legacy_ctrl, + VBUS_SENSE_CTL_MASK, + VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); + } + + /* + * PLL Delay CONFIGURATION settings. The following parameters control + * the bring up of the plls. + */ + val = readl(&usbctlr->utmip_misc_cfg1); + clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, + timing[PARAM_STABLE_COUNT] << UTMIP_PLLU_STABLE_COUNT_SHIFT); + clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, + timing[PARAM_ACTIVE_DELAY_COUNT] << + UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); + writel(val, &usbctlr->utmip_misc_cfg1); + + /* Set PLL enable delay count and crystal frequency count */ + val = readl(&usbctlr->utmip_pll_cfg1); + clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, + timing[PARAM_ENABLE_DELAY_COUNT] << + UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); + clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, + timing[PARAM_XTAL_FREQ_COUNT] << + UTMIP_XTAL_FREQ_COUNT_SHIFT); + writel(val, &usbctlr->utmip_pll_cfg1); + + /* Setting the tracking length time */ + clrsetbits_le32(&usbctlr->utmip_bias_cfg1, + UTMIP_BIAS_PDTRK_COUNT_MASK, + timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT); + + /* Program debounce time for VBUS to become valid */ + clrsetbits_le32(&usbctlr->utmip_debounce_cfg0, + UTMIP_DEBOUNCE_CFG0_MASK, + timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT); + + setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J); + + /* Disable battery charge enabling bit */ + setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG); + + clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE); + setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL); + + /* + * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT + * Setting these fields, together with default values of the + * other fields, results in programming the registers below as + * follows: + * UTMIP_HSRX_CFG0 = 0x9168c000 + * UTMIP_HSRX_CFG1 = 0x13 + */ + + /* Set PLL enable delay count and Crystal frequency count */ + val = readl(&usbctlr->utmip_hsrx_cfg0); + clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK, + utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); + clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK, + utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); + writel(val, &usbctlr->utmip_hsrx_cfg0); + + /* Configure the UTMIP_HS_SYNC_START_DLY */ + clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1, + UTMIP_HS_SYNC_START_DLY_MASK, + utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT); + + /* Preceed the crystal clock disable by >100ns delay. */ + udelay(1); + + /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ + setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); + + /* Finished the per-controller init. */ + + /* De-assert UTMIP_RESET to bring out of reset. */ + clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); + + /* Wait for the phy clock to become valid in 100 ms */ + for (loop_count = 100000; loop_count != 0; loop_count--) { + if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) + break; + udelay(1); + } + if (loop_count == 100000) + return -1; + + return 0; +} + +static void power_up_port(struct usb_ctlr *usbctlr) +{ + /* Deassert power down state */ + clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN | + UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); + clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN | + UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); +} + +static void config_clock(const u32 timing[]) +{ + clock_start_pll(CLOCK_ID_USB, + timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP], + timing[PARAM_CPCON], timing[PARAM_LFCON]); +} + +/** + * Add a new USB port to the list of available ports. + * + * @param config USB port configuration + * @return 0 if ok, -1 if error (too many ports) + */ +static int add_port(struct fdt_usb *config, const u32 timing[]) +{ + struct usb_ctlr *usbctlr = config->reg; + + if (port_count == USB_PORTS_MAX) { + debug("tegrausb: Cannot register more than %d ports\n", + USB_PORTS_MAX); + return -1; + } + if (init_usb_controller(config, usbctlr, timing)) { + debug("tegrausb: Cannot init port\n"); + return -1; + } + if (config->utmi) { + /* Disable ICUSB FS/LS transceiver */ + clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1); + + /* Select UTMI parallel interface */ + clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, + PTS_UTMI << PTS_SHIFT); + clrbits_le32(&usbctlr->port_sc1, STS); + power_up_port(usbctlr); + } + port[port_count++] = *config; + + return 0; +} + +int tegrausb_start_port(unsigned portnum, u32 *hccr, u32 *hcor) +{ + struct usb_ctlr *usbctlr; + + if (portnum >= port_count) + return -1; + tegrausb_stop_port(); + set_host_mode(&port[portnum]); + + usbctlr = port[portnum].reg; + *hccr = (u32)&usbctlr->cap_length; + *hcor = (u32)&usbctlr->usb_cmd; + port_current = portnum; + return 0; +} + +int tegrausb_stop_port(void) +{ + struct usb_ctlr *usbctlr; + + if (port_current == -1) + return -1; + + usbctlr = port[port_current].reg; + + /* Stop controller */ + writel(0, &usbctlr->usb_cmd); + udelay(1000); + + /* Initiate controller reset */ + writel(2, &usbctlr->usb_cmd); + udelay(1000); + port_current = -1; + return 0; +} + +int fdt_decode_usb(const void *blob, int node, unsigned osc_frequency_mhz, + struct fdt_usb *config) +{ + const char *phy, *mode; + + config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg"); + mode = fdt_getprop(blob, node, "dr_mode", NULL); + if (mode) { + if (0 == strcmp(mode, "host")) + config->dr_mode = DR_MODE_HOST; + else if (0 == strcmp(mode, "peripheral")) + config->dr_mode = DR_MODE_DEVICE; + else if (0 == strcmp(mode, "otg")) + config->dr_mode = DR_MODE_OTG; + else { + debug("%s: Cannot decode dr_mode '%s'\n", __func__, + mode); + return -FDT_ERR_NOTFOUND; + } + } else { + config->dr_mode = DR_MODE_HOST; + } + + phy = fdt_getprop(blob, node, "phy_type", NULL); + config->utmi = phy && 0 == strcmp("utmi", phy); + config->enabled = fdtdec_get_is_enabled(blob, node); + config->has_legacy_mode = fdtdec_get_bool(blob, node, + "nvidia,has-legacy-mode"); + config->periph_id = clock_decode_periph_id(blob, node); + if (config->periph_id == PERIPH_ID_NONE) { + debug("%s: Missing/invalid peripheral ID\n", __func__); + return -FDT_ERR_NOTFOUND; + } + fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio); + debug("enabled=%d, legacy_mode=%d, utmi=%d, periph_id=%d, vbus=%d, " + "dr_mode=%d\n", config->enabled, config->has_legacy_mode, + config->utmi, config->periph_id, config->vbus_gpio.gpio, + config->dr_mode); + + return 0; +} + +int board_usb_init(const void *blob) +{ + struct fdt_usb config; + unsigned osc_freq = clock_get_rate(CLOCK_ID_OSC); + enum clock_osc_freq freq; + int node_list[USB_PORTS_MAX]; + int node, count, i; + + /* Set up the USB clocks correctly based on our oscillator frequency */ + freq = clock_get_osc_freq(); + config_clock(usb_pll[freq]); + + /* count may return <0 on error */ + count = fdtdec_find_aliases_for_id(blob, "usb", + COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX); + for (i = 0; i < count; i++) { + debug("USB %d: ", i); + node = node_list[i]; + if (!node) + continue; + if (fdt_decode_usb(blob, node, osc_freq, &config)) { + debug("Cannot decode USB node %s\n", + fdt_get_name(blob, node, NULL)); + return -1; + } + + if (add_port(&config, usb_pll[freq])) + return -1; + set_host_mode(&config); + } + port_current = -1; + + return 0; +} diff --git a/arch/arm/include/asm/arch-tegra2/tegra2.h b/arch/arm/include/asm/arch-tegra2/tegra2.h index 8941443ad8e..baae2ebed38 100644 --- a/arch/arm/include/asm/arch-tegra2/tegra2.h +++ b/arch/arm/include/asm/arch-tegra2/tegra2.h @@ -41,6 +41,8 @@ #define TEGRA2_SPI_BASE (NV_PA_APB_MISC_BASE + 0xC380) #define NV_PA_PMC_BASE 0x7000E400 #define NV_PA_CSITE_BASE 0x70040000 +#define TEGRA_USB1_BASE 0xC5000000 +#define TEGRA_USB3_BASE 0xC5008000 #define TEGRA2_SDRC_CS0 NV_PA_SDRAM_BASE #define LOW_LEVEL_SRAM_STACK 0x4000FFFC diff --git a/arch/arm/include/asm/arch-tegra2/usb.h b/arch/arm/include/asm/arch-tegra2/usb.h new file mode 100644 index 00000000000..638033be503 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra2/usb.h @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _TEGRA_USB_H_ +#define _TEGRA_USB_H_ + + +/* USB Controller (USBx_CONTROLLER_) regs */ +struct usb_ctlr { + /* 0x000 */ + uint id; + uint reserved0; + uint host; + uint device; + + /* 0x010 */ + uint txbuf; + uint rxbuf; + uint reserved1[2]; + + /* 0x020 */ + uint reserved2[56]; + + /* 0x100 */ + u16 cap_length; + u16 hci_version; + uint hcs_params; + uint hcc_params; + uint reserved3[5]; + + /* 0x120 */ + uint dci_version; + uint dcc_params; + uint reserved4[6]; + + /* 0x140 */ + uint usb_cmd; + uint usb_sts; + uint usb_intr; + uint frindex; + + /* 0x150 */ + uint reserved5; + uint periodic_list_base; + uint async_list_addr; + uint async_tt_sts; + + /* 0x160 */ + uint burst_size; + uint tx_fill_tuning; + uint reserved6; /* is this port_sc1 on some controllers? */ + uint icusb_ctrl; + + /* 0x170 */ + uint ulpi_viewport; + uint reserved7; + uint endpt_nak; + uint endpt_nak_enable; + + /* 0x180 */ + uint reserved; + uint port_sc1; + uint reserved8[6]; + + /* 0x1a0 */ + uint reserved9; + uint otgsc; + uint usb_mode; + uint endpt_setup_stat; + + /* 0x1b0 */ + uint reserved10[20]; + + /* 0x200 */ + uint reserved11[0x80]; + + /* 0x400 */ + uint susp_ctrl; + uint phy_vbus_sensors; + uint phy_vbus_wakeup_id; + uint phy_alt_vbus_sys; + + /* 0x410 */ + uint usb1_legacy_ctrl; + uint reserved12[3]; + + /* 0x420 */ + uint reserved13[56]; + + /* 0x500 */ + uint reserved14[64 * 3]; + + /* 0x800 */ + uint utmip_pll_cfg0; + uint utmip_pll_cfg1; + uint utmip_xcvr_cfg0; + uint utmip_bias_cfg0; + + /* 0x810 */ + uint utmip_hsrx_cfg0; + uint utmip_hsrx_cfg1; + uint utmip_fslsrx_cfg0; + uint utmip_fslsrx_cfg1; + + /* 0x820 */ + uint utmip_tx_cfg0; + uint utmip_misc_cfg0; + uint utmip_misc_cfg1; + uint utmip_debounce_cfg0; + + /* 0x830 */ + uint utmip_bat_chrg_cfg0; + uint utmip_spare_cfg0; + uint utmip_xcvr_cfg1; + uint utmip_bias_cfg1; +}; + + +/* USB1_LEGACY_CTRL */ +#define USB1_NO_LEGACY_MODE 1 + +#define VBUS_SENSE_CTL_SHIFT 1 +#define VBUS_SENSE_CTL_MASK (3 << VBUS_SENSE_CTL_SHIFT) +#define VBUS_SENSE_CTL_VBUS_WAKEUP 0 +#define VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP 1 +#define VBUS_SENSE_CTL_AB_SESS_VLD 2 +#define VBUS_SENSE_CTL_A_SESS_VLD 3 + +/* USBx_IF_USB_SUSP_CTRL_0 */ +#define UTMIP_PHY_ENB (1 << 12) +#define UTMIP_RESET (1 << 11) +#define USB_PHY_CLK_VALID (1 << 7) + +/* USBx_UTMIP_MISC_CFG1 */ +#define UTMIP_PLLU_STABLE_COUNT_SHIFT 6 +#define UTMIP_PLLU_STABLE_COUNT_MASK \ + (0xfff << UTMIP_PLLU_STABLE_COUNT_SHIFT) +#define UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT 18 +#define UTMIP_PLL_ACTIVE_DLY_COUNT_MASK \ + (0x1f << UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT) +#define UTMIP_PHY_XTAL_CLOCKEN (1 << 30) + +/* USBx_UTMIP_PLL_CFG1_0 */ +#define UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT 27 +#define UTMIP_PLLU_ENABLE_DLY_COUNT_MASK \ + (0xf << UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT) +#define UTMIP_XTAL_FREQ_COUNT_SHIFT 0 +#define UTMIP_XTAL_FREQ_COUNT_MASK 0xfff + +/* USBx_UTMIP_BIAS_CFG1_0 */ +#define UTMIP_BIAS_PDTRK_COUNT_SHIFT 3 +#define UTMIP_BIAS_PDTRK_COUNT_MASK \ + (0x1f << UTMIP_BIAS_PDTRK_COUNT_SHIFT) + +#define UTMIP_DEBOUNCE_CFG0_SHIFT 0 +#define UTMIP_DEBOUNCE_CFG0_MASK 0xffff + +/* USBx_UTMIP_TX_CFG0_0 */ +#define UTMIP_FS_PREAMBLE_J (1 << 19) + +/* USBx_UTMIP_BAT_CHRG_CFG0_0 */ +#define UTMIP_PD_CHRG 1 + +/* USBx_UTMIP_XCVR_CFG0_0 */ +#define UTMIP_XCVR_LSBIAS_SE (1 << 21) + +/* USBx_UTMIP_SPARE_CFG0_0 */ +#define FUSE_SETUP_SEL (1 << 3) + +/* USBx_UTMIP_HSRX_CFG0_0 */ +#define UTMIP_IDLE_WAIT_SHIFT 15 +#define UTMIP_IDLE_WAIT_MASK (0x1f << UTMIP_IDLE_WAIT_SHIFT) +#define UTMIP_ELASTIC_LIMIT_SHIFT 10 +#define UTMIP_ELASTIC_LIMIT_MASK \ + (0x1f << UTMIP_ELASTIC_LIMIT_SHIFT) + +/* USBx_UTMIP_HSRX_CFG0_1 */ +#define UTMIP_HS_SYNC_START_DLY_SHIFT 1 +#define UTMIP_HS_SYNC_START_DLY_MASK \ + (0xf << UTMIP_HS_SYNC_START_DLY_SHIFT) + +/* USBx_CONTROLLER_2_USB2D_ICUSB_CTRL_0 */ +#define IC_ENB1 (1 << 3) + +/* SB2_CONTROLLER_2_USB2D_PORTSC1_0 */ +#define PTS_SHIFT 30 +#define PTS_MASK (3U << PTS_SHIFT) +#define PTS_UTMI 0 +#define PTS_RESERVED 1 +#define PTS_ULP 2 +#define PTS_ICUSB_SER 3 + +#define STS (1 << 29) + +/* USBx_UTMIP_XCVR_CFG0_0 */ +#define UTMIP_FORCE_PD_POWERDOWN (1 << 14) +#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) +#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) + +/* USBx_UTMIP_XCVR_CFG1_0 */ +#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) +#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) +#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) + +/* USB3_IF_USB_PHY_VBUS_SENSORS_0 */ +#define VBUS_VLD_STS (1 << 26) + + +/* Change the USB host port into host mode */ +void usb_set_host_mode(void); + +/* Setup USB on the board */ +int board_usb_init(const void *blob); + +/** + * Start up the given port number (ports are numbered from 0 on each board). + * This returns values for the appropriate hccr and hcor addresses to use for + * USB EHCI operations. + * + * @param portnum port number to start + * @param hccr returns start address of EHCI HCCR registers + * @param hcor returns start address of EHCI HCOR registers + * @return 0 if ok, -1 on error (generally invalid port number) + */ +int tegrausb_start_port(unsigned portnum, u32 *hccr, u32 *hcor); + +/** + * Stop the current port + * + * @return 0 if ok, -1 if no port was active + */ +int tegrausb_stop_port(void); + +#endif /* _TEGRA_USB_H_ */ diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 53ad70af23c..0d4657edf2f 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -50,6 +50,7 @@ COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o COBJS-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o +COBJS-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o COBJS := $(COBJS-y) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c new file mode 100644 index 00000000000..a7e105b9921 --- /dev/null +++ b/drivers/usb/host/ehci-tegra.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +#include "ehci.h" +#include "ehci-core.h" + +#include +#include + + +/* + * Create the appropriate control structures to manage + * a new EHCI host controller. + */ +int ehci_hcd_init(void) +{ + u32 our_hccr, our_hcor; + + /* + * Select the first port, as we don't have a way of selecting others + * yet + */ + if (tegrausb_start_port(0, &our_hccr, &our_hcor)) + return -1; + + hccr = (struct ehci_hccr *)our_hccr; + hcor = (struct ehci_hcor *)our_hcor; + + return 0; +} + +/* + * Destroy the appropriate control structures corresponding + * the the EHCI host controller. + */ +int ehci_hcd_stop(void) +{ + tegrausb_stop_port(); + return 0; +} diff --git a/include/fdtdec.h b/include/fdtdec.h index 2f3842d9a30..bde9873656a 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -57,6 +57,7 @@ struct fdt_memory { */ enum fdt_compat_id { COMPAT_UNKNOWN, + COMPAT_NVIDIA_TEGRA20_USB, /* Tegra2 USB port */ COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index de83226ed1f..4ca442a2afd 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -37,6 +37,7 @@ DECLARE_GLOBAL_DATA_PTR; #define COMPAT(id, name) name static const char * const compat_names[COMPAT_COUNT] = { COMPAT(UNKNOWN, ""), + COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) -- cgit v1.3.1 From 96a78ac0c445999ce21fb42ecab061479b4d7056 Mon Sep 17 00:00:00 2001 From: Yen Lin Date: Tue, 6 Mar 2012 19:00:23 +0000 Subject: tegra: i2c: Add I2C driver Add basic i2c driver for Tegra2 with 8- and 16-bit address support. The driver requires CONFIG_OF_CONTROL to obtain its configuration from the device tree. (Simon Glass: sjg@chromium.org modified for upstream) Signed-off-by: Simon Glass Acked-by: Heiko Schocher Acked-by: Stephen Warren Signed-off-by: Tom Warren --- arch/arm/include/asm/arch-tegra2/tegra_i2c.h | 157 ++++++++ drivers/i2c/Makefile | 1 + drivers/i2c/tegra_i2c.c | 569 +++++++++++++++++++++++++++ include/fdtdec.h | 2 + lib/fdtdec.c | 2 + 5 files changed, 731 insertions(+) create mode 100644 arch/arm/include/asm/arch-tegra2/tegra_i2c.h create mode 100644 drivers/i2c/tegra_i2c.c (limited to 'drivers') diff --git a/arch/arm/include/asm/arch-tegra2/tegra_i2c.h b/arch/arm/include/asm/arch-tegra2/tegra_i2c.h new file mode 100644 index 00000000000..0a7d99c5858 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra2/tegra_i2c.h @@ -0,0 +1,157 @@ +/* + * NVIDIA Tegra2 I2C controller + * + * Copyright 2010-2011 NVIDIA Corporation + * + * This software may be used and distributed according to the + * terms of the GNU Public License, Version 2, incorporated + * herein by reference. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _TEGRA_I2C_H_ +#define _TEGRA_I2C_H_ + +#include + +enum { + I2C_TIMEOUT_USEC = 10000, /* Wait time for completion */ + I2C_FIFO_DEPTH = 8, /* I2C fifo depth */ +}; + +enum i2c_transaction_flags { + I2C_IS_WRITE = 0x1, /* for I2C write operation */ + I2C_IS_10_BIT_ADDRESS = 0x2, /* for 10-bit I2C slave address */ + I2C_USE_REPEATED_START = 0x4, /* for repeat start */ + I2C_NO_ACK = 0x8, /* for slave that won't generate ACK */ + I2C_SOFTWARE_CONTROLLER = 0x10, /* for I2C transfer using GPIO */ + I2C_NO_STOP = 0x20, +}; + +/* Contians the I2C transaction details */ +struct i2c_trans_info { + /* flags to indicate the transaction details */ + enum i2c_transaction_flags flags; + u32 address; /* I2C slave device address */ + u32 num_bytes; /* number of bytes to be transferred */ + /* + * Send/receive buffer. For the I2C send operation this buffer should + * be filled with the data to be sent to the slave device. For the I2C + * receive operation this buffer is filled with the data received from + * the slave device. + */ + u8 *buf; + int is_10bit_address; +}; + +struct i2c_control { + u32 tx_fifo; + u32 rx_fifo; + u32 packet_status; + u32 fifo_control; + u32 fifo_status; + u32 int_mask; + u32 int_status; +}; + +struct dvc_ctlr { + u32 ctrl1; /* 00: DVC_CTRL_REG1 */ + u32 ctrl2; /* 04: DVC_CTRL_REG2 */ + u32 ctrl3; /* 08: DVC_CTRL_REG3 */ + u32 status; /* 0C: DVC_STATUS_REG */ + u32 ctrl; /* 10: DVC_I2C_CTRL_REG */ + u32 addr_data; /* 14: DVC_I2C_ADDR_DATA_REG */ + u32 reserved_0[2]; /* 18: */ + u32 req; /* 20: DVC_REQ_REGISTER */ + u32 addr_data3; /* 24: DVC_I2C_ADDR_DATA_REG_3 */ + u32 reserved_1[6]; /* 28: */ + u32 cnfg; /* 40: DVC_I2C_CNFG */ + u32 cmd_addr0; /* 44: DVC_I2C_CMD_ADDR0 */ + u32 cmd_addr1; /* 48: DVC_I2C_CMD_ADDR1 */ + u32 cmd_data1; /* 4C: DVC_I2C_CMD_DATA1 */ + u32 cmd_data2; /* 50: DVC_I2C_CMD_DATA2 */ + u32 reserved_2[2]; /* 54: */ + u32 i2c_status; /* 5C: DVC_I2C_STATUS */ + struct i2c_control control; /* 60 ~ 78 */ +}; + +struct i2c_ctlr { + u32 cnfg; /* 00: I2C_I2C_CNFG */ + u32 cmd_addr0; /* 04: I2C_I2C_CMD_ADDR0 */ + u32 cmd_addr1; /* 08: I2C_I2C_CMD_DATA1 */ + u32 cmd_data1; /* 0C: I2C_I2C_CMD_DATA2 */ + u32 cmd_data2; /* 10: DVC_I2C_CMD_DATA2 */ + u32 reserved_0[2]; /* 14: */ + u32 status; /* 1C: I2C_I2C_STATUS */ + u32 sl_cnfg; /* 20: I2C_I2C_SL_CNFG */ + u32 sl_rcvd; /* 24: I2C_I2C_SL_RCVD */ + u32 sl_status; /* 28: I2C_I2C_SL_STATUS */ + u32 sl_addr1; /* 2C: I2C_I2C_SL_ADDR1 */ + u32 sl_addr2; /* 30: I2C_I2C_SL_ADDR2 */ + u32 reserved_1[2]; /* 34: */ + u32 sl_delay_count; /* 3C: I2C_I2C_SL_DELAY_COUNT */ + u32 reserved_2[4]; /* 40: */ + struct i2c_control control; /* 50 ~ 68 */ +}; + +/* bit fields definitions for IO Packet Header 1 format */ +#define PKT_HDR1_PROTOCOL_SHIFT 4 +#define PKT_HDR1_PROTOCOL_MASK (0xf << PKT_HDR1_PROTOCOL_SHIFT) +#define PKT_HDR1_CTLR_ID_SHIFT 12 +#define PKT_HDR1_CTLR_ID_MASK (0xf << PKT_HDR1_CTLR_ID_SHIFT) +#define PKT_HDR1_PKT_ID_SHIFT 16 +#define PKT_HDR1_PKT_ID_MASK (0xff << PKT_HDR1_PKT_ID_SHIFT) +#define PROTOCOL_TYPE_I2C 1 + +/* bit fields definitions for IO Packet Header 2 format */ +#define PKT_HDR2_PAYLOAD_SIZE_SHIFT 0 +#define PKT_HDR2_PAYLOAD_SIZE_MASK (0xfff << PKT_HDR2_PAYLOAD_SIZE_SHIFT) + +/* bit fields definitions for IO Packet Header 3 format */ +#define PKT_HDR3_READ_MODE_SHIFT 19 +#define PKT_HDR3_READ_MODE_MASK (1 << PKT_HDR3_READ_MODE_SHIFT) +#define PKT_HDR3_SLAVE_ADDR_SHIFT 0 +#define PKT_HDR3_SLAVE_ADDR_MASK (0x3ff << PKT_HDR3_SLAVE_ADDR_SHIFT) + +#define DVC_CTRL_REG3_I2C_HW_SW_PROG_SHIFT 26 +#define DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK \ + (1 << DVC_CTRL_REG3_I2C_HW_SW_PROG_SHIFT) + +/* I2C_CNFG */ +#define I2C_CNFG_NEW_MASTER_FSM_SHIFT 11 +#define I2C_CNFG_NEW_MASTER_FSM_MASK (1 << I2C_CNFG_NEW_MASTER_FSM_SHIFT) +#define I2C_CNFG_PACKET_MODE_SHIFT 10 +#define I2C_CNFG_PACKET_MODE_MASK (1 << I2C_CNFG_PACKET_MODE_SHIFT) + +/* I2C_SL_CNFG */ +#define I2C_SL_CNFG_NEWSL_SHIFT 2 +#define I2C_SL_CNFG_NEWSL_MASK (1 << I2C_SL_CNFG_NEWSL_SHIFT) + +/* I2C_FIFO_STATUS */ +#define TX_FIFO_FULL_CNT_SHIFT 0 +#define TX_FIFO_FULL_CNT_MASK (0xf << TX_FIFO_FULL_CNT_SHIFT) +#define TX_FIFO_EMPTY_CNT_SHIFT 4 +#define TX_FIFO_EMPTY_CNT_MASK (0xf << TX_FIFO_EMPTY_CNT_SHIFT) + +/* I2C_INTERRUPT_STATUS */ +#define I2C_INT_XFER_COMPLETE_SHIFT 7 +#define I2C_INT_XFER_COMPLETE_MASK (1 << I2C_INT_XFER_COMPLETE_SHIFT) +#define I2C_INT_NO_ACK_SHIFT 3 +#define I2C_INT_NO_ACK_MASK (1 << I2C_INT_NO_ACK_SHIFT) +#define I2C_INT_ARBITRATION_LOST_SHIFT 2 +#define I2C_INT_ARBITRATION_LOST_MASK (1 << I2C_INT_ARBITRATION_LOST_SHIFT) + +#endif diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 504db03c711..f86e46c111f 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -41,6 +41,7 @@ COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_SPEAR_I2C) += spr_i2c.o +COBJS-$(CONFIG_TEGRA_I2C) += tegra_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o COBJS-$(CONFIG_SH_I2C) += sh_i2c.o diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c new file mode 100644 index 00000000000..21f68972692 --- /dev/null +++ b/drivers/i2c/tegra_i2c.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Copyright (c) 2010-2011 NVIDIA Corporation + * NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static unsigned int i2c_bus_num; + +/* Information about i2c controller */ +struct i2c_bus { + int id; + enum periph_id periph_id; + int speed; + int pinmux_config; + struct i2c_control *control; + struct i2c_ctlr *regs; + int is_dvc; /* DVC type, rather than I2C */ + int inited; /* bus is inited */ +}; + +static struct i2c_bus i2c_controllers[TEGRA_I2C_NUM_CONTROLLERS]; + +static void set_packet_mode(struct i2c_bus *i2c_bus) +{ + u32 config; + + config = I2C_CNFG_NEW_MASTER_FSM_MASK | I2C_CNFG_PACKET_MODE_MASK; + + if (i2c_bus->is_dvc) { + struct dvc_ctlr *dvc = (struct dvc_ctlr *)i2c_bus->regs; + + writel(config, &dvc->cnfg); + } else { + writel(config, &i2c_bus->regs->cnfg); + /* + * program I2C_SL_CNFG.NEWSL to ENABLE. This fixes probe + * issues, i.e., some slaves may be wrongly detected. + */ + setbits_le32(&i2c_bus->regs->sl_cnfg, I2C_SL_CNFG_NEWSL_MASK); + } +} + +static void i2c_reset_controller(struct i2c_bus *i2c_bus) +{ + /* Reset I2C controller. */ + reset_periph(i2c_bus->periph_id, 1); + + /* re-program config register to packet mode */ + set_packet_mode(i2c_bus); +} + +static void i2c_init_controller(struct i2c_bus *i2c_bus) +{ + /* + * Use PLLP - DP-04508-001_v06 datasheet indicates a divisor of 8 + * here, in section 23.3.1, but in fact we seem to need a factor of + * 16 to get the right frequency. + */ + clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH, + i2c_bus->speed * 2 * 8); + + /* Reset I2C controller. */ + i2c_reset_controller(i2c_bus); + + /* Configure I2C controller. */ + if (i2c_bus->is_dvc) { /* only for DVC I2C */ + struct dvc_ctlr *dvc = (struct dvc_ctlr *)i2c_bus->regs; + + setbits_le32(&dvc->ctrl3, DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK); + } + + funcmux_select(i2c_bus->periph_id, i2c_bus->pinmux_config); +} + +static void send_packet_headers( + struct i2c_bus *i2c_bus, + struct i2c_trans_info *trans, + u32 packet_id) +{ + u32 data; + + /* prepare header1: Header size = 0 Protocol = I2C, pktType = 0 */ + data = PROTOCOL_TYPE_I2C << PKT_HDR1_PROTOCOL_SHIFT; + data |= packet_id << PKT_HDR1_PKT_ID_SHIFT; + data |= i2c_bus->id << PKT_HDR1_CTLR_ID_SHIFT; + writel(data, &i2c_bus->control->tx_fifo); + debug("pkt header 1 sent (0x%x)\n", data); + + /* prepare header2 */ + data = (trans->num_bytes - 1) << PKT_HDR2_PAYLOAD_SIZE_SHIFT; + writel(data, &i2c_bus->control->tx_fifo); + debug("pkt header 2 sent (0x%x)\n", data); + + /* prepare IO specific header: configure the slave address */ + data = trans->address << PKT_HDR3_SLAVE_ADDR_SHIFT; + + /* Enable Read if it is not a write transaction */ + if (!(trans->flags & I2C_IS_WRITE)) + data |= PKT_HDR3_READ_MODE_MASK; + + /* Write I2C specific header */ + writel(data, &i2c_bus->control->tx_fifo); + debug("pkt header 3 sent (0x%x)\n", data); +} + +static int wait_for_tx_fifo_empty(struct i2c_control *control) +{ + u32 count; + int timeout_us = I2C_TIMEOUT_USEC; + + while (timeout_us >= 0) { + count = (readl(&control->fifo_status) & TX_FIFO_EMPTY_CNT_MASK) + >> TX_FIFO_EMPTY_CNT_SHIFT; + if (count == I2C_FIFO_DEPTH) + return 1; + udelay(10); + timeout_us -= 10; + } + + return 0; +} + +static int wait_for_rx_fifo_notempty(struct i2c_control *control) +{ + u32 count; + int timeout_us = I2C_TIMEOUT_USEC; + + while (timeout_us >= 0) { + count = (readl(&control->fifo_status) & TX_FIFO_FULL_CNT_MASK) + >> TX_FIFO_FULL_CNT_SHIFT; + if (count) + return 1; + udelay(10); + timeout_us -= 10; + } + + return 0; +} + +static int wait_for_transfer_complete(struct i2c_control *control) +{ + int int_status; + int timeout_us = I2C_TIMEOUT_USEC; + + while (timeout_us >= 0) { + int_status = readl(&control->int_status); + if (int_status & I2C_INT_NO_ACK_MASK) + return -int_status; + if (int_status & I2C_INT_ARBITRATION_LOST_MASK) + return -int_status; + if (int_status & I2C_INT_XFER_COMPLETE_MASK) + return 0; + + udelay(10); + timeout_us -= 10; + } + + return -1; +} + +static int send_recv_packets(struct i2c_bus *i2c_bus, + struct i2c_trans_info *trans) +{ + struct i2c_control *control = i2c_bus->control; + u32 int_status; + u32 words; + u8 *dptr; + u32 local; + uchar last_bytes; + int error = 0; + int is_write = trans->flags & I2C_IS_WRITE; + + /* clear status from previous transaction, XFER_COMPLETE, NOACK, etc. */ + int_status = readl(&control->int_status); + writel(int_status, &control->int_status); + + send_packet_headers(i2c_bus, trans, 1); + + words = DIV_ROUND_UP(trans->num_bytes, 4); + last_bytes = trans->num_bytes & 3; + dptr = trans->buf; + + while (words) { + u32 *wptr = (u32 *)dptr; + + if (is_write) { + /* deal with word alignment */ + if ((unsigned)dptr & 3) { + memcpy(&local, dptr, sizeof(u32)); + writel(local, &control->tx_fifo); + debug("pkt data sent (0x%x)\n", local); + } else { + writel(*wptr, &control->tx_fifo); + debug("pkt data sent (0x%x)\n", *wptr); + } + if (!wait_for_tx_fifo_empty(control)) { + error = -1; + goto exit; + } + } else { + if (!wait_for_rx_fifo_notempty(control)) { + error = -1; + goto exit; + } + /* + * for the last word, we read into our local buffer, + * in case that caller did not provide enough buffer. + */ + local = readl(&control->rx_fifo); + if ((words == 1) && last_bytes) + memcpy(dptr, (char *)&local, last_bytes); + else if ((unsigned)dptr & 3) + memcpy(dptr, &local, sizeof(u32)); + else + *wptr = local; + debug("pkt data received (0x%x)\n", local); + } + words--; + dptr += sizeof(u32); + } + + if (wait_for_transfer_complete(control)) { + error = -1; + goto exit; + } + return 0; +exit: + /* error, reset the controller. */ + i2c_reset_controller(i2c_bus); + + return error; +} + +static int tegra2_i2c_write_data(u32 addr, u8 *data, u32 len) +{ + int error; + struct i2c_trans_info trans_info; + + trans_info.address = addr; + trans_info.buf = data; + trans_info.flags = I2C_IS_WRITE; + trans_info.num_bytes = len; + trans_info.is_10bit_address = 0; + + error = send_recv_packets(&i2c_controllers[i2c_bus_num], &trans_info); + if (error) + debug("tegra2_i2c_write_data: Error (%d) !!!\n", error); + + return error; +} + +static int tegra2_i2c_read_data(u32 addr, u8 *data, u32 len) +{ + int error; + struct i2c_trans_info trans_info; + + trans_info.address = addr | 1; + trans_info.buf = data; + trans_info.flags = 0; + trans_info.num_bytes = len; + trans_info.is_10bit_address = 0; + + error = send_recv_packets(&i2c_controllers[i2c_bus_num], &trans_info); + if (error) + debug("tegra2_i2c_read_data: Error (%d) !!!\n", error); + + return error; +} + +#ifndef CONFIG_OF_CONTROL +#error "Please enable device tree support to use this driver" +#endif + +unsigned int i2c_get_bus_speed(void) +{ + return i2c_controllers[i2c_bus_num].speed; +} + +int i2c_set_bus_speed(unsigned int speed) +{ + struct i2c_bus *i2c_bus; + + i2c_bus = &i2c_controllers[i2c_bus_num]; + i2c_bus->speed = speed; + i2c_init_controller(i2c_bus); + + return 0; +} + +static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus) +{ + i2c_bus->regs = (struct i2c_ctlr *)fdtdec_get_addr(blob, node, "reg"); + + /* + * We don't have a binding for pinmux yet. Leave it out for now. So + * far no one needs anything other than the default. + */ + i2c_bus->pinmux_config = FUNCMUX_DEFAULT; + i2c_bus->speed = fdtdec_get_int(blob, node, "clock-frequency", 0); + i2c_bus->periph_id = clock_decode_periph_id(blob, node); + + /* + * We can't specify the pinmux config in the fdt, so I2C2 will not + * work on Seaboard. It normally has no devices on it anyway. + * You could add in this little hack if you need to use it. + * The correct solution is a pinmux binding in the fdt. + * + * if (i2c_bus->periph_id == PERIPH_ID_I2C2) + * i2c_bus->pinmux_config = FUNCMUX_I2C2_PTA; + */ + if (i2c_bus->periph_id == -1) + return -FDT_ERR_NOTFOUND; + + return 0; +} + +/* + * Process a list of nodes, adding them to our list of I2C ports. + * + * @param blob fdt blob + * @param node_list list of nodes to process (any <=0 are ignored) + * @param count number of nodes to process + * @param is_dvc 1 if these are DVC ports, 0 if standard I2C + * @return 0 if ok, -1 on error + */ +static int process_nodes(const void *blob, int node_list[], int count, + int is_dvc) +{ + struct i2c_bus *i2c_bus; + int i; + + /* build the i2c_controllers[] for each controller */ + for (i = 0; i < count; i++) { + int node = node_list[i]; + + if (node <= 0) + continue; + + i2c_bus = &i2c_controllers[i]; + i2c_bus->id = i; + + if (i2c_get_config(blob, node, i2c_bus)) { + printf("i2c_init_board: failed to decode bus %d\n", i); + return -1; + } + + i2c_bus->is_dvc = is_dvc; + if (is_dvc) { + i2c_bus->control = + &((struct dvc_ctlr *)i2c_bus->regs)->control; + } else { + i2c_bus->control = &i2c_bus->regs->control; + } + debug("%s: controller bus %d at %p, periph_id %d, speed %d: ", + is_dvc ? "dvc" : "i2c", i, i2c_bus->regs, + i2c_bus->periph_id, i2c_bus->speed); + i2c_init_controller(i2c_bus); + debug("ok\n"); + i2c_bus->inited = 1; + + /* Mark position as used */ + node_list[i] = -1; + } + + return 0; +} + +/* Sadly there is no error return from this function */ +void i2c_init_board(void) +{ + int node_list[TEGRA_I2C_NUM_CONTROLLERS]; + const void *blob = gd->fdt_blob; + int count; + + /* First get the normal i2c ports */ + count = fdtdec_find_aliases_for_id(blob, "i2c", + COMPAT_NVIDIA_TEGRA20_I2C, node_list, + TEGRA_I2C_NUM_CONTROLLERS); + if (process_nodes(blob, node_list, count, 0)) + return; + + /* Now look for dvc ports */ + count = fdtdec_add_aliases_for_id(blob, "i2c", + COMPAT_NVIDIA_TEGRA20_DVC, node_list, + TEGRA_I2C_NUM_CONTROLLERS); + if (process_nodes(blob, node_list, count, 1)) + return; +} + +void i2c_init(int speed, int slaveaddr) +{ + /* This will override the speed selected in the fdt for that port */ + debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr); + i2c_set_bus_speed(speed); +} + +/* i2c write version without the register address */ +int i2c_write_data(uchar chip, uchar *buffer, int len) +{ + int rc; + + debug("i2c_write_data: chip=0x%x, len=0x%x\n", chip, len); + debug("write_data: "); + /* use rc for counter */ + for (rc = 0; rc < len; ++rc) + debug(" 0x%02x", buffer[rc]); + debug("\n"); + + /* Shift 7-bit address over for lower-level i2c functions */ + rc = tegra2_i2c_write_data(chip << 1, buffer, len); + if (rc) + debug("i2c_write_data(): rc=%d\n", rc); + + return rc; +} + +/* i2c read version without the register address */ +int i2c_read_data(uchar chip, uchar *buffer, int len) +{ + int rc; + + debug("inside i2c_read_data():\n"); + /* Shift 7-bit address over for lower-level i2c functions */ + rc = tegra2_i2c_read_data(chip << 1, buffer, len); + if (rc) { + debug("i2c_read_data(): rc=%d\n", rc); + return rc; + } + + debug("i2c_read_data: "); + /* reuse rc for counter*/ + for (rc = 0; rc < len; ++rc) + debug(" 0x%02x", buffer[rc]); + debug("\n"); + + return 0; +} + +/* Probe to see if a chip is present. */ +int i2c_probe(uchar chip) +{ + int rc; + uchar reg; + + debug("i2c_probe: addr=0x%x\n", chip); + reg = 0; + rc = i2c_write_data(chip, ®, 1); + if (rc) { + debug("Error probing 0x%x.\n", chip); + return 1; + } + return 0; +} + +static int i2c_addr_ok(const uint addr, const int alen) +{ + /* We support 7 or 10 bit addresses, so one or two bytes each */ + return alen == 1 || alen == 2; +} + +/* Read bytes */ +int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + uint offset; + int i; + + debug("i2c_read: chip=0x%x, addr=0x%x, len=0x%x\n", + chip, addr, len); + if (!i2c_addr_ok(addr, alen)) { + debug("i2c_read: Bad address %x.%d.\n", addr, alen); + return 1; + } + for (offset = 0; offset < len; offset++) { + if (alen) { + uchar data[alen]; + for (i = 0; i < alen; i++) { + data[alen - i - 1] = + (addr + offset) >> (8 * i); + } + if (i2c_write_data(chip, data, alen)) { + debug("i2c_read: error sending (0x%x)\n", + addr); + return 1; + } + } + if (i2c_read_data(chip, buffer + offset, 1)) { + debug("i2c_read: error reading (0x%x)\n", addr); + return 1; + } + } + + return 0; +} + +/* Write bytes */ +int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + uint offset; + int i; + + debug("i2c_write: chip=0x%x, addr=0x%x, len=0x%x\n", + chip, addr, len); + if (!i2c_addr_ok(addr, alen)) { + debug("i2c_write: Bad address %x.%d.\n", addr, alen); + return 1; + } + for (offset = 0; offset < len; offset++) { + uchar data[alen + 1]; + for (i = 0; i < alen; i++) + data[alen - i - 1] = (addr + offset) >> (8 * i); + data[alen] = buffer[offset]; + if (i2c_write_data(chip, data, alen + 1)) { + debug("i2c_write: error sending (0x%x)\n", addr); + return 1; + } + } + + return 0; +} + +#if defined(CONFIG_I2C_MULTI_BUS) +/* + * Functions for multiple I2C bus handling + */ +unsigned int i2c_get_bus_num(void) +{ + return i2c_bus_num; +} + +int i2c_set_bus_num(unsigned int bus) +{ + if (bus >= TEGRA_I2C_NUM_CONTROLLERS || !i2c_controllers[bus].inited) + return -1; + i2c_bus_num = bus; + + return 0; +} +#endif diff --git a/include/fdtdec.h b/include/fdtdec.h index 1e198f8c630..171c6284853 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -58,6 +58,8 @@ struct fdt_memory { enum fdt_compat_id { COMPAT_UNKNOWN, COMPAT_NVIDIA_TEGRA20_USB, /* Tegra2 USB port */ + COMPAT_NVIDIA_TEGRA20_I2C, /* Tegra2 i2c */ + COMPAT_NVIDIA_TEGRA20_DVC, /* Tegra2 dvc (really just i2c) */ COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 2149bd70684..bdec1a0d962 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -38,6 +38,8 @@ DECLARE_GLOBAL_DATA_PTR; static const char * const compat_names[COMPAT_COUNT] = { COMPAT(UNKNOWN, ""), COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"), + COMPAT(NVIDIA_TEGRA20_I2C, "nvidia,tegra20-i2c"), + COMPAT(NVIDIA_TEGRA20_DVC, "nvidia,tegra20-i2c-dvc"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) -- cgit v1.3.1