From a86ac9540e20c8e1d84342306b7dc1126222bae7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 Feb 2015 02:26:44 +0900 Subject: ARM: UniPhier: include instead of Since commit 0e7368c6c426 (kbuild: prepare for moving headers into mach-*/include/mach), we can replace #include with so we do not need to create the symbolic link during the build. Signed-off-by: Masahiro Yamada --- drivers/usb/host/ehci-uniphier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-uniphier.c b/drivers/usb/host/ehci-uniphier.c index 32a4375..42e2204 100644 --- a/drivers/usb/host/ehci-uniphier.c +++ b/drivers/usb/host/ehci-uniphier.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "ehci.h" #ifdef CONFIG_OF_CONTROL -- cgit v1.1 From d0c47b3ef7c582ec984edeba08984b0acc2ffcba Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 Feb 2015 02:26:46 +0900 Subject: serial: UniPhier: use 32 bit register access For PH1-Pro4, the 8 bit write access to LCR register (offset = 0x11) is not working correctly. As a side effect, it also modifies MCR register (offset = 0x10) and results in unexpected behavior. Signed-off-by: Masahiro Yamada --- drivers/serial/serial_uniphier.c | 54 +++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c index e8a1608..327e0dc 100644 --- a/drivers/serial/serial_uniphier.c +++ b/drivers/serial/serial_uniphier.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2014 Panasonic Corporation + * Copyright (C) 2012-2015 Panasonic Corporation * Author: Masahiro Yamada * * SPDX-License-Identifier: GPL-2.0+ @@ -13,31 +13,25 @@ #include #include -#define UART_REG(x) \ - u8 x; \ - u8 postpad_##x[3]; - /* * Note: Register map is slightly different from that of 16550. */ struct uniphier_serial { - UART_REG(rbr); /* 0x00 */ - UART_REG(ier); /* 0x04 */ - UART_REG(iir); /* 0x08 */ - UART_REG(fcr); /* 0x0c */ - u8 mcr; /* 0x10 */ - u8 lcr; - u16 __postpad; - UART_REG(lsr); /* 0x14 */ - UART_REG(msr); /* 0x18 */ - u32 __none1; - u32 __none2; - u16 dlr; - u16 __postpad2; + u32 rx; /* In: Receive buffer */ +#define tx rx /* Out: Transmit buffer */ + u32 ier; /* Interrupt Enable Register */ + u32 iir; /* In: Interrupt ID Register */ + u32 char_fcr; /* Charactor / FIFO Control Register */ + u32 lcr_mcr; /* Line/Modem Control Register */ +#define LCR_SHIFT 8 +#define LCR_MASK (0xff << (LCR_SHIFT)) + u32 lsr; /* In: Line Status Register */ + u32 msr; /* In: Modem Status Register */ + u32 __rsv0; + u32 __rsv1; + u32 dlr; /* Divisor Latch Register */ }; -#define thr rbr - struct uniphier_serial_private_data { struct uniphier_serial __iomem *membase; }; @@ -51,12 +45,16 @@ static int uniphier_serial_setbrg(struct udevice *dev, int baudrate) struct uniphier_serial __iomem *port = uniphier_serial_port(dev); const unsigned int mode_x_div = 16; unsigned int divisor; + u32 tmp; - writeb(UART_LCR_WLEN8, &port->lcr); + tmp = readl(&port->lcr_mcr); + tmp &= ~LCR_MASK; + tmp |= UART_LCR_WLEN8 << LCR_SHIFT; + writel(tmp, &port->lcr_mcr); divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate); - writew(divisor, &port->dlr); + writel(divisor, &port->dlr); return 0; } @@ -65,20 +63,20 @@ static int uniphier_serial_getc(struct udevice *dev) { struct uniphier_serial __iomem *port = uniphier_serial_port(dev); - if (!(readb(&port->lsr) & UART_LSR_DR)) + if (!(readl(&port->lsr) & UART_LSR_DR)) return -EAGAIN; - return readb(&port->rbr); + return readl(&port->rx); } static int uniphier_serial_putc(struct udevice *dev, const char c) { struct uniphier_serial __iomem *port = uniphier_serial_port(dev); - if (!(readb(&port->lsr) & UART_LSR_THRE)) + if (!(readl(&port->lsr) & UART_LSR_THRE)) return -EAGAIN; - writeb(c, &port->thr); + writel(c, &port->tx); return 0; } @@ -88,9 +86,9 @@ static int uniphier_serial_pending(struct udevice *dev, bool input) struct uniphier_serial __iomem *port = uniphier_serial_port(dev); if (input) - return readb(&port->lsr) & UART_LSR_DR; + return readl(&port->lsr) & UART_LSR_DR; else - return !(readb(&port->lsr) & UART_LSR_THRE); + return !(readl(&port->lsr) & UART_LSR_THRE); } static int uniphier_serial_probe(struct udevice *dev) -- cgit v1.1 From 099cf77c155ffd9aef7c3783c608d7574177bda9 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 Feb 2015 02:26:47 +0900 Subject: serial: UniPhier: move LCR register setting to probe function We do not have to set the LCR register every time we change the baud-rate. We just need to set it up once in the probe function. Signed-off-by: Masahiro Yamada --- drivers/serial/serial_uniphier.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c index 327e0dc..a6bd27f 100644 --- a/drivers/serial/serial_uniphier.c +++ b/drivers/serial/serial_uniphier.c @@ -45,12 +45,6 @@ static int uniphier_serial_setbrg(struct udevice *dev, int baudrate) struct uniphier_serial __iomem *port = uniphier_serial_port(dev); const unsigned int mode_x_div = 16; unsigned int divisor; - u32 tmp; - - tmp = readl(&port->lcr_mcr); - tmp &= ~LCR_MASK; - tmp |= UART_LCR_WLEN8 << LCR_SHIFT; - writel(tmp, &port->lcr_mcr); divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate); @@ -93,14 +87,22 @@ static int uniphier_serial_pending(struct udevice *dev, bool input) static int uniphier_serial_probe(struct udevice *dev) { + u32 tmp; struct uniphier_serial_private_data *priv = dev_get_priv(dev); struct uniphier_serial_platform_data *plat = dev_get_platdata(dev); + struct uniphier_serial __iomem *port; - priv->membase = map_sysmem(plat->base, sizeof(struct uniphier_serial)); - - if (!priv->membase) + port = map_sysmem(plat->base, sizeof(struct uniphier_serial)); + if (!port) return -ENOMEM; + priv->membase = port; + + tmp = readl(&port->lcr_mcr); + tmp &= ~LCR_MASK; + tmp |= UART_LCR_WLEN8 << LCR_SHIFT; + writel(tmp, &port->lcr_mcr); + return 0; } -- cgit v1.1 From 44f597adebb369ceb5921d4f18b73e415e83441f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 Feb 2015 02:26:54 +0900 Subject: ARM: UniPhier: remove EHCI platform devices Now UniPhier platform highly depends on Device Tree configuration (CONFIG_OF_CONTROL is select'ed by Kconfig). Since the EHCI is only used on main U-Boot, we can drop platform devices of the EHCI controllers. We still keep UART platform devices because they might be useful for SPL. Signed-off-by: Masahiro Yamada Acked-by: Marek Vasut --- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/ehci-uniphier.c | 14 +------------- 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 30d1457..0e005c2 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -47,7 +47,7 @@ if USB_EHCI_HCD config USB_EHCI_UNIPHIER bool "Support for Panasonic UniPhier on-chip EHCI USB controller" - depends on ARCH_UNIPHIER + depends on ARCH_UNIPHIER && OF_CONTROL default y ---help--- Enables support for the on-chip EHCI controller on Panasonic diff --git a/drivers/usb/host/ehci-uniphier.c b/drivers/usb/host/ehci-uniphier.c index 42e2204..68959ef 100644 --- a/drivers/usb/host/ehci-uniphier.c +++ b/drivers/usb/host/ehci-uniphier.c @@ -9,10 +9,9 @@ #include #include #include +#include #include "ehci.h" -#ifdef CONFIG_OF_CONTROL -#include DECLARE_GLOBAL_DATA_PTR; #define FDT gd->fdt_blob @@ -35,18 +34,7 @@ static int get_uniphier_ehci_base(int index, struct ehci_hccr **base) return -ENODEV; /* not found */ } -#else -static int get_uniphier_ehci_base(int index, struct ehci_hccr **base) -{ - *base = (struct ehci_hccr *)uniphier_ehci_platdata[index].base; - return 0; -} -#endif -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. - */ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { -- cgit v1.1 From 4c7d025368fce4825a23aee90bd9a8fa1a95bbd7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 Feb 2015 02:26:55 +0900 Subject: ARM: UniPhier: move uniphier_ehci_reset() function Because uniphier_ehci_reset() is only called from ehci-uniphier.c, it can be a static function there. Signed-off-by: Masahiro Yamada Acked-by: Marek Vasut --- drivers/usb/host/ehci-uniphier.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-uniphier.c b/drivers/usb/host/ehci-uniphier.c index 68959ef..b5ec296 100644 --- a/drivers/usb/host/ehci-uniphier.c +++ b/drivers/usb/host/ehci-uniphier.c @@ -7,8 +7,9 @@ #include #include +#include #include -#include +#include #include #include "ehci.h" @@ -35,6 +36,18 @@ static int get_uniphier_ehci_base(int index, struct ehci_hccr **base) return -ENODEV; /* not found */ } +static void uniphier_ehci_reset(int index, int on) +{ + u32 tmp; + + tmp = readl(MIO_USB_RSTCTRL(index)); + if (on) + tmp &= ~MIO_USB_RSTCTRL_XRST; + else + tmp |= MIO_USB_RSTCTRL_XRST; + writel(tmp, MIO_USB_RSTCTRL(index)); +} + int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { -- cgit v1.1 From 1e7df7c4e4a1ad12b764c55369c313c1731dc4e8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 Feb 2015 02:27:00 +0900 Subject: usb: UniPhier: add UniPhier on-chip xHCI host driver support Support xHCI host driver used on Panasonic UniPhier platform. Signed-off-by: Masahiro Yamada Acked-by: Marek Vasut --- drivers/usb/host/Kconfig | 8 ++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-uniphier.c | 85 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 drivers/usb/host/xhci-uniphier.c (limited to 'drivers') diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0e005c2..24a595f 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -17,6 +17,14 @@ config USB_XHCI if USB_XHCI_HCD +config USB_XHCI_UNIPHIER + bool "Support for Panasonic UniPhier on-chip xHCI USB controller" + depends on ARCH_UNIPHIER + default y + ---help--- + Enables support for the on-chip xHCI controller on Panasonic + UniPhier SoCs. + endif config USB_EHCI_HCD diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 66d6e9a..eb6f34b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_UNIPHIER) += xhci-uniphier.o # designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-uniphier.c b/drivers/usb/host/xhci-uniphier.c new file mode 100644 index 0000000..08b15e0 --- /dev/null +++ b/drivers/usb/host/xhci-uniphier.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2015 Panasonic Corporation + * Author: Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include "xhci.h" + +static int get_uniphier_xhci_base(int index, struct xhci_hccr **base) +{ + DECLARE_GLOBAL_DATA_PTR; + int node_list[2]; + fdt_addr_t addr; + int count; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "usb", + COMPAT_PANASONIC_XHCI, node_list, + ARRAY_SIZE(node_list)); + + if (index >= count) + return -ENODEV; + + addr = fdtdec_get_addr(gd->fdt_blob, node_list[index], "reg"); + if (addr == FDT_ADDR_T_NONE) + return -ENODEV; + + *base = (struct xhci_hccr *)addr; + + return 0; +} + +#define USB3_RST_CTRL 0x00100040 +#define IOMMU_RST_N (1 << 5) +#define LINK_RST_N (1 << 4) + +static void uniphier_xhci_reset(void __iomem *base, int on) +{ + u32 tmp; + + tmp = readl(base + USB3_RST_CTRL); + + if (on) + tmp &= ~(IOMMU_RST_N | LINK_RST_N); + else + tmp |= IOMMU_RST_N | LINK_RST_N; + + writel(tmp, base + USB3_RST_CTRL); +} + +int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) +{ + int ret; + struct xhci_hccr *cr; + struct xhci_hcor *or; + + ret = get_uniphier_xhci_base(index, &cr); + if (ret < 0) + return ret; + + uniphier_xhci_reset(cr, 0); + + or = (void *)cr + HC_LENGTH(xhci_readl(&cr->cr_capbase)); + + *hccr = cr; + *hcor = or; + + return 0; +} + +void xhci_hcd_stop(int index) +{ + int ret; + struct xhci_hccr *cr; + + ret = get_uniphier_xhci_base(index, &cr); + if (ret < 0) + return; + + uniphier_xhci_reset(cr, 1); +} -- cgit v1.1