279 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright (C) 2006, 2008 Atmel Corporation
 | |
|  *
 | |
|  * SPDX-License-Identifier:	GPL-2.0+
 | |
|  */
 | |
| #include <common.h>
 | |
| 
 | |
| #include <asm/io.h>
 | |
| 
 | |
| #include <asm/arch/chip-features.h>
 | |
| #include <asm/arch/hardware.h>
 | |
| #include <asm/arch/portmux.h>
 | |
| 
 | |
| /*
 | |
|  * Lots of small functions here. We depend on --gc-sections getting
 | |
|  * rid of the ones we don't need.
 | |
|  */
 | |
| void portmux_enable_ebi(unsigned int bus_width, unsigned int addr_width,
 | |
| 		unsigned long flags, unsigned long drive_strength)
 | |
| {
 | |
| 	unsigned long porte_mask = 0;
 | |
| 
 | |
| 	if (bus_width > 16)
 | |
| 		portmux_select_peripheral(PORTMUX_PORT_E, 0xffff,
 | |
| 				PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
 | |
| 	if (addr_width > 23)
 | |
| 		porte_mask |= (((1 << (addr_width - 23)) - 1) & 7) << 16;
 | |
| 	if (flags & PORTMUX_EBI_CS(2))
 | |
| 		porte_mask |= 1 << 25;
 | |
| 	if (flags & PORTMUX_EBI_CS(4))
 | |
| 		porte_mask |= 1 << 21;
 | |
| 	if (flags & PORTMUX_EBI_CS(5))
 | |
| 		porte_mask |= 1 << 22;
 | |
| 	if (flags & (PORTMUX_EBI_CF(0) | PORTMUX_EBI_CF(1)))
 | |
| 		porte_mask |= (1 << 19) | (1 << 20) | (1 << 23);
 | |
| 
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_E, porte_mask,
 | |
| 			PORTMUX_FUNC_A, 0);
 | |
| 
 | |
| 	if (flags & PORTMUX_EBI_NWAIT)
 | |
| 		portmux_select_peripheral(PORTMUX_PORT_E, 1 << 24,
 | |
| 				PORTMUX_FUNC_A, PORTMUX_PULL_UP);
 | |
| }
 | |
| 
 | |
| #ifdef AT32AP700x_CHIP_HAS_MACB
 | |
| void portmux_enable_macb0(unsigned long flags, unsigned long drive_strength)
 | |
| {
 | |
| 	unsigned long portc_mask;
 | |
| 
 | |
| 	portc_mask = (1 << 3)	/* TXD0	*/
 | |
| 		| (1 << 4)	/* TXD1	*/
 | |
| 		| (1 << 7)	/* TXEN	*/
 | |
| 		| (1 << 8)	/* TXCK */
 | |
| 		| (1 << 9)	/* RXD0	*/
 | |
| 		| (1 << 10)	/* RXD1	*/
 | |
| 		| (1 << 13)	/* RXER	*/
 | |
| 		| (1 << 15)	/* RXDV	*/
 | |
| 		| (1 << 16)	/* MDC	*/
 | |
| 		| (1 << 17);	/* MDIO	*/
 | |
| 
 | |
| 	if (flags & PORTMUX_MACB_MII)
 | |
| 		portc_mask |= (1 << 0)	/* COL	*/
 | |
| 			| (1 << 1)	/* CRS	*/
 | |
| 			| (1 << 2)	/* TXER	*/
 | |
| 			| (1 << 5)	/* TXD2	*/
 | |
| 			| (1 << 6)	/* TXD3 */
 | |
| 			| (1 << 11)	/* RXD2	*/
 | |
| 			| (1 << 12)	/* RXD3	*/
 | |
| 			| (1 << 14);	/* RXCK	*/
 | |
| 
 | |
| 	if (flags & PORTMUX_MACB_SPEED)
 | |
| 		portc_mask |= (1 << 18);/* SPD	*/
 | |
| 
 | |
| 	/* REVISIT: Some pins are probably pure outputs */
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
 | |
| 			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
 | |
| }
 | |
| 
 | |
| void portmux_enable_macb1(unsigned long flags, unsigned long drive_strength)
 | |
| {
 | |
| 	unsigned long portc_mask = 0;
 | |
| 	unsigned long portd_mask;
 | |
| 
 | |
| 	portd_mask = (1 << 13)	/* TXD0	*/
 | |
| 		| (1 << 14)	/* TXD1	*/
 | |
| 		| (1 << 11)	/* TXEN	*/
 | |
| 		| (1 << 12)	/* TXCK */
 | |
| 		| (1 << 10)	/* RXD0	*/
 | |
| 		| (1 << 6)	/* RXD1	*/
 | |
| 		| (1 << 5)	/* RXER	*/
 | |
| 		| (1 << 4)	/* RXDV	*/
 | |
| 		| (1 << 3)	/* MDC	*/
 | |
| 		| (1 << 2);	/* MDIO	*/
 | |
| 
 | |
| 	if (flags & PORTMUX_MACB_MII)
 | |
| 		portc_mask = (1 << 19)	/* COL	*/
 | |
| 			| (1 << 23)	/* CRS	*/
 | |
| 			| (1 << 26)	/* TXER	*/
 | |
| 			| (1 << 27)	/* TXD2	*/
 | |
| 			| (1 << 28)	/* TXD3 */
 | |
| 			| (1 << 29)	/* RXD2	*/
 | |
| 			| (1 << 30)	/* RXD3	*/
 | |
| 			| (1 << 24);	/* RXCK	*/
 | |
| 
 | |
| 	if (flags & PORTMUX_MACB_SPEED)
 | |
| 		portd_mask |= (1 << 15);/* SPD	*/
 | |
| 
 | |
| 	/* REVISIT: Some pins are probably pure outputs */
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_D, portd_mask,
 | |
| 			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
 | |
| 			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef AT32AP700x_CHIP_HAS_MMCI
 | |
| void portmux_enable_mmci(unsigned int slot, unsigned long flags,
 | |
| 		unsigned long drive_strength)
 | |
| {
 | |
| 	unsigned long mask;
 | |
| 	unsigned long portmux_flags = PORTMUX_PULL_UP;
 | |
| 
 | |
| 	/* First, the common CLK signal. It doesn't need a pull-up */
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_A, 1 << 10,
 | |
| 			PORTMUX_FUNC_A, 0);
 | |
| 
 | |
| 	if (flags & PORTMUX_MMCI_EXT_PULLUP)
 | |
| 		portmux_flags = 0;
 | |
| 
 | |
| 	/* Then, the per-slot signals */
 | |
| 	switch (slot) {
 | |
| 	case 0:
 | |
| 		mask = (1 << 11) | (1 << 12);	/* CMD and DATA0 */
 | |
| 		if (flags & PORTMUX_MMCI_4BIT)
 | |
| 			/* DATA1..DATA3 */
 | |
| 			mask |= (1 << 13) | (1 << 14) | (1 << 15);
 | |
| 		portmux_select_peripheral(PORTMUX_PORT_A, mask,
 | |
| 				PORTMUX_FUNC_A, portmux_flags);
 | |
| 		break;
 | |
| 	case 1:
 | |
| 		mask = (1 << 6) | (1 << 7);	/* CMD and DATA0 */
 | |
| 		if (flags & PORTMUX_MMCI_4BIT)
 | |
| 			/* DATA1..DATA3 */
 | |
| 			mask |= (1 << 8) | (1 << 9) | (1 << 10);
 | |
| 		portmux_select_peripheral(PORTMUX_PORT_B, mask,
 | |
| 				PORTMUX_FUNC_B, portmux_flags);
 | |
| 		break;
 | |
| 	}
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef AT32AP700x_CHIP_HAS_SPI
 | |
| void portmux_enable_spi0(unsigned long cs_mask, unsigned long drive_strength)
 | |
| {
 | |
| 	unsigned long pin_mask;
 | |
| 
 | |
| 	/* MOSI and SCK */
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_A, (1 << 1) | (1 << 2),
 | |
| 			PORTMUX_FUNC_A, 0);
 | |
| 	/* MISO may float */
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_A, 1 << 0,
 | |
| 			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
 | |
| 
 | |
| 	/* Set up NPCSx as GPIO outputs, initially high */
 | |
| 	pin_mask = (cs_mask & 7) << 3;
 | |
| 	if (cs_mask & (1 << 3))
 | |
| 		pin_mask |= 1 << 20;
 | |
| 
 | |
| 	portmux_select_gpio(PORTMUX_PORT_A, pin_mask,
 | |
| 			PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
 | |
| }
 | |
| 
 | |
| void portmux_enable_spi1(unsigned long cs_mask, unsigned long drive_strength)
 | |
| {
 | |
| 	/* MOSI and SCK */
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_B, (1 << 1) | (1 << 5),
 | |
| 			PORTMUX_FUNC_B, 0);
 | |
| 	/* MISO may float */
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_B, 1 << 0,
 | |
| 			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
 | |
| 
 | |
| 	/* Set up NPCSx as GPIO outputs, initially high */
 | |
| 	portmux_select_gpio(PORTMUX_PORT_B, (cs_mask & 7) << 2,
 | |
| 			PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
 | |
| 	portmux_select_gpio(PORTMUX_PORT_A, (cs_mask & 8) << (27 - 3),
 | |
| 			PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef AT32AP700x_CHIP_HAS_LCDC
 | |
| void portmux_enable_lcdc(int pin_config)
 | |
| {
 | |
| 	unsigned long portc_mask = 0;
 | |
| 	unsigned long portd_mask = 0;
 | |
| 	unsigned long porte_mask = 0;
 | |
| 
 | |
| 	switch (pin_config) {
 | |
| 	case 0:
 | |
| 		portc_mask = (1 << 19)	/* CC     */
 | |
| 			| (1 << 20)	/* HSYNC  */
 | |
| 			| (1 << 21)	/* PCLK   */
 | |
| 			| (1 << 22)	/* VSYNC  */
 | |
| 			| (1 << 23)	/* DVAL   */
 | |
| 			| (1 << 24)	/* MODE   */
 | |
| 			| (1 << 25)	/* PWR    */
 | |
| 			| (1 << 26)	/* DATA0  */
 | |
| 			| (1 << 27)	/* DATA1  */
 | |
| 			| (1 << 28)	/* DATA2  */
 | |
| 			| (1 << 29)	/* DATA3  */
 | |
| 			| (1 << 30)	/* DATA4  */
 | |
| 			| (1 << 31);	/* DATA5  */
 | |
| 
 | |
| 		portd_mask = (1 << 0)	/* DATA6  */
 | |
| 			| (1 << 1)	/* DATA7  */
 | |
| 			| (1 << 2)	/* DATA8  */
 | |
| 			| (1 << 3)	/* DATA9  */
 | |
| 			| (1 << 4)	/* DATA10 */
 | |
| 			| (1 << 5)	/* DATA11 */
 | |
| 			| (1 << 6)	/* DATA12 */
 | |
| 			| (1 << 7)	/* DATA13 */
 | |
| 			| (1 << 8)	/* DATA14 */
 | |
| 			| (1 << 9)	/* DATA15 */
 | |
| 			| (1 << 10)	/* DATA16 */
 | |
| 			| (1 << 11)	/* DATA17 */
 | |
| 			| (1 << 12)	/* DATA18 */
 | |
| 			| (1 << 13)	/* DATA19 */
 | |
| 			| (1 << 14)	/* DATA20 */
 | |
| 			| (1 << 15)	/* DATA21 */
 | |
| 			| (1 << 16)	/* DATA22 */
 | |
| 			| (1 << 17);	/* DATA23 */
 | |
| 		break;
 | |
| 
 | |
| 	case 1:
 | |
| 		portc_mask = (1 << 20)	/* HSYNC  */
 | |
| 			| (1 << 21)	/* PCLK   */
 | |
| 			| (1 << 22)	/* VSYNC  */
 | |
| 			| (1 << 25)	/* PWR    */
 | |
| 			| (1 << 31);	/* DATA5  */
 | |
| 
 | |
| 		portd_mask = (1 << 0)	/* DATA6  */
 | |
| 			| (1 << 1)	/* DATA7  */
 | |
| 			| (1 << 7)	/* DATA13 */
 | |
| 			| (1 << 8)	/* DATA14 */
 | |
| 			| (1 << 9)	/* DATA15 */
 | |
| 			| (1 << 16)	/* DATA22 */
 | |
| 			| (1 << 17);	/* DATA23 */
 | |
| 
 | |
| 		porte_mask = (1 << 0)	/* CC     */
 | |
| 			| (1 << 1)	/* DVAL   */
 | |
| 			| (1 << 2)	/* MODE   */
 | |
| 			| (1 << 3)	/* DATA0  */
 | |
| 			| (1 << 4)	/* DATA1  */
 | |
| 			| (1 << 5)	/* DATA2  */
 | |
| 			| (1 << 6)	/* DATA3  */
 | |
| 			| (1 << 7)	/* DATA4  */
 | |
| 			| (1 << 8)	/* DATA8  */
 | |
| 			| (1 << 9)	/* DATA9  */
 | |
| 			| (1 << 10)	/* DATA10 */
 | |
| 			| (1 << 11)	/* DATA11 */
 | |
| 			| (1 << 12)	/* DATA12 */
 | |
| 			| (1 << 13)	/* DATA16 */
 | |
| 			| (1 << 14)	/* DATA17 */
 | |
| 			| (1 << 15)	/* DATA18 */
 | |
| 			| (1 << 16)	/* DATA19 */
 | |
| 			| (1 << 17)	/* DATA20 */
 | |
| 			| (1 << 18);	/* DATA21 */
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	/* REVISIT: Some pins are probably pure outputs */
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
 | |
| 			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_D, portd_mask,
 | |
| 			PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
 | |
| 	portmux_select_peripheral(PORTMUX_PORT_E, porte_mask,
 | |
| 			PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
 | |
| }
 | |
| #endif
 |