Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e62db384 authored by Simon Horman's avatar Simon Horman
Browse files

Merge branch 'sh-sci' into soc3-base

parents 250d829f ec09c5eb
Loading
Loading
Loading
Loading
+153 −167
Original line number Diff line number Diff line
@@ -23,35 +23,34 @@

#undef DEBUG

#include <linux/module.h>
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/ctype.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/sh_dma.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/sysrq.h>
#include <linux/ioport.h>
#include <linux/major.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/console.h>
#include <linux/platform_device.h>
#include <linux/serial_sci.h>
#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/cpufreq.h>
#include <linux/clk.h>
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/string.h>
#include <linux/sysrq.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>

#ifdef CONFIG_SUPERH
#include <asm/sh_bios.h>
@@ -64,6 +63,10 @@ struct sci_port {

	/* Platform configuration */
	struct plat_sci_port	*cfg;
	int			overrun_bit;
	unsigned int		error_mask;
	unsigned int		sampling_rate;


	/* Break timer */
	struct timer_list	break_timer;
@@ -74,8 +77,8 @@ struct sci_port {
	/* Function clock */
	struct clk		*fclk;

	int			irqs[SCIx_NR_IRQS];
	char			*irqstr[SCIx_NR_IRQS];
	char			*gpiostr[SCIx_NR_FNS];

	struct dma_chan			*chan_tx;
	struct dma_chan			*chan_rx;
@@ -421,9 +424,9 @@ static void sci_port_enable(struct sci_port *sci_port)

	pm_runtime_get_sync(sci_port->port.dev);

	clk_enable(sci_port->iclk);
	clk_prepare_enable(sci_port->iclk);
	sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
	clk_enable(sci_port->fclk);
	clk_prepare_enable(sci_port->fclk);
}

static void sci_port_disable(struct sci_port *sci_port)
@@ -431,8 +434,16 @@ static void sci_port_disable(struct sci_port *sci_port)
	if (!sci_port->port.dev)
		return;

	clk_disable(sci_port->fclk);
	clk_disable(sci_port->iclk);
	/* Cancel the break timer to ensure that the timer handler will not try
	 * to access the hardware with clocks and power disabled. Reset the
	 * break flag to make the break debouncing state machine ready for the
	 * next break.
	 */
	del_timer_sync(&sci_port->break_timer);
	sci_port->break_flag = 0;

	clk_disable_unprepare(sci_port->fclk);
	clk_disable_unprepare(sci_port->iclk);

	pm_runtime_put_sync(sci_port->port.dev);
}
@@ -557,7 +568,7 @@ static inline int sci_rxd_in(struct uart_port *port)
		return 1;

	/* Cast for ARM damage */
	return !!__raw_readb((void __iomem *)s->cfg->port_reg);
	return !!__raw_readb((void __iomem *)(uintptr_t)s->cfg->port_reg);
}

