diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-nomadik.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-nomadik.c | 392 |
1 files changed, 341 insertions, 51 deletions
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 3197870d740a..36d20293de5c 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/irqdomain.h> | 25 | #include <linux/irqdomain.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
28 | #include <linux/of_address.h> | ||
29 | #include <linux/pinctrl/machine.h> | ||
28 | #include <linux/pinctrl/pinctrl.h> | 30 | #include <linux/pinctrl/pinctrl.h> |
29 | #include <linux/pinctrl/pinmux.h> | 31 | #include <linux/pinctrl/pinmux.h> |
30 | #include <linux/pinctrl/pinconf.h> | 32 | #include <linux/pinctrl/pinconf.h> |
@@ -32,8 +34,8 @@ | |||
32 | #include <linux/pinctrl/consumer.h> | 34 | #include <linux/pinctrl/consumer.h> |
33 | #include <linux/platform_data/pinctrl-nomadik.h> | 35 | #include <linux/platform_data/pinctrl-nomadik.h> |
34 | #include <asm/mach/irq.h> | 36 | #include <asm/mach/irq.h> |
35 | #include <mach/irqs.h> | ||
36 | #include "pinctrl-nomadik.h" | 37 | #include "pinctrl-nomadik.h" |
38 | #include "core.h" | ||
37 | 39 | ||
38 | /* | 40 | /* |
39 | * The GPIO module in the Nomadik family of Systems-on-Chip is an | 41 | * The GPIO module in the Nomadik family of Systems-on-Chip is an |
@@ -216,7 +218,7 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset) | |||
216 | u32 falling = nmk_chip->fimsc & BIT(offset); | 218 | u32 falling = nmk_chip->fimsc & BIT(offset); |
217 | u32 rising = nmk_chip->rimsc & BIT(offset); | 219 | u32 rising = nmk_chip->rimsc & BIT(offset); |
218 | int gpio = nmk_chip->chip.base + offset; | 220 | int gpio = nmk_chip->chip.base + offset; |
219 | int irq = NOMADIK_GPIO_TO_IRQ(gpio); | 221 | int irq = irq_find_mapping(nmk_chip->domain, offset); |
220 | struct irq_data *d = irq_get_irq_data(irq); | 222 | struct irq_data *d = irq_get_irq_data(irq); |
221 | 223 | ||
222 | if (!rising && !falling) | 224 | if (!rising && !falling) |
@@ -1341,8 +1343,7 @@ static int nmk_gpio_probe(struct platform_device *dev) | |||
1341 | 1343 | ||
1342 | if (of_property_read_u32(np, "gpio-bank", &dev->id)) { | 1344 | if (of_property_read_u32(np, "gpio-bank", &dev->id)) { |
1343 | dev_err(&dev->dev, "gpio-bank property not found\n"); | 1345 | dev_err(&dev->dev, "gpio-bank property not found\n"); |
1344 | ret = -EINVAL; | 1346 | return -EINVAL; |
1345 | goto out; | ||
1346 | } | 1347 | } |
1347 | 1348 | ||
1348 | pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP; | 1349 | pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP; |
@@ -1350,41 +1351,29 @@ static int nmk_gpio_probe(struct platform_device *dev) | |||
1350 | } | 1351 | } |
1351 | 1352 | ||
1352 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | 1353 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
1353 | if (!res) { | 1354 | if (!res) |
1354 | ret = -ENOENT; | 1355 | return -ENOENT; |
1355 | goto out; | ||
1356 | } | ||
1357 | 1356 | ||
1358 | irq = platform_get_irq(dev, 0); | 1357 | irq = platform_get_irq(dev, 0); |
1359 | if (irq < 0) { | 1358 | if (irq < 0) |
1360 | ret = irq; | 1359 | return irq; |
1361 | goto out; | ||
1362 | } | ||
1363 | 1360 | ||
1364 | secondary_irq = platform_get_irq(dev, 1); | 1361 | secondary_irq = platform_get_irq(dev, 1); |
1365 | if (secondary_irq >= 0 && !pdata->get_secondary_status) { | 1362 | if (secondary_irq >= 0 && !pdata->get_secondary_status) |
1366 | ret = -EINVAL; | 1363 | return -EINVAL; |
1367 | goto out; | ||
1368 | } | ||
1369 | 1364 | ||
1370 | base = devm_request_and_ioremap(&dev->dev, res); | 1365 | base = devm_ioremap_resource(&dev->dev, res); |
1371 | if (!base) { | 1366 | if (IS_ERR(base)) |
1372 | ret = -ENOMEM; | 1367 | return PTR_ERR(base); |
1373 | goto out; | ||
1374 | } | ||
1375 | 1368 | ||
1376 | clk = devm_clk_get(&dev->dev, NULL); | 1369 | clk = devm_clk_get(&dev->dev, NULL); |
1377 | if (IS_ERR(clk)) { | 1370 | if (IS_ERR(clk)) |
1378 | ret = PTR_ERR(clk); | 1371 | return PTR_ERR(clk); |
1379 | goto out; | ||
1380 | } | ||
1381 | clk_prepare(clk); | 1372 | clk_prepare(clk); |
1382 | 1373 | ||
1383 | nmk_chip = devm_kzalloc(&dev->dev, sizeof(*nmk_chip), GFP_KERNEL); | 1374 | nmk_chip = devm_kzalloc(&dev->dev, sizeof(*nmk_chip), GFP_KERNEL); |
1384 | if (!nmk_chip) { | 1375 | if (!nmk_chip) |
1385 | ret = -ENOMEM; | 1376 | return -ENOMEM; |
1386 | goto out; | ||
1387 | } | ||
1388 | 1377 | ||
1389 | /* | 1378 | /* |
1390 | * The virt address in nmk_chip->addr is in the nomadik register space, | 1379 | * The virt address in nmk_chip->addr is in the nomadik register space, |
@@ -1418,7 +1407,7 @@ static int nmk_gpio_probe(struct platform_device *dev) | |||
1418 | 1407 | ||
1419 | ret = gpiochip_add(&nmk_chip->chip); | 1408 | ret = gpiochip_add(&nmk_chip->chip); |
1420 | if (ret) | 1409 | if (ret) |
1421 | goto out; | 1410 | return ret; |
1422 | 1411 | ||
1423 | BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); | 1412 | BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); |
1424 | 1413 | ||
@@ -1427,14 +1416,15 @@ static int nmk_gpio_probe(struct platform_device *dev) | |||
1427 | platform_set_drvdata(dev, nmk_chip); | 1416 | platform_set_drvdata(dev, nmk_chip); |
1428 | 1417 | ||
1429 | if (!np) | 1418 | if (!np) |
1430 | irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio); | 1419 | irq_start = pdata->first_irq; |
1431 | nmk_chip->domain = irq_domain_add_simple(np, | 1420 | nmk_chip->domain = irq_domain_add_simple(np, |
1432 | NMK_GPIO_PER_CHIP, irq_start, | 1421 | NMK_GPIO_PER_CHIP, irq_start, |
1433 | &nmk_gpio_irq_simple_ops, nmk_chip); | 1422 | &nmk_gpio_irq_simple_ops, nmk_chip); |
1434 | if (!nmk_chip->domain) { | 1423 | if (!nmk_chip->domain) { |
1435 | dev_err(&dev->dev, "failed to create irqdomain\n"); | 1424 | dev_err(&dev->dev, "failed to create irqdomain\n"); |
1436 | ret = -ENOSYS; | 1425 | /* Just do this, no matter if it fails */ |
1437 | goto out; | 1426 | ret = gpiochip_remove(&nmk_chip->chip); |
1427 | return -ENOSYS; | ||
1438 | } | 1428 | } |
1439 | 1429 | ||
1440 | nmk_gpio_init_irq(nmk_chip); | 1430 | nmk_gpio_init_irq(nmk_chip); |
@@ -1442,12 +1432,6 @@ static int nmk_gpio_probe(struct platform_device *dev) | |||
1442 | dev_info(&dev->dev, "at address %p\n", nmk_chip->addr); | 1432 | dev_info(&dev->dev, "at address %p\n", nmk_chip->addr); |
1443 | 1433 | ||
1444 | return 0; | 1434 | return 0; |
1445 | |||
1446 | out: | ||
1447 | dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, | ||
1448 | pdata->first_gpio, pdata->first_gpio+31); | ||
1449 | |||
1450 | return ret; | ||
1451 | } | 1435 | } |
1452 | 1436 | ||
1453 | static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev) | 1437 | static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev) |
@@ -1508,11 +1492,285 @@ static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, | |||
1508 | nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); | 1492 | nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); |
1509 | } | 1493 | } |
1510 | 1494 | ||
1495 | static void nmk_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, | ||
1496 | struct pinctrl_map *map, unsigned num_maps) | ||
1497 | { | ||
1498 | int i; | ||
1499 | |||
1500 | for (i = 0; i < num_maps; i++) | ||
1501 | if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN) | ||
1502 | kfree(map[i].data.configs.configs); | ||
1503 | kfree(map); | ||
1504 | } | ||
1505 | |||
1506 | static int nmk_dt_reserve_map(struct pinctrl_map **map, unsigned *reserved_maps, | ||
1507 | unsigned *num_maps, unsigned reserve) | ||
1508 | { | ||
1509 | unsigned old_num = *reserved_maps; | ||
1510 | unsigned new_num = *num_maps + reserve; | ||
1511 | struct pinctrl_map *new_map; | ||
1512 | |||
1513 | if (old_num >= new_num) | ||
1514 | return 0; | ||
1515 | |||
1516 | new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); | ||
1517 | if (!new_map) | ||
1518 | return -ENOMEM; | ||
1519 | |||
1520 | memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); | ||
1521 | |||
1522 | *map = new_map; | ||
1523 | *reserved_maps = new_num; | ||
1524 | |||
1525 | return 0; | ||
1526 | } | ||
1527 | |||
1528 | static int nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps, | ||
1529 | unsigned *num_maps, const char *group, | ||
1530 | const char *function) | ||
1531 | { | ||
1532 | if (*num_maps == *reserved_maps) | ||
1533 | return -ENOSPC; | ||
1534 | |||
1535 | (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; | ||
1536 | (*map)[*num_maps].data.mux.group = group; | ||
1537 | (*map)[*num_maps].data.mux.function = function; | ||
1538 | (*num_maps)++; | ||
1539 | |||
1540 | return 0; | ||
1541 | } | ||
1542 | |||
1543 | static int nmk_dt_add_map_configs(struct pinctrl_map **map, | ||
1544 | unsigned *reserved_maps, | ||
1545 | unsigned *num_maps, const char *group, | ||
1546 | unsigned long *configs, unsigned num_configs) | ||
1547 | { | ||
1548 | unsigned long *dup_configs; | ||
1549 | |||
1550 | if (*num_maps == *reserved_maps) | ||
1551 | return -ENOSPC; | ||
1552 | |||
1553 | dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), | ||
1554 | GFP_KERNEL); | ||
1555 | if (!dup_configs) | ||
1556 | return -ENOMEM; | ||
1557 | |||
1558 | (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN; | ||
1559 | |||
1560 | (*map)[*num_maps].data.configs.group_or_pin = group; | ||
1561 | (*map)[*num_maps].data.configs.configs = dup_configs; | ||
1562 | (*map)[*num_maps].data.configs.num_configs = num_configs; | ||
1563 | (*num_maps)++; | ||
1564 | |||
1565 | return 0; | ||
1566 | } | ||
1567 | |||
1568 | #define NMK_CONFIG_PIN(x,y) { .property = x, .config = y, } | ||
1569 | #define NMK_CONFIG_PIN_ARRAY(x,y) { .property = x, .choice = y, \ | ||
1570 | .size = ARRAY_SIZE(y), } | ||
1571 | |||
1572 | static const unsigned long nmk_pin_input_modes[] = { | ||
1573 | PIN_INPUT_NOPULL, | ||
1574 | PIN_INPUT_PULLUP, | ||
1575 | PIN_INPUT_PULLDOWN, | ||
1576 | }; | ||
1577 | |||
1578 | static const unsigned long nmk_pin_output_modes[] = { | ||
1579 | PIN_OUTPUT_LOW, | ||
1580 | PIN_OUTPUT_HIGH, | ||
1581 | PIN_DIR_OUTPUT, | ||
1582 | }; | ||
1583 | |||
1584 | static const unsigned long nmk_pin_sleep_modes[] = { | ||
1585 | PIN_SLEEPMODE_DISABLED, | ||
1586 | PIN_SLEEPMODE_ENABLED, | ||
1587 | }; | ||
1588 | |||
1589 | static const unsigned long nmk_pin_sleep_input_modes[] = { | ||
1590 | PIN_SLPM_INPUT_NOPULL, | ||
1591 | PIN_SLPM_INPUT_PULLUP, | ||
1592 | PIN_SLPM_INPUT_PULLDOWN, | ||
1593 | PIN_SLPM_DIR_INPUT, | ||
1594 | }; | ||
1595 | |||
1596 | static const unsigned long nmk_pin_sleep_output_modes[] = { | ||
1597 | PIN_SLPM_OUTPUT_LOW, | ||
1598 | PIN_SLPM_OUTPUT_HIGH, | ||
1599 | PIN_SLPM_DIR_OUTPUT, | ||
1600 | }; | ||
1601 | |||
1602 | static const unsigned long nmk_pin_sleep_wakeup_modes[] = { | ||
1603 | PIN_SLPM_WAKEUP_DISABLE, | ||
1604 | PIN_SLPM_WAKEUP_ENABLE, | ||
1605 | }; | ||
1606 | |||
1607 | static const unsigned long nmk_pin_gpio_modes[] = { | ||
1608 | PIN_GPIOMODE_DISABLED, | ||
1609 | PIN_GPIOMODE_ENABLED, | ||
1610 | }; | ||
1611 | |||
1612 | static const unsigned long nmk_pin_sleep_pdis_modes[] = { | ||
1613 | PIN_SLPM_PDIS_DISABLED, | ||
1614 | PIN_SLPM_PDIS_ENABLED, | ||
1615 | }; | ||
1616 | |||
1617 | struct nmk_cfg_param { | ||
1618 | const char *property; | ||
1619 | unsigned long config; | ||
1620 | const unsigned long *choice; | ||
1621 | int size; | ||
1622 | }; | ||
1623 | |||
1624 | static const struct nmk_cfg_param nmk_cfg_params[] = { | ||
1625 | NMK_CONFIG_PIN_ARRAY("ste,input", nmk_pin_input_modes), | ||
1626 | NMK_CONFIG_PIN_ARRAY("ste,output", nmk_pin_output_modes), | ||
1627 | NMK_CONFIG_PIN_ARRAY("ste,sleep", nmk_pin_sleep_modes), | ||
1628 | NMK_CONFIG_PIN_ARRAY("ste,sleep-input", nmk_pin_sleep_input_modes), | ||
1629 | NMK_CONFIG_PIN_ARRAY("ste,sleep-output", nmk_pin_sleep_output_modes), | ||
1630 | NMK_CONFIG_PIN_ARRAY("ste,sleep-wakeup", nmk_pin_sleep_wakeup_modes), | ||
1631 | NMK_CONFIG_PIN_ARRAY("ste,gpio", nmk_pin_gpio_modes), | ||
1632 | NMK_CONFIG_PIN_ARRAY("ste,sleep-pull-disable", nmk_pin_sleep_pdis_modes), | ||
1633 | }; | ||
1634 | |||
1635 | static int nmk_dt_pin_config(int index, int val, unsigned long *config) | ||
1636 | { | ||
1637 | int ret = 0; | ||
1638 | |||
1639 | if (nmk_cfg_params[index].choice == NULL) | ||
1640 | *config = nmk_cfg_params[index].config; | ||
1641 | else { | ||
1642 | /* test if out of range */ | ||
1643 | if (val < nmk_cfg_params[index].size) { | ||
1644 | *config = nmk_cfg_params[index].config | | ||
1645 | nmk_cfg_params[index].choice[val]; | ||
1646 | } | ||
1647 | } | ||
1648 | return ret; | ||
1649 | } | ||
1650 | |||
1651 | static const char *nmk_find_pin_name(struct pinctrl_dev *pctldev, const char *pin_name) | ||
1652 | { | ||
1653 | int i, pin_number; | ||
1654 | struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); | ||
1655 | |||
1656 | if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1) | ||
1657 | for (i = 0; i < npct->soc->npins; i++) | ||
1658 | if (npct->soc->pins[i].number == pin_number) | ||
1659 | return npct->soc->pins[i].name; | ||
1660 | return NULL; | ||
1661 | } | ||
1662 | |||
1663 | static bool nmk_pinctrl_dt_get_config(struct device_node *np, | ||
1664 | unsigned long *configs) | ||
1665 | { | ||
1666 | bool has_config = 0; | ||
1667 | unsigned long cfg = 0; | ||
1668 | int i, val, ret; | ||
1669 | |||
1670 | for (i = 0; i < ARRAY_SIZE(nmk_cfg_params); i++) { | ||
1671 | ret = of_property_read_u32(np, | ||
1672 | nmk_cfg_params[i].property, &val); | ||
1673 | if (ret != -EINVAL) { | ||
1674 | if (nmk_dt_pin_config(i, val, &cfg) == 0) { | ||
1675 | *configs |= cfg; | ||
1676 | has_config = 1; | ||
1677 | } | ||
1678 | } | ||
1679 | } | ||
1680 | |||
1681 | return has_config; | ||
1682 | } | ||
1683 | |||
1684 | int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, | ||
1685 | struct device_node *np, | ||
1686 | struct pinctrl_map **map, | ||
1687 | unsigned *reserved_maps, | ||
1688 | unsigned *num_maps) | ||
1689 | { | ||
1690 | int ret; | ||
1691 | const char *function = NULL; | ||
1692 | unsigned long configs = 0; | ||
1693 | bool has_config = 0; | ||
1694 | unsigned reserve = 0; | ||
1695 | struct property *prop; | ||
1696 | const char *group, *gpio_name; | ||
1697 | struct device_node *np_config; | ||
1698 | |||
1699 | ret = of_property_read_string(np, "ste,function", &function); | ||
1700 | if (ret >= 0) | ||
1701 | reserve = 1; | ||
1702 | |||
1703 | has_config = nmk_pinctrl_dt_get_config(np, &configs); | ||
1704 | |||
1705 | np_config = of_parse_phandle(np, "ste,config", 0); | ||
1706 | if (np_config) | ||
1707 | has_config |= nmk_pinctrl_dt_get_config(np_config, &configs); | ||
1708 | |||
1709 | ret = of_property_count_strings(np, "ste,pins"); | ||
1710 | if (ret < 0) | ||
1711 | goto exit; | ||
1712 | |||
1713 | if (has_config) | ||
1714 | reserve++; | ||
1715 | |||
1716 | reserve *= ret; | ||
1717 | |||
1718 | ret = nmk_dt_reserve_map(map, reserved_maps, num_maps, reserve); | ||
1719 | if (ret < 0) | ||
1720 | goto exit; | ||
1721 | |||
1722 | of_property_for_each_string(np, "ste,pins", prop, group) { | ||
1723 | if (function) { | ||
1724 | ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps, | ||
1725 | group, function); | ||
1726 | if (ret < 0) | ||
1727 | goto exit; | ||
1728 | } | ||
1729 | if (has_config) { | ||
1730 | gpio_name = nmk_find_pin_name(pctldev, group); | ||
1731 | |||
1732 | ret = nmk_dt_add_map_configs(map, reserved_maps, num_maps, | ||
1733 | gpio_name, &configs, 1); | ||
1734 | if (ret < 0) | ||
1735 | goto exit; | ||
1736 | } | ||
1737 | |||
1738 | } | ||
1739 | exit: | ||
1740 | return ret; | ||
1741 | } | ||
1742 | |||
1743 | int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, | ||
1744 | struct device_node *np_config, | ||
1745 | struct pinctrl_map **map, unsigned *num_maps) | ||
1746 | { | ||
1747 | unsigned reserved_maps; | ||
1748 | struct device_node *np; | ||
1749 | int ret; | ||
1750 | |||
1751 | reserved_maps = 0; | ||
1752 | *map = NULL; | ||
1753 | *num_maps = 0; | ||
1754 | |||
1755 | for_each_child_of_node(np_config, np) { | ||
1756 | ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map, | ||
1757 | &reserved_maps, num_maps); | ||
1758 | if (ret < 0) { | ||
1759 | nmk_pinctrl_dt_free_map(pctldev, *map, *num_maps); | ||
1760 | return ret; | ||
1761 | } | ||
1762 | } | ||
1763 | |||
1764 | return 0; | ||
1765 | } | ||
1766 | |||
1511 | static struct pinctrl_ops nmk_pinctrl_ops = { | 1767 | static struct pinctrl_ops nmk_pinctrl_ops = { |
1512 | .get_groups_count = nmk_get_groups_cnt, | 1768 | .get_groups_count = nmk_get_groups_cnt, |
1513 | .get_group_name = nmk_get_group_name, | 1769 | .get_group_name = nmk_get_group_name, |
1514 | .get_group_pins = nmk_get_group_pins, | 1770 | .get_group_pins = nmk_get_group_pins, |
1515 | .pin_dbg_show = nmk_pin_dbg_show, | 1771 | .pin_dbg_show = nmk_pin_dbg_show, |
1772 | .dt_node_to_map = nmk_pinctrl_dt_node_to_map, | ||
1773 | .dt_free_map = nmk_pinctrl_dt_free_map, | ||
1516 | }; | 1774 | }; |
1517 | 1775 | ||
1518 | static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) | 1776 | static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) |
@@ -1850,16 +2108,39 @@ static const struct of_device_id nmk_pinctrl_match[] = { | |||
1850 | .data = (void *)PINCTRL_NMK_STN8815, | 2108 | .data = (void *)PINCTRL_NMK_STN8815, |
1851 | }, | 2109 | }, |
1852 | { | 2110 | { |
1853 | .compatible = "stericsson,nmk_pinctrl", | 2111 | .compatible = "stericsson,nmk-pinctrl", |
1854 | .data = (void *)PINCTRL_NMK_DB8500, | 2112 | .data = (void *)PINCTRL_NMK_DB8500, |
1855 | }, | 2113 | }, |
1856 | {}, | 2114 | {}, |
1857 | }; | 2115 | }; |
1858 | 2116 | ||
2117 | static int nmk_pinctrl_suspend(struct platform_device *pdev, pm_message_t state) | ||
2118 | { | ||
2119 | struct nmk_pinctrl *npct; | ||
2120 | |||
2121 | npct = platform_get_drvdata(pdev); | ||
2122 | if (!npct) | ||
2123 | return -EINVAL; | ||
2124 | |||
2125 | return pinctrl_force_sleep(npct->pctl); | ||
2126 | } | ||
2127 | |||
2128 | static int nmk_pinctrl_resume(struct platform_device *pdev) | ||
2129 | { | ||
2130 | struct nmk_pinctrl *npct; | ||
2131 | |||
2132 | npct = platform_get_drvdata(pdev); | ||
2133 | if (!npct) | ||
2134 | return -EINVAL; | ||
2135 | |||
2136 | return pinctrl_force_default(npct->pctl); | ||
2137 | } | ||
2138 | |||
1859 | static int nmk_pinctrl_probe(struct platform_device *pdev) | 2139 | static int nmk_pinctrl_probe(struct platform_device *pdev) |
1860 | { | 2140 | { |
1861 | const struct platform_device_id *platid = platform_get_device_id(pdev); | 2141 | const struct platform_device_id *platid = platform_get_device_id(pdev); |
1862 | struct device_node *np = pdev->dev.of_node; | 2142 | struct device_node *np = pdev->dev.of_node; |
2143 | struct device_node *prcm_np; | ||
1863 | struct nmk_pinctrl *npct; | 2144 | struct nmk_pinctrl *npct; |
1864 | struct resource *res; | 2145 | struct resource *res; |
1865 | unsigned int version = 0; | 2146 | unsigned int version = 0; |
@@ -1888,21 +2169,26 @@ static int nmk_pinctrl_probe(struct platform_device *pdev) | |||
1888 | if (version == PINCTRL_NMK_DB8540) | 2169 | if (version == PINCTRL_NMK_DB8540) |
1889 | nmk_pinctrl_db8540_init(&npct->soc); | 2170 | nmk_pinctrl_db8540_init(&npct->soc); |
1890 | 2171 | ||
2172 | if (np) { | ||
2173 | prcm_np = of_parse_phandle(np, "prcm", 0); | ||
2174 | if (prcm_np) | ||
2175 | npct->prcm_base = of_iomap(prcm_np, 0); | ||
2176 | } | ||
2177 | |||
2178 | /* Allow platform passed information to over-write DT. */ | ||
1891 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2179 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1892 | if (res) { | 2180 | if (res) |
1893 | npct->prcm_base = devm_ioremap(&pdev->dev, res->start, | 2181 | npct->prcm_base = devm_ioremap(&pdev->dev, res->start, |
1894 | resource_size(res)); | 2182 | resource_size(res)); |
1895 | if (!npct->prcm_base) { | 2183 | if (!npct->prcm_base) { |
1896 | dev_err(&pdev->dev, | 2184 | if (version == PINCTRL_NMK_STN8815) { |
1897 | "failed to ioremap PRCM registers\n"); | 2185 | dev_info(&pdev->dev, |
1898 | return -ENOMEM; | 2186 | "No PRCM base, " |
2187 | "assuming no ALT-Cx control is available\n"); | ||
2188 | } else { | ||
2189 | dev_err(&pdev->dev, "missing PRCM base address\n"); | ||
2190 | return -EINVAL; | ||
1899 | } | 2191 | } |
1900 | } else if (version == PINCTRL_NMK_STN8815) { | ||
1901 | dev_info(&pdev->dev, | ||
1902 | "No PRCM base, assume no ALT-Cx control is available\n"); | ||
1903 | } else { | ||
1904 | dev_err(&pdev->dev, "missing PRCM base address\n"); | ||
1905 | return -EINVAL; | ||
1906 | } | 2192 | } |
1907 | 2193 | ||
1908 | /* | 2194 | /* |
@@ -1967,6 +2253,10 @@ static struct platform_driver nmk_pinctrl_driver = { | |||
1967 | }, | 2253 | }, |
1968 | .probe = nmk_pinctrl_probe, | 2254 | .probe = nmk_pinctrl_probe, |
1969 | .id_table = nmk_pinctrl_id, | 2255 | .id_table = nmk_pinctrl_id, |
2256 | #ifdef CONFIG_PM | ||
2257 | .suspend = nmk_pinctrl_suspend, | ||
2258 | .resume = nmk_pinctrl_resume, | ||
2259 | #endif | ||
1970 | }; | 2260 | }; |
1971 | 2261 | ||
1972 | static int __init nmk_gpio_init(void) | 2262 | static int __init nmk_gpio_init(void) |