diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/block/dwc_ahsata.c | 34 | ||||
| -rw-r--r-- | drivers/gpio/omap_gpio.c | 2 | ||||
| -rw-r--r-- | drivers/gpio/s3c2440_gpio.c | 6 | ||||
| -rw-r--r-- | drivers/gpio/s5p_gpio.c | 9 | ||||
| -rw-r--r-- | drivers/i2c/s3c24x0_i2c.c | 3 | ||||
| -rw-r--r-- | drivers/net/fec_mxc.c | 23 | ||||
| -rw-r--r-- | drivers/power/battery/bat_trats.c | 13 | ||||
| -rw-r--r-- | drivers/power/power_core.c | 3 | ||||
| -rw-r--r-- | drivers/serial/serial_s5p.c | 78 | ||||
| -rw-r--r-- | drivers/spi/mxc_spi.c | 28 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-tegra.c | 300 | ||||
| -rw-r--r-- | drivers/usb/ulpi/omap-ulpi-viewport.c | 42 | ||||
| -rw-r--r-- | drivers/video/exynos_fimd.c | 3 | ||||
| -rw-r--r-- | drivers/video/mxsfb.c | 2 | 
14 files changed, 432 insertions, 114 deletions
| diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c index c9b71f7e1..98f2c52ee 100644 --- a/drivers/block/dwc_ahsata.c +++ b/drivers/block/dwc_ahsata.c @@ -447,10 +447,13 @@ static int ahci_exec_ata_cmd(struct ahci_probe_ent *probe_ent,  	if (buf && buf_len)  		sg_count = ahci_fill_sg(probe_ent, port, buf, buf_len);  	opts = (sizeof(struct sata_fis_h2d) >> 2) | (sg_count << 16); -	if (is_write) +	if (is_write) {  		opts |= 0x40; +		flush_cache((ulong)buf, buf_len); +	}  	ahci_fill_cmd_slot(pp, cmd_slot, opts); +	flush_cache((int)(pp->cmd_slot), AHCI_PORT_PRIV_DMA_SZ);  	writel_with_flush(1 << cmd_slot, &(port_mmio->ci));  	if (waiting_for_cmd_completed((u8 *)&(port_mmio->ci), @@ -458,8 +461,12 @@ static int ahci_exec_ata_cmd(struct ahci_probe_ent *probe_ent,  		printf("timeout exit!\n");  		return -1;  	} +	invalidate_dcache_range((int)(pp->cmd_slot), +				(int)(pp->cmd_slot)+AHCI_PORT_PRIV_DMA_SZ);  	debug("ahci_exec_ata_cmd: %d byte transferred.\n",  	      pp->cmd_slot->status); +	if (!is_write) +		invalidate_dcache_range((ulong)buf, (ulong)buf+buf_len);  	return buf_len;  } @@ -468,7 +475,8 @@ static void ahci_set_feature(u8 dev, u8 port)  {  	struct ahci_probe_ent *probe_ent =  		(struct ahci_probe_ent *)sata_dev_desc[dev].priv; -	struct sata_fis_h2d h2d, *cfis = &h2d; +	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); +	struct sata_fis_h2d *cfis = &h2d;  	memset(cfis, 0, sizeof(struct sata_fis_h2d));  	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D; @@ -615,7 +623,8 @@ static void dwc_ahsata_identify(int dev, u16 *id)  {  	struct ahci_probe_ent *probe_ent =  		(struct ahci_probe_ent *)sata_dev_desc[dev].priv; -	struct sata_fis_h2d h2d, *cfis = &h2d; +	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); +	struct sata_fis_h2d *cfis = &h2d;  	u8 port = probe_ent->hard_port_no;  	memset(cfis, 0, sizeof(struct sata_fis_h2d)); @@ -645,7 +654,8 @@ static u32 dwc_ahsata_rw_cmd(int dev, u32 start, u32 blkcnt,  {  	struct ahci_probe_ent *probe_ent =  		(struct ahci_probe_ent *)sata_dev_desc[dev].priv; -	struct sata_fis_h2d h2d, *cfis = &h2d; +	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); +	struct sata_fis_h2d *cfis = &h2d;  	u8 port = probe_ent->hard_port_no;  	u32 block; @@ -675,7 +685,8 @@ void dwc_ahsata_flush_cache(int dev)  {  	struct ahci_probe_ent *probe_ent =  		(struct ahci_probe_ent *)sata_dev_desc[dev].priv; -	struct sata_fis_h2d h2d, *cfis = &h2d; +	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); +	struct sata_fis_h2d *cfis = &h2d;  	u8 port = probe_ent->hard_port_no;  	memset(cfis, 0, sizeof(struct sata_fis_h2d)); @@ -692,7 +703,8 @@ static u32 dwc_ahsata_rw_cmd_ext(int dev, u32 start, lbaint_t blkcnt,  {  	struct ahci_probe_ent *probe_ent =  		(struct ahci_probe_ent *)sata_dev_desc[dev].priv; -	struct sata_fis_h2d h2d, *cfis = &h2d; +	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); +	struct sata_fis_h2d *cfis = &h2d;  	u8 port = probe_ent->hard_port_no;  	u64 block; @@ -728,7 +740,8 @@ u32 dwc_ahsata_rw_ncq_cmd(int dev, u32 start, lbaint_t blkcnt,  {  	struct ahci_probe_ent *probe_ent =  		(struct ahci_probe_ent *)sata_dev_desc[dev].priv; -	struct sata_fis_h2d h2d, *cfis = &h2d; +	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); +	struct sata_fis_h2d *cfis = &h2d;  	u8 port = probe_ent->hard_port_no;  	u64 block; @@ -769,7 +782,8 @@ void dwc_ahsata_flush_cache_ext(int dev)  {  	struct ahci_probe_ent *probe_ent =  		(struct ahci_probe_ent *)sata_dev_desc[dev].priv; -	struct sata_fis_h2d h2d, *cfis = &h2d; +	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN); +	struct sata_fis_h2d *cfis = &h2d;  	u8 port = probe_ent->hard_port_no;  	memset(cfis, 0, sizeof(struct sata_fis_h2d)); @@ -912,7 +926,9 @@ int scan_sata(int dev)  	u8 port = probe_ent->hard_port_no;  	block_dev_desc_t *pdev = &(sata_dev_desc[dev]); -	id = (u16 *)malloc(ATA_ID_WORDS * 2); +	id = (u16 *)memalign(ARCH_DMA_MINALIGN, +				roundup(ARCH_DMA_MINALIGN, +					(ATA_ID_WORDS * 2)));  	if (!id) {  		printf("id malloc failed\n\r");  		return -1; diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index a30d7f060..f16e9ae4d 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -55,7 +55,7 @@ static inline int get_gpio_index(int gpio)  int gpio_is_valid(int gpio)  { -	return (gpio >= 0) && (gpio < 192); +	return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);  }  static int check_gpio(int gpio) diff --git a/drivers/gpio/s3c2440_gpio.c b/drivers/gpio/s3c2440_gpio.c index 43bbf1160..09b04eb94 100644 --- a/drivers/gpio/s3c2440_gpio.c +++ b/drivers/gpio/s3c2440_gpio.c @@ -61,7 +61,7 @@ int gpio_set_value(unsigned gpio, int value)  	else  		l &= ~bit; -	return writel(port, l); +	return writel(l, port);  }  int gpio_get_value(unsigned gpio) @@ -85,11 +85,11 @@ int gpio_free(unsigned gpio)  int gpio_direction_input(unsigned gpio)  { -	return writel(GPIO_FULLPORT(gpio), GPIO_INPUT << GPIO_BIT(gpio)); +	return writel(GPIO_INPUT << GPIO_BIT(gpio), GPIO_FULLPORT(gpio));  }  int gpio_direction_output(unsigned gpio, int value)  { -	writel(GPIO_FULLPORT(gpio), GPIO_OUTPUT << GPIO_BIT(gpio)); +	writel(GPIO_OUTPUT << GPIO_BIT(gpio), GPIO_FULLPORT(gpio));  	return gpio_set_value(gpio, value);  } diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c index 656bf4a06..4efb76855 100644 --- a/drivers/gpio/s5p_gpio.c +++ b/drivers/gpio/s5p_gpio.c @@ -48,15 +48,8 @@ void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)  void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en)  { -	unsigned int value; -  	s5p_gpio_cfg_pin(bank, gpio, GPIO_OUTPUT); - -	value = readl(&bank->dat); -	value &= ~DAT_MASK(gpio); -	if (en) -		value |= DAT_SET(gpio); -	writel(value, &bank->dat); +	s5p_gpio_set_value(bank, gpio, en);  }  void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio) diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index 46d25061e..382e4c2ec 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -518,8 +518,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)  #ifdef CONFIG_OF_CONTROL  void board_i2c_init(const void *blob)  { +	int i;  	int node_list[CONFIG_MAX_I2C_NUM]; -	int count, i; +	int count;  	count = fdtdec_find_aliases_for_id(blob, "i2c",  		COMPAT_SAMSUNG_S3C2440_I2C, node_list, diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index da95e285b..ec5b9db66 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -560,7 +560,6 @@ static int fec_init(struct eth_device *dev, bd_t* bd)  		}  		memset(fec->tbd_base, 0, size);  		fec_tbd_init(fec); -		flush_dcache_range((unsigned)fec->tbd_base, size);  	}  	/* @@ -738,6 +737,28 @@ static int fec_send(struct eth_device *dev, void *packet, int length)  	flush_dcache_range(addr, addr + size);  	/* +	 * Below we read the DMA descriptor's last four bytes back from the +	 * DRAM. This is important in order to make sure that all WRITE +	 * operations on the bus that were triggered by previous cache FLUSH +	 * have completed. +	 * +	 * Otherwise, on MX28, it is possible to observe a corruption of the +	 * DMA descriptors. Please refer to schematic "Figure 1-2" in MX28RM +	 * for the bus structure of MX28. The scenario is as follows: +	 * +	 * 1) ARM core triggers a series of WRITEs on the AHB_ARB2 bus going +	 *    to DRAM due to flush_dcache_range() +	 * 2) ARM core writes the FEC registers via AHB_ARB2 +	 * 3) FEC DMA starts reading/writing from/to DRAM via AHB_ARB3 +	 * +	 * Note that 2) does sometimes finish before 1) due to reordering of +	 * WRITE accesses on the AHB bus, therefore triggering 3) before the +	 * DMA descriptor is fully written into DRAM. This results in occasional +	 * corruption of the DMA descriptor. +	 */ +	readl(addr + size - 4); + +	/*  	 * Enable SmartDMA transmit task  	 */  	fec_tx_task_enable(fec); diff --git a/drivers/power/battery/bat_trats.c b/drivers/power/battery/bat_trats.c index ca0d21465..97a966115 100644 --- a/drivers/power/battery/bat_trats.c +++ b/drivers/power/battery/bat_trats.c @@ -41,18 +41,23 @@ static int power_battery_charge(struct pmic *bat)  	for (k = 0; bat->chrg->chrg_bat_present(p_bat->chrg) &&  		     bat->chrg->chrg_type(p_bat->muic) &&  		     battery->state_of_chrg < 100; k++) { -		udelay(10000000); -		puts("."); +		udelay(2000000); +		if (!(k % 5)) +			puts(".");  		bat->fg->fg_battery_update(p_bat->fg, bat); -		if (k == 100) { +		if (k == 200) {  			debug(" %d [V]", battery->voltage_uV);  			puts("\n");  			k = 0;  		} +		if (ctrlc()) { +			printf("\nCharging disabled on request.\n"); +			goto exit; +		}  	} - + exit:  	bat->chrg->chrg_state(p_bat->chrg, CHARGER_DISABLE, 0);  	return 0; diff --git a/drivers/power/power_core.c b/drivers/power/power_core.c index 90df2c58c..f16b9dc06 100644 --- a/drivers/power/power_core.c +++ b/drivers/power/power_core.c @@ -205,7 +205,8 @@ int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		if (strcmp(argv[3], "charge") == 0) {  			if (p->pbat) { -				printf("PRINT BAT charge %s\n", p->name); +				printf("BAT: %s charging (ctrl+c to break)\n", +				       p->name);  				if (p->low_power_mode)  					p->low_power_mode();  				if (p->pbat->battery_charge) diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c index e65125ccd..6836c7a22 100644 --- a/drivers/serial/serial_s5p.c +++ b/drivers/serial/serial_s5p.c @@ -22,6 +22,7 @@   */  #include <common.h> +#include <fdtdec.h>  #include <linux/compiler.h>  #include <asm/io.h>  #include <asm/arch/uart.h> @@ -34,10 +35,21 @@ DECLARE_GLOBAL_DATA_PTR;  #define RX_FIFO_FULL_MASK	(1 << 8)  #define TX_FIFO_FULL_MASK	(1 << 24) +/* Information about a serial port */ +struct fdt_serial { +	u32 base_addr;  /* address of registers in physical memory */ +	u8 port_id;     /* uart port number */ +	u8 enabled;     /* 1 if enabled, 0 if disabled */ +} config __attribute__ ((section(".data"))); +  static inline struct s5p_uart *s5p_get_base_uart(int dev_index)  { +#ifdef CONFIG_OF_CONTROL +	return (struct s5p_uart *)(config.base_addr); +#else  	u32 offset = dev_index * sizeof(struct s5p_uart);  	return (struct s5p_uart *)(samsung_get_base_uart() + offset); +#endif  }  /* @@ -73,6 +85,16 @@ void serial_setbrg_dev(const int dev_index)  	u32 baudrate = gd->baudrate;  	u32 val; +#if defined(CONFIG_SILENT_CONSOLE) && \ +		defined(CONFIG_OF_CONTROL) && \ +		!defined(CONFIG_SPL_BUILD) +	if (fdtdec_get_config_int(gd->fdt_blob, "silent_console", 0)) +		gd->flags |= GD_FLG_SILENT; +#endif + +	if (!config.enabled) +		return; +  	val = uclk / baudrate;  	writel(val / 16 - 1, &uart->ubrdiv); @@ -133,6 +155,9 @@ int serial_getc_dev(const int dev_index)  {  	struct s5p_uart *const uart = s5p_get_base_uart(dev_index); +	if (!config.enabled) +		return 0; +  	/* wait for character to arrive */  	while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |  					 RX_FIFO_FULL_MASK))) { @@ -150,6 +175,9 @@ void serial_putc_dev(const char c, const int dev_index)  {  	struct s5p_uart *const uart = s5p_get_base_uart(dev_index); +	if (!config.enabled) +		return; +  	/* wait for room in the tx FIFO */  	while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {  		if (serial_err_check(dev_index, 1)) @@ -170,6 +198,9 @@ int serial_tstc_dev(const int dev_index)  {  	struct s5p_uart *const uart = s5p_get_base_uart(dev_index); +	if (!config.enabled) +		return 0; +  	return (int)(readl(&uart->utrstat) & 0x1);  } @@ -212,8 +243,54 @@ DECLARE_S5P_SERIAL_FUNCTIONS(3);  struct serial_device s5p_serial3_device =  	INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3"); +#ifdef CONFIG_OF_CONTROL +int fdtdec_decode_console(int *index, struct fdt_serial *uart) +{ +	const void *blob = gd->fdt_blob; +	int node; + +	node = fdt_path_offset(blob, "console"); +	if (node < 0) +		return node; + +	uart->base_addr = fdtdec_get_addr(blob, node, "reg"); +	if (uart->base_addr == FDT_ADDR_T_NONE) +		return -FDT_ERR_NOTFOUND; + +	uart->port_id = fdtdec_get_int(blob, node, "id", -1); +	uart->enabled = fdtdec_get_is_enabled(blob, node); + +	return 0; +} +#endif +  __weak struct serial_device *default_serial_console(void)  { +#ifdef CONFIG_OF_CONTROL +	int index = 0; + +	if ((!config.base_addr) && (fdtdec_decode_console(&index, &config))) { +		debug("Cannot decode default console node\n"); +		return NULL; +	} + +	switch (config.port_id) { +	case 0: +		return &s5p_serial0_device; +	case 1: +		return &s5p_serial1_device; +	case 2: +		return &s5p_serial2_device; +	case 3: +		return &s5p_serial3_device; +	default: +		debug("Unknown config.port_id: %d", config.port_id); +		break; +	} + +	return NULL; +#else +	config.enabled = 1;  #if defined(CONFIG_SERIAL0)  	return &s5p_serial0_device;  #elif defined(CONFIG_SERIAL1) @@ -225,6 +302,7 @@ __weak struct serial_device *default_serial_console(void)  #else  #error "CONFIG_SERIAL? missing."  #endif +#endif  }  void s5p_serial_initialize(void) diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index 2ea322833..9c68d7d29 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -128,8 +128,8 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,  		unsigned int max_hz, unsigned int mode)  {  	u32 clk_src = mxc_get_clock(MXC_CSPI_CLK); -	s32 pre_div = 0, post_div = 0, i, reg_ctrl, reg_config; -	u32 ss_pol = 0, sclkpol = 0, sclkpha = 0; +	s32 reg_ctrl, reg_config; +	u32 ss_pol = 0, sclkpol = 0, sclkpha = 0, pre_div = 0, post_div = 0;  	struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;  	if (max_hz == 0) { @@ -147,26 +147,20 @@ static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,  	reg_ctrl |=  MXC_CSPICTRL_EN;  	reg_write(®s->ctrl, reg_ctrl); -	/* -	 * The following computation is taken directly from Freescale's code. -	 */  	if (clk_src > max_hz) { -		pre_div = DIV_ROUND_UP(clk_src, max_hz); -		if (pre_div > 16) { -			post_div = pre_div / 16; -			pre_div = 15; -		} -		if (post_div != 0) { -			for (i = 0; i < 16; i++) { -				if ((1 << i) >= post_div) -					break; -			} -			if (i == 16) { +		pre_div = (clk_src - 1) / max_hz; +		/* fls(1) = 1, fls(0x80000000) = 32, fls(16) = 5 */ +		post_div = fls(pre_div); +		if (post_div > 4) { +			post_div -= 4; +			if (post_div >= 16) {  				printf("Error: no divider for the freq: %d\n",  					max_hz);  				return -1;  			} -			post_div = i; +			pre_div >>= post_div; +		} else { +			post_div = 0;  		}  	} diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 554145a25..a9603bc10 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -1,6 +1,6 @@  /*   * Copyright (c) 2011 The Chromium OS Authors. - * Copyright (c) 2009-2012 NVIDIA Corporation + * Copyright (c) 2009-2013 NVIDIA Corporation   * Copyright (c) 2013 Lucas Stach   *   * See file CREDITS for list of people who contributed to this @@ -28,6 +28,8 @@  #include <asm-generic/gpio.h>  #include <asm/arch/clock.h>  #include <asm/arch-tegra/usb.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch/usb.h>  #include <usb.h>  #include <usb/ulpi.h>  #include <libfdt.h> @@ -35,6 +37,11 @@  #include "ehci.h" +#define USB1_ADDR_MASK	0xFFFF0000 + +#define HOSTPC1_DEVLC	0x84 +#define HOSTPC1_PSPD(x)		(((x) >> 25) & 0x3) +  #ifdef CONFIG_USB_ULPI  	#ifndef CONFIG_USB_ULPI_VIEWPORT  	#error	"To use CONFIG_USB_ULPI on Tegra Boards you have to also \ @@ -87,6 +94,8 @@ struct fdt_usb {  static struct fdt_usb port[USB_PORTS_MAX];	/* List of valid USB ports */  static unsigned port_count;			/* Number of available ports */ +/* Port that needs to clear CSC after Port Reset */ +static u32 port_addr_clear_csc;  /*   * This table has USB timing parameters for each Oscillator frequency we @@ -129,7 +138,7 @@ static unsigned port_count;			/* Number of available ports */   *   * 4. The 20 microsecond delay after bias cell operation.   */ -static const unsigned usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { +static const unsigned T20_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = {  	/* DivN, DivM, DivP, CPCON, LFCON, Delays             Debounce, Bias */  	{ 0x3C0, 0x0D, 0x00, 0xC,   0,  0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 },  	{ 0x0C8, 0x04, 0x00, 0x3,   0,  0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, @@ -137,6 +146,22 @@ static const unsigned usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = {  	{ 0x3C0, 0x1A, 0x00, 0xC,   0,  0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 }  }; +static const unsigned T30_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { +	/* DivN, DivM, DivP, CPCON, LFCON, Delays             Debounce, Bias */ +	{ 0x3C0, 0x0D, 0x00, 0xC,   1,  0x02, 0x33, 0x09, 0x7F, 0x7EF4, 5 }, +	{ 0x0C8, 0x04, 0x00, 0x3,   0,  0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 7 }, +	{ 0x3C0, 0x0C, 0x00, 0xC,   1,  0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, +	{ 0x3C0, 0x1A, 0x00, 0xC,   1,  0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } +}; + +static const unsigned T114_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { +	/* DivN, DivM, DivP, CPCON, LFCON, Delays             Debounce, Bias */ +	{ 0x3C0, 0x0D, 0x00, 0xC,   2,  0x02, 0x33, 0x09, 0x7F, 0x7EF4, 6 }, +	{ 0x0C8, 0x04, 0x00, 0x3,   2,  0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 8 }, +	{ 0x3C0, 0x0C, 0x00, 0xC,   2,  0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, +	{ 0x3C0, 0x1A, 0x00, 0xC,   2,  0x04, 0x66, 0x09, 0xFE, 0xFDE8, 0xB } +}; +  /* UTMIP Idle Wait Delay */  static const u8 utmip_idle_wait_delay = 17; @@ -146,6 +171,33 @@ static const u8 utmip_elastic_limit = 16;  /* UTMIP High Speed Sync Start Delay */  static const u8 utmip_hs_sync_start_delay = 9; +struct fdt_usb_controller { +	int compat; +	/* flag to determine whether controller supports hostpc register */ +	u32 has_hostpc:1; +	const unsigned *pll_parameter; +}; + +static struct fdt_usb_controller fdt_usb_controllers[] = { +	{ +		.compat		= COMPAT_NVIDIA_TEGRA20_USB, +		.has_hostpc	= 0, +		.pll_parameter	= (const unsigned *)T20_usb_pll, +	}, +	{ +		.compat		= COMPAT_NVIDIA_TEGRA30_USB, +		.has_hostpc	= 1, +		.pll_parameter	= (const unsigned *)T30_usb_pll, +	}, +	{ +		.compat		= COMPAT_NVIDIA_TEGRA114_USB, +		.has_hostpc	= 1, +		.pll_parameter	= (const unsigned *)T114_usb_pll, +	}, +}; + +static struct fdt_usb_controller *controller; +  /*   * A known hardware issue where Connect Status Change bit of PORTSC register   * of USB1 controller will be set after Port Reset. @@ -156,13 +208,52 @@ static const u8 utmip_hs_sync_start_delay = 9;  void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)  {  	mdelay(50); -	if (((u32) status_reg & TEGRA_USB_ADDR_MASK) != TEGRA_USB1_BASE) +	/* This is to avoid PORT_ENABLE bit to be cleared in "ehci-hcd.c". */ +	if (controller->has_hostpc) +		*reg |= EHCI_PS_PE; + +	if (((u32)status_reg & TEGRA_USB_ADDR_MASK) != port_addr_clear_csc)  		return;  	/* For EHCI_PS_CSC to be cleared in ehci_hcd.c */  	if (ehci_readl(status_reg) & EHCI_PS_CSC)  		*reg |= EHCI_PS_CSC;  } +/* + * This ehci_set_usbmode overrides the weak function ehci_set_usbmode + * in "ehci-hcd.c". + */ +void ehci_set_usbmode(int index) +{ +	struct fdt_usb *config; +	struct usb_ctlr *usbctlr; +	uint32_t tmp; + +	config = &port[index]; +	usbctlr = config->reg; + +	tmp = ehci_readl(&usbctlr->usb_mode); +	tmp |= USBMODE_CM_HC; +	ehci_writel(&usbctlr->usb_mode, tmp); +} + +/* + * This ehci_get_port_speed overrides the weak function ehci_get_port_speed + * in "ehci-hcd.c". + */ +int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) +{ +	uint32_t tmp; +	uint32_t *reg_ptr; + +	if (controller->has_hostpc) { +		reg_ptr = (uint32_t *)((u8 *)&hcor->or_usbcmd + HOSTPC1_DEVLC); +		tmp = ehci_readl(reg_ptr); +		return HOSTPC1_PSPD(tmp); +	} else +		return PORTSC_PSPD(reg); +} +  /* Put the port into host mode */  static void set_host_mode(struct fdt_usb *config)  { @@ -209,6 +300,16 @@ void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr)  		setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB);  } +static const unsigned *get_pll_timing(void) +{ +	const unsigned *timing; + +	timing = controller->pll_parameter + +		clock_get_osc_freq() * PARAM_COUNT; + +	return timing; +} +  /* set up the UTMI USB controller with the parameters provided */  static int init_utmi_usb_controller(struct fdt_usb *config)  { @@ -216,6 +317,8 @@ static int init_utmi_usb_controller(struct fdt_usb *config)  	int loop_count;  	const unsigned *timing;  	struct usb_ctlr *usbctlr = config->reg; +	struct clk_rst_ctlr *clkrst; +	struct usb_ctlr *usb1ctlr;  	clock_enable(config->periph_id); @@ -232,35 +335,97 @@ static int init_utmi_usb_controller(struct fdt_usb *config)  	 * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP  	 * mux must be switched to actually use a_sess_vld threshold.  	 */ -	if (fdt_gpio_isvalid(&config->vbus_gpio)) { +	if (config->dr_mode == DR_MODE_OTG && +	    fdt_gpio_isvalid(&config->vbus_gpio))  		clrsetbits_le32(&usbctlr->usb1_legacy_ctrl,  			VBUS_SENSE_CTL_MASK,  			VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); -	}  	/*  	 * PLL Delay CONFIGURATION settings. The following parameters control  	 * the bring up of the plls.  	 */ -	timing = usb_pll[clock_get_osc_freq()]; +	timing = get_pll_timing(); + +	if (!controller->has_hostpc) { +		val = readl(&usbctlr->utmip_misc_cfg1); +		clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, +				timing[PARAM_STABLE_COUNT] << +				UTMIP_PLLU_STABLE_COUNT_SHIFT); +		clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, +				timing[PARAM_ACTIVE_DELAY_COUNT] << +				UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); +		writel(val, &usbctlr->utmip_misc_cfg1); + +		/* Set PLL enable delay count and crystal frequency count */ +		val = readl(&usbctlr->utmip_pll_cfg1); +		clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, +				timing[PARAM_ENABLE_DELAY_COUNT] << +				UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); +		clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, +				timing[PARAM_XTAL_FREQ_COUNT] << +				UTMIP_XTAL_FREQ_COUNT_SHIFT); +		writel(val, &usbctlr->utmip_pll_cfg1); +	} else { +		clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + +		val = readl(&clkrst->crc_utmip_pll_cfg2); +		clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, +				timing[PARAM_STABLE_COUNT] << +				UTMIP_PLLU_STABLE_COUNT_SHIFT); +		clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, +				timing[PARAM_ACTIVE_DELAY_COUNT] << +				UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); +		writel(val, &clkrst->crc_utmip_pll_cfg2); + +		/* Set PLL enable delay count and crystal frequency count */ +		val = readl(&clkrst->crc_utmip_pll_cfg1); +		clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, +				timing[PARAM_ENABLE_DELAY_COUNT] << +				UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); +		clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, +				timing[PARAM_XTAL_FREQ_COUNT] << +				UTMIP_XTAL_FREQ_COUNT_SHIFT); +		writel(val, &clkrst->crc_utmip_pll_cfg1); -	val = readl(&usbctlr->utmip_misc_cfg1); -	clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, -		timing[PARAM_STABLE_COUNT] << UTMIP_PLLU_STABLE_COUNT_SHIFT); -	clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, -		timing[PARAM_ACTIVE_DELAY_COUNT] << -			UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); -	writel(val, &usbctlr->utmip_misc_cfg1); +		/* Disable Power Down state for PLL */ +		clrbits_le32(&clkrst->crc_utmip_pll_cfg1, +			     PLLU_POWERDOWN | PLL_ENABLE_POWERDOWN | +			     PLL_ACTIVE_POWERDOWN); -	/* Set PLL enable delay count and crystal frequency count */ -	val = readl(&usbctlr->utmip_pll_cfg1); -	clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, -		timing[PARAM_ENABLE_DELAY_COUNT] << -			UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); -	clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, -		timing[PARAM_XTAL_FREQ_COUNT] << -			UTMIP_XTAL_FREQ_COUNT_SHIFT); -	writel(val, &usbctlr->utmip_pll_cfg1); +		/* Recommended PHY settings for EYE diagram */ +		val = readl(&usbctlr->utmip_xcvr_cfg0); +		clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MASK, +				0x4 << UTMIP_XCVR_SETUP_SHIFT); +		clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB_MASK, +				0x3 << UTMIP_XCVR_SETUP_MSB_SHIFT); +		clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB_MASK, +				0x8 << UTMIP_XCVR_HSSLEW_MSB_SHIFT); +		writel(val, &usbctlr->utmip_xcvr_cfg0); +		clrsetbits_le32(&usbctlr->utmip_xcvr_cfg1, +				UTMIP_XCVR_TERM_RANGE_ADJ_MASK, +				0x7 << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT); + +		/* Some registers can be controlled from USB1 only. */ +		if (config->periph_id != PERIPH_ID_USBD) { +			clock_enable(PERIPH_ID_USBD); +			/* Disable Reset if in Reset state */ +			reset_set_enable(PERIPH_ID_USBD, 0); +		} +		usb1ctlr = (struct usb_ctlr *) +			((u32)config->reg & USB1_ADDR_MASK); +		val = readl(&usb1ctlr->utmip_bias_cfg0); +		setbits_le32(&val, UTMIP_HSDISCON_LEVEL_MSB); +		clrsetbits_le32(&val, UTMIP_HSDISCON_LEVEL_MASK, +				0x1 << UTMIP_HSDISCON_LEVEL_SHIFT); +		clrsetbits_le32(&val, UTMIP_HSSQUELCH_LEVEL_MASK, +				0x2 << UTMIP_HSSQUELCH_LEVEL_SHIFT); +		writel(val, &usb1ctlr->utmip_bias_cfg0); + +		/* Miscellaneous setting mentioned in Programming Guide */ +		clrbits_le32(&usbctlr->utmip_misc_cfg0, +			     UTMIP_SUSPEND_EXIT_ON_EDGE); +	}  	/* Setting the tracking length time */  	clrsetbits_le32(&usbctlr->utmip_bias_cfg1, @@ -308,6 +473,14 @@ static int init_utmi_usb_controller(struct fdt_usb *config)  	/* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */  	setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); +	if (controller->has_hostpc) { +		if (config->periph_id == PERIPH_ID_USBD) +			clrbits_le32(&clkrst->crc_utmip_pll_cfg2, +				     UTMIP_FORCE_PD_SAMP_A_POWERDOWN); +		if (config->periph_id == PERIPH_ID_USB3) +			clrbits_le32(&clkrst->crc_utmip_pll_cfg2, +				     UTMIP_FORCE_PD_SAMP_C_POWERDOWN); +	}  	/* Finished the per-controller init. */  	/* De-assert UTMIP_RESET to bring out of reset. */ @@ -336,6 +509,18 @@ static int init_utmi_usb_controller(struct fdt_usb *config)  	clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN |  		UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); +	if (controller->has_hostpc) { +		/* +		 * BIAS Pad Power Down is common among all 3 USB +		 * controllers and can be controlled from USB1 only. +		 */ +		usb1ctlr = (struct usb_ctlr *) +			((u32)config->reg & USB1_ADDR_MASK); +		clrbits_le32(&usb1ctlr->utmip_bias_cfg0, UTMIP_BIASPD); +		udelay(25); +		clrbits_le32(&usb1ctlr->utmip_bias_cfg1, +			     UTMIP_FORCE_PDTRK_POWERDOWN); +	}  	return 0;  } @@ -438,7 +623,7 @@ static void config_clock(const u32 timing[])  		timing[PARAM_CPCON], timing[PARAM_LFCON]);  } -int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) +static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)  {  	const char *phy, *mode; @@ -466,6 +651,8 @@ int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)  	config->enabled = fdtdec_get_is_enabled(blob, node);  	config->has_legacy_mode = fdtdec_get_bool(blob, node,  						  "nvidia,has-legacy-mode"); +	if (config->has_legacy_mode) +		port_addr_clear_csc = (u32) config->reg;  	config->periph_id = clock_decode_periph_id(blob, node);  	if (config->periph_id == PERIPH_ID_NONE) {  		debug("%s: Missing/invalid peripheral ID\n", __func__); @@ -483,20 +670,22 @@ int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config)  	return 0;  } -int board_usb_init(const void *blob) +/* + * process_usb_nodes() - Process a list of USB nodes, adding them to our list + *			of USB ports. + * @blob:	fdt blob + * @node_list:	list of nodes to process (any <=0 are ignored) + * @count:	number of nodes to process + * + * Return:	0 - ok, -1 - error + */ +static int process_usb_nodes(const void *blob, int node_list[], int count)  {  	struct fdt_usb config; -	enum clock_osc_freq freq; -	int node_list[USB_PORTS_MAX]; -	int node, count, i; +	int node, i; +	int clk_done = 0; -	/* Set up the USB clocks correctly based on our oscillator frequency */ -	freq = clock_get_osc_freq(); -	config_clock(usb_pll[freq]); - -	/* count may return <0 on error */ -	count = fdtdec_find_aliases_for_id(blob, "usb", -			COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX); +	port_count = 0;  	for (i = 0; i < count; i++) {  		if (port_count == USB_PORTS_MAX) {  			printf("tegrausb: Cannot register more than %d ports\n", @@ -513,6 +702,10 @@ int board_usb_init(const void *blob)  			      fdt_get_name(blob, node, NULL));  			return -1;  		} +		if (!clk_done) { +			config_clock(get_pll_timing()); +			clk_done = 1; +		}  		config.initialized = 0;  		/* add new USB port to the list of available ports */ @@ -522,6 +715,31 @@ int board_usb_init(const void *blob)  	return 0;  } +int board_usb_init(const void *blob) +{ +	int node_list[USB_PORTS_MAX]; +	int count, err = 0; +	int i; + +	for (i = 0; i < ARRAY_SIZE(fdt_usb_controllers); i++) { +		controller = &fdt_usb_controllers[i]; + +		count = fdtdec_find_aliases_for_id(blob, "usb", +			controller->compat, node_list, USB_PORTS_MAX); +		if (count) { +			err = process_usb_nodes(blob, node_list, count); +			if (err) +				printf("%s: Error processing USB node!\n", +				       __func__); +			return err; +		} +	} +	if (i == ARRAY_SIZE(fdt_usb_controllers)) +		controller = NULL; + +	return err; +} +  /**   * Start up the given port number (ports are numbered from 0 on each board).   * This returns values for the appropriate hccr and hcor addresses to use for @@ -564,6 +782,20 @@ success:  	usbctlr = config->reg;  	*hccr = (struct ehci_hccr *)&usbctlr->cap_length;  	*hcor = (struct ehci_hcor *)&usbctlr->usb_cmd; + +	if (controller->has_hostpc) { +		/* Set to Host mode after Controller Reset was done */ +		clrsetbits_le32(&usbctlr->usb_mode, USBMODE_CM_HC, +				USBMODE_CM_HC); +		/* Select UTMI parallel interface after setting host mode */ +		if (config->utmi) { +			clrsetbits_le32((char *)&usbctlr->usb_cmd + +					HOSTPC1_DEVLC, PTS_MASK, +					PTS_UTMI << PTS_SHIFT); +			clrbits_le32((char *)&usbctlr->usb_cmd + +				     HOSTPC1_DEVLC, STS); +		} +	}  	return 0;  } diff --git a/drivers/usb/ulpi/omap-ulpi-viewport.c b/drivers/usb/ulpi/omap-ulpi-viewport.c index 3c1ea1a52..4db7fa43c 100644 --- a/drivers/usb/ulpi/omap-ulpi-viewport.c +++ b/drivers/usb/ulpi/omap-ulpi-viewport.c @@ -22,18 +22,19 @@  #include <asm/io.h>  #include <usb/ulpi.h> -#define OMAP_ULPI_WR_OPSEL	(3 << 21) -#define OMAP_ULPI_ACCESS	(1 << 31) +#define OMAP_ULPI_WR_OPSEL	(2 << 22) +#define OMAP_ULPI_RD_OPSEL	(3 << 22) +#define OMAP_ULPI_START		(1 << 31)  /* - * Wait for the ULPI Access to complete + * Wait for having ulpi in done state   */  static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask)  {  	int timeout = CONFIG_USB_ULPI_TIMEOUT;  	while (--timeout) { -		if ((readl(ulpi_vp->viewport_addr) & mask)) +		if (!(readl(ulpi_vp->viewport_addr) & mask))  			return 0;  		udelay(1); @@ -43,40 +44,15 @@ static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask)  }  /* - * Wake the ULPI PHY up for communication - * - * returns 0 on success. - */ -static int ulpi_wakeup(struct ulpi_viewport *ulpi_vp) -{ -	int err; - -	if (readl(ulpi_vp->viewport_addr) & OMAP_ULPI_ACCESS) -		return 0; /* already awake */ - -	writel(OMAP_ULPI_ACCESS, ulpi_vp->viewport_addr); - -	err = ulpi_wait(ulpi_vp, OMAP_ULPI_ACCESS); -	if (err) -		debug("ULPI wakeup timed out\n"); - -	return err; -} - -/*   * Issue a ULPI read/write request   */  static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value)  {  	int err; -	err = ulpi_wakeup(ulpi_vp); -	if (err) -		return err; -  	writel(value, ulpi_vp->viewport_addr); -	err = ulpi_wait(ulpi_vp, OMAP_ULPI_ACCESS); +	err = ulpi_wait(ulpi_vp, OMAP_ULPI_START);  	if (err)  		debug("ULPI request timed out\n"); @@ -85,7 +61,7 @@ static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value)  int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value)  { -	u32 val = ((ulpi_vp->port_num & 0xf) << 24) | +	u32 val = OMAP_ULPI_START | (((ulpi_vp->port_num + 1) & 0xf) << 24) |  			OMAP_ULPI_WR_OPSEL | ((u32)reg << 16) | (value & 0xff);  	return ulpi_request(ulpi_vp, val); @@ -94,8 +70,8 @@ int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value)  u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg)  {  	int err; -	u32 val = ((ulpi_vp->port_num & 0xf) << 24) | -			 OMAP_ULPI_WR_OPSEL | ((u32)reg << 16); +	u32 val = OMAP_ULPI_START | (((ulpi_vp->port_num + 1) & 0xf) << 24) | +			 OMAP_ULPI_RD_OPSEL | ((u32)reg << 16);  	err = ulpi_request(ulpi_vp, val);  	if (err) diff --git a/drivers/video/exynos_fimd.c b/drivers/video/exynos_fimd.c index 33599499e..7243ea335 100644 --- a/drivers/video/exynos_fimd.c +++ b/drivers/video/exynos_fimd.c @@ -280,8 +280,9 @@ void exynos_fimd_lcd_init(vidinfo_t *vid)  								node, "reg");  	if (fimd_ctrl == NULL)  		debug("Can't get the FIMD base address\n"); -#endif +#else  	fimd_ctrl = (struct exynos_fb *)samsung_get_base_fimd(); +#endif  	offset = exynos_fimd_get_base_offset(); diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index b18941935..b0f7ef8d4 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -137,7 +137,7 @@ void *video_hw_init(void)  	/* Suck display configuration from "videomode" variable */  	penv = getenv("videomode");  	if (!penv) { -		printf("MXSFB: 'videomode' variable not set!"); +		puts("MXSFB: 'videomode' variable not set!\n");  		return NULL;  	} |