/* ********************************************************************** *
@@ -733,8 +744,6 @@ static void sci_break_timer(unsigned long data)
{
	struct sci_port *port = (struct sci_port *)data;

	sci_port_enable(port);

	if (sci_rxd_in(&port->port) == 0) {
		port->break_flag = 1;
		sci_schedule_break_timer(port);
@@ -744,8 +753,6 @@ static void sci_break_timer(unsigned long data)
		sci_schedule_break_timer(port);
	} else
		port->break_flag = 0;

	sci_port_disable(port);
}

static int sci_handle_errors(struct uart_port *port)
@@ -755,11 +762,8 @@ static int sci_handle_errors(struct uart_port *port)
	struct tty_port *tport = &port->state->port;
	struct sci_port *s = to_sci_port(port);

	/*
	 * Handle overruns, if supported.
	 */
	if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) {
		if (status & (1 << s->cfg->overrun_bit)) {
	/* Handle overruns */
	if (status & (1 << s->overrun_bit)) {
		port->icount.overrun++;

		/* overrun error */
@@ -768,7 +772,6 @@ static int sci_handle_errors(struct uart_port *port)

		dev_notice(port->dev, "overrun error");
	}
	}

	if (status & SCxSR_FER(port)) {
		if (sci_rxd_in(port) == 0) {
@@ -829,7 +832,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
	if (!reg->size)
		return 0;

	if ((serial_port_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
	if ((serial_port_in(port, SCLSR) & (1 << s->overrun_bit))) {
		serial_port_out(port, SCLSR, 0);

		port->icount.overrun++;
@@ -1075,19 +1078,19 @@ static int sci_request_irq(struct sci_port *port)

	for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
		struct sci_irq_desc *desc;
		unsigned int irq;
		int irq;

		if (SCIx_IRQ_IS_MUXED(port)) {
			i = SCIx_MUX_IRQ;
			irq = up->irq;
		} else {
			irq = port->cfg->irqs[i];
			irq = port->irqs[i];

			/*
			 * Certain port types won't support all of the
			 * available interrupt sources.
			 */
			if (unlikely(!irq))
			if (unlikely(irq < 0))
				continue;
		}

@@ -1112,7 +1115,7 @@ static int sci_request_irq(struct sci_port *port)

out_noirq:
	while (--i >= 0)
		free_irq(port->cfg->irqs[i], port);
		free_irq(port->irqs[i], port);

out_nomem:
	while (--j >= 0)
@@ -1130,16 +1133,16 @@ static void sci_free_irq(struct sci_port *port)
	 * IRQ first.
	 */
	for (i = 0; i < SCIx_NR_IRQS; i++) {
		unsigned int irq = port->cfg->irqs[i];
		int irq = port->irqs[i];

		/*
		 * Certain port types won't support all of the available
		 * interrupt sources.
		 */
		if (unlikely(!irq))
		if (unlikely(irq < 0))
			continue;

		free_irq(port->cfg->irqs[i], port);
		free_irq(port->irqs[i], port);
		kfree(port->irqstr[i]);

		if (SCIx_IRQ_IS_MUXED(port)) {
@@ -1149,67 +1152,6 @@ static void sci_free_irq(struct sci_port *port)
	}
}

static const char *sci_gpio_names[SCIx_NR_FNS] = {
	"sck", "rxd", "txd", "cts", "rts",
};

static const char *sci_gpio_str(unsigned int index)
{
	return sci_gpio_names[index];
}

static void sci_init_gpios(struct sci_port *port)
{
	struct uart_port *up = &port->port;
	int i;

	if (!port->cfg)
		return;

	for (i = 0; i < SCIx_NR_FNS; i++) {
		const char *desc;
		int ret;

		if (!port->cfg->gpios[i])
			continue;

		desc = sci_gpio_str(i);

		port->gpiostr[i] = kasprintf(GFP_KERNEL, "%s:%s",
					     dev_name(up->dev), desc);

		/*
		 * If we've failed the allocation, we can still continue
		 * on with a NULL string.
		 */
		if (!port->gpiostr[i])
			dev_notice(up->dev, "%s string allocation failure\n",
				   desc);

		ret = gpio_request(port->cfg->gpios[i], port->gpiostr[i]);
		if (unlikely(ret != 0)) {
			dev_notice(up->dev, "failed %s gpio request\n", desc);

			/*
			 * If we can't get the GPIO for whatever reason,
			 * no point in keeping the verbose string around.
			 */
			kfree(port->gpiostr[i]);
		}
	}
}

static void sci_free_gpios(struct sci_port *port)
{
	int i;

	for (i = 0; i < SCIx_NR_FNS; i++)
		if (port->cfg->gpios[i]) {
			gpio_free(port->cfg->gpios[i]);
			kfree(port->gpiostr[i]);
		}
}

static unsigned int sci_tx_empty(struct uart_port *port)
{
	unsigned short status = serial_port_in(port, SCxSR);
@@ -1309,7 +1251,7 @@ static int sci_dma_rx_push(struct sci_port *s, size_t count)
	}

	if (room < count)
		dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
		dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n",
			 count - room);
	if (!room)
		return room;
@@ -1442,7 +1384,7 @@ static void work_fn_rx(struct work_struct *work)
		int count;

		chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
		dev_dbg(port->dev, "Read %u bytes with cookie %d\n",
		dev_dbg(port->dev, "Read %zu bytes with cookie %d\n",
			sh_desc->partial, sh_desc->cookie);

		spin_lock_irqsave(&port->lock, flags);
@@ -1655,7 +1597,7 @@ static void rx_timer_fn(unsigned long arg)

	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
		scr &= ~0x4000;
		enable_irq(s->cfg->irqs[1]);
		enable_irq(s->irqs[SCIx_RXI_IRQ]);
	}
	serial_port_out(port, SCSCR, scr | SCSCR_RIE);
	dev_dbg(port->dev, "DMA Rx timed out\n");
@@ -1691,16 +1633,17 @@ static void sci_request_dma(struct uart_port *port)
		s->chan_tx = chan;
		sg_init_table(&s->sg_tx, 1);
		/* UART circular tx buffer is an aligned page. */
		BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
		BUG_ON((uintptr_t)port->state->xmit.buf & ~PAGE_MASK);
		sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf),
			    UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK);
			    UART_XMIT_SIZE,
			    (uintptr_t)port->state->xmit.buf & ~PAGE_MASK);
		nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE);
		if (!nent)
			sci_tx_dma_release(s, false);
		else
			dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
				sg_dma_len(&s->sg_tx),
				port->state->xmit.buf, sg_dma_address(&s->sg_tx));
			dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__,
				sg_dma_len(&s->sg_tx), port->state->xmit.buf,
				&sg_dma_address(&s->sg_tx));

		s->sg_len_tx = nent;

@@ -1740,7 +1683,7 @@ static void sci_request_dma(struct uart_port *port)

			sg_init_table(sg, 1);
			sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
				    (int)buf[i] & ~PAGE_MASK);
				    (uintptr_t)buf[i] & ~PAGE_MASK);
			sg_dma_address(sg) = dma[i];
		}

@@ -1808,20 +1751,21 @@ static void sci_shutdown(struct uart_port *port)
	sci_free_irq(s);
}

static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
				   unsigned long freq)
{
	switch (algo_id) {
	if (s->sampling_rate)
		return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1;

	switch (s->cfg->scbrr_algo_id) {
	case SCBRR_ALGO_1:
		return ((freq + 16 * bps) / (16 * bps) - 1);
		return freq / (16 * bps);
	case SCBRR_ALGO_2:
		return ((freq + 16 * bps) / (32 * bps) - 1);
		return DIV_ROUND_CLOSEST(freq, 32 * bps) - 1;
	case SCBRR_ALGO_3:
		return (((freq * 2) + 16 * bps) / (16 * bps) - 1);
		return freq / (8 * bps);
	case SCBRR_ALGO_4:
		return (((freq * 2) + 16 * bps) / (32 * bps) - 1);
	case SCBRR_ALGO_5:
		return (((freq * 1000 / 32) / bps) - 1);
		return DIV_ROUND_CLOSEST(freq, 16 * bps) - 1;
	}

	/* Warn, but use a safe default */
@@ -1903,12 +1847,11 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,

	baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
	if (likely(baud && port->uartclk)) {
		if (s->cfg->scbrr_algo_id == SCBRR_ALGO_6) {
		if (s->cfg->type == PORT_HSCIF) {
			sci_baud_calc_hscif(baud, port->uartclk, &t, &srr,
					    &cks);
		} else {
			t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud,
					   port->uartclk);
			t = sci_scbrr_calc(s, baud, port->uartclk);
			for (cks = 0; t >= 256 && cks <= 3; cks++)
				t >>= 2;
		}
@@ -2115,10 +2058,6 @@ static void sci_config_port(struct uart_port *port, int flags)

static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
{
	struct sci_port *s = to_sci_port(port);

	if (ser->irq != s->cfg->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
		return -EINVAL;
	if (ser->baud_base < 2400)
		/* No paper tape reader for Mitch.. */
		return -EINVAL;
@@ -2151,11 +2090,13 @@ static struct uart_ops sci_uart_ops = {
};

static int sci_init_single(struct platform_device *dev,
				     struct sci_port *sci_port,
				     unsigned int index,
				     struct plat_sci_port *p)
			   struct sci_port *sci_port, unsigned int index,
			   struct plat_sci_port *p, bool early)
{
	struct uart_port *port = &sci_port->port;
	const struct resource *res;
	unsigned int sampling_rate;
	unsigned int i;
	int ret;

	sci_port->cfg	= p;
@@ -2164,31 +2105,90 @@ static int sci_init_single(struct platform_device *dev,
	port->iotype	= UPIO_MEM;
	port->line	= index;

	if (dev->num_resources) {
		/* Device has resources, use them. */
		res = platform_get_resource(dev, IORESOURCE_MEM, 0);
		if (res == NULL)
			return -ENOMEM;

		port->mapbase = res->start;

		for (i = 0; i < ARRAY_SIZE(sci_port->irqs); ++i)
			sci_port->irqs[i] = platform_get_irq(dev, i);

		/* The SCI generates several interrupts. They can be muxed
		 * together or connected to different interrupt lines. In the
		 * muxed case only one interrupt resource is specified. In the
		 * non-muxed case three or four interrupt resources are
		 * specified, as the BRI interrupt is optional.
		 */
		if (sci_port->irqs[0] < 0)
			return -ENXIO;

		if (sci_port->irqs[1] < 0) {
			sci_port->irqs[1] = sci_port->irqs[0];
			sci_port->irqs[2] = sci_port->irqs[0];
			sci_port->irqs[3] = sci_port->irqs[0];
		}
	} else {
		/* No resources, use old-style platform data. */
		port->mapbase = p->mapbase;
		for (i = 0; i < ARRAY_SIZE(sci_port->irqs); ++i)
			sci_port->irqs[i] = p->irqs[i] ? p->irqs[i] : -ENXIO;
	}

	if (p->regtype == SCIx_PROBE_REGTYPE) {
		ret = sci_probe_regmap(p);
		if (unlikely(ret))
			return ret;
	}

	switch (p->type) {
	case PORT_SCIFB:
		port->fifosize = 256;
		sci_port->overrun_bit = 9;
		sampling_rate = 16;
		break;
	case PORT_HSCIF:
		port->fifosize = 128;
		sampling_rate = 0;
		sci_port->overrun_bit = 0;
		break;
	case PORT_SCIFA:
		port->fifosize = 64;
		sci_port->overrun_bit = 9;
		sampling_rate = 16;
		break;
	case PORT_SCIF:
		port->fifosize = 16;
		if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) {
			sci_port->overrun_bit = 9;
			sampling_rate = 16;
		} else {
			sci_port->overrun_bit = 0;
			sampling_rate = 32;
		}
		break;
	default:
		port->fifosize = 1;
		sci_port->overrun_bit = 5;
		sampling_rate = 32;
		break;
	}

	if (p->regtype == SCIx_PROBE_REGTYPE) {
		ret = sci_probe_regmap(p);
		if (unlikely(ret))
			return ret;
	/* Set the sampling rate if the baud rate calculation algorithm isn't
	 * specified.
	 */
	if (p->scbrr_algo_id == SCBRR_ALGO_NONE) {
		/* SCIFA on sh7723 and sh7724 need a custom sampling rate that
		 * doesn't match the SoC datasheet, this should be investigated.
		 * Let platform data override the sampling rate for now.
		 */
		sci_port->sampling_rate = p->sampling_rate ? p->sampling_rate
					: sampling_rate;
	}

	if (dev) {
	if (!early) {
		sci_port->iclk = clk_get(&dev->dev, "sci_ick");
		if (IS_ERR(sci_port->iclk)) {
			sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
@@ -2208,8 +2208,6 @@ static int sci_init_single(struct platform_device *dev,

		port->dev = &dev->dev;

		sci_init_gpios(sci_port);

		pm_runtime_enable(&dev->dev);
	}

@@ -2220,32 +2218,22 @@ static int sci_init_single(struct platform_device *dev,
	/*
	 * Establish some sensible defaults for the error detection.
	 */
	if (!p->error_mask)
		p->error_mask = (p->type == PORT_SCI) ?
	sci_port->error_mask = (p->type == PORT_SCI) ?
			SCI_DEFAULT_ERROR_MASK : SCIF_DEFAULT_ERROR_MASK;

	/*
	 * Establish sensible defaults for the overrun detection, unless
	 * the part has explicitly disabled support for it.
	 */
	if (p->overrun_bit != SCIx_NOT_SUPPORTED) {
		if (p->type == PORT_SCI)
			p->overrun_bit = 5;
		else if (p->scbrr_algo_id == SCBRR_ALGO_4)
			p->overrun_bit = 9;
		else
			p->overrun_bit = 0;

	/*
	 * Make the error mask inclusive of overrun detection, if
	 * supported.
	 */
		p->error_mask |= (1 << p->overrun_bit);
	}
	sci_port->error_mask |= 1 << sci_port->overrun_bit;

	port->mapbase		= p->mapbase;
	port->type		= p->type;
	port->flags		= p->flags;
	port->flags		= UPF_FIXED_PORT | p->flags;
	port->regshift		= p->regshift;

	/*
@@ -2255,7 +2243,7 @@ static int sci_init_single(struct platform_device *dev,
	 *
	 * For the muxed case there's nothing more to do.
	 */
	port->irq		= p->irqs[SCIx_RXI_IRQ];
	port->irq		= sci_port->irqs[SCIx_RXI_IRQ];
	port->irqflags		= 0;

	port->serial_in		= sci_serial_in;
@@ -2270,8 +2258,6 @@ static int sci_init_single(struct platform_device *dev,

static void sci_cleanup_single(struct sci_port *port)
{
	sci_free_gpios(port);

	clk_put(port->iclk);
	clk_put(port->fclk);

@@ -2387,7 +2373,7 @@ static int sci_probe_earlyprintk(struct platform_device *pdev)

	early_serial_console.index = pdev->id;

	sci_init_single(NULL, &sci_ports[pdev->id], pdev->id, cfg);
	sci_init_single(pdev, &sci_ports[pdev->id], pdev->id, cfg, true);

	serial_console_setup(&early_serial_console, early_serial_buf);

@@ -2454,7 +2440,7 @@ static int sci_probe_single(struct platform_device *dev,
		return -EINVAL;
	}

	ret = sci_init_single(dev, sciport, index, p);
	ret = sci_init_single(dev, sciport, index, p, false);
	if (ret)
		return ret;

+1 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
#define SCxSR_PER(port)		(((port)->type == PORT_SCI) ? SCI_PER    : SCIF_PER)
#define SCxSR_BRK(port)		(((port)->type == PORT_SCI) ? 0x00       : SCIF_BRK)

#define SCxSR_ERRORS(port)	(to_sci_port(port)->cfg->error_mask)
#define SCxSR_ERRORS(port)	(to_sci_port(port)->error_mask)

#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
+10 −24
Original line number Diff line number Diff line
@@ -11,11 +11,11 @@
#define SCIx_NOT_SUPPORTED	(-1)

enum {
	SCBRR_ALGO_1,		/* ((clk + 16 * bps) / (16 * bps) - 1) */
	SCBRR_ALGO_2,		/* ((clk + 16 * bps) / (32 * bps) - 1) */
	SCBRR_ALGO_3,		/* (((clk * 2) + 16 * bps) / (16 * bps) - 1) */
	SCBRR_ALGO_4,		/* (((clk * 2) + 16 * bps) / (32 * bps) - 1) */
	SCBRR_ALGO_5,		/* (((clk * 1000 / 32) / bps) - 1) */
	SCBRR_ALGO_NONE,	/* Compute sampling rate in the driver */
	SCBRR_ALGO_1,		/* clk / (16 * bps) */
	SCBRR_ALGO_2,		/* DIV_ROUND_CLOSEST(clk, 32 * bps) - 1 */
	SCBRR_ALGO_3,		/* clk / (8 * bps) */
	SCBRR_ALGO_4,		/* DIV_ROUND_CLOSEST(clk, 16 * bps) - 1 */
	SCBRR_ALGO_6,		/* HSCIF variable sample rate algorithm */
};

@@ -70,17 +70,6 @@ enum {
	SCIx_MUX_IRQ = SCIx_NR_IRQS,	/* special case */
};

/* Offsets into the sci_port->gpios array */
enum {
	SCIx_SCK,
	SCIx_RXD,
	SCIx_TXD,
	SCIx_CTS,
	SCIx_RTS,

	SCIx_NR_FNS,
};

enum {
	SCIx_PROBE_REGTYPE,

@@ -108,10 +97,10 @@ enum {
}

#define SCIx_IRQ_IS_MUXED(port)			\
	((port)->cfg->irqs[SCIx_ERI_IRQ] ==	\
	 (port)->cfg->irqs[SCIx_RXI_IRQ]) ||	\
	((port)->cfg->irqs[SCIx_ERI_IRQ] &&	\
	 !(port)->cfg->irqs[SCIx_RXI_IRQ])
	((port)->irqs[SCIx_ERI_IRQ] ==	\
	 (port)->irqs[SCIx_RXI_IRQ]) ||	\
	((port)->irqs[SCIx_ERI_IRQ] &&	\
	 ((port)->irqs[SCIx_RXI_IRQ] < 0))
/*
 * SCI register subset common for all port types.
 * Not all registers will exist on all parts.
@@ -142,20 +131,17 @@ struct plat_sci_port_ops {
struct plat_sci_port {
	unsigned long	mapbase;		/* resource base */
	unsigned int	irqs[SCIx_NR_IRQS];	/* ERI, RXI, TXI, BRI */
	unsigned int	gpios[SCIx_NR_FNS];	/* SCK, RXD, TXD, CTS, RTS */
	unsigned int	type;			/* SCI / SCIF / IRDA / HSCIF */
	upf_t		flags;			/* UPF_* flags */
	unsigned long	capabilities;		/* Port features/capabilities */

	unsigned int	sampling_rate;
	unsigned int	scbrr_algo_id;		/* SCBRR calculation algo */
	unsigned int	scscr;			/* SCSCR initialization */

	/*
	 * Platform overrides if necessary, defaults otherwise.
	 */
	int		overrun_bit;
	unsigned int	error_mask;

	int		port_reg;
	unsigned char	regshift;
	unsigned char	regtype;