Esempio n. 1
0
static void ixp2400_msf_free_rbuf_entries(struct ixp2400_msf_parameters *mp)
{
	int size_bits;
	int i;

	
	size_bits = mp->rx_mode & IXP2400_RX_MODE_RBUF_SIZE_MASK;
	if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_64) {
		for (i = 1; i < 128; i++) {
			if (i == 9 || i == 18 || i == 27)
				continue;
			ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
		}
	} else if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_128) {
		for (i = 1; i < 64; i++) {
			if (i == 4 || i == 9 || i == 13)
				continue;
			ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
		}
	} else if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_256) {
		for (i = 1; i < 32; i++) {
			if (i == 2 || i == 4 || i == 6)
				continue;
			ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
		}
	}
}
Esempio n. 2
0
static void update_gpio_int_csrs(void)
{
	ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
	ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
	ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
	ixp2000_reg_wrb(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
}
Esempio n. 3
0
/*
 * We only do anything if we are the master NPU on the board.
 * The slave NPU only has the ethernet chip going directly to
 * the PCIB interrupt input.
 */
void __init ixdp2x01_init_irq(void)
{
	int irq = 0;

	/* initialize chip specific interrupts */
	ixp2000_init_irq();

	if (machine_is_ixdp2401())
		valid_irq_mask = IXDP2401_VALID_IRQ_MASK;
	else
		valid_irq_mask = IXDP2801_VALID_IRQ_MASK;

	/* Mask all interrupts from CPLD, disable simulation */
	ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG, 0xffffffff);
	ixp2000_reg_write(IXDP2X01_INT_SIM_REG, 0);

	for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
		if (irq & valid_irq_mask) {
			set_irq_chip(irq, &ixdp2x01_irq_chip);
			set_irq_handler(irq, do_level_IRQ);
			set_irq_flags(irq, IRQF_VALID);
		} else {
			set_irq_flags(irq, 0);
		}
	}

	/* Hook into PCI interrupts */
	set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x01_irq_handler);
}
Esempio n. 4
0
static void ixp2000_GPIO_irq_mask_ack(unsigned int irq)
{
	ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));

	ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
	ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
	ixp2000_reg_wrb(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
}
Esempio n. 5
0
static void ixp2000_pci_irq_unmask(unsigned int irq)
{
	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
	if (irq == IRQ_IXP2000_PCIA)
		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26)));
	else if (irq == IRQ_IXP2000_PCIB)
		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));
}
Esempio n. 6
0
static void
wdt_enable(void)
{
    ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE);
    ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE);
    ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate);
    ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE);
}
Esempio n. 7
0
static irqreturn_t
hr_time_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	ixp2000_reg_write(IXP2000_T2_CTL, 0);
	ixp2000_reg_write(IXP2000_T2_CLR, 1);

	do_hr_timer_int();
	return IRQ_HANDLED;
}
Esempio n. 8
0
void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
{
	ixp2000_reg_write(IXP2000_SLOWPORT_CCR, old_cfg->CCR);
	ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, old_cfg->WTC);
	ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, old_cfg->RTC);
	ixp2000_reg_write(IXP2000_SLOWPORT_PCR, old_cfg->PCR);
	ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, old_cfg->ADC);

	spin_unlock_irqrestore(&ixp2000_slowport_lock, 
					ixp2000_slowport_irq_flags);
}
Esempio n. 9
0
void __init ixp2000_init_irq(void)
{
    int irq;

    /*
     * Mask all sources
     */
    ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, 0xffffffff);
    ixp2000_reg_write(IXP2000_FIQ_ENABLE_CLR, 0xffffffff);

    /* clear all GPIO edge/level detects */
    ixp2000_reg_write(IXP2000_GPIO_REDR, 0);
    ixp2000_reg_write(IXP2000_GPIO_FEDR, 0);
    ixp2000_reg_write(IXP2000_GPIO_LSHR, 0);
    ixp2000_reg_write(IXP2000_GPIO_LSLR, 0);
    ixp2000_reg_write(IXP2000_GPIO_INCR, -1);

    /* clear PCI interrupt sources */
    ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, 0);

    /*
     * Certain bits in the IRQ status register of the
     * IXP2000 are reserved. Instead of trying to map
     * things non 1:1 from bit position to IRQ number,
     * we mark the reserved IRQs as invalid. This makes
     * our mask/unmask code much simpler.
     */
    for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {
        if ((1 << irq) & IXP2000_VALID_IRQ_MASK) {
            set_irq_chip(irq, &ixp2000_irq_chip);
            set_irq_handler(irq, do_level_IRQ);
            set_irq_flags(irq, IRQF_VALID);
        } else set_irq_flags(irq, 0);
    }

    /*
     * GPIO IRQs are invalid until someone sets the interrupt mode
     * by calling set_irq_type().
     */
    for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
        set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
        set_irq_handler(irq, do_level_IRQ);
        set_irq_flags(irq, 0);
    }
    set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);

    /*
     * Enable PCI irqs.  The actual PCI[AB] decoding is done in
     * entry-macro.S, so we don't need a chained handler for the
     * PCI interrupt source.
     */
    ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI));
    for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
        set_irq_chip(irq, &ixp2000_pci_irq_chip);
        set_irq_handler(irq, do_level_IRQ);
        set_irq_flags(irq, IRQF_VALID);
    }
}
Esempio n. 10
0
void __init ixp2000_init_time(unsigned long tick_rate)
{
	ixp2000_reg_write(IXP2000_T1_CLR, 0);
	ixp2000_reg_write(IXP2000_T2_CLR, 0);

	ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
	ticks_per_usec = tick_rate / 1000000;

	ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy);
	ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));

	/* register for interrupt */
	setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq);
}
Esempio n. 11
0
void ixp2400_msf_init(struct ixp2400_msf_parameters *mp)
{
	u32 value;
	int i;

	
	ixp2400_pll_init(mp);

	
	value = ixp2000_reg_read(IXP2000_RESET0);
	ixp2000_reg_write(IXP2000_RESET0, value | 0x80);
	ixp2000_reg_write(IXP2000_RESET0, value & ~0x80);

	
	ixp2000_reg_write(IXP2000_MSF_RX_MPHY_POLL_LIMIT, mp->rx_poll_ports - 1);
	ixp2000_reg_write(IXP2000_MSF_RX_CONTROL, mp->rx_mode);
	for (i = 0; i < 4; i++) {
		ixp2000_reg_write(IXP2000_MSF_RX_UP_CONTROL_0 + i,
						mp->rx_channel_mode[i]);
	}
	ixp2400_msf_free_rbuf_entries(mp);
	ixp2400_msf_enable_rx(mp);

	
	ixp2000_reg_write(IXP2000_MSF_TX_MPHY_POLL_LIMIT, mp->tx_poll_ports - 1);
	ixp2000_reg_write(IXP2000_MSF_TX_CONTROL, mp->tx_mode);
	for (i = 0; i < 4; i++) {
		ixp2000_reg_write(IXP2000_MSF_TX_UP_CONTROL_0 + i,
						mp->tx_channel_mode[i]);
	}
	ixp2400_msf_enable_tx(mp);
}
Esempio n. 12
0
static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct ixpdev_priv *ip = netdev_priv(dev);
	struct ixpdev_tx_desc *desc;
	int entry;
	unsigned long flags;

	if (unlikely(skb->len > PAGE_SIZE)) {
		
		dev_kfree_skb(skb);
		return NETDEV_TX_OK;
	}

	entry = tx_pointer;
	tx_pointer = (tx_pointer + 1) % TX_BUF_COUNT;

	desc = tx_desc + entry;
	desc->pkt_length = skb->len;
	desc->channel = ip->channel;

	skb_copy_and_csum_dev(skb, phys_to_virt(desc->buf_addr));
	dev_kfree_skb(skb);

	ixp2000_reg_write(RING_TX_PENDING,
		TX_BUF_DESC_BASE + (entry * sizeof(struct ixpdev_tx_desc)));

	local_irq_save(flags);
	ip->tx_queue_entries++;
	if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
		netif_stop_queue(dev);
	local_irq_restore(flags);

	return NETDEV_TX_OK;
}
Esempio n. 13
0
static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct ixpdev_priv *ip = netdev_priv(dev);
	struct ixpdev_tx_desc *desc;
	int entry;

	if (unlikely(skb->len > PAGE_SIZE)) {
		/* @@@ Count drops.  */
		dev_kfree_skb(skb);
		return 0;
	}

	entry = tx_pointer;
	tx_pointer = (tx_pointer + 1) % TX_BUF_COUNT;

	desc = tx_desc + entry;
	desc->pkt_length = skb->len;
	desc->channel = ip->channel;

	skb_copy_and_csum_dev(skb, phys_to_virt(desc->buf_addr));
	dev_kfree_skb(skb);

	ixp2000_reg_write(RING_TX_PENDING,
		TX_BUF_DESC_BASE + (entry * sizeof(struct ixpdev_tx_desc)));

	dev->trans_start = jiffies;

	local_irq_disable();
	ip->tx_queue_entries++;
	if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
		netif_stop_queue(dev);
	local_irq_enable();

	return 0;
}
Esempio n. 14
0
/*************************************************************************
 * Slowport access routines
 *************************************************************************/
void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg *old_cfg)
{
	spin_lock_irqsave(&ixp2000_slowport_lock, ixp2000_slowport_irq_flags);

	old_cfg->CCR = *IXP2000_SLOWPORT_CCR;
	old_cfg->WTC = *IXP2000_SLOWPORT_WTC2;
	old_cfg->RTC = *IXP2000_SLOWPORT_RTC2;
	old_cfg->PCR = *IXP2000_SLOWPORT_PCR;
	old_cfg->ADC = *IXP2000_SLOWPORT_ADC;

	ixp2000_reg_write(IXP2000_SLOWPORT_CCR, new_cfg->CCR);
	ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, new_cfg->WTC);
	ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, new_cfg->RTC);
	ixp2000_reg_write(IXP2000_SLOWPORT_PCR, new_cfg->PCR);
	ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
}
Esempio n. 15
0
static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type)
{
	int line = irq - IRQ_IXP2000_GPIO0;

	/*
	 * First, configure this GPIO line as an input.
	 */
	ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);

	/*
	 * Then, set the proper trigger type.
	 */
	if (type & IRQT_FALLING)
		GPIO_IRQ_falling_edge |= 1 << line;
	else
		GPIO_IRQ_falling_edge &= ~(1 << line);
	if (type & IRQT_RISING)
		GPIO_IRQ_rising_edge |= 1 << line;
	else
		GPIO_IRQ_rising_edge &= ~(1 << line);
	if (type & IRQT_LOW)
		GPIO_IRQ_level_low |= 1 << line;
	else
		GPIO_IRQ_level_low &= ~(1 << line);
	if (type & IRQT_HIGH)
		GPIO_IRQ_level_high |= 1 << line;
	else
		GPIO_IRQ_level_high &= ~(1 << line);
	update_gpio_int_csrs();

	return 0;
}
Esempio n. 16
0
void __init ixp2000_map_io(void)
{
	extern unsigned int processor_id;

	/*
	 * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE for
	 * tweaking the PMDs so XCB=101. On IXP2800s we use the normal
	 * PMD flags.
	 */
	if ((processor_id & 0xfffffff0) == 0x69054190) {
		int i;

		printk(KERN_INFO "Enabling IXP2400 erratum #66 workaround\n");

		for(i=0;i<ARRAY_SIZE(ixp2000_io_desc);i++)
			ixp2000_io_desc[i].type = MT_IXP2000_DEVICE;
	}

	iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
	early_serial_setup(&ixp2000_serial_port);

#ifdef CONFIG_KGDB_8250
	kgdb8250_add_port(0, &ixp2000_serial_port);
#endif

	/* Set slowport to 8-bit mode.  */
	ixp2000_reg_write(IXP2000_SLOWPORT_FRM, 1);
}
Esempio n. 17
0
static void ixp2400_msf_enable_tx(struct ixp2400_msf_parameters *mp)
{
	u32 value;

	value = ixp2000_reg_read(IXP2000_MSF_TX_CONTROL) & 0x0fffffff;
	value |= ixp2400_msf_valid_channels(mp->tx_mode) << 28;
	ixp2000_reg_write(IXP2000_MSF_TX_CONTROL, value);
}
Esempio n. 18
0
static void ixp2400_pll_init(struct ixp2400_msf_parameters *mp)
{
	int rx_dual_clock;
	int tx_dual_clock;
	u32 value;

	
	rx_dual_clock = !!(mp->rx_mode & IXP2400_RX_MODE_WIDTH_MASK);
	tx_dual_clock = !!(mp->tx_mode & IXP2400_TX_MODE_WIDTH_MASK);

	
	value = ixp2000_reg_read(IXP2000_MSF_CLK_CNTRL);

	
	value |= 0x0000f0f0;
	ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);

	
	value &= ~0x03000000;
	value |= (rx_dual_clock << 24) | (tx_dual_clock << 25);

	
	value &= ~0x00ff0000;
	value |= mp->rxclk01_multiplier << 16;
	value |= mp->rxclk23_multiplier << 18;
	value |= mp->txclk01_multiplier << 20;
	value |= mp->txclk23_multiplier << 22;

	
	ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);

	
	value &= ~(0x00005000 | rx_dual_clock << 13 | tx_dual_clock << 15);
	ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);

	
	value &= ~(0x00000050 | rx_dual_clock << 5 | tx_dual_clock << 7);
	ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);

	
	udelay(100);
}
Esempio n. 19
0
/* dev always points to nds[0].  */
static int ixpdev_poll(struct napi_struct *napi, int budget)
{
	struct ixpdev_priv *ip = container_of(napi, struct ixpdev_priv, napi);
	struct net_device *dev = ip->dev;
	int rx;

	rx = 0;
	do {
		ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff);

		rx = ixpdev_rx(dev, rx, budget);
		if (rx >= budget)
			break;
	} while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff);

	netif_rx_complete(napi);
	ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);

	return rx;
}
Esempio n. 20
0
File: ixpdev.c Progetto: E-LLP/n900
static int ixpdev_rx(struct net_device *dev, int processed, int budget)
{
	while (processed < budget) {
		struct ixpdev_rx_desc *desc;
		struct sk_buff *skb;
		void *buf;
		u32 _desc;

		_desc = ixp2000_reg_read(RING_RX_DONE);
		if (_desc == 0)
			return 0;

		desc = rx_desc +
			((_desc - RX_BUF_DESC_BASE) / sizeof(struct ixpdev_rx_desc));
		buf = phys_to_virt(desc->buf_addr);

		if (desc->pkt_length < 4 || desc->pkt_length > PAGE_SIZE) {
			printk(KERN_ERR "ixp2000: rx err, length %d\n",
					desc->pkt_length);
			goto err;
		}

		if (desc->channel < 0 || desc->channel >= nds_count) {
			printk(KERN_ERR "ixp2000: rx err, channel %d\n",
					desc->channel);
			goto err;
		}

		/* @@@ Make FCS stripping configurable.  */
		desc->pkt_length -= 4;

		if (unlikely(!netif_running(nds[desc->channel])))
			goto err;

		skb = netdev_alloc_skb(dev, desc->pkt_length + 2);
		if (likely(skb != NULL)) {
			skb_reserve(skb, 2);
			skb_copy_to_linear_data(skb, buf, desc->pkt_length);
			skb_put(skb, desc->pkt_length);
			skb->protocol = eth_type_trans(skb, nds[desc->channel]);

			dev->last_rx = jiffies;

			netif_receive_skb(skb);
		}

err:
		ixp2000_reg_write(RING_RX_PENDING, _desc);
		processed++;
	}

	return processed;
}
Esempio n. 21
0
void gpio_line_config(int line, int direction)
{
    unsigned long flags;

    local_irq_save(flags);
    if (direction == GPIO_OUT) {
        irq_desc[line + IRQ_IXP2000_GPIO0].valid = 0;

        /* if it's an output, it ain't an interrupt anymore */
        GPIO_IRQ_falling_edge &= ~(1 << line);
        GPIO_IRQ_rising_edge &= ~(1 << line);
        GPIO_IRQ_level_low &= ~(1 << line);
        GPIO_IRQ_level_high &= ~(1 << line);
        update_gpio_int_csrs();

        ixp2000_reg_write(IXP2000_GPIO_PDSR, 1 << line);
    } else if (direction == GPIO_IN) {
        ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);
    }
    local_irq_restore(flags);
}
Esempio n. 22
0
static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	write_seqlock(&xtime_lock);

	/* clear timer 1 */
	ixp2000_reg_write(IXP2000_T1_CLR, 1);
	
	timer_tick(regs);

	write_sequnlock(&xtime_lock);

	return IRQ_HANDLED;
}
Esempio n. 23
0
void ixp2000_uengine_csr_write(int uengine, int offset, u32 value)
{
	void *uebase;
	u32 *local_csr_status;
	u32 *reg;

	uebase = ixp2000_uengine_csr_area(uengine);

	local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
	reg = (u32 *)(uebase + offset);
	do {
		ixp2000_reg_write(reg, value);
	} while (ixp2000_reg_read(local_csr_status) & 1);
}
Esempio n. 24
0
int
schedule_hr_timer_int(unsigned ref_jiffies, int ref_cycles)
{
	int temp_cycles;
	extern unsigned long processor_id;

	if ((processor_id & 0xf) < 4) {
		return -EIO;
	}	

	/*
	 * Get offset from last jiffy
	 */
	temp_cycles = (ref_jiffies - jiffies) * arch_cycles_per_jiffy + ref_cycles - get_arch_cycles(jiffies);
	if(unlikely(temp_cycles <= 0))
		return -ETIME;

	ixp2000_reg_write(IXP2000_T2_CTL, 0);
	ixp2000_reg_write(IXP2000_T2_CLD, temp_cycles);
	ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));

	return 0;
}
Esempio n. 25
0
static int ixpdev_close(struct net_device *dev)
{
	struct ixpdev_priv *ip = netdev_priv(dev);

	netif_stop_queue(dev);
	napi_disable(&ip->napi);
	set_port_admin_status(ip->channel, 0);

	if (!--nds_open) {
		ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0xffff);
		free_irq(IRQ_IXP2000_THDA0, nds);
	}

	return 0;
}
Esempio n. 26
0
static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    write_seqlock(&xtime_lock);

    /* clear timer 1 */
    ixp2000_reg_write(IXP2000_T1_CLR, 1);

    while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
        timer_tick(regs);
        next_jiffy_time -= ticks_per_jiffy;
    }

    write_sequnlock(&xtime_lock);

    return IRQ_HANDLED;
}
Esempio n. 27
0
void __init ixp2000_init_time(unsigned long tick_rate)
{
    ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
    ticks_per_usec = tick_rate / 1000000;

    /*
     * We use timer 1 as our timer interrupt.
     */
    ixp2000_reg_write(IXP2000_T1_CLR, 0);
    ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
    ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));

    /*
     * We use a second timer as a monotonic counter for tracking
     * missed jiffies.  The IXP2000 has four timers, but if we're
     * on an A-step IXP2800, timer 2 and 3 don't work, so on those
     * chips we use timer 4.  Timer 4 is the only timer that can
     * be used for the watchdog, so we use timer 2 if we're on a
     * non-buggy chip.
     */
    if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
        printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");

        ixp2000_reg_write(IXP2000_T4_CLR, 0);
        ixp2000_reg_write(IXP2000_T4_CLD, -1);
        ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
        missing_jiffy_timer_csr = IXP2000_T4_CSR;
    } else {
        ixp2000_reg_write(IXP2000_T2_CLR, 0);
        ixp2000_reg_write(IXP2000_T2_CLD, -1);
        ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
        missing_jiffy_timer_csr = IXP2000_T2_CSR;
    }
    next_jiffy_time = 0xffffffff;

    /* register for interrupt */
    setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq);
}
Esempio n. 28
0
void 
hr_time_init(void)
{
	extern unsigned long processor_id;
	unsigned long prod_id = *IXP2000_PROD_ID;

	/*
	 * HRT will only work on revision B0 or B1 CPUs
	 */
	if ((processor_id & 0xf) < 4) {
		printk(KERN_ERR "IXP2800 Rev A%d - HRT disabled\n",
				processor_id & 0xf);
		return;
	}	

	scaled_arch_cycles_per_nsec = div_sc24(ixp2000_tick_rate, NSEC_PER_SEC);

	scaled_nsec_per_arch_cycle = div_sc24(NSEC_PER_SEC, ixp2000_tick_rate);

	ixp2000_reg_write(IXP2000_T2_CTL, 0);

	setup_irq(IRQ_IXP2000_TIMER2, &hr_timer_irq);
}
Esempio n. 29
0
static int ixpdev_open(struct net_device *dev)
{
	struct ixpdev_priv *ip = netdev_priv(dev);
	int err;

	napi_enable(&ip->napi);
	if (!nds_open++) {
		err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt,
					IRQF_SHARED, "ixp2000_eth", nds);
		if (err) {
			nds_open--;
			napi_disable(&ip->napi);
			return err;
		}

		ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0xffff);
	}

	set_port_admin_status(ip->channel, 1);
	netif_start_queue(dev);

	return 0;
}
Esempio n. 30
0
void __init ixp2000_init_time(unsigned long tick_rate)
{
	ixp2000_reg_write(IXP2000_T1_CLR, 0);
	ixp2000_reg_write(IXP2000_T4_CLR, 0);

	ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
	ticks_per_usec = tick_rate / 1000000;

	ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
	ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));

	/*
	 * We use T4 as a monotonic counter to track missed jiffies
	 */
	ixp2000_reg_write(IXP2000_T4_CLD, -1);
	ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
 	next_jiffy_time = 0xffffffff;

	/* register for interrupt */
	setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq);
}