aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-02 19:35:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-02 19:35:49 -0400
commita727eaf64ff084a50b983fc506810c7a576b7ce3 (patch)
treecb82642227ed590ebc43b12cfad285a2d7681d5d /arch
parent755a9ba7bf24a45b6dbf8bb15a5a56c8ed12461a (diff)
parent45e70b7d48d53d5eb193c6b3f012b31ca135fb4c (diff)
Merge tag 'drivers-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc into next
Pull ARM SoC driver changes from Olof Johansson: "SoC-near driver changes that we're merging through our tree. Mostly because they depend on other changes we have staged, but in some cases because the driver maintainers preferred that we did it this way. This contains a largeish cleanup series of the omap_l3_noc bus driver, cpuidle rework for Exynos, some reset driver conversions and a long branch of TI EDMA fixes and cleanups, with more to come next release. The TI EDMA cleanups is a shared branch with the dmaengine tree, with a handful of Davinci-specific fixes on top. After discussion at last year's KS (and some more on the mailing lists), we are here adding a drivers/soc directory. The purpose of this is to keep per-vendor shared code that's needed by different drivers but that doesn't fit into the MFD (nor drivers/platform) model. We expect to keep merging contents for this hierarchy through arm-soc so we can keep an eye on what the vendors keep adding here and not making it a free-for-all to shove in crazy stuff" * tag 'drivers-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (101 commits) cpufreq: exynos: Fix driver compilation with ARCH_MULTIPLATFORM tty: serial: msm: Remove direct access to GSBI power: reset: keystone-reset: introduce keystone reset driver Documentation: dt: add bindings for keystone pll control controller Documentation: dt: add bindings for keystone reset driver soc: qcom: fix of_device_id table ARM: EXYNOS: Fix kernel panic when unplugging CPU1 on exynos ARM: EXYNOS: Move the driver to drivers/cpuidle directory ARM: EXYNOS: Cleanup all unneeded headers from cpuidle.c ARM: EXYNOS: Pass the AFTR callback to the platform_data ARM: EXYNOS: Move S5P_CHECK_SLEEP into pm.c ARM: EXYNOS: Move the power sequence call in the cpu_pm notifier ARM: EXYNOS: Move the AFTR state function into pm.c ARM: EXYNOS: Encapsulate the AFTR code into a function ARM: EXYNOS: Disable cpuidle for exynos5440 ARM: EXYNOS: Encapsulate boot vector code into a function for cpuidle ARM: EXYNOS: Pass wakeup mask parameter to function for cpuidle ARM: EXYNOS: Remove ifdef for scu_enable in pm ARM: EXYNOS: Move scu_enable in the cpu_pm notifier ARM: EXYNOS: Use the cpu_pm notifier for pm ...
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/boot/dts/am33xx.dtsi3
-rw-r--r--arch/arm/boot/dts/am4372.dtsi3
-rw-r--r--arch/arm/common/edma.c197
-rw-r--r--arch/arm/mach-davinci/devices-da8xx.c31
-rw-r--r--arch/arm/mach-davinci/dm355.c14
-rw-r--r--arch/arm/mach-davinci/dm365.c16
-rw-r--r--arch/arm/mach-davinci/dm644x.c14
-rw-r--r--arch/arm/mach-davinci/dm646x.c16
-rw-r--r--arch/arm/mach-exynos/Makefile1
-rw-r--r--arch/arm/mach-exynos/common.h2
-rw-r--r--arch/arm/mach-exynos/cpuidle.c255
-rw-r--r--arch/arm/mach-exynos/exynos.c8
-rw-r--r--arch/arm/mach-exynos/platsmp.c2
-rw-r--r--arch/arm/mach-exynos/pm.c152
-rw-r--r--arch/arm/mach-exynos/regs-pmu.h2
15 files changed, 228 insertions, 488 deletions
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 586397cf6e9c..9f53e824b037 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -147,9 +147,6 @@
147 <0x44e10f90 0x40>; 147 <0x44e10f90 0x40>;
148 interrupts = <12 13 14>; 148 interrupts = <12 13 14>;
149 #dma-cells = <1>; 149 #dma-cells = <1>;
150 dma-channels = <64>;
151 ti,edma-regions = <4>;
152 ti,edma-slots = <256>;
153 }; 150 };
154 151
155 gpio0: gpio@44e07000 { 152 gpio0: gpio@44e07000 {
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 1704e853f163..794c73e5c4e4 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -112,9 +112,6 @@
112 <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, 112 <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
113 <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; 113 <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
114 #dma-cells = <1>; 114 #dma-cells = <1>;
115 dma-channels = <64>;
116 ti,edma-regions = <4>;
117 ti,edma-slots = <256>;
118 }; 115 };
119 116
120 uart0: serial@44e09000 { 117 uart0: serial@44e09000 {
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
index 5339009b3c0c..485be42519b9 100644
--- a/arch/arm/common/edma.c
+++ b/arch/arm/common/edma.c
@@ -102,7 +102,13 @@
102#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5)) 102#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5))
103 103
104#define EDMA_DCHMAP 0x0100 /* 64 registers */ 104#define EDMA_DCHMAP 0x0100 /* 64 registers */
105#define CHMAP_EXIST BIT(24) 105
106/* CCCFG register */
107#define GET_NUM_DMACH(x) (x & 0x7) /* bits 0-2 */
108#define GET_NUM_PAENTRY(x) ((x & 0x7000) >> 12) /* bits 12-14 */
109#define GET_NUM_EVQUE(x) ((x & 0x70000) >> 16) /* bits 16-18 */
110#define GET_NUM_REGN(x) ((x & 0x300000) >> 20) /* bits 20-21 */
111#define CHMAP_EXIST BIT(24)
106 112
107#define EDMA_MAX_DMACH 64 113#define EDMA_MAX_DMACH 64
108#define EDMA_MAX_PARAMENTRY 512 114#define EDMA_MAX_PARAMENTRY 512
@@ -233,7 +239,6 @@ struct edma {
233 unsigned num_region; 239 unsigned num_region;
234 unsigned num_slots; 240 unsigned num_slots;
235 unsigned num_tc; 241 unsigned num_tc;
236 unsigned num_cc;
237 enum dma_event_q default_queue; 242 enum dma_event_q default_queue;
238 243
239 /* list of channels with no even trigger; terminated by "-1" */ 244 /* list of channels with no even trigger; terminated by "-1" */
@@ -290,12 +295,6 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
290 ~(0x7 << bit), queue_no << bit); 295 ~(0x7 << bit), queue_no << bit);
291} 296}
292 297
293static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no)
294{
295 int bit = queue_no * 4;
296 edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
297}
298
299static void __init assign_priority_to_queue(unsigned ctlr, int queue_no, 298static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
300 int priority) 299 int priority)
301{ 300{
@@ -994,29 +993,23 @@ void edma_set_dest(unsigned slot, dma_addr_t dest_port,
994EXPORT_SYMBOL(edma_set_dest); 993EXPORT_SYMBOL(edma_set_dest);
995 994
996/** 995/**
997 * edma_get_position - returns the current transfer points 996 * edma_get_position - returns the current transfer point
998 * @slot: parameter RAM slot being examined 997 * @slot: parameter RAM slot being examined
999 * @src: pointer to source port position 998 * @dst: true selects the dest position, false the source
1000 * @dst: pointer to destination port position
1001 * 999 *
1002 * Returns current source and destination addresses for a particular 1000 * Returns the position of the current active slot
1003 * parameter RAM slot. Its channel should not be active when this is called.
1004 */ 1001 */
1005void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst) 1002dma_addr_t edma_get_position(unsigned slot, bool dst)
1006{ 1003{
1007 struct edmacc_param temp; 1004 u32 offs, ctlr = EDMA_CTLR(slot);
1008 unsigned ctlr;
1009 1005
1010 ctlr = EDMA_CTLR(slot);
1011 slot = EDMA_CHAN_SLOT(slot); 1006 slot = EDMA_CHAN_SLOT(slot);
1012 1007
1013 edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp); 1008 offs = PARM_OFFSET(slot);
1014 if (src != NULL) 1009 offs += dst ? PARM_DST : PARM_SRC;
1015 *src = temp.src; 1010
1016 if (dst != NULL) 1011 return edma_read(ctlr, offs);
1017 *dst = temp.dst;
1018} 1012}
1019EXPORT_SYMBOL(edma_get_position);
1020 1013
1021/** 1014/**
1022 * edma_set_src_index - configure DMA source address indexing 1015 * edma_set_src_index - configure DMA source address indexing
@@ -1421,6 +1414,67 @@ void edma_clear_event(unsigned channel)
1421} 1414}
1422EXPORT_SYMBOL(edma_clear_event); 1415EXPORT_SYMBOL(edma_clear_event);
1423 1416
1417static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
1418 struct edma *edma_cc)
1419{
1420 int i;
1421 u32 value, cccfg;
1422 s8 (*queue_priority_map)[2];
1423
1424 /* Decode the eDMA3 configuration from CCCFG register */
1425 cccfg = edma_read(0, EDMA_CCCFG);
1426
1427 value = GET_NUM_REGN(cccfg);
1428 edma_cc->num_region = BIT(value);
1429
1430 value = GET_NUM_DMACH(cccfg);
1431 edma_cc->num_channels = BIT(value + 1);
1432
1433 value = GET_NUM_PAENTRY(cccfg);
1434 edma_cc->num_slots = BIT(value + 4);
1435
1436 value = GET_NUM_EVQUE(cccfg);
1437 edma_cc->num_tc = value + 1;
1438
1439 dev_dbg(dev, "eDMA3 HW configuration (cccfg: 0x%08x):\n", cccfg);
1440 dev_dbg(dev, "num_region: %u\n", edma_cc->num_region);
1441 dev_dbg(dev, "num_channel: %u\n", edma_cc->num_channels);
1442 dev_dbg(dev, "num_slot: %u\n", edma_cc->num_slots);
1443 dev_dbg(dev, "num_tc: %u\n", edma_cc->num_tc);
1444
1445 /* Nothing need to be done if queue priority is provided */
1446 if (pdata->queue_priority_mapping)
1447 return 0;
1448
1449 /*
1450 * Configure TC/queue priority as follows:
1451 * Q0 - priority 0
1452 * Q1 - priority 1
1453 * Q2 - priority 2
1454 * ...
1455 * The meaning of priority numbers: 0 highest priority, 7 lowest
1456 * priority. So Q0 is the highest priority queue and the last queue has
1457 * the lowest priority.
1458 */
1459 queue_priority_map = devm_kzalloc(dev,
1460 (edma_cc->num_tc + 1) * sizeof(s8),
1461 GFP_KERNEL);
1462 if (!queue_priority_map)
1463 return -ENOMEM;
1464
1465 for (i = 0; i < edma_cc->num_tc; i++) {
1466 queue_priority_map[i][0] = i;
1467 queue_priority_map[i][1] = i;
1468 }
1469 queue_priority_map[i][0] = -1;
1470 queue_priority_map[i][1] = -1;
1471
1472 pdata->queue_priority_mapping = queue_priority_map;
1473 pdata->default_queue = 0;
1474
1475 return 0;
1476}
1477
1424#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES) 1478#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES)
1425 1479
1426static int edma_xbar_event_map(struct device *dev, struct device_node *node, 1480static int edma_xbar_event_map(struct device *dev, struct device_node *node,
@@ -1471,65 +1525,16 @@ static int edma_of_parse_dt(struct device *dev,
1471 struct device_node *node, 1525 struct device_node *node,
1472 struct edma_soc_info *pdata) 1526 struct edma_soc_info *pdata)
1473{ 1527{
1474 int ret = 0, i; 1528 int ret = 0;
1475 u32 value;
1476 struct property *prop; 1529 struct property *prop;
1477 size_t sz; 1530 size_t sz;
1478 struct edma_rsv_info *rsv_info; 1531 struct edma_rsv_info *rsv_info;
1479 s8 (*queue_tc_map)[2], (*queue_priority_map)[2];
1480
1481 memset(pdata, 0, sizeof(struct edma_soc_info));
1482
1483 ret = of_property_read_u32(node, "dma-channels", &value);
1484 if (ret < 0)
1485 return ret;
1486 pdata->n_channel = value;
1487
1488 ret = of_property_read_u32(node, "ti,edma-regions", &value);
1489 if (ret < 0)
1490 return ret;
1491 pdata->n_region = value;
1492
1493 ret = of_property_read_u32(node, "ti,edma-slots", &value);
1494 if (ret < 0)
1495 return ret;
1496 pdata->n_slot = value;
1497
1498 pdata->n_cc = 1;
1499 1532
1500 rsv_info = devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL); 1533 rsv_info = devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL);
1501 if (!rsv_info) 1534 if (!rsv_info)
1502 return -ENOMEM; 1535 return -ENOMEM;
1503 pdata->rsv = rsv_info; 1536 pdata->rsv = rsv_info;
1504 1537
1505 queue_tc_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL);
1506 if (!queue_tc_map)
1507 return -ENOMEM;
1508
1509 for (i = 0; i < 3; i++) {
1510 queue_tc_map[i][0] = i;
1511 queue_tc_map[i][1] = i;
1512 }
1513 queue_tc_map[i][0] = -1;
1514 queue_tc_map[i][1] = -1;
1515
1516 pdata->queue_tc_mapping = queue_tc_map;
1517
1518 queue_priority_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL);
1519 if (!queue_priority_map)
1520 return -ENOMEM;
1521
1522 for (i = 0; i < 3; i++) {
1523 queue_priority_map[i][0] = i;
1524 queue_priority_map[i][1] = i;
1525 }
1526 queue_priority_map[i][0] = -1;
1527 queue_priority_map[i][1] = -1;
1528
1529 pdata->queue_priority_mapping = queue_priority_map;
1530
1531 pdata->default_queue = 0;
1532
1533 prop = of_find_property(node, "ti,edma-xbar-event-map", &sz); 1538 prop = of_find_property(node, "ti,edma-xbar-event-map", &sz);
1534 if (prop) 1539 if (prop)
1535 ret = edma_xbar_event_map(dev, node, pdata, sz); 1540 ret = edma_xbar_event_map(dev, node, pdata, sz);
@@ -1556,6 +1561,7 @@ static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev,
1556 return ERR_PTR(ret); 1561 return ERR_PTR(ret);
1557 1562
1558 dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap); 1563 dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
1564 dma_cap_set(DMA_CYCLIC, edma_filter_info.dma_cap);
1559 of_dma_controller_register(dev->of_node, of_dma_simple_xlate, 1565 of_dma_controller_register(dev->of_node, of_dma_simple_xlate,
1560 &edma_filter_info); 1566 &edma_filter_info);
1561 1567
@@ -1574,7 +1580,6 @@ static int edma_probe(struct platform_device *pdev)
1574 struct edma_soc_info **info = pdev->dev.platform_data; 1580 struct edma_soc_info **info = pdev->dev.platform_data;
1575 struct edma_soc_info *ninfo[EDMA_MAX_CC] = {NULL}; 1581 struct edma_soc_info *ninfo[EDMA_MAX_CC] = {NULL};
1576 s8 (*queue_priority_mapping)[2]; 1582 s8 (*queue_priority_mapping)[2];
1577 s8 (*queue_tc_mapping)[2];
1578 int i, j, off, ln, found = 0; 1583 int i, j, off, ln, found = 0;
1579 int status = -1; 1584 int status = -1;
1580 const s16 (*rsv_chans)[2]; 1585 const s16 (*rsv_chans)[2];
@@ -1585,7 +1590,6 @@ static int edma_probe(struct platform_device *pdev)
1585 struct resource *r[EDMA_MAX_CC] = {NULL}; 1590 struct resource *r[EDMA_MAX_CC] = {NULL};
1586 struct resource res[EDMA_MAX_CC]; 1591 struct resource res[EDMA_MAX_CC];
1587 char res_name[10]; 1592 char res_name[10];
1588 char irq_name[10];
1589 struct device_node *node = pdev->dev.of_node; 1593 struct device_node *node = pdev->dev.of_node;
1590 struct device *dev = &pdev->dev; 1594 struct device *dev = &pdev->dev;
1591 int ret; 1595 int ret;
@@ -1650,12 +1654,10 @@ static int edma_probe(struct platform_device *pdev)
1650 if (!edma_cc[j]) 1654 if (!edma_cc[j])
1651 return -ENOMEM; 1655 return -ENOMEM;
1652 1656
1653 edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel, 1657 /* Get eDMA3 configuration from IP */
1654 EDMA_MAX_DMACH); 1658 ret = edma_setup_from_hw(dev, info[j], edma_cc[j]);
1655 edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot, 1659 if (ret)
1656 EDMA_MAX_PARAMENTRY); 1660 return ret;
1657 edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
1658 EDMA_MAX_CC);
1659 1661
1660 edma_cc[j]->default_queue = info[j]->default_queue; 1662 edma_cc[j]->default_queue = info[j]->default_queue;
1661 1663
@@ -1707,14 +1709,21 @@ static int edma_probe(struct platform_device *pdev)
1707 1709
1708 if (node) { 1710 if (node) {
1709 irq[j] = irq_of_parse_and_map(node, 0); 1711 irq[j] = irq_of_parse_and_map(node, 0);
1712 err_irq[j] = irq_of_parse_and_map(node, 2);
1710 } else { 1713 } else {
1714 char irq_name[10];
1715
1711 sprintf(irq_name, "edma%d", j); 1716 sprintf(irq_name, "edma%d", j);
1712 irq[j] = platform_get_irq_byname(pdev, irq_name); 1717 irq[j] = platform_get_irq_byname(pdev, irq_name);
1718
1719 sprintf(irq_name, "edma%d_err", j);
1720 err_irq[j] = platform_get_irq_byname(pdev, irq_name);
1713 } 1721 }
1714 edma_cc[j]->irq_res_start = irq[j]; 1722 edma_cc[j]->irq_res_start = irq[j];
1715 status = devm_request_irq(&pdev->dev, irq[j], 1723 edma_cc[j]->irq_res_end = err_irq[j];
1716 dma_irq_handler, 0, "edma", 1724
1717 &pdev->dev); 1725 status = devm_request_irq(dev, irq[j], dma_irq_handler, 0,
1726 "edma", dev);
1718 if (status < 0) { 1727 if (status < 0) {
1719 dev_dbg(&pdev->dev, 1728 dev_dbg(&pdev->dev,
1720 "devm_request_irq %d failed --> %d\n", 1729 "devm_request_irq %d failed --> %d\n",
@@ -1722,16 +1731,8 @@ static int edma_probe(struct platform_device *pdev)
1722 return status; 1731 return status;
1723 } 1732 }
1724 1733
1725 if (node) { 1734 status = devm_request_irq(dev, err_irq[j], dma_ccerr_handler, 0,
1726 err_irq[j] = irq_of_parse_and_map(node, 2); 1735 "edma_error", dev);
1727 } else {
1728 sprintf(irq_name, "edma%d_err", j);
1729 err_irq[j] = platform_get_irq_byname(pdev, irq_name);
1730 }
1731 edma_cc[j]->irq_res_end = err_irq[j];
1732 status = devm_request_irq(&pdev->dev, err_irq[j],
1733 dma_ccerr_handler, 0,
1734 "edma_error", &pdev->dev);
1735 if (status < 0) { 1736 if (status < 0) {
1736 dev_dbg(&pdev->dev, 1737 dev_dbg(&pdev->dev,
1737 "devm_request_irq %d failed --> %d\n", 1738 "devm_request_irq %d failed --> %d\n",
@@ -1742,14 +1743,8 @@ static int edma_probe(struct platform_device *pdev)
1742 for (i = 0; i < edma_cc[j]->num_channels; i++) 1743 for (i = 0; i < edma_cc[j]->num_channels; i++)
1743 map_dmach_queue(j, i, info[j]->default_queue); 1744 map_dmach_queue(j, i, info[j]->default_queue);
1744 1745
1745 queue_tc_mapping = info[j]->queue_tc_mapping;
1746 queue_priority_mapping = info[j]->queue_priority_mapping; 1746 queue_priority_mapping = info[j]->queue_priority_mapping;
1747 1747
1748 /* Event queue to TC mapping */
1749 for (i = 0; queue_tc_mapping[i][0] != -1; i++)
1750 map_queue_tc(j, queue_tc_mapping[i][0],
1751 queue_tc_mapping[i][1]);
1752
1753 /* Event queue priority mapping */ 1748 /* Event queue priority mapping */
1754 for (i = 0; queue_priority_mapping[i][0] != -1; i++) 1749 for (i = 0; queue_priority_mapping[i][0] != -1; i++)
1755 assign_priority_to_queue(j, 1750 assign_priority_to_queue(j,
@@ -1762,7 +1757,7 @@ static int edma_probe(struct platform_device *pdev)
1762 if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST) 1757 if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
1763 map_dmach_param(j); 1758 map_dmach_param(j);
1764 1759
1765 for (i = 0; i < info[j]->n_region; i++) { 1760 for (i = 0; i < edma_cc[j]->num_region; i++) {
1766 edma_write_array2(j, EDMA_DRAE, i, 0, 0x0); 1761 edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
1767 edma_write_array2(j, EDMA_DRAE, i, 1, 0x0); 1762 edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
1768 edma_write_array(j, EDMA_QRAE, i, 0x0); 1763 edma_write_array(j, EDMA_QRAE, i, 0x0);
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 56ea41d5f849..b85b781b05fd 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -134,13 +134,6 @@ struct platform_device da8xx_serial_device[] = {
134 } 134 }
135}; 135};
136 136
137static s8 da8xx_queue_tc_mapping[][2] = {
138 /* {event queue no, TC no} */
139 {0, 0},
140 {1, 1},
141 {-1, -1}
142};
143
144static s8 da8xx_queue_priority_mapping[][2] = { 137static s8 da8xx_queue_priority_mapping[][2] = {
145 /* {event queue no, Priority} */ 138 /* {event queue no, Priority} */
146 {0, 3}, 139 {0, 3},
@@ -148,12 +141,6 @@ static s8 da8xx_queue_priority_mapping[][2] = {
148 {-1, -1} 141 {-1, -1}
149}; 142};
150 143
151static s8 da850_queue_tc_mapping[][2] = {
152 /* {event queue no, TC no} */
153 {0, 0},
154 {-1, -1}
155};
156
157static s8 da850_queue_priority_mapping[][2] = { 144static s8 da850_queue_priority_mapping[][2] = {
158 /* {event queue no, Priority} */ 145 /* {event queue no, Priority} */
159 {0, 3}, 146 {0, 3},
@@ -161,12 +148,6 @@ static s8 da850_queue_priority_mapping[][2] = {
161}; 148};
162 149
163static struct edma_soc_info da830_edma_cc0_info = { 150static struct edma_soc_info da830_edma_cc0_info = {
164 .n_channel = 32,
165 .n_region = 4,
166 .n_slot = 128,
167 .n_tc = 2,
168 .n_cc = 1,
169 .queue_tc_mapping = da8xx_queue_tc_mapping,
170 .queue_priority_mapping = da8xx_queue_priority_mapping, 151 .queue_priority_mapping = da8xx_queue_priority_mapping,
171 .default_queue = EVENTQ_1, 152 .default_queue = EVENTQ_1,
172}; 153};
@@ -177,22 +158,10 @@ static struct edma_soc_info *da830_edma_info[EDMA_MAX_CC] = {
177 158
178static struct edma_soc_info da850_edma_cc_info[] = { 159static struct edma_soc_info da850_edma_cc_info[] = {
179 { 160 {
180 .n_channel = 32,
181 .n_region = 4,
182 .n_slot = 128,
183 .n_tc = 2,
184 .n_cc = 1,
185 .queue_tc_mapping = da8xx_queue_tc_mapping,
186 .queue_priority_mapping = da8xx_queue_priority_mapping, 161 .queue_priority_mapping = da8xx_queue_priority_mapping,
187 .default_queue = EVENTQ_1, 162 .default_queue = EVENTQ_1,
188 }, 163 },
189 { 164 {
190 .n_channel = 32,
191 .n_region = 4,
192 .n_slot = 128,
193 .n_tc = 1,
194 .n_cc = 1,
195 .queue_tc_mapping = da850_queue_tc_mapping,
196 .queue_priority_mapping = da850_queue_priority_mapping, 165 .queue_priority_mapping = da850_queue_priority_mapping,
197 .default_queue = EVENTQ_0, 166 .default_queue = EVENTQ_0,
198 }, 167 },
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 07381d8cea62..2f3ed3a58d57 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -569,14 +569,6 @@ static u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
569/*----------------------------------------------------------------------*/ 569/*----------------------------------------------------------------------*/
570 570
571static s8 571static s8
572queue_tc_mapping[][2] = {
573 /* {event queue no, TC no} */
574 {0, 0},
575 {1, 1},
576 {-1, -1},
577};
578
579static s8
580queue_priority_mapping[][2] = { 572queue_priority_mapping[][2] = {
581 /* {event queue no, Priority} */ 573 /* {event queue no, Priority} */
582 {0, 3}, 574 {0, 3},
@@ -585,12 +577,6 @@ queue_priority_mapping[][2] = {
585}; 577};
586 578
587static struct edma_soc_info edma_cc0_info = { 579static struct edma_soc_info edma_cc0_info = {
588 .n_channel = 64,
589 .n_region = 4,
590 .n_slot = 128,
591 .n_tc = 2,
592 .n_cc = 1,
593 .queue_tc_mapping = queue_tc_mapping,
594 .queue_priority_mapping = queue_priority_mapping, 580 .queue_priority_mapping = queue_priority_mapping,
595 .default_queue = EVENTQ_1, 581 .default_queue = EVENTQ_1,
596}; 582};
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 08a61b938333..0ae8114f5cc9 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -853,16 +853,6 @@ static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
853 853
854/* Four Transfer Controllers on DM365 */ 854/* Four Transfer Controllers on DM365 */
855static s8 855static s8
856dm365_queue_tc_mapping[][2] = {
857 /* {event queue no, TC no} */
858 {0, 0},
859 {1, 1},
860 {2, 2},
861 {3, 3},
862 {-1, -1},
863};
864
865static s8
866dm365_queue_priority_mapping[][2] = { 856dm365_queue_priority_mapping[][2] = {
867 /* {event queue no, Priority} */ 857 /* {event queue no, Priority} */
868 {0, 7}, 858 {0, 7},
@@ -873,12 +863,6 @@ dm365_queue_priority_mapping[][2] = {
873}; 863};
874 864
875static struct edma_soc_info edma_cc0_info = { 865static struct edma_soc_info edma_cc0_info = {
876 .n_channel = 64,
877 .n_region = 4,
878 .n_slot = 256,
879 .n_tc = 4,
880 .n_cc = 1,
881 .queue_tc_mapping = dm365_queue_tc_mapping,
882 .queue_priority_mapping = dm365_queue_priority_mapping, 866 .queue_priority_mapping = dm365_queue_priority_mapping,
883 .default_queue = EVENTQ_3, 867 .default_queue = EVENTQ_3,
884}; 868};
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 5debffba4b24..dc52657909c4 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -499,14 +499,6 @@ static u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
499/*----------------------------------------------------------------------*/ 499/*----------------------------------------------------------------------*/
500 500
501static s8 501static s8
502queue_tc_mapping[][2] = {
503 /* {event queue no, TC no} */
504 {0, 0},
505 {1, 1},
506 {-1, -1},
507};
508
509static s8
510queue_priority_mapping[][2] = { 502queue_priority_mapping[][2] = {
511 /* {event queue no, Priority} */ 503 /* {event queue no, Priority} */
512 {0, 3}, 504 {0, 3},
@@ -515,12 +507,6 @@ queue_priority_mapping[][2] = {
515}; 507};
516 508
517static struct edma_soc_info edma_cc0_info = { 509static struct edma_soc_info edma_cc0_info = {
518 .n_channel = 64,
519 .n_region = 4,
520 .n_slot = 128,
521 .n_tc = 2,
522 .n_cc = 1,
523 .queue_tc_mapping = queue_tc_mapping,
524 .queue_priority_mapping = queue_priority_mapping, 510 .queue_priority_mapping = queue_priority_mapping,
525 .default_queue = EVENTQ_1, 511 .default_queue = EVENTQ_1,
526}; 512};
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 332d00d24dc2..6c3bbea7d77d 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -533,16 +533,6 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
533 533
534/* Four Transfer Controllers on DM646x */ 534/* Four Transfer Controllers on DM646x */
535static s8 535static s8
536dm646x_queue_tc_mapping[][2] = {
537 /* {event queue no, TC no} */
538 {0, 0},
539 {1, 1},
540 {2, 2},
541 {3, 3},
542 {-1, -1},
543};
544
545static s8
546dm646x_queue_priority_mapping[][2] = { 536dm646x_queue_priority_mapping[][2] = {
547 /* {event queue no, Priority} */ 537 /* {event queue no, Priority} */
548 {0, 4}, 538 {0, 4},
@@ -553,12 +543,6 @@ dm646x_queue_priority_mapping[][2] = {
553}; 543};
554 544
555static struct edma_soc_info edma_cc0_info = { 545static struct edma_soc_info edma_cc0_info = {
556 .n_channel = 64,
557 .n_region = 6, /* 0-1, 4-7 */
558 .n_slot = 512,
559 .n_tc = 4,
560 .n_cc = 1,
561 .queue_tc_mapping = dm646x_queue_tc_mapping,
562 .queue_priority_mapping = dm646x_queue_priority_mapping, 546 .queue_priority_mapping = dm646x_queue_priority_mapping,
563 .default_queue = EVENTQ_1, 547 .default_queue = EVENTQ_1,
564}; 548};
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 9f3258880949..788f26d21141 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -18,7 +18,6 @@ obj-$(CONFIG_ARCH_EXYNOS) += exynos.o pmu.o exynos-smc.o firmware.o
18 18
19obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o 19obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o
20obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o 20obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
21obj-$(CONFIG_CPU_IDLE) += cpuidle.o
22 21
23obj-$(CONFIG_SMP) += platsmp.o headsmp.o 22obj-$(CONFIG_SMP) += platsmp.o headsmp.o
24 23
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 5dba5a1ee6c2..80b90e346ca0 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -115,6 +115,7 @@ void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
115 115
116struct map_desc; 116struct map_desc;
117extern void __iomem *sysram_ns_base_addr; 117extern void __iomem *sysram_ns_base_addr;
118extern void __iomem *sysram_base_addr;
118void exynos_init_io(void); 119void exynos_init_io(void);
119void exynos_restart(enum reboot_mode mode, const char *cmd); 120void exynos_restart(enum reboot_mode mode, const char *cmd);
120void exynos_cpuidle_init(void); 121void exynos_cpuidle_init(void);
@@ -165,6 +166,7 @@ extern int exynos_cpu_power_state(int cpu);
165extern void exynos_cluster_power_down(int cluster); 166extern void exynos_cluster_power_down(int cluster);
166extern void exynos_cluster_power_up(int cluster); 167extern void exynos_cluster_power_up(int cluster);
167extern int exynos_cluster_power_state(int cluster); 168extern int exynos_cluster_power_state(int cluster);
169extern void exynos_enter_aftr(void);
168 170
169extern void s5p_init_cpu(void __iomem *cpuid_addr); 171extern void s5p_init_cpu(void __iomem *cpuid_addr);
170extern unsigned int samsung_rev(void); 172extern unsigned int samsung_rev(void);
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
deleted file mode 100644
index 3dd385ebf195..000000000000
--- a/arch/arm/mach-exynos/cpuidle.c
+++ /dev/null
@@ -1,255 +0,0 @@
1/* linux/arch/arm/mach-exynos4/cpuidle.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9*/
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/cpuidle.h>
14#include <linux/cpu_pm.h>
15#include <linux/io.h>
16#include <linux/export.h>
17#include <linux/module.h>
18#include <linux/time.h>
19#include <linux/platform_device.h>
20
21#include <asm/proc-fns.h>
22#include <asm/smp_scu.h>
23#include <asm/suspend.h>
24#include <asm/unified.h>
25#include <asm/cpuidle.h>
26
27#include <plat/pm.h>
28
29#include <mach/map.h>
30
31#include "common.h"
32#include "regs-pmu.h"
33
34#define REG_DIRECTGO_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
35 S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
36 (S5P_VA_SYSRAM + 0x24) : S5P_INFORM0))
37#define REG_DIRECTGO_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
38 S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
39 (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1))
40
41#define S5P_CHECK_AFTR 0xFCBA0D10
42
43#define EXYNOS5_PWR_CTRL1 (S5P_VA_CMU + 0x01020)
44#define EXYNOS5_PWR_CTRL2 (S5P_VA_CMU + 0x01024)
45
46#define PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28)
47#define PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16)
48#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
49#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
50#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
51#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
52#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
53#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
54
55#define PWR_CTRL2_DIV2_UP_EN (1 << 25)
56#define PWR_CTRL2_DIV1_UP_EN (1 << 24)
57#define PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16)
58#define PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8)
59#define PWR_CTRL2_CORE2_UP_RATIO (1 << 4)
60#define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
61
62static int exynos4_enter_lowpower(struct cpuidle_device *dev,
63 struct cpuidle_driver *drv,
64 int index);
65
66static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
67
68static struct cpuidle_driver exynos4_idle_driver = {
69 .name = "exynos4_idle",
70 .owner = THIS_MODULE,
71 .states = {
72 [0] = ARM_CPUIDLE_WFI_STATE,
73 [1] = {
74 .enter = exynos4_enter_lowpower,
75 .exit_latency = 300,
76 .target_residency = 100000,
77 .flags = CPUIDLE_FLAG_TIME_VALID,
78 .name = "C1",
79 .desc = "ARM power down",
80 },
81 },
82 .state_count = 2,
83 .safe_state_index = 0,
84};
85
86/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
87static void exynos4_set_wakeupmask(void)
88{
89 __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK);
90}
91
92static unsigned int g_pwr_ctrl, g_diag_reg;
93
94static void save_cpu_arch_register(void)
95{
96 /*read power control register*/
97 asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
98 /*read diagnostic register*/
99 asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
100 return;
101}
102
103static void restore_cpu_arch_register(void)
104{
105 /*write power control register*/
106 asm("mcr p15, 0, %0, c15, c0, 0" : : "r"(g_pwr_ctrl) : "cc");
107 /*write diagnostic register*/
108 asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
109 return;
110}
111
112static int idle_finisher(unsigned long flags)
113{
114 cpu_do_idle();
115 return 1;
116}
117
118static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
119 struct cpuidle_driver *drv,
120 int index)
121{
122 unsigned long tmp;
123
124 exynos4_set_wakeupmask();
125
126 /* Set value of power down register for aftr mode */
127 exynos_sys_powerdown_conf(SYS_AFTR);
128
129 __raw_writel(virt_to_phys(exynos_cpu_resume), REG_DIRECTGO_ADDR);
130 __raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG);
131
132 save_cpu_arch_register();
133
134 /* Setting Central Sequence Register for power down mode */
135 tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
136 tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
137 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
138
139 cpu_pm_enter();
140 cpu_suspend(0, idle_finisher);
141
142#ifdef CONFIG_SMP
143 if (!soc_is_exynos5250())
144 scu_enable(S5P_VA_SCU);
145#endif
146 cpu_pm_exit();
147
148 restore_cpu_arch_register();
149
150 /*
151 * If PMU failed while entering sleep mode, WFI will be
152 * ignored by PMU and then exiting cpu_do_idle().
153 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
154 * in this situation.
155 */
156 tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
157 if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
158 tmp |= S5P_CENTRAL_LOWPWR_CFG;
159 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
160 }
161
162 /* Clear wakeup state register */
163 __raw_writel(0x0, S5P_WAKEUP_STAT);
164
165 return index;
166}
167
168static int exynos4_enter_lowpower(struct cpuidle_device *dev,
169 struct cpuidle_driver *drv,
170 int index)
171{
172 int new_index = index;
173
174 /* AFTR can only be entered when cores other than CPU0 are offline */
175 if (num_online_cpus() > 1 || dev->cpu != 0)
176 new_index = drv->safe_state_index;
177
178 if (new_index == 0)
179 return arm_cpuidle_simple_enter(dev, drv, new_index);
180 else
181 return exynos4_enter_core0_aftr(dev, drv, new_index);
182}
183
184static void __init exynos5_core_down_clk(void)
185{
186 unsigned int tmp;
187
188 /*
189 * Enable arm clock down (in idle) and set arm divider
190 * ratios in WFI/WFE state.
191 */
192 tmp = PWR_CTRL1_CORE2_DOWN_RATIO | \
193 PWR_CTRL1_CORE1_DOWN_RATIO | \
194 PWR_CTRL1_DIV2_DOWN_EN | \
195 PWR_CTRL1_DIV1_DOWN_EN | \
196 PWR_CTRL1_USE_CORE1_WFE | \
197 PWR_CTRL1_USE_CORE0_WFE | \
198 PWR_CTRL1_USE_CORE1_WFI | \
199 PWR_CTRL1_USE_CORE0_WFI;
200 __raw_writel(tmp, EXYNOS5_PWR_CTRL1);
201
202 /*
203 * Enable arm clock up (on exiting idle). Set arm divider
204 * ratios when not in idle along with the standby duration
205 * ratios.
206 */
207 tmp = PWR_CTRL2_DIV2_UP_EN | \
208 PWR_CTRL2_DIV1_UP_EN | \
209 PWR_CTRL2_DUR_STANDBY2_VAL | \
210 PWR_CTRL2_DUR_STANDBY1_VAL | \
211 PWR_CTRL2_CORE2_UP_RATIO | \
212 PWR_CTRL2_CORE1_UP_RATIO;
213 __raw_writel(tmp, EXYNOS5_PWR_CTRL2);
214}
215
216static int exynos_cpuidle_probe(struct platform_device *pdev)
217{
218 int cpu_id, ret;
219 struct cpuidle_device *device;
220
221 if (soc_is_exynos5250())
222 exynos5_core_down_clk();
223
224 if (soc_is_exynos5440())
225 exynos4_idle_driver.state_count = 1;
226
227 ret = cpuidle_register_driver(&exynos4_idle_driver);
228 if (ret) {
229 dev_err(&pdev->dev, "failed to register cpuidle driver\n");
230 return ret;
231 }
232
233 for_each_online_cpu(cpu_id) {
234 device = &per_cpu(exynos4_cpuidle_device, cpu_id);
235 device->cpu = cpu_id;
236
237 ret = cpuidle_register_device(device);
238 if (ret) {
239 dev_err(&pdev->dev, "failed to register cpuidle device\n");
240 return ret;
241 }
242 }
243
244 return 0;
245}
246
247static struct platform_driver exynos_cpuidle_driver = {
248 .probe = exynos_cpuidle_probe,
249 .driver = {
250 .name = "exynos_cpuidle",
251 .owner = THIS_MODULE,
252 },
253};
254
255module_platform_driver(exynos_cpuidle_driver);
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 4800b1ce3d71..bc43e22693b7 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -169,12 +169,16 @@ void exynos_restart(enum reboot_mode mode, const char *cmd)
169} 169}
170 170
171static struct platform_device exynos_cpuidle = { 171static struct platform_device exynos_cpuidle = {
172 .name = "exynos_cpuidle", 172 .name = "exynos_cpuidle",
173 .id = -1, 173 .dev.platform_data = exynos_enter_aftr,
174 .id = -1,
174}; 175};
175 176
176void __init exynos_cpuidle_init(void) 177void __init exynos_cpuidle_init(void)
177{ 178{
179 if (soc_is_exynos5440())
180 return;
181
178 platform_device_register(&exynos_cpuidle); 182 platform_device_register(&exynos_cpuidle);
179} 183}
180 184
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 112bc66927a1..ec02422e8499 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -32,7 +32,7 @@
32 32
33extern void exynos4_secondary_startup(void); 33extern void exynos4_secondary_startup(void);
34 34
35static void __iomem *sysram_base_addr; 35void __iomem *sysram_base_addr;
36void __iomem *sysram_ns_base_addr; 36void __iomem *sysram_ns_base_addr;
37 37
38static void __init exynos_smp_prepare_sysram(void) 38static void __init exynos_smp_prepare_sysram(void)
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index aba2ff6e443d..87c0d34c7fba 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/suspend.h> 17#include <linux/suspend.h>
18#include <linux/syscore_ops.h> 18#include <linux/syscore_ops.h>
19#include <linux/cpu_pm.h>
19#include <linux/io.h> 20#include <linux/io.h>
20#include <linux/irqchip/arm-gic.h> 21#include <linux/irqchip/arm-gic.h>
21#include <linux/err.h> 22#include <linux/err.h>
@@ -165,9 +166,75 @@ int exynos_cluster_power_state(int cluster)
165 S5P_CORE_LOCAL_PWR_EN); 166 S5P_CORE_LOCAL_PWR_EN);
166} 167}
167 168
169#define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
170 S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
171 (sysram_base_addr + 0x24) : S5P_INFORM0))
172#define EXYNOS_BOOT_VECTOR_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
173 S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
174 (sysram_base_addr + 0x20) : S5P_INFORM1))
175
176#define S5P_CHECK_AFTR 0xFCBA0D10
177#define S5P_CHECK_SLEEP 0x00000BAD
178
179/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
180static void exynos_set_wakeupmask(long mask)
181{
182 __raw_writel(mask, S5P_WAKEUP_MASK);
183}
184
185static void exynos_cpu_set_boot_vector(long flags)
186{
187 __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
188 __raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG);
189}
190
191void exynos_enter_aftr(void)
192{
193 exynos_set_wakeupmask(0x0000ff3e);
194 exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
195 /* Set value of power down register for aftr mode */
196 exynos_sys_powerdown_conf(SYS_AFTR);
197}
198
168/* For Cortex-A9 Diagnostic and Power control register */ 199/* For Cortex-A9 Diagnostic and Power control register */
169static unsigned int save_arm_register[2]; 200static unsigned int save_arm_register[2];
170 201
202static void exynos_cpu_save_register(void)
203{
204 unsigned long tmp;
205
206 /* Save Power control register */
207 asm ("mrc p15, 0, %0, c15, c0, 0"
208 : "=r" (tmp) : : "cc");
209
210 save_arm_register[0] = tmp;
211
212 /* Save Diagnostic register */
213 asm ("mrc p15, 0, %0, c15, c0, 1"
214 : "=r" (tmp) : : "cc");
215
216 save_arm_register[1] = tmp;
217}
218
219static void exynos_cpu_restore_register(void)
220{
221 unsigned long tmp;
222
223 /* Restore Power control register */
224 tmp = save_arm_register[0];
225
226 asm volatile ("mcr p15, 0, %0, c15, c0, 0"
227 : : "r" (tmp)
228 : "cc");
229
230 /* Restore Diagnostic register */
231 tmp = save_arm_register[1];
232
233 asm volatile ("mcr p15, 0, %0, c15, c0, 1"
234 : : "r" (tmp)
235 : "cc");
236}
237
171static int exynos_cpu_suspend(unsigned long arg) 238static int exynos_cpu_suspend(unsigned long arg)
172{ 239{
173#ifdef CONFIG_CACHE_L2X0 240#ifdef CONFIG_CACHE_L2X0
@@ -212,37 +279,34 @@ static void exynos_pm_prepare(void)
212 __raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0); 279 __raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
213} 280}
214 281
215static int exynos_pm_suspend(void) 282static void exynos_pm_central_suspend(void)
216{ 283{
217 unsigned long tmp; 284 unsigned long tmp;
218 285
219 /* Setting Central Sequence Register for power down mode */ 286 /* Setting Central Sequence Register for power down mode */
220
221 tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); 287 tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
222 tmp &= ~S5P_CENTRAL_LOWPWR_CFG; 288 tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
223 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); 289 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
290}
291
292static int exynos_pm_suspend(void)
293{
294 unsigned long tmp;
295
296 exynos_pm_central_suspend();
224 297
225 /* Setting SEQ_OPTION register */ 298 /* Setting SEQ_OPTION register */
226 299
227 tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0); 300 tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
228 __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION); 301 __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
229 302
230 if (!soc_is_exynos5250()) { 303 if (!soc_is_exynos5250())
231 /* Save Power control register */ 304 exynos_cpu_save_register();
232 asm ("mrc p15, 0, %0, c15, c0, 0"
233 : "=r" (tmp) : : "cc");
234 save_arm_register[0] = tmp;
235
236 /* Save Diagnostic register */
237 asm ("mrc p15, 0, %0, c15, c0, 1"
238 : "=r" (tmp) : : "cc");
239 save_arm_register[1] = tmp;
240 }
241 305
242 return 0; 306 return 0;
243} 307}
244 308
245static void exynos_pm_resume(void) 309static int exynos_pm_central_resume(void)
246{ 310{
247 unsigned long tmp; 311 unsigned long tmp;
248 312
@@ -259,22 +323,20 @@ static void exynos_pm_resume(void)
259 /* clear the wakeup state register */ 323 /* clear the wakeup state register */
260 __raw_writel(0x0, S5P_WAKEUP_STAT); 324 __raw_writel(0x0, S5P_WAKEUP_STAT);
261 /* No need to perform below restore code */ 325 /* No need to perform below restore code */
262 goto early_wakeup; 326 return -1;
263 }
264 if (!soc_is_exynos5250()) {
265 /* Restore Power control register */
266 tmp = save_arm_register[0];
267 asm volatile ("mcr p15, 0, %0, c15, c0, 0"
268 : : "r" (tmp)
269 : "cc");
270
271 /* Restore Diagnostic register */
272 tmp = save_arm_register[1];
273 asm volatile ("mcr p15, 0, %0, c15, c0, 1"
274 : : "r" (tmp)
275 : "cc");
276 } 327 }
277 328
329 return 0;
330}
331
332static void exynos_pm_resume(void)
333{
334 if (exynos_pm_central_resume())
335 goto early_wakeup;
336
337 if (!soc_is_exynos5250())
338 exynos_cpu_restore_register();
339
278 /* For release retention */ 340 /* For release retention */
279 341
280 __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION); 342 __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
@@ -291,7 +353,7 @@ static void exynos_pm_resume(void)
291 353
292 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 354 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
293 355
294 if (IS_ENABLED(CONFIG_SMP) && !soc_is_exynos5250()) 356 if (!soc_is_exynos5250())
295 scu_enable(S5P_VA_SCU); 357 scu_enable(S5P_VA_SCU);
296 358
297early_wakeup: 359early_wakeup:
@@ -369,10 +431,42 @@ static const struct platform_suspend_ops exynos_suspend_ops = {
369 .valid = suspend_valid_only_mem, 431 .valid = suspend_valid_only_mem,
370}; 432};
371 433
434static int exynos_cpu_pm_notifier(struct notifier_block *self,
435 unsigned long cmd, void *v)
436{
437 int cpu = smp_processor_id();
438
439 switch (cmd) {
440 case CPU_PM_ENTER:
441 if (cpu == 0) {
442 exynos_pm_central_suspend();
443 exynos_cpu_save_register();
444 }
445 break;
446
447 case CPU_PM_EXIT:
448 if (cpu == 0) {
449 if (!soc_is_exynos5250())
450 scu_enable(S5P_VA_SCU);
451 exynos_cpu_restore_register();
452 exynos_pm_central_resume();
453 }
454 break;
455 }
456
457 return NOTIFY_OK;
458}
459
460static struct notifier_block exynos_cpu_pm_notifier_block = {
461 .notifier_call = exynos_cpu_pm_notifier,
462};
463
372void __init exynos_pm_init(void) 464void __init exynos_pm_init(void)
373{ 465{
374 u32 tmp; 466 u32 tmp;
375 467
468 cpu_pm_register_notifier(&exynos_cpu_pm_notifier_block);
469
376 /* Platform-specific GIC callback */ 470 /* Platform-specific GIC callback */
377 gic_arch_extn.irq_set_wake = exynos_irq_set_wake; 471 gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
378 472
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index 4179f6a6d595..1d13b08708f0 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -129,8 +129,6 @@
129#define S5P_CORE_LOCAL_PWR_EN 0x3 129#define S5P_CORE_LOCAL_PWR_EN 0x3
130#define S5P_INT_LOCAL_PWR_EN 0x7 130#define S5P_INT_LOCAL_PWR_EN 0x7
131 131
132#define S5P_CHECK_SLEEP 0x00000BAD
133
134/* Only for EXYNOS4210 */ 132/* Only for EXYNOS4210 */
135#define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154) 133#define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154)
136#define S5P_CMU_RESET_LCD1_LOWPWR S5P_PMUREG(0x1174) 134#define S5P_CMU_RESET_LCD1_LOWPWR S5P_PMUREG(0x1174)