diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/ahci_platform.c | 1 | ||||
-rw-r--r-- | drivers/ata/libahci.c | 9 | ||||
-rw-r--r-- | drivers/cpufreq/qoriq-cpufreq.c | 42 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 19 | ||||
-rw-r--r-- | drivers/mtd/spi-nor/fsl-quadspi.c | 8 | ||||
-rw-r--r-- | drivers/soc/fsl/ls1/ftm_alarm.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/fsl_lpuart.c | 27 | ||||
-rw-r--r-- | drivers/video/fsl-dcu-fb.c | 6 |
9 files changed, 93 insertions, 25 deletions
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 7d3b853..1da09c1 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -326,6 +326,7 @@ disable_unprepare_clk: static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); static const struct of_device_id ahci_of_match[] = { + { .compatible = "fsl,ls1021a-ahci", }, { .compatible = "snps,spear-ahci", }, { .compatible = "snps,exynos5440-ahci", }, {}, diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index cfb7447..689b5f8 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1426,15 +1426,19 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); struct ata_port *ap = link->ap; struct ahci_port_priv *pp = ap->private_data; + void __iomem *port_mmio = ahci_port_base(link->ap); u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; struct ata_taskfile tf; bool online; int rc; + u32 save_cmd, tmp; DPRINTK("ENTER\n"); ahci_stop_engine(ap); + save_cmd = readl(port_mmio + PORT_CMD); + /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(link->device, &tf); tf.command = ATA_BUSY; @@ -1443,6 +1447,11 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, rc = sata_link_hardreset(link, timing, deadline, &online, ahci_check_ready); + /* Revert the saved cmd value, if not match with original */ + tmp = readl(port_mmio + PORT_CMD); + if (tmp != save_cmd) + writel(save_cmd, port_mmio + PORT_CMD); + ahci_start_engine(ap); if (online) diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 16c1e7b..36b2e6e 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c @@ -25,12 +25,12 @@ /** * struct cpu_data - per CPU data struct * @clk: the clk of CPU - * @parent: the parent node of cpu clock + * @pclk: the parent clock of cpu * @table: frequency table */ struct cpu_data { struct clk *clk; - struct device_node *parent; + struct clk **pclk; struct cpufreq_frequency_table *table; }; @@ -205,7 +205,7 @@ static void set_affected_cpus(struct cpufreq_policy *policy) static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) { - struct device_node *np; + struct device_node *np, *pnode; int i, count, ret; u32 freq, mask; struct clk *clk; @@ -230,17 +230,23 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) goto err_nomem2; } - data->parent = of_parse_phandle(np, "clocks", 0); - if (!data->parent) { + pnode = of_parse_phandle(np, "clocks", 0); + if (!pnode) { pr_err("%s: could not get clock information\n", __func__); goto err_nomem2; } - count = of_property_count_strings(data->parent, "clock-names"); + count = of_property_count_strings(pnode, "clock-names"); + data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL); + if (!data->pclk) { + pr_err("%s: no memory\n", __func__); + goto err_node; + } + table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); if (!table) { pr_err("%s: no memory\n", __func__); - goto err_node; + goto err_pclk; } if (fmask) @@ -249,7 +255,8 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) mask = 0x0; for (i = 0; i < count; i++) { - clk = of_clk_get(data->parent, i); + clk = of_clk_get(pnode, i); + data->pclk[i] = clk; freq = clk_get_rate(clk); /* * the clock is valid if its frequency is not masked @@ -288,13 +295,16 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) cpufreq_frequency_table_get_attr(table, cpu); of_node_put(np); + of_node_put(pnode); return 0; err_nomem1: kfree(table); +err_pclk: + kfree(data->pclk); err_node: - of_node_put(data->parent); + of_node_put(pnode); err_nomem2: per_cpu(cpu_data, cpu) = NULL; kfree(data); @@ -309,7 +319,7 @@ static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) struct cpu_data *data = per_cpu(cpu_data, policy->cpu); cpufreq_frequency_table_put_attr(policy->cpu); - of_node_put(data->parent); + kfree(data->pclk); kfree(data->table); kfree(data); @@ -390,8 +400,8 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy, struct clk *parent; int ret; struct cpu_data *data = per_cpu(cpu_data, policy->cpu); -#if (defined(CONFIG_PPC) && defined(CONFIG_HOTPLUG_CPU)) int workaround = 0; +#if (defined(CONFIG_PPC) && defined(CONFIG_HOTPLUG_CPU)) /* * workaround should be applied on 2 conditions: @@ -417,15 +427,21 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy, mutex_lock(&cpufreq_lock); cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); - parent = of_clk_get(data->parent, data->table[new].driver_data); + parent = data->pclk[data->table[new].driver_data]; #if (defined(CONFIG_PPC) && defined(CONFIG_HOTPLUG_CPU)) - if (t4240_workaround == 1) { + if (workaround == 1) { freqs.new = freqs.old; ret = -1; } #endif + if (workaround == 0) { + ret = clk_set_parent(data->clk, parent); + if (ret) + ret = -1; + } + cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); mutex_unlock(&cpufreq_lock); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 22c07fb..1f9612d 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -118,6 +118,7 @@ int cpuidle_idle_call(void) struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv; int next_state, entered_state; + bool broadcast; if (off) return -ENODEV; @@ -142,11 +143,14 @@ int cpuidle_idle_call(void) return 0; } - trace_cpu_idle_rcuidle(next_state, dev->cpu); + broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP); + + if (broadcast && + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu)) + return -EBUSY; - if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, - &dev->cpu); + + trace_cpu_idle_rcuidle(next_state, dev->cpu); if (cpuidle_state_is_coupled(dev, drv, next_state)) entered_state = cpuidle_enter_state_coupled(dev, drv, @@ -154,12 +158,11 @@ int cpuidle_idle_call(void) else entered_state = cpuidle_enter_state(dev, drv, next_state); - if (drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, - &dev->cpu); - trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); + if (broadcast) + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); + /* give the governor an opportunity to reflect on the outcome */ if (cpuidle_curr_governor->reflect) cpuidle_curr_governor->reflect(dev, entered_state); diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 2dd29c3..399c5e2 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c @@ -704,6 +704,10 @@ static int fsl_qspi_nor_setup(struct fsl_qspi *q) qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, base + QUADSPI_MCR); + /* clear flag register before enable the interrupt */ + reg = qspi_readl(q, q->iobase + QUADSPI_FR); + qspi_writel(q, reg, q->iobase + QUADSPI_FR); + /* enable the interrupt */ qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); @@ -941,6 +945,10 @@ static int fsl_qspi_probe(struct platform_device *pdev) goto irq_failed; } + /* In case of interrupt arrive immediately after requesting irq, + * kernel will panic without init_completion. + */ + init_completion(&q->c); ret = devm_request_irq(dev, ret, fsl_qspi_irq_handler, 0, pdev->name, q); if (ret) { diff --git a/drivers/soc/fsl/ls1/ftm_alarm.c b/drivers/soc/fsl/ls1/ftm_alarm.c index 5135964..dec0c1c 100644 --- a/drivers/soc/fsl/ls1/ftm_alarm.c +++ b/drivers/soc/fsl/ls1/ftm_alarm.c @@ -243,6 +243,8 @@ static int ftm_alarm_probe(struct platform_device *pdev) return ret; } + device_init_wakeup(&pdev->dev, true); + alarm_freq = (u32)FIXED_FREQ_CLK / (u32)MAX_FREQ_DIV; ftm_clean_alarm(); diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 864f4d5..dd6d3b0 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -337,10 +337,10 @@ static int dspi_transfer_one_message(struct spi_master *master, dspi->cur_msg = message; dspi->cur_chip = spi_get_ctldata(spi); dspi->cs = spi->chip_select; + dspi->cs_change = 0; if (dspi->cur_transfer->transfer_list.next == &dspi->cur_msg->transfers) - transfer->cs_change = 1; - dspi->cs_change = transfer->cs_change; + dspi->cs_change = 1; dspi->void_write_data = dspi->cur_chip->void_write_data; dspi->dataflags = 0; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 426bd5a..05a8235 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -721,8 +721,8 @@ static int lpuart_startup(struct uart_port *port) unsigned long flags; unsigned char temp; - ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0, - DRIVER_NAME, sport); + ret = devm_request_irq(port->dev, port->irq, lpuart_int, + IRQF_NO_SUSPEND, DRIVER_NAME, sport); if (ret) return ret; @@ -1431,6 +1431,12 @@ static int lpuart_probe(struct platform_device *pdev) return ret; } + /* + * Make device's PM flags reflect the wake-up capability, but + * let the user space enable it to wake up the system as needed. + */ + device_set_wakeup_capable(&pdev->dev, true); + return 0; } @@ -1449,6 +1455,23 @@ static int lpuart_remove(struct platform_device *pdev) static int lpuart_suspend(struct device *dev) { struct lpuart_port *sport = dev_get_drvdata(dev); + unsigned long temp; + + if (sport->lpuart32) { + /* disable Rx/Tx and interrupts */ + temp = lpuart32_read(sport->port.membase + UARTCTRL); + temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE); + if (!device_may_wakeup(dev)) + temp &= ~(UARTCTRL_RIE | UARTCTRL_RE); + lpuart32_write(temp, sport->port.membase + UARTCTRL); + } else { + /* disable Rx/Tx and interrupts */ + temp = readb(sport->port.membase + UARTCR2); + temp &= ~(UARTCR2_TE | UARTCR2_TIE | UARTCR2_TCIE); + if (!device_may_wakeup(dev)) + temp &= ~(UARTCR2_RIE | UARTCR2_RE); + writeb(temp, sport->port.membase + UARTCR2); + } uart_suspend_port(&lpuart_reg, &sport->port); diff --git a/drivers/video/fsl-dcu-fb.c b/drivers/video/fsl-dcu-fb.c index 3fc0b79..81a8541 100644 --- a/drivers/video/fsl-dcu-fb.c +++ b/drivers/video/fsl-dcu-fb.c @@ -138,6 +138,10 @@ #define TCON_CTRL1 0x00 #define TCON_BYPASS_ENABLE BIT(29) +#define SCFG_PIXCLKCR 0x28 +#define PXCKEN BIT(31) +#define PXCK_DISABLE 0 + #define MFB_SET_ALPHA _IOW('M', 0, __u8) #define MFB_GET_ALPHA _IOR('M', 0, __u8) #define MFB_SET_LAYER _IOW('M', 4, struct layer_display_offset) @@ -1184,6 +1188,7 @@ static int fsl_dcu_suspend(struct device *dev) { struct dcu_fb_data *dcufb = dev_get_drvdata(dev); + regmap_write(dcufb->scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE); regcache_cache_only(dcufb->regmap, true); regcache_mark_dirty(dcufb->regmap); clk_disable_unprepare(dcufb->clk); @@ -1223,6 +1228,7 @@ static int fsl_dcu_resume(struct device *dev) reset_total_layers(np, dcufb); regcache_cache_only(dcufb->regmap, false); regcache_sync(dcufb->regmap); + regmap_write(dcufb->scfg_regmap, SCFG_PIXCLKCR, PXCKEN); return 0; } |