* [PATCH 0/3] AMBA Bus support @ 2012-09-01 10:22 Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 1/3] Introduce ARM AMBA bus Jean-Christophe PLAGNIOL-VILLARD 0 siblings, 1 reply; 6+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-01 10:22 UTC (permalink / raw) To: barebox Hi, this first patch series add the AMBA Bus support and is a preperation for the adding of the ST-E ux500 support please pull The following changes since commit 44e196a22ea87b1b08b25547a0b99fc795fecdf6: Merge branch 'for-next/ppc' into next (2012-08-13 21:39:34 +0200) are available in the git repository at: git://git.jcrosoft.org/barebox.git tags/amba_bus for you to fetch changes up to f2dc82e31bdaf1baa3191940ce1f7789270c8d14: amba-pl011: add st specific init (2012-09-01 16:56:36 +0800) ---------------------------------------------------------------- arm: Introduce ARM AMBA bus This allow to detect the amba device and use the right driver for it at runtime. With pl011 amba support (ARM & ST Variant) Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> ---------------------------------------------------------------- Jean-Christophe PLAGNIOL-VILLARD (3): Introduce ARM AMBA bus amba-pl011: switch to amba bus amba-pl011: add st specific init arch/arm/mach-nomadik/8815.c | 9 +++-- arch/arm/mach-versatile/core.c | 7 +++- drivers/Makefile | 1 + drivers/amba/Makefile | 2 + drivers/amba/bus.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/serial/amba-pl011.c | 74 +++++++++++++++++++++++++++++------ include/linux/amba/bus.h | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/amba/serial.h | 29 ++++++++++++++ 8 files changed, 473 insertions(+), 18 deletions(-) create mode 100644 drivers/amba/Makefile create mode 100644 drivers/amba/bus.c create mode 100644 include/linux/amba/bus.h Best Regards, J. _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] Introduce ARM AMBA bus 2012-09-01 10:22 [PATCH 0/3] AMBA Bus support Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-01 12:36 ` Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 2/3] amba-pl011: switch to amba bus Jean-Christophe PLAGNIOL-VILLARD ` (2 more replies) 0 siblings, 3 replies; 6+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-01 12:36 UTC (permalink / raw) To: barebox This will allow to detect the amba device and use the right driver for it at runtime. The code is base on linux 3.5. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> --- drivers/Makefile | 1 + drivers/amba/Makefile | 2 + drivers/amba/bus.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/amba/bus.h | 157 ++++++++++++++++++++++++++++++++++ 4 files changed, 372 insertions(+) create mode 100644 drivers/amba/Makefile create mode 100644 drivers/amba/bus.c create mode 100644 include/linux/amba/bus.h diff --git a/drivers/Makefile b/drivers/Makefile index 005ab24..ceb8f82 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,4 +1,5 @@ obj-y += base/ +obj-$(CONFIG_ARM_AMBA) += amba/ obj-y += net/ obj-y += serial/ obj-y += mtd/ diff --git a/drivers/amba/Makefile b/drivers/amba/Makefile new file mode 100644 index 0000000..a4a511b --- /dev/null +++ b/drivers/amba/Makefile @@ -0,0 +1,2 @@ + +obj-y += bus.o diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c new file mode 100644 index 0000000..6cde349 --- /dev/null +++ b/drivers/amba/bus.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. + * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * Under GPLv2. + */ +#include <common.h> +#include <driver.h> +#include <linux/clk.h> +#include <linux/amba/bus.h> +#include <io.h> + +#define to_amba_driver(d) container_of(d, struct amba_driver, drv) + +static const struct amba_id * +amba_lookup(const struct amba_id *table, struct amba_device *dev) +{ + int ret = 0; + + while (table->mask) { + ret = (dev->periphid & table->mask) == table->id; + if (ret) + break; + table++; + } + + return ret ? table : NULL; +} + +static int amba_match(struct device_d *dev, struct driver_d *drv) +{ + struct amba_device *pcdev = to_amba_device(dev); + + struct amba_driver *pcdrv = to_amba_driver(drv); + + return amba_lookup(pcdrv->id_table, pcdev) == NULL; +} + +static int amba_get_enable_pclk(struct amba_device *pcdev) +{ + struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk"); + int ret; + + pcdev->pclk = pclk; + + if (IS_ERR(pclk)) + return PTR_ERR(pclk); + + ret = clk_enable(pclk); + if (ret) { + clk_put(pclk); + } + + return ret; +} + +static int amba_probe(struct device_d *dev) +{ + struct amba_device *pcdev = to_amba_device(dev); + struct amba_driver *pcdrv = to_amba_driver(dev->driver); + const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); + + return pcdrv->probe(pcdev, id); +} + +static void amba_remove(struct device_d *dev) +{ + struct amba_device *pcdev = to_amba_device(dev); + struct amba_driver *drv = to_amba_driver(dev->driver); + + drv->remove(pcdev); +} + +struct bus_type amba_bustype = { + .name = "amba", + .match = amba_match, + .probe = amba_probe, + .remove = amba_remove, +}; + +int amba_driver_register(struct amba_driver *drv) +{ + drv->drv.bus = &amba_bustype; +#define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn + SETFN(probe); + SETFN(remove); + + return register_driver(&drv->drv); +} + +/** + * amba_device_add - add a previously allocated AMBA device structure + * @dev: AMBA device allocated by amba_device_alloc + * @parent: resource parent for this devices resources + * + * Claim the resource, and read the device cell ID if not already + * initialized. Register the AMBA device with the Linux device + * manager. + */ +int amba_device_add(struct amba_device *dev) +{ + u32 size; + void __iomem *tmp; + int i, ret; + struct resource *res = NULL; + + dev->dev.bus = &amba_bustype; + + /* + * Dynamically calculate the size of the resource + * and use this for iomap + */ + size = resource_size(&dev->res); + res = request_iomem_region("amba", dev->res.start, dev->res.end); + if (!res) + return -ENOMEM; + dev->base = tmp = (void __force __iomem *)res->start; + if (!tmp) { + ret = -ENOMEM; + goto err_release; + } + + /* Hard-coded primecell ID instead of plug-n-play */ + if (dev->periphid != 0) + goto skip_probe; + + ret = amba_get_enable_pclk(dev); + if (ret == 0) { + u32 pid, cid; + + /* + * Read pid and cid based on size of resource + * they are located at end of region + */ + for (pid = 0, i = 0; i < 4; i++) + pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << + (i * 8); + for (cid = 0, i = 0; i < 4; i++) + cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << + (i * 8); + + if (cid == AMBA_CID) + dev->periphid = pid; + + if (!dev->periphid) + ret = -ENODEV; + } + + if (ret) + goto err_release; + + skip_probe: + ret = register_device(&dev->dev); + if (ret) + goto err_release; + + return ret; + err_release: + release_region(res); + return ret; +} + +struct amba_device * +amba_aphb_device_add(struct device_d *parent, const char *name, int id, + resource_size_t base, size_t size, + void *pdata, unsigned int periphid) +{ + struct amba_device *dev; + int ret; + + dev = amba_device_alloc(name, id, base, size); + if (!dev) + return ERR_PTR(-ENOMEM); + + dev->periphid = periphid; + dev->dev.platform_data = pdata; + dev->dev.parent = parent; + + ret = amba_device_add(dev); + if (ret) { + return ERR_PTR(ret); + } + + return dev; +} + +/** + * amba_device_alloc - allocate an AMBA device + * @name: sysfs name of the AMBA device + * @base: base of AMBA device + * @size: size of AMBA device + * + * Allocate and initialize an AMBA device structure. Returns %NULL + * on failure. + */ +struct amba_device *amba_device_alloc(const char *name, int id, resource_size_t base, + size_t size) +{ + struct amba_device *dev; + + dev = xzalloc(sizeof(*dev)); + if (dev) { + strcpy(dev->dev.name, name); + dev->dev.id = id; + dev->res.start = base; + dev->res.end = base + size - 1; + dev->res.flags = IORESOURCE_MEM; + } + + return dev; +} + diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h new file mode 100644 index 0000000..34e6ace --- /dev/null +++ b/include/linux/amba/bus.h @@ -0,0 +1,157 @@ +/* + * linux/include/amba/bus.h + * + * This device type deals with ARM PrimeCells and anything else that + * presents a proper CID (0xB105F00D) at the end of the I/O register + * region or that is derived from a PrimeCell. + * + * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. + * + * 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. + */ +#ifndef ASMARM_AMBA_H +#define ASMARM_AMBA_H + +#include <linux/clk.h> +#include <driver.h> +#include <linux/err.h> + +#define AMBA_CID 0xb105f00d + +/** + * struct amba_id - identifies a device on an AMBA bus + * @id: The significant bits if the hardware device ID + * @mask: Bitmask specifying which bits of the id field are significant when + * matching. A driver binds to a device when ((hardware device ID) & mask) + * == id. + * @data: Private data used by the driver. + */ +struct amba_id { + unsigned int id; + unsigned int mask; +#ifndef __KERNEL__ + kernel_ulong_t data; +#else + void *data; +#endif +}; + +struct clk; + +struct amba_device { + struct device_d dev; + struct resource res; + void __iomem *base; + struct clk *pclk; + unsigned int periphid; +}; + +struct amba_driver { + struct driver_d drv; + int (*probe)(struct amba_device *, const struct amba_id *); + int (*remove)(struct amba_device *); + const struct amba_id *id_table; +}; + +enum amba_vendor { + AMBA_VENDOR_ARM = 0x41, + AMBA_VENDOR_ST = 0x80, +}; + +extern struct bus_type amba_bustype; + +#define to_amba_device(d) container_of(d, struct amba_device, dev) + +#define amba_get_drvdata(d) dev_get_drvdata(&d->dev) +#define amba_set_drvdata(d,p) dev_set_drvdata(&d->dev, p) + +int amba_driver_register(struct amba_driver *); +void amba_driver_unregister(struct amba_driver *); +struct amba_device *amba_device_alloc(const char *, int id, resource_size_t, size_t); +void amba_device_put(struct amba_device *); +int amba_device_add(struct amba_device *); +int amba_device_register(struct amba_device *, struct resource *); + +struct amba_device * +amba_aphb_device_add(struct device_d *parent, const char *name, int id, + resource_size_t base, size_t size, + void *pdata, unsigned int periphid); + +static inline struct amba_device * +amba_apb_device_add(struct device_d *parent, const char *name, int id, + resource_size_t base, size_t size, + void *pdata, unsigned int periphid) +{ + return amba_aphb_device_add(parent, name, id, base, size, pdata, + periphid); +} + +static inline struct amba_device * +amba_ahb_device_add(struct device_d *parent, const char *name, int id, + resource_size_t base, size_t size, + void *pdata, unsigned int periphid) +{ + return amba_aphb_device_add(parent, name, id, base, size, pdata, + periphid); +} + + +void amba_device_unregister(struct amba_device *); +struct amba_device *amba_find_device(const char *, struct device_d *, unsigned int, unsigned int); +int amba_request_regions(struct amba_device *, const char *); +void amba_release_regions(struct amba_device *); + +static inline void __iomem *amba_get_mem_region(struct amba_device *dev) +{ + return dev->base; +} + +#define amba_pclk_enable(d) \ + (IS_ERR((d)->pclk) ? 0 : clk_enable((d)->pclk)) + +#define amba_pclk_disable(d) \ + do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0) + +/* Some drivers don't use the struct amba_device */ +#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff) +#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f) +#define AMBA_MANF_BITS(a) (((a) >> 12) & 0xff) +#define AMBA_PART_BITS(a) ((a) & 0xfff) + +#define amba_config(d) AMBA_CONFIG_BITS((d)->periphid) +#define amba_rev(d) AMBA_REV_BITS((d)->periphid) +#define amba_manf(d) AMBA_MANF_BITS((d)->periphid) +#define amba_part(d) AMBA_PART_BITS((d)->periphid) + +#define __AMBA_DEV(busid, data) \ + { \ + .init_name = busid, \ + .platform_data = data, \ + } + +/* + * APB devices do not themselves have the ability to address memory, + * so DMA masks should be zero (much like USB peripheral devices.) + * The DMA controller DMA masks should be used instead (much like + * USB host controllers in conventional PCs.) + */ +#define AMBA_APB_DEVICE(name, busid, id, base, data) \ +struct amba_device name##_device = { \ + .dev = __AMBA_DEV(busid, data), \ + .res = DEFINE_RES_MEM(base, SZ_4K), \ + .periphid = id, \ +} + +/* + * AHB devices are DMA capable, so set their DMA masks + */ +#define AMBA_AHB_DEVICE(name, busid, id, base, data) \ +struct amba_device name##_device = { \ + .dev = __AMBA_DEV(busid, data), \ + .res = DEFINE_RES_MEM(base, SZ_4K), \ + .periphid = id, \ +} + +#endif -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/3] amba-pl011: switch to amba bus 2012-09-01 12:36 ` [PATCH 1/3] Introduce ARM AMBA bus Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-01 12:36 ` Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 3/3] amba-pl011: add st specific init Jean-Christophe PLAGNIOL-VILLARD 2012-09-10 7:25 ` [PATCH 1/3] Introduce ARM AMBA bus Sascha Hauer 2 siblings, 0 replies; 6+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-01 12:36 UTC (permalink / raw) To: barebox switch as the same time the nomadik and versatile arch that use the driver. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> --- arch/arm/mach-nomadik/8815.c | 9 +++++---- arch/arm/mach-versatile/core.c | 7 +++++-- drivers/serial/amba-pl011.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-nomadik/8815.c b/arch/arm/mach-nomadik/8815.c index e385598..aecd9e0 100644 --- a/arch/arm/mach-nomadik/8815.c +++ b/arch/arm/mach-nomadik/8815.c @@ -25,6 +25,7 @@ #include <mach/hardware.h> #include <asm/armlinux.h> #include <generated/mach-types.h> +#include <linux/amba/bus.h> #include "clock.h" @@ -32,12 +33,15 @@ static struct clk st8815_clk_48 = { .rate = 48 * 1000 * 1000, }; +static struct clk st8815_dummy; + void st8815_add_device_sdram(u32 size) { arm_add_mem_device("ram0", 0x00000000, size); } static struct clk_lookup clocks_lookups[] = { + CLKDEV_CON_ID("apb_pclk", &st8815_dummy), CLKDEV_DEV_ID("uart-pl0110", &st8815_clk_48), CLKDEV_DEV_ID("uart-pl0111", &st8815_clk_48), }; @@ -53,7 +57,6 @@ postcore_initcall(st8815_clkdev_init); void st8815_register_uart(unsigned id) { resource_size_t start; - struct device_d *dev; switch (id) { case 0: @@ -63,7 +66,5 @@ void st8815_register_uart(unsigned id) start = NOMADIK_UART1_BASE; break; } - dev = add_generic_device("uart-pl011", id, NULL, start, 4096, - IORESOURCE_MEM, NULL); - nmdk_clk_create(&st8815_clk_48, dev_name(dev)); + amba_apb_device_add(NULL, "uart-pl011", id, start, 4096, NULL, 0); } diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index bdf48f9..86cc755 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -34,6 +34,7 @@ #include <linux/clkdev.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/amba/bus.h> #include <io.h> #include <asm/hardware/arm_timer.h> @@ -51,6 +52,8 @@ struct clk { unsigned long rate; }; +static struct clk ref_clk_dummy; + static struct clk ref_clk_24 = { .rate = 24000000, }; @@ -145,6 +148,7 @@ static int vpb_clocksource_init(void) core_initcall(vpb_clocksource_init); static struct clk_lookup clocks_lookups[] = { + CLKDEV_CON_ID("apb_pclk", &ref_clk_dummy), CLKDEV_DEV_ID("uart-pl0110", &ref_clk_24), CLKDEV_DEV_ID("uart-pl0111", &ref_clk_24), CLKDEV_DEV_ID("uart-pl0112", &ref_clk_24), @@ -179,8 +183,7 @@ void versatile_register_uart(unsigned id) default: return; } - add_generic_device("uart-pl011", id, NULL, start, 4096, - IORESOURCE_MEM, NULL); + amba_apb_device_add(NULL, "uart-pl011", id, start, 4096, NULL, 0); } void __noreturn reset_cpu (unsigned long ignored) diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index f8c55c4..77f8c8a 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -35,6 +35,7 @@ #include <linux/amba/serial.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/amba/bus.h> /* * We wrap our port structure around the generic console_device. @@ -118,11 +119,8 @@ static int pl011_tstc(struct console_device *cdev) int pl011_init_port (struct console_device *cdev) { - struct device_d *dev = cdev->dev; struct amba_uart_port *uart = to_amba_uart_port(cdev); - uart->base = dev_request_mem_region(dev, 0); - /* ** First, disable everything. */ @@ -154,19 +152,20 @@ int pl011_init_port (struct console_device *cdev) return 0; } -static int pl011_probe(struct device_d *dev) +static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct amba_uart_port *uart; struct console_device *cdev; uart = xzalloc(sizeof(struct amba_uart_port)); - uart->clk = clk_get(dev, NULL); + uart->clk = clk_get(&dev->dev, NULL); + uart->base = amba_get_mem_region(dev); if (IS_ERR(uart->clk)) return PTR_ERR(uart->clk); cdev = &uart->uart; - cdev->dev = dev; + cdev->dev = &dev->dev; cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR; cdev->tstc = pl011_tstc; cdev->putc = pl011_putc; @@ -182,14 +181,29 @@ static int pl011_probe(struct device_d *dev) return 0; } -static struct driver_d pl011_driver = { - .name = "uart-pl011", - .probe = pl011_probe, +static struct amba_id pl011_ids[] = { + { + .id = 0x00041011, + .mask = 0x000fffff, + }, + { + .id = 0x00380802, + .mask = 0x00ffffff, + }, + { 0, 0 }, +}; + +struct amba_driver pl011_driver = { + .drv = { + .name = "uart-pl011", + }, + .probe = pl011_probe, + .id_table = pl011_ids, }; static int pl011_init(void) { - register_driver(&pl011_driver); + amba_driver_register(&pl011_driver); return 0; } -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/3] amba-pl011: add st specific init 2012-09-01 12:36 ` [PATCH 1/3] Introduce ARM AMBA bus Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 2/3] amba-pl011: switch to amba bus Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-01 12:36 ` Jean-Christophe PLAGNIOL-VILLARD 2012-09-10 7:25 ` [PATCH 1/3] Introduce ARM AMBA bus Sascha Hauer 2 siblings, 0 replies; 6+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-01 12:36 UTC (permalink / raw) To: barebox This is need on the new IP for ux500 Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> --- drivers/serial/amba-pl011.c | 40 ++++++++++++++++++++++++++++++++++++++-- include/linux/amba/serial.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 77f8c8a..b62dc9f 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -45,6 +45,23 @@ struct amba_uart_port { struct console_device uart; /* uart */ struct clk *clk; /* uart clock */ u32 uartclk; + struct vendor_data *vendor; +}; + +/* There is by now at least one vendor with differing details, so handle it */ +struct vendor_data { + unsigned int lcrh_tx; + unsigned int lcrh_rx; +}; + +static struct vendor_data vendor_arm = { + .lcrh_tx = UART011_LCRH, + .lcrh_rx = UART011_LCRH, +}; + +static struct vendor_data vendor_st = { + .lcrh_tx = ST_UART011_LCRH_TX, + .lcrh_rx = ST_UART011_LCRH_RX, }; static inline struct amba_uart_port * @@ -117,6 +134,23 @@ static int pl011_tstc(struct console_device *cdev) return !(readl(uart->base + UART01x_FR) & UART01x_FR_RXFE); } +static void pl011_rlcr(struct amba_uart_port *uart, u32 lcr) +{ + struct vendor_data *vendor = uart->vendor; + + writew(lcr, uart->base + vendor->lcrh_rx); + if (vendor->lcrh_tx != vendor->lcrh_rx) { + int i; + /* + * Wait 10 PCLKs before writing LCRH_TX register, + * to get this delay write read only register 10 times + */ + for (i = 0; i < 10; ++i) + writew(0xff, uart->base + UART011_MIS); + writew(lcr, uart->base + vendor->lcrh_tx); + } +} + int pl011_init_port (struct console_device *cdev) { struct amba_uart_port *uart = to_amba_uart_port(cdev); @@ -140,8 +174,7 @@ int pl011_init_port (struct console_device *cdev) /* ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled. */ - writel((UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN), - uart->base + UART011_LCRH); + pl011_rlcr(uart, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN); /* ** Finally, enable the UART @@ -160,6 +193,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uart = xzalloc(sizeof(struct amba_uart_port)); uart->clk = clk_get(&dev->dev, NULL); uart->base = amba_get_mem_region(dev); + uart->vendor = (void*)id->data; if (IS_ERR(uart->clk)) return PTR_ERR(uart->clk); @@ -185,10 +219,12 @@ static struct amba_id pl011_ids[] = { { .id = 0x00041011, .mask = 0x000fffff, + .data = &vendor_arm, }, { .id = 0x00380802, .mask = 0x00ffffff, + .data = &vendor_st, }, { 0, 0 }, }; diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index f4d7bf8..6670f1f 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -32,16 +32,20 @@ #define UART01x_RSR 0x04 /* Receive status register (Read). */ #define UART01x_ECR 0x04 /* Error clear register (Write). */ #define UART010_LCRH 0x08 /* Line control register, high byte. */ +#define ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */ #define UART010_LCRM 0x0C /* Line control register, middle byte. */ +#define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */ #define UART010_LCRL 0x10 /* Line control register, low byte. */ #define UART010_CR 0x14 /* Control register. */ #define UART01x_FR 0x18 /* Flag register (Read only). */ #define UART010_IIR 0x1C /* Interrupt indentification register (Read). */ #define UART010_ICR 0x1C /* Interrupt clear register (Write). */ +#define ST_UART011_LCRH_RX 0x1C /* Rx line control register. */ #define UART01x_ILPR 0x20 /* IrDA low power counter register. */ #define UART011_IBRD 0x24 /* Integer baud rate divisor register. */ #define UART011_FBRD 0x28 /* Fractional baud rate divisor register. */ #define UART011_LCRH 0x2c /* Line control register. */ +#define ST_UART011_LCRH_TX 0x2c /* Tx Line control register. */ #define UART011_CR 0x30 /* Control register. */ #define UART011_IFLS 0x34 /* Interrupt fifo level select. */ #define UART011_IMSC 0x38 /* Interrupt mask. */ @@ -49,6 +53,15 @@ #define UART011_MIS 0x40 /* Masked interrupt status. */ #define UART011_ICR 0x44 /* Interrupt clear register. */ #define UART011_DMACR 0x48 /* DMA control register. */ +#define ST_UART011_XFCR 0x50 /* XON/XOFF control register. */ +#define ST_UART011_XON1 0x54 /* XON1 register. */ +#define ST_UART011_XON2 0x58 /* XON2 register. */ +#define ST_UART011_XOFF1 0x5C /* XON1 register. */ +#define ST_UART011_XOFF2 0x60 /* XON2 register. */ +#define ST_UART011_ITCR 0x80 /* Integration test control register. */ +#define ST_UART011_ITIP 0x84 /* Integration test input register. */ +#define ST_UART011_ABCR 0x100 /* Autobaud control register. */ +#define ST_UART011_ABIMSC 0x15C /* Autobaud interrupt mask/clear register. */ #define UART011_DR_OE (1 << 11) #define UART011_DR_BE (1 << 10) @@ -84,6 +97,7 @@ #define UART010_CR_TIE 0x0020 #define UART010_CR_RIE 0x0010 #define UART010_CR_MSIE 0x0008 +#define ST_UART011_CR_OVSFACT 0x0008 /* Oversampling factor */ #define UART01x_CR_IIRLP 0x0004 /* SIR low power mode */ #define UART01x_CR_SIREN 0x0002 /* SIR enable */ #define UART01x_CR_UARTEN 0x0001 /* UART enable */ @@ -99,6 +113,21 @@ #define UART01x_LCRH_PEN 0x02 #define UART01x_LCRH_BRK 0x01 +#define ST_UART011_DMAWM_RX_1 (0 << 3) +#define ST_UART011_DMAWM_RX_2 (1 << 3) +#define ST_UART011_DMAWM_RX_4 (2 << 3) +#define ST_UART011_DMAWM_RX_8 (3 << 3) +#define ST_UART011_DMAWM_RX_16 (4 << 3) +#define ST_UART011_DMAWM_RX_32 (5 << 3) +#define ST_UART011_DMAWM_RX_48 (6 << 3) +#define ST_UART011_DMAWM_TX_1 0 +#define ST_UART011_DMAWM_TX_2 1 +#define ST_UART011_DMAWM_TX_4 2 +#define ST_UART011_DMAWM_TX_8 3 +#define ST_UART011_DMAWM_TX_16 4 +#define ST_UART011_DMAWM_TX_32 5 +#define ST_UART011_DMAWM_TX_48 6 + #define UART010_IIR_RTIS 0x08 #define UART010_IIR_TIS 0x04 #define UART010_IIR_RIS 0x02 -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] Introduce ARM AMBA bus 2012-09-01 12:36 ` [PATCH 1/3] Introduce ARM AMBA bus Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 2/3] amba-pl011: switch to amba bus Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 3/3] amba-pl011: add st specific init Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-10 7:25 ` Sascha Hauer 2 siblings, 0 replies; 6+ messages in thread From: Sascha Hauer @ 2012-09-10 7:25 UTC (permalink / raw) To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox On Sat, Sep 01, 2012 at 02:36:28PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote: > This will allow to detect the amba device and use the right driver for it at > runtime. > > The code is base on linux 3.5. > > + > +int amba_driver_register(struct amba_driver *drv) > +{ > + drv->drv.bus = &amba_bustype; > +#define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn > + SETFN(probe); > + SETFN(remove); Can we please drop this SETFN and just open code it? Being able to grep for amba_probe and finding its users is quite convenient. No, I don't care that in Linux it's also done like this. > +struct amba_device *amba_device_alloc(const char *name, int id, resource_size_t base, > + size_t size) > +{ > + struct amba_device *dev; > + > + dev = xzalloc(sizeof(*dev)); > + if (dev) { xzalloc always returns a valid pointer. > + strcpy(dev->dev.name, name); > + dev->dev.id = id; > + dev->res.start = base; > + dev->res.end = base + size - 1; > + dev->res.flags = IORESOURCE_MEM; > + } > + > + return dev; > +} > + > +/** > + * struct amba_id - identifies a device on an AMBA bus > + * @id: The significant bits if the hardware device ID > + * @mask: Bitmask specifying which bits of the id field are significant when > + * matching. A driver binds to a device when ((hardware device ID) & mask) > + * == id. > + * @data: Private data used by the driver. > + */ > +struct amba_id { > + unsigned int id; > + unsigned int mask; > +#ifndef __KERNEL__ > + kernel_ulong_t data; > +#else > + void *data; > +#endif Drop this ifdef. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 0/3 v2] AMBA Bus support @ 2012-09-11 4:47 Jean-Christophe PLAGNIOL-VILLARD 2012-09-11 4:51 ` [PATCH 1/3] Introduce ARM AMBA bus Jean-Christophe PLAGNIOL-VILLARD 0 siblings, 1 reply; 6+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-11 4:47 UTC (permalink / raw) To: barebox Hi, v2: upadte comment this first patch series add the AMBA Bus support and is a preperation for the adding of the ST-E ux500 support please pull The following changes since commit 298d15571da8d1cb71e7fd87cc53cad3b2bf1d12: i.MX51: unbreak FEC iomux (2012-09-07 10:28:17 +0200) are available in the git repository at: git://git.jcrosoft.org/barebox.git tags/amba_bus for you to fetch changes up to 75a0136ccae3899aee91f1d8d38274c426f99175: amba-pl011: add st specific init (2012-09-11 12:48:34 +0800) ---------------------------------------------------------------- arm: Introduce ARM AMBA bus This allow to detect the amba device and use the right driver for it at runtime. With pl011 amba support (ARM & ST Variant) Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> ---------------------------------------------------------------- Jean-Christophe PLAGNIOL-VILLARD (3): Introduce ARM AMBA bus amba-pl011: switch to amba bus amba-pl011: add st specific init arch/arm/mach-nomadik/8815.c | 9 +++---- arch/arm/mach-versatile/core.c | 7 ++++-- drivers/Makefile | 1 + drivers/amba/Makefile | 2 ++ drivers/amba/bus.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/serial/amba-pl011.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++---------- include/linux/amba/bus.h | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/amba/serial.h | 29 +++++++++++++++++++++++ 8 files changed, 467 insertions(+), 18 deletions(-) create mode 100644 drivers/amba/Makefile create mode 100644 drivers/amba/bus.c create mode 100644 include/linux/amba/bus.h Best Regards, J. _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] Introduce ARM AMBA bus 2012-09-11 4:47 [PATCH 0/3 v2] AMBA Bus support Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-11 4:51 ` Jean-Christophe PLAGNIOL-VILLARD 0 siblings, 0 replies; 6+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-09-11 4:51 UTC (permalink / raw) To: barebox This will allow to detect the amba device and use the right driver for it at runtime. The code is base on linux 3.5. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> --- drivers/Makefile | 1 + drivers/amba/Makefile | 2 + drivers/amba/bus.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/amba/bus.h | 153 +++++++++++++++++++++++++++++++++ 4 files changed, 366 insertions(+) create mode 100644 drivers/amba/Makefile create mode 100644 drivers/amba/bus.c create mode 100644 include/linux/amba/bus.h diff --git a/drivers/Makefile b/drivers/Makefile index 28a5cb8..0b44e90 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,4 +1,5 @@ obj-y += base/ +obj-$(CONFIG_ARM_AMBA) += amba/ obj-y += net/ obj-y += serial/ obj-y += mtd/ diff --git a/drivers/amba/Makefile b/drivers/amba/Makefile new file mode 100644 index 0000000..a4a511b --- /dev/null +++ b/drivers/amba/Makefile @@ -0,0 +1,2 @@ + +obj-y += bus.o diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c new file mode 100644 index 0000000..383c77e --- /dev/null +++ b/drivers/amba/bus.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. + * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * Under GPLv2. + */ +#include <common.h> +#include <driver.h> +#include <linux/clk.h> +#include <linux/amba/bus.h> +#include <io.h> + +#define to_amba_driver(d) container_of(d, struct amba_driver, drv) + +static const struct amba_id * +amba_lookup(const struct amba_id *table, struct amba_device *dev) +{ + int ret = 0; + + while (table->mask) { + ret = (dev->periphid & table->mask) == table->id; + if (ret) + break; + table++; + } + + return ret ? table : NULL; +} + +static int amba_match(struct device_d *dev, struct driver_d *drv) +{ + struct amba_device *pcdev = to_amba_device(dev); + + struct amba_driver *pcdrv = to_amba_driver(drv); + + return amba_lookup(pcdrv->id_table, pcdev) == NULL; +} + +static int amba_get_enable_pclk(struct amba_device *pcdev) +{ + struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk"); + int ret; + + pcdev->pclk = pclk; + + if (IS_ERR(pclk)) + return PTR_ERR(pclk); + + ret = clk_enable(pclk); + if (ret) { + clk_put(pclk); + } + + return ret; +} + +static int amba_probe(struct device_d *dev) +{ + struct amba_device *pcdev = to_amba_device(dev); + struct amba_driver *pcdrv = to_amba_driver(dev->driver); + const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); + + return pcdrv->probe(pcdev, id); +} + +static void amba_remove(struct device_d *dev) +{ + struct amba_device *pcdev = to_amba_device(dev); + struct amba_driver *drv = to_amba_driver(dev->driver); + + drv->remove(pcdev); +} + +struct bus_type amba_bustype = { + .name = "amba", + .match = amba_match, + .probe = amba_probe, + .remove = amba_remove, +}; + +int amba_driver_register(struct amba_driver *drv) +{ + drv->drv.bus = &amba_bustype; + + if (drv->probe) + drv->drv.probe = amba_probe; + if (drv->remove) + drv->drv.remove = amba_remove; + + return register_driver(&drv->drv); +} + +/** + * amba_device_add - add a previously allocated AMBA device structure + * @dev: AMBA device allocated by amba_device_alloc + * @parent: resource parent for this devices resources + * + * Claim the resource, and read the device cell ID if not already + * initialized. Register the AMBA device with the Linux device + * manager. + */ +int amba_device_add(struct amba_device *dev) +{ + u32 size; + void __iomem *tmp; + int i, ret; + struct resource *res = NULL; + + dev->dev.bus = &amba_bustype; + + /* + * Dynamically calculate the size of the resource + * and use this for iomap + */ + size = resource_size(&dev->res); + res = request_iomem_region("amba", dev->res.start, dev->res.end); + if (!res) + return -ENOMEM; + dev->base = tmp = (void __force __iomem *)res->start; + if (!tmp) { + ret = -ENOMEM; + goto err_release; + } + + /* Hard-coded primecell ID instead of plug-n-play */ + if (dev->periphid != 0) + goto skip_probe; + + ret = amba_get_enable_pclk(dev); + if (ret == 0) { + u32 pid, cid; + + /* + * Read pid and cid based on size of resource + * they are located at end of region + */ + for (pid = 0, i = 0; i < 4; i++) + pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << + (i * 8); + for (cid = 0, i = 0; i < 4; i++) + cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << + (i * 8); + + if (cid == AMBA_CID) + dev->periphid = pid; + + if (!dev->periphid) + ret = -ENODEV; + } + + if (ret) + goto err_release; + + skip_probe: + ret = register_device(&dev->dev); + if (ret) + goto err_release; + + return ret; + err_release: + release_region(res); + return ret; +} + +struct amba_device * +amba_aphb_device_add(struct device_d *parent, const char *name, int id, + resource_size_t base, size_t size, + void *pdata, unsigned int periphid) +{ + struct amba_device *dev; + int ret; + + dev = amba_device_alloc(name, id, base, size); + + dev->periphid = periphid; + dev->dev.platform_data = pdata; + dev->dev.parent = parent; + + ret = amba_device_add(dev); + if (ret) + return ERR_PTR(ret); + + return dev; +} + +/** + * amba_device_alloc - allocate an AMBA device + * @name: sysfs name of the AMBA device + * @base: base of AMBA device + * @size: size of AMBA device + * + * Allocate and initialize an AMBA device structure. Returns %NULL + * on failure. + */ +struct amba_device *amba_device_alloc(const char *name, int id, resource_size_t base, + size_t size) +{ + struct amba_device *dev; + + dev = xzalloc(sizeof(*dev)); + + strcpy(dev->dev.name, name); + dev->dev.id = id; + dev->res.start = base; + dev->res.end = base + size - 1; + dev->res.flags = IORESOURCE_MEM; + + return dev; +} + diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h new file mode 100644 index 0000000..cb3e3bd --- /dev/null +++ b/include/linux/amba/bus.h @@ -0,0 +1,153 @@ +/* + * linux/include/amba/bus.h + * + * This device type deals with ARM PrimeCells and anything else that + * presents a proper CID (0xB105F00D) at the end of the I/O register + * region or that is derived from a PrimeCell. + * + * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. + * + * 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. + */ +#ifndef ASMARM_AMBA_H +#define ASMARM_AMBA_H + +#include <linux/clk.h> +#include <driver.h> +#include <linux/err.h> + +#define AMBA_CID 0xb105f00d + +/** + * struct amba_id - identifies a device on an AMBA bus + * @id: The significant bits if the hardware device ID + * @mask: Bitmask specifying which bits of the id field are significant when + * matching. A driver binds to a device when ((hardware device ID) & mask) + * == id. + * @data: Private data used by the driver. + */ +struct amba_id { + unsigned int id; + unsigned int mask; + void *data; +}; + +struct clk; + +struct amba_device { + struct device_d dev; + struct resource res; + void __iomem *base; + struct clk *pclk; + unsigned int periphid; +}; + +struct amba_driver { + struct driver_d drv; + int (*probe)(struct amba_device *, const struct amba_id *); + int (*remove)(struct amba_device *); + const struct amba_id *id_table; +}; + +enum amba_vendor { + AMBA_VENDOR_ARM = 0x41, + AMBA_VENDOR_ST = 0x80, +}; + +extern struct bus_type amba_bustype; + +#define to_amba_device(d) container_of(d, struct amba_device, dev) + +#define amba_get_drvdata(d) dev_get_drvdata(&d->dev) +#define amba_set_drvdata(d,p) dev_set_drvdata(&d->dev, p) + +int amba_driver_register(struct amba_driver *); +void amba_driver_unregister(struct amba_driver *); +struct amba_device *amba_device_alloc(const char *, int id, resource_size_t, size_t); +void amba_device_put(struct amba_device *); +int amba_device_add(struct amba_device *); +int amba_device_register(struct amba_device *, struct resource *); + +struct amba_device * +amba_aphb_device_add(struct device_d *parent, const char *name, int id, + resource_size_t base, size_t size, + void *pdata, unsigned int periphid); + +static inline struct amba_device * +amba_apb_device_add(struct device_d *parent, const char *name, int id, + resource_size_t base, size_t size, + void *pdata, unsigned int periphid) +{ + return amba_aphb_device_add(parent, name, id, base, size, pdata, + periphid); +} + +static inline struct amba_device * +amba_ahb_device_add(struct device_d *parent, const char *name, int id, + resource_size_t base, size_t size, + void *pdata, unsigned int periphid) +{ + return amba_aphb_device_add(parent, name, id, base, size, pdata, + periphid); +} + + +void amba_device_unregister(struct amba_device *); +struct amba_device *amba_find_device(const char *, struct device_d *, unsigned int, unsigned int); +int amba_request_regions(struct amba_device *, const char *); +void amba_release_regions(struct amba_device *); + +static inline void __iomem *amba_get_mem_region(struct amba_device *dev) +{ + return dev->base; +} + +#define amba_pclk_enable(d) \ + (IS_ERR((d)->pclk) ? 0 : clk_enable((d)->pclk)) + +#define amba_pclk_disable(d) \ + do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0) + +/* Some drivers don't use the struct amba_device */ +#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff) +#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f) +#define AMBA_MANF_BITS(a) (((a) >> 12) & 0xff) +#define AMBA_PART_BITS(a) ((a) & 0xfff) + +#define amba_config(d) AMBA_CONFIG_BITS((d)->periphid) +#define amba_rev(d) AMBA_REV_BITS((d)->periphid) +#define amba_manf(d) AMBA_MANF_BITS((d)->periphid) +#define amba_part(d) AMBA_PART_BITS((d)->periphid) + +#define __AMBA_DEV(busid, data) \ + { \ + .init_name = busid, \ + .platform_data = data, \ + } + +/* + * APB devices do not themselves have the ability to address memory, + * so DMA masks should be zero (much like USB peripheral devices.) + * The DMA controller DMA masks should be used instead (much like + * USB host controllers in conventional PCs.) + */ +#define AMBA_APB_DEVICE(name, busid, id, base, data) \ +struct amba_device name##_device = { \ + .dev = __AMBA_DEV(busid, data), \ + .res = DEFINE_RES_MEM(base, SZ_4K), \ + .periphid = id, \ +} + +/* + * AHB devices are DMA capable, so set their DMA masks + */ +#define AMBA_AHB_DEVICE(name, busid, id, base, data) \ +struct amba_device name##_device = { \ + .dev = __AMBA_DEV(busid, data), \ + .res = DEFINE_RES_MEM(base, SZ_4K), \ + .periphid = id, \ +} + +#endif -- 1.7.10.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-09-11 4:53 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-09-01 10:22 [PATCH 0/3] AMBA Bus support Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 1/3] Introduce ARM AMBA bus Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 2/3] amba-pl011: switch to amba bus Jean-Christophe PLAGNIOL-VILLARD 2012-09-01 12:36 ` [PATCH 3/3] amba-pl011: add st specific init Jean-Christophe PLAGNIOL-VILLARD 2012-09-10 7:25 ` [PATCH 1/3] Introduce ARM AMBA bus Sascha Hauer 2012-09-11 4:47 [PATCH 0/3 v2] AMBA Bus support Jean-Christophe PLAGNIOL-VILLARD 2012-09-11 4:51 ` [PATCH 1/3] Introduce ARM AMBA bus Jean-Christophe PLAGNIOL-VILLARD
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox