From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
To: Krzysztof Halasa <khc@pm.waw.pl>
Cc: barebox@lists.infradead.org
Subject: Re: [PATCH] ARM: Support for IXP4xx hardware Queue Manager.
Date: Mon, 8 Apr 2013 09:31:50 +0200 [thread overview]
Message-ID: <20130408073150.GW1568@game.jcrosoft.org> (raw)
In-Reply-To: <m3k3oe15g9.fsf_-_@intrepid.localdomain>
same here no printf use dev_dbg or pr_debug
On 21:55 Sun 07 Apr , Krzysztof Halasa wrote:
> Signed-off-by: Krzysztof Hałasa <khc@pm.waw.pl>
>
> diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
> index e69de29..9244be9 100644
> --- a/arch/arm/mach-ixp4xx/Kconfig
> +++ b/arch/arm/mach-ixp4xx/Kconfig
> @@ -0,0 +1,9 @@
> +if ARCH_IXP4XX
> +
> +config IXP4XX_QMGR
> + tristate "IXP4xx Queue Manager support"
> + help
> + This driver supports IXP4xx built-in hardware queue manager
> + and is required by the Ethernet driver.
> +
> +endif
> diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
> index d8a3d7f..09a0d63 100644
> --- a/arch/arm/mach-ixp4xx/Makefile
> +++ b/arch/arm/mach-ixp4xx/Makefile
> @@ -1 +1,2 @@
> obj-y += generic.o
> +obj-$(CONFIG_IXP4XX_QMGR) += qmgr.o
> diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
> new file mode 100644
> index 0000000..4e9b8d4
> --- /dev/null
> +++ b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
> @@ -0,0 +1,164 @@
> +/*
> + * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of version 2 of the GNU General Public License
> + * as published by the Free Software Foundation.
> + */
> +
> +#ifndef IXP4XX_QMGR_H
> +#define IXP4XX_QMGR_H
> +
> +#include <common.h>
> +#include <mach/ixp4xx-regs.h>
> +#include <asm/io.h>
> +
> +#define DEBUG_QMGR 0
> +
> +#define HALF_QUEUES 32
> +#define QUEUES 64
> +#define MAX_QUEUE_LENGTH 4 /* in dwords */
> +
> +#define QUEUE_STAT1_EMPTY 1 /* queue status bits */
> +#define QUEUE_STAT1_NEARLY_EMPTY 2
> +#define QUEUE_STAT1_NEARLY_FULL 4
> +#define QUEUE_STAT1_FULL 8
> +#define QUEUE_STAT2_UNDERFLOW 1
> +#define QUEUE_STAT2_OVERFLOW 2
> +
> +#define QUEUE_WATERMARK_0_ENTRIES 0
> +#define QUEUE_WATERMARK_1_ENTRY 1
> +#define QUEUE_WATERMARK_2_ENTRIES 2
> +#define QUEUE_WATERMARK_4_ENTRIES 3
> +#define QUEUE_WATERMARK_8_ENTRIES 4
> +#define QUEUE_WATERMARK_16_ENTRIES 5
> +#define QUEUE_WATERMARK_32_ENTRIES 6
> +#define QUEUE_WATERMARK_64_ENTRIES 7
> +
> +/* queue interrupt request conditions */
> +#define QUEUE_IRQ_SRC_EMPTY 0
> +#define QUEUE_IRQ_SRC_NEARLY_EMPTY 1
> +#define QUEUE_IRQ_SRC_NEARLY_FULL 2
> +#define QUEUE_IRQ_SRC_FULL 3
> +#define QUEUE_IRQ_SRC_NOT_EMPTY 4
> +#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY 5
> +#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL 6
> +#define QUEUE_IRQ_SRC_NOT_FULL 7
> +
> +struct qmgr_regs {
> + u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */
> + u32 stat1[4]; /* 0x400 - 0x40F */
> + u32 stat2[2]; /* 0x410 - 0x417 */
> + u32 statne_h; /* 0x418 - queue nearly empty */
> + u32 statf_h; /* 0x41C - queue full */
> + u32 irqsrc[4]; /* 0x420 - 0x42F IRC source */
> + u32 irqen[2]; /* 0x430 - 0x437 IRQ enabled */
> + u32 irqstat[2]; /* 0x438 - 0x43F - IRQ access only */
> + u32 reserved[1776];
> + u32 sram[2048]; /* 0x2000 - 0x3FFF - config and buffer */
> +};
> +
> +static const struct qmgr_regs *qmgr_regs = (struct qmgr_regs *)IXP4XX_QMGR_BASE;
> +
> +void qmgr_set_irq(unsigned int queue, int src,
> + void (*handler)(void *pdev), void *pdev);
> +void qmgr_enable_irq(unsigned int queue);
> +void qmgr_disable_irq(unsigned int queue);
> +
> +/* request_ and release_queue() must be called from non-IRQ context */
> +
> +#if DEBUG_QMGR
> +extern char qmgr_queue_descs[HALF_QUEUES][32];
> +
> +void qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
> + unsigned int nearly_empty_watermark,
> + unsigned int nearly_full_watermark,
> + const char *desc_format, const char* name);
> +#else
> +void __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
> + unsigned int nearly_empty_watermark,
> + unsigned int nearly_full_watermark);
> +#define qmgr_request_queue(queue, len, nearly_empty_watermark, \
> + nearly_full_watermark, desc_format, name) \
> + __qmgr_request_queue(queue, len, nearly_empty_watermark, \
> + nearly_full_watermark)
> +#endif
> +
> +void qmgr_release_queue(unsigned int queue);
> +
> +
> +static inline void qmgr_put_entry(unsigned int queue, u32 val)
> +{
> +#if DEBUG_QMGR
> + BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
> +
> + fprintf(stderr, "Queue %s(%i) put %X\n",
> + qmgr_queue_descs[queue], queue, val);
> +#endif
> + __raw_writel(val, &qmgr_regs->acc[queue][0]);
> +}
> +
> +static inline u32 qmgr_get_entry(unsigned int queue)
> +{
> + u32 val;
> + val = __raw_readl(&qmgr_regs->acc[queue][0]);
> +#if DEBUG_QMGR
> + BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
> +
> + fprintf(stderr, "Queue %s(%i) get %X\n",
> + qmgr_queue_descs[queue], queue, val);
> +#endif
> + return val;
> +}
> +
> +static inline int __qmgr_get_stat1(unsigned int queue)
> +{
> + return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
> + >> ((queue & 7) << 2)) & 0xF;
> +}
> +
> +/**
> + * qmgr_stat_empty() - checks if a hardware queue is empty
> + * @queue: queue number
> + *
> + * Returns non-zero value if the queue is empty.
> + */
> +static inline int qmgr_stat_empty(unsigned int queue)
> +{
> + return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY;
> +}
> +
> +/**
> + * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark
> + * @queue: queue number
> + *
> + * Returns non-zero value if the queue is below low watermark.
> + */
> +static inline int qmgr_stat_below_low_watermark(unsigned int queue)
> +{
> + return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY;
> +}
> +
> +/**
> + * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark
> + * @queue: queue number
> + *
> + * Returns non-zero value if the queue is above high watermark
> + */
> +static inline int qmgr_stat_above_high_watermark(unsigned int queue)
> +{
> + return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL;
> +}
> +
> +/**
> + * qmgr_stat_full() - checks if a hardware queue is full
> + * @queue: queue number
> + *
> + * Returns non-zero value if the queue is full.
> + */
> +static inline int qmgr_stat_full(unsigned int queue)
> +{
> + return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL;
> +}
> +
> +#endif
> diff --git a/arch/arm/mach-ixp4xx/qmgr.c b/arch/arm/mach-ixp4xx/qmgr.c
> new file mode 100644
> index 0000000..81b6522
> --- /dev/null
> +++ b/arch/arm/mach-ixp4xx/qmgr.c
> @@ -0,0 +1,259 @@
> +/*
> + * Intel IXP4xx Queue Manager driver for Linux
> + *
> + * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of version 2 of the GNU General Public License
> + * as published by the Free Software Foundation.
> + */
> +
> +#include <init.h>
> +#include <errno.h>
> +#include <mach/qmgr.h>
> +
> +static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
> +
> +#if DEBUG_QMGR
> +char qmgr_queue_descs[HALF_QUEUES][32];
> +#endif
> +
> +#ifdef CONFIG_USE_IRQ
> +
> +static void (*irq_handlers[HALF_QUEUES])(void *pdev);
> +static void *irq_pdevs[HALF_QUEUES];
> +
> +void qmgr_set_irq(unsigned int queue, int src,
> + void (*handler)(void *pdev), void *pdev)
> +{
> + const u32 *reg;
> + int bit;
> + BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
> + reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
> + bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
> + __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg);
> +
> + irq_handlers[queue] = handler;
> + irq_pdevs[queue] = pdev;
> +}
> +
> +
> +static void qmgr_irq1_a0(void *data)
> +{
> + int i;
> + u32 en_bitmap, src, stat;
> +
> + /* ACK - it may clear any bits so don't rely on it */
> + __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]);
> +
> + en_bitmap = qmgr_regs->irqen[0];
> + while (en_bitmap) {
> + i = fls(en_bitmap) - 1; /* number of the last "low" queue */
> + en_bitmap &= ~BIT(i);
> + src = qmgr_regs->irqsrc[i >> 3];
> + stat = qmgr_regs->stat1[i >> 3];
> + if (src & 4) /* the IRQ condition is inverted */
> + stat = ~stat;
> + if (stat & BIT(src & 3))
> + irq_handlers[i](irq_pdevs[i]);
> + }
> +}
> +
> +
> +static void qmgr_irq1(void *data)
> +{
> + int i;
> + u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[0]);
> +
> + if (!req_bitmap)
> + return;
> + __raw_writel(req_bitmap, &qmgr_regs->irqstat[0]); /* ACK */
> +
> + while (req_bitmap) {
> + i = fls(req_bitmap) - 1; /* number of the last queue */
> + req_bitmap &= ~BIT(i);
> + irq_handlers[i](irq_pdevs[i]);
> + }
> +}
> +
> +
> +void qmgr_enable_irq(unsigned int queue)
> +{
> + u32 mask = 1 << queue;
> +
> + __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | mask,
> + &qmgr_regs->irqen[0]);
> +}
> +
> +void qmgr_disable_irq(unsigned int queue)
> +{
> + u32 mask = 1 << queue;
> +
> + __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~mask,
> + &qmgr_regs->irqen[0]);
> + __raw_writel(mask, &qmgr_regs->irqstat[0]); /* clear */
> +}
> +
> +#endif /* CONFIG_USE_IRQ */
> +
> +static inline void shift_mask(u32 *mask)
> +{
> + mask[3] = mask[3] << 1 | mask[2] >> 31;
> + mask[2] = mask[2] << 1 | mask[1] >> 31;
> + mask[1] = mask[1] << 1 | mask[0] >> 31;
> + mask[0] <<= 1;
> +}
> +
> +#if DEBUG_QMGR
> +void qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
> + unsigned int nearly_empty_watermark,
> + unsigned int nearly_full_watermark,
> + const char *desc_format, const char* name)
> +#else
> +void __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
> + unsigned int nearly_empty_watermark,
> + unsigned int nearly_full_watermark)
> +#endif
??
> +{
> + u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
> +
> + BUG_ON(queue >= HALF_QUEUES);
> + BUG_ON((nearly_empty_watermark | nearly_full_watermark) & ~7);
> +
> + switch (len) {
> + case 16:
> + cfg = 0 << 24;
> + mask[0] = 0x1;
> + break;
> + case 32:
> + cfg = 1 << 24;
> + mask[0] = 0x3;
> + break;
> + case 64:
> + cfg = 2 << 24;
> + mask[0] = 0xF;
> + break;
> + case 128:
> + cfg = 3 << 24;
> + mask[0] = 0xFF;
> + break;
> + default:
> + BUG();
> + }
> +
> + cfg |= nearly_empty_watermark << 26;
> + cfg |= nearly_full_watermark << 29;
> + len /= 16; /* in 16-dwords: 1, 2, 4 or 8 */
> + mask[1] = mask[2] = mask[3] = 0;
> +
> + BUG_ON(__raw_readl(&qmgr_regs->sram[queue]));
> +
> + while (1) {
> + if (!(used_sram_bitmap[0] & mask[0]) &&
> + !(used_sram_bitmap[1] & mask[1]) &&
> + !(used_sram_bitmap[2] & mask[2]) &&
> + !(used_sram_bitmap[3] & mask[3]))
> + break; /* found free space */
> +
> + addr++;
> + shift_mask(mask);
> + if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) {
> + fprintf(stderr, "qmgr: no free SRAM space for"
> + " queue %i\n", queue);
> + BUG();
> + }
> + }
> +
> + used_sram_bitmap[0] |= mask[0];
> + used_sram_bitmap[1] |= mask[1];
> + used_sram_bitmap[2] |= mask[2];
> + used_sram_bitmap[3] |= mask[3];
> + __raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]);
> +#if DEBUG_QMGR
> + /* no snprintf() */
> + sprintf(qmgr_queue_descs[queue], desc_format, name);
> + fprintf(stderr, "qmgr: requested queue %s(%i) addr = 0x%02X\n",
> + qmgr_queue_descs[queue], queue, addr);
> +#endif
> +}
> +
> +void qmgr_release_queue(unsigned int queue)
> +{
> + u32 cfg, addr, mask[4];
> +
> + BUG_ON(queue >= HALF_QUEUES); /* not in valid range */
> +
> + cfg = __raw_readl(&qmgr_regs->sram[queue]);
> + addr = (cfg >> 14) & 0xFF;
> +
> + BUG_ON(!addr); /* not requested */
> +
> + switch ((cfg >> 24) & 3) {
> + case 0: mask[0] = 0x1; break;
> + case 1: mask[0] = 0x3; break;
> + case 2: mask[0] = 0xF; break;
> + case 3: mask[0] = 0xFF; break;
> + }
> +
> + mask[1] = mask[2] = mask[3] = 0;
> +
> + while (addr--)
> + shift_mask(mask);
> +
> +#if DEBUG_QMGR
> + fprintf(stderr, "qmgr: releasing queue %s(%i)\n",
> + qmgr_queue_descs[queue], queue);
> + qmgr_queue_descs[queue][0] = '\x0';
> +#endif
> + __raw_writel(0, &qmgr_regs->sram[queue]);
> +
> + used_sram_bitmap[0] &= ~mask[0];
> + used_sram_bitmap[1] &= ~mask[1];
> + used_sram_bitmap[2] &= ~mask[2];
> + used_sram_bitmap[3] &= ~mask[3];
> +#ifdef CONFIG_USE_IRQ
> + irq_handlers[queue] = NULL; /* catch IRQ bugs */
> +#endif
> +
> + while ((addr = qmgr_get_entry(queue)))
> + fprintf(stderr, "qmgr: released queue %i not empty: 0x%08X\n",
> + queue, addr);
> +}
> +
> +static int __init qmgr_init(void)
> +{
> + int i;
> +#ifdef CONFIG_USE_IRQ
> + interrupt_handler_t *handler;
we have no irq support on barebox
> +#endif
> +
> + /* reset qmgr registers */
> + for (i = 0; i < 4; i++) {
> + __raw_writel(0x33333333, &qmgr_regs->stat1[i]);
> + __raw_writel(0, &qmgr_regs->irqsrc[i]);
> + }
> + for (i = 0; i < 2; i++) {
> + __raw_writel(0, &qmgr_regs->stat2[i]);
> + __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */
> + __raw_writel(0, &qmgr_regs->irqen[i]);
> + }
> +
> + __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h);
> + __raw_writel(0, &qmgr_regs->statf_h);
> +
> + for (i = 0; i < QUEUES; i++)
> + __raw_writel(0, &qmgr_regs->sram[i]);
> +
> +#ifdef CONFIG_USE_IRQ
> + if (cpu_is_ixp42x_rev_a0())
> + handler = qmgr_irq1_a0;
> + else
> + handler = qmgr_irq1;
> +
> + irq_install_handler(IXP425_QM1_IRQ, handler, NULL);
> +#endif
> + used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
> + return 0;
> +}
> +
> +coredevice_initcall(qmgr_init);
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2013-04-08 7:35 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-30 11:19 IXP4xx again Krzysztof Halasa
2013-03-30 11:24 ` [PATCH] ARM: XScale processors don't support "clean+invalidate D entry" operation Krzysztof Halasa
2013-03-30 11:25 ` [PATCH] Implement ALTERNATE memory layout Krzysztof Halasa
2013-03-30 12:01 ` Alexander Shiyan
2013-03-30 13:15 ` Krzysztof Halasa
2013-03-30 13:23 ` Re[2]: " Alexander Shiyan
2013-03-30 19:57 ` Krzysztof Halasa
2013-03-30 18:45 ` Antony Pavlov
2013-04-01 18:04 ` Sascha Hauer
2013-04-02 7:20 ` Sascha Hauer
2013-03-30 11:26 ` [PATCH] ARM: Add support for IXP4xx CPU and for Goramo Multilink router platform Krzysztof Halasa
2013-04-02 6:52 ` Sascha Hauer
2013-04-07 11:42 ` Krzysztof Halasa
2013-04-07 19:54 ` [PATCH] ARM: Support for IXP4xx CPU Krzysztof Halasa
2013-04-08 7:27 ` Jean-Christophe PLAGNIOL-VILLARD
2013-04-14 10:30 ` Krzysztof Halasa
2013-04-14 11:51 ` Jean-Christophe PLAGNIOL-VILLARD
2013-04-07 19:55 ` [PATCH] ARM: Support for IXP4xx hardware Queue Manager Krzysztof Halasa
2013-04-08 7:31 ` Jean-Christophe PLAGNIOL-VILLARD [this message]
2013-04-07 19:57 ` [PATCH] ARM: Support for IXP4xx Network Processor Engines (NPEs) Krzysztof Halasa
2013-04-08 7:30 ` Jean-Christophe PLAGNIOL-VILLARD
2013-04-07 19:58 ` [PATCH] ARM: Support for IXP4xx built-in Ethernet interfaces Krzysztof Halasa
2013-04-08 7:29 ` Jean-Christophe PLAGNIOL-VILLARD
2013-04-08 7:56 ` [PATCH] ARM: Add support for IXP4xx CPU and for Goramo Multilink router platform Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130408073150.GW1568@game.jcrosoft.org \
--to=plagnioj@jcrosoft.com \
--cc=barebox@lists.infradead.org \
--cc=khc@pm.waw.pl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox