|  | @@ -1224,3 +1224,191 @@ at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned i
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  struct platform_device *__init
 | 
	
		
			
				|  |  | +at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct platform_device *pdev;
 | 
	
		
			
				|  |  | +	u32 pin_mask;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	switch (id) {
 | 
	
		
			
				|  |  | +	case 0:
 | 
	
		
			
				|  |  | +		pdev = &atmel_spi0_device;
 | 
	
		
			
				|  |  | +		pin_mask  = (1 << 1) | (1 << 2);	/* MOSI & SCK */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		/* pullup MISO so a level is always defined */
 | 
	
		
			
				|  |  | +		select_peripheral(PIOA, (1 << 0), PERIPH_A, AT32_GPIOF_PULLUP);
 | 
	
		
			
				|  |  | +		select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		at32_spi_setup_slaves(0, b, n);
 | 
	
		
			
				|  |  | +		break;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	case 1:
 | 
	
		
			
				|  |  | +		pdev = &atmel_spi1_device;
 | 
	
		
			
				|  |  | +		pin_mask  = (1 << 1) | (1 << 5);	/* MOSI */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		/* pullup MISO so a level is always defined */
 | 
	
		
			
				|  |  | +		select_peripheral(PIOB, (1 << 0), PERIPH_B, AT32_GPIOF_PULLUP);
 | 
	
		
			
				|  |  | +		select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		at32_spi_setup_slaves(1, b, n);
 | 
	
		
			
				|  |  | +		break;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	default:
 | 
	
		
			
				|  |  | +		return NULL;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	spi_register_board_info(b, n);
 | 
	
		
			
				|  |  | +	platform_device_register(pdev);
 | 
	
		
			
				|  |  | +	return pdev;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* --------------------------------------------------------------------
 | 
	
		
			
				|  |  | + *  TWI
 | 
	
		
			
				|  |  | + * -------------------------------------------------------------------- */
 | 
	
		
			
				|  |  | +static struct resource atmel_twi0_resource[] __initdata = {
 | 
	
		
			
				|  |  | +	PBMEM(0xffe00800),
 | 
	
		
			
				|  |  | +	IRQ(5),
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +static struct clk atmel_twi0_pclk = {
 | 
	
		
			
				|  |  | +	.name		= "twi_pclk",
 | 
	
		
			
				|  |  | +	.parent		= &pba_clk,
 | 
	
		
			
				|  |  | +	.mode		= pba_clk_mode,
 | 
	
		
			
				|  |  | +	.get_rate	= pba_clk_get_rate,
 | 
	
		
			
				|  |  | +	.index		= 2,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct platform_device *__init at32_add_device_twi(unsigned int id,
 | 
	
		
			
				|  |  | +						    struct i2c_board_info *b,
 | 
	
		
			
				|  |  | +						    unsigned int n)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct platform_device *pdev;
 | 
	
		
			
				|  |  | +	u32 pin_mask;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (id != 0)
 | 
	
		
			
				|  |  | +		return NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pdev = platform_device_alloc("atmel_twi", id);
 | 
	
		
			
				|  |  | +	if (!pdev)
 | 
	
		
			
				|  |  | +		return NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (platform_device_add_resources(pdev, atmel_twi0_resource,
 | 
	
		
			
				|  |  | +				ARRAY_SIZE(atmel_twi0_resource)))
 | 
	
		
			
				|  |  | +		goto err_add_resources;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pin_mask  = (1 << 6) | (1 << 7);	/* SDA & SDL */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	atmel_twi0_pclk.dev = &pdev->dev;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (b)
 | 
	
		
			
				|  |  | +		i2c_register_board_info(id, b, n);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	platform_device_add(pdev);
 | 
	
		
			
				|  |  | +	return pdev;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +err_add_resources:
 | 
	
		
			
				|  |  | +	platform_device_put(pdev);
 | 
	
		
			
				|  |  | +	return NULL;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* --------------------------------------------------------------------
 | 
	
		
			
				|  |  | + * MMC
 | 
	
		
			
				|  |  | + * -------------------------------------------------------------------- */
 | 
	
		
			
				|  |  | +static struct resource atmel_mci0_resource[] __initdata = {
 | 
	
		
			
				|  |  | +	PBMEM(0xfff02400),
 | 
	
		
			
				|  |  | +	IRQ(28),
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +static struct clk atmel_mci0_pclk = {
 | 
	
		
			
				|  |  | +	.name		= "mci_clk",
 | 
	
		
			
				|  |  | +	.parent		= &pbb_clk,
 | 
	
		
			
				|  |  | +	.mode		= pbb_clk_mode,
 | 
	
		
			
				|  |  | +	.get_rate	= pbb_clk_get_rate,
 | 
	
		
			
				|  |  | +	.index		= 9,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct platform_device *__init
 | 
	
		
			
				|  |  | +at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct platform_device		*pdev;
 | 
	
		
			
				|  |  | +	struct mci_dma_data	        *slave;
 | 
	
		
			
				|  |  | +	u32				pioa_mask;
 | 
	
		
			
				|  |  | +	u32				piob_mask;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (id != 0 || !data)
 | 
	
		
			
				|  |  | +		return NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Must have at least one usable slot */
 | 
	
		
			
				|  |  | +	if (!data->slot[0].bus_width && !data->slot[1].bus_width)
 | 
	
		
			
				|  |  | +		return NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pdev = platform_device_alloc("atmel_mci", id);
 | 
	
		
			
				|  |  | +	if (!pdev)
 | 
	
		
			
				|  |  | +		goto fail;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (platform_device_add_resources(pdev, atmel_mci0_resource,
 | 
	
		
			
				|  |  | +				ARRAY_SIZE(atmel_mci0_resource)))
 | 
	
		
			
				|  |  | +		goto fail;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	slave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
 | 
	
		
			
				|  |  | +	if (!slave)
 | 
	
		
			
				|  |  | +		goto fail;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	slave->sdata.dma_dev = &dw_dmac0_device.dev;
 | 
	
		
			
				|  |  | +	slave->sdata.cfg_hi = (DWC_CFGH_SRC_PER(0)
 | 
	
		
			
				|  |  | +				| DWC_CFGH_DST_PER(1));
 | 
	
		
			
				|  |  | +	slave->sdata.cfg_lo &= ~(DWC_CFGL_HS_DST_POL
 | 
	
		
			
				|  |  | +				| DWC_CFGL_HS_SRC_POL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	data->dma_slave = slave;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (platform_device_add_data(pdev, data,
 | 
	
		
			
				|  |  | +				sizeof(struct mci_platform_data)))
 | 
	
		
			
				|  |  | +		goto fail_free;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* CLK line is common to both slots */
 | 
	
		
			
				|  |  | +	pioa_mask = 1 << 10;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	switch (data->slot[0].bus_width) {
 | 
	
		
			
				|  |  | +	case 4:
 | 
	
		
			
				|  |  | +		pioa_mask |= 1 << 13;		/* DATA1 */
 | 
	
		
			
				|  |  | +		pioa_mask |= 1 << 14;		/* DATA2 */
 | 
	
		
			
				|  |  | +		pioa_mask |= 1 << 15;		/* DATA3 */
 | 
	
		
			
				|  |  | +		/* fall through */
 | 
	
		
			
				|  |  | +	case 1:
 | 
	
		
			
				|  |  | +		pioa_mask |= 1 << 11;		/* CMD	 */
 | 
	
		
			
				|  |  | +		pioa_mask |= 1 << 12;		/* DATA0 */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (gpio_is_valid(data->slot[0].detect_pin))
 | 
	
		
			
				|  |  | +			at32_select_gpio(data->slot[0].detect_pin, 0);
 | 
	
		
			
				|  |  | +		if (gpio_is_valid(data->slot[0].wp_pin))
 | 
	
		
			
				|  |  | +			at32_select_gpio(data->slot[0].wp_pin, 0);
 | 
	
		
			
				|  |  | +		break;
 | 
	
		
			
				|  |  | +	case 0:
 | 
	
		
			
				|  |  | +		/* Slot is unused */
 | 
	
		
			
				|  |  | +		break;
 | 
	
		
			
				|  |  | +	default:
 | 
	
		
			
				|  |  | +		goto fail_free;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	select_peripheral(PIOA, pioa_mask, PERIPH_A, 0);
 | 
	
		
			
				|  |  | +	piob_mask = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	switch (data->slot[1].bus_width) {
 | 
	
		
			
				|  |  | +	case 4:
 | 
	
		
			
				|  |  | +		piob_mask |= 1 <<  8;		/* DATA1 */
 | 
	
		
			
				|  |  | +		piob_mask |= 1 <<  9;		/* DATA2 */
 | 
	
		
			
				|  |  | +		piob_mask |= 1 << 10;		/* DATA3 */
 | 
	
		
			
				|  |  | +		/* fall through */
 | 
	
		
			
				|  |  | +	case 1:
 | 
	
		
			
				|  |  | +		piob_mask |= 1 <<  6;		/* CMD	 */
 | 
	
		
			
				|  |  | +		piob_mask |= 1 <<  7;		/* DATA0 */
 | 
	
		
			
				|  |  | +		select_peripheral(PIOB, piob_mask, PERIPH_B, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (gpio_is_valid(data->slot[1].detect_pin))
 | 
	
		
			
				|  |  | +			at32_select_gpio(data->slot[1].detect_pin, 0);
 | 
	
		
			
				|  |  | +		if (gpio_is_valid(data->slot[1].wp_pin))
 | 
	
		
			
				|  |  | +			at32_select_gpio(data->slot[1].wp_pin, 0);
 | 
	
		
			
				|  |  | +		break;
 | 
	
		
			
				|  |  | +	case 0:
 | 
	
		
			
				|  |  | +		/* Slot is unused */
 | 
	
		
			
				|  |  | +		break;
 |