summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci_platform.c1
-rw-r--r--drivers/ata/libahci.c9
-rw-r--r--drivers/cpufreq/qoriq-cpufreq.c42
-rw-r--r--drivers/cpuidle/cpuidle.c19
-rw-r--r--drivers/mtd/spi-nor/fsl-quadspi.c8
-rw-r--r--drivers/soc/fsl/ls1/ftm_alarm.c2
-rw-r--r--drivers/spi/spi-fsl-dspi.c4
-rw-r--r--drivers/tty/serial/fsl_lpuart.c27
-rw-r--r--drivers/video/fsl-dcu-fb.c6
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;
}