|  | @@ -494,3 +494,185 @@ static struct irq_chip balloon3_irq_chip = {
 | 
	
		
			
				|  |  |  	.name		= "FPGA",
 | 
	
		
			
				|  |  |  	.irq_ack	= balloon3_mask_irq,
 | 
	
		
			
				|  |  |  	.irq_mask	= balloon3_mask_irq,
 | 
	
		
			
				|  |  | +	.irq_unmask	= balloon3_unmask_irq,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void balloon3_irq_handler(unsigned int irq, struct irq_desc *desc)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	unsigned long pending = __raw_readl(BALLOON3_INT_CONTROL_REG) &
 | 
	
		
			
				|  |  | +					balloon3_irq_enabled;
 | 
	
		
			
				|  |  | +	do {
 | 
	
		
			
				|  |  | +		/* clear useless edge notification */
 | 
	
		
			
				|  |  | +		if (desc->irq_data.chip->irq_ack) {
 | 
	
		
			
				|  |  | +			struct irq_data *d;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			d = irq_get_irq_data(BALLOON3_AUX_NIRQ);
 | 
	
		
			
				|  |  | +			desc->irq_data.chip->irq_ack(d);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		while (pending) {
 | 
	
		
			
				|  |  | +			irq = BALLOON3_IRQ(0) + __ffs(pending);
 | 
	
		
			
				|  |  | +			generic_handle_irq(irq);
 | 
	
		
			
				|  |  | +			pending &= pending - 1;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		pending = __raw_readl(BALLOON3_INT_CONTROL_REG) &
 | 
	
		
			
				|  |  | +				balloon3_irq_enabled;
 | 
	
		
			
				|  |  | +	} while (pending);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void __init balloon3_init_irq(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int irq;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pxa27x_init_irq();
 | 
	
		
			
				|  |  | +	/* setup extra Balloon3 irqs */
 | 
	
		
			
				|  |  | +	for (irq = BALLOON3_IRQ(0); irq <= BALLOON3_IRQ(7); irq++) {
 | 
	
		
			
				|  |  | +		irq_set_chip_and_handler(irq, &balloon3_irq_chip,
 | 
	
		
			
				|  |  | +					 handle_level_irq);
 | 
	
		
			
				|  |  | +		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	irq_set_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler);
 | 
	
		
			
				|  |  | +	irq_set_irq_type(BALLOON3_AUX_NIRQ, IRQ_TYPE_EDGE_FALLING);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pr_debug("%s: chained handler installed - irq %d automatically "
 | 
	
		
			
				|  |  | +		"enabled\n", __func__, BALLOON3_AUX_NIRQ);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/******************************************************************************
 | 
	
		
			
				|  |  | + * GPIO expander
 | 
	
		
			
				|  |  | + ******************************************************************************/
 | 
	
		
			
				|  |  | +#if defined(CONFIG_GPIO_PCF857X) || defined(CONFIG_GPIO_PCF857X_MODULE)
 | 
	
		
			
				|  |  | +static struct pcf857x_platform_data balloon3_pcf857x_pdata = {
 | 
	
		
			
				|  |  | +	.gpio_base	= BALLOON3_PCF_GPIO_BASE,
 | 
	
		
			
				|  |  | +	.n_latch	= 0,
 | 
	
		
			
				|  |  | +	.setup		= NULL,
 | 
	
		
			
				|  |  | +	.teardown	= NULL,
 | 
	
		
			
				|  |  | +	.context	= NULL,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static struct i2c_board_info __initdata balloon3_i2c_devs[] = {
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		I2C_BOARD_INFO("pcf8574a", 0x38),
 | 
	
		
			
				|  |  | +		.platform_data	= &balloon3_pcf857x_pdata,
 | 
	
		
			
				|  |  | +	},
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void __init balloon3_i2c_init(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	pxa_set_i2c_info(NULL);
 | 
	
		
			
				|  |  | +	i2c_register_board_info(0, ARRAY_AND_SIZE(balloon3_i2c_devs));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +static inline void balloon3_i2c_init(void) {}
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/******************************************************************************
 | 
	
		
			
				|  |  | + * NAND
 | 
	
		
			
				|  |  | + ******************************************************************************/
 | 
	
		
			
				|  |  | +#if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
 | 
	
		
			
				|  |  | +static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct nand_chip *this = mtd->priv;
 | 
	
		
			
				|  |  | +	uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (ctrl & NAND_CTRL_CHANGE) {
 | 
	
		
			
				|  |  | +		if (ctrl & NAND_CLE)
 | 
	
		
			
				|  |  | +			balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLCLE;
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +			balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLCLE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (ctrl & NAND_ALE)
 | 
	
		
			
				|  |  | +			balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLALE;
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +			balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLALE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (balloon3_ctl_clr)
 | 
	
		
			
				|  |  | +			__raw_writel(balloon3_ctl_clr,
 | 
	
		
			
				|  |  | +				BALLOON3_NAND_CONTROL_REG);
 | 
	
		
			
				|  |  | +		if (balloon3_ctl_set)
 | 
	
		
			
				|  |  | +			__raw_writel(balloon3_ctl_set,
 | 
	
		
			
				|  |  | +				BALLOON3_NAND_CONTROL_REG +
 | 
	
		
			
				|  |  | +				BALLOON3_FPGA_SETnCLR);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (cmd != NAND_CMD_NONE)
 | 
	
		
			
				|  |  | +		writeb(cmd, this->IO_ADDR_W);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void balloon3_nand_select_chip(struct mtd_info *mtd, int chip)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (chip < 0 || chip > 3)
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Assert all nCE lines */
 | 
	
		
			
				|  |  | +	__raw_writew(
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3,
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Deassert correct nCE line */
 | 
	
		
			
				|  |  | +	__raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip,
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL_REG);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int balloon3_nand_dev_ready(struct mtd_info *mtd)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return __raw_readl(BALLOON3_NAND_STAT_REG) & BALLOON3_NAND_STAT_RNB;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int balloon3_nand_probe(struct platform_device *pdev)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	uint16_t ver;
 | 
	
		
			
				|  |  | +	int ret;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	__raw_writew(BALLOON3_NAND_CONTROL2_16BIT,
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL2_REG + BALLOON3_FPGA_SETnCLR);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	ver = __raw_readw(BALLOON3_FPGA_VER);
 | 
	
		
			
				|  |  | +	if (ver < 0x4f08)
 | 
	
		
			
				|  |  | +		pr_warn("The FPGA code, version 0x%04x, is too old. "
 | 
	
		
			
				|  |  | +			"NAND support might be broken in this version!", ver);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Power up the NAND chips */
 | 
	
		
			
				|  |  | +	ret = gpio_request(BALLOON3_GPIO_RUN_NAND, "NAND");
 | 
	
		
			
				|  |  | +	if (ret)
 | 
	
		
			
				|  |  | +		goto err1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	ret = gpio_direction_output(BALLOON3_GPIO_RUN_NAND, 1);
 | 
	
		
			
				|  |  | +	if (ret)
 | 
	
		
			
				|  |  | +		goto err2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	gpio_set_value(BALLOON3_GPIO_RUN_NAND, 1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Deassert all nCE lines and write protect line */
 | 
	
		
			
				|  |  | +	__raw_writel(
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL_FLWP,
 | 
	
		
			
				|  |  | +		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +err2:
 | 
	
		
			
				|  |  | +	gpio_free(BALLOON3_GPIO_RUN_NAND);
 | 
	
		
			
				|  |  | +err1:
 | 
	
		
			
				|  |  | +	return ret;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void balloon3_nand_remove(struct platform_device *pdev)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	/* Power down the NAND chips */
 | 
	
		
			
				|  |  | +	gpio_set_value(BALLOON3_GPIO_RUN_NAND, 0);
 | 
	
		
			
				|  |  | +	gpio_free(BALLOON3_GPIO_RUN_NAND);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static struct mtd_partition balloon3_partition_info[] = {
 | 
	
		
			
				|  |  | +	[0] = {
 | 
	
		
			
				|  |  | +		.name	= "Boot",
 | 
	
		
			
				|  |  | +		.offset	= 0,
 | 
	
		
			
				|  |  | +		.size	= SZ_4M,
 | 
	
		
			
				|  |  | +	},
 | 
	
		
			
				|  |  | +	[1] = {
 | 
	
		
			
				|  |  | +		.name	= "RootFS",
 | 
	
		
			
				|  |  | +		.offset	= MTDPART_OFS_APPEND,
 | 
	
		
			
				|  |  | +		.size	= MTDPART_SIZ_FULL
 |