diff options
Diffstat (limited to 'drivers/hte/hte-tegra194.c')
| -rw-r--r-- | drivers/hte/hte-tegra194.c | 210 |
1 files changed, 176 insertions, 34 deletions
diff --git a/drivers/hte/hte-tegra194.c b/drivers/hte/hte-tegra194.c index 49a27af22742..690eb9be30fb 100644 --- a/drivers/hte/hte-tegra194.c +++ b/drivers/hte/hte-tegra194.c @@ -12,7 +12,6 @@ #include <linux/stat.h> #include <linux/interrupt.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/hte.h> #include <linux/uaccess.h> @@ -62,6 +61,10 @@ #define NV_AON_HTE_SLICE2_IRQ_GPIO_25 25 #define NV_AON_HTE_SLICE2_IRQ_GPIO_26 26 #define NV_AON_HTE_SLICE2_IRQ_GPIO_27 27 +#define NV_AON_HTE_SLICE2_IRQ_GPIO_28 28 +#define NV_AON_HTE_SLICE2_IRQ_GPIO_29 29 +#define NV_AON_HTE_SLICE2_IRQ_GPIO_30 30 +#define NV_AON_HTE_SLICE2_IRQ_GPIO_31 31 #define HTE_TECTRL 0x0 #define HTE_TETSCH 0x4 @@ -114,6 +117,7 @@ struct tegra_hte_line_data { struct tegra_hte_data { enum tegra_hte_type type; + u32 slices; u32 map_sz; u32 sec_map_sz; const struct tegra_hte_line_mapped *map; @@ -128,7 +132,7 @@ struct tegra_hte_soc { const struct tegra_hte_data *prov_data; struct tegra_hte_line_data *line_data; struct hte_chip *chip; - struct gpio_chip *c; + struct gpio_device *gdev; void __iomem *regs; }; @@ -220,18 +224,129 @@ static const struct tegra_hte_line_mapped tegra194_aon_gpio_sec_map[] = { [39] = {NV_AON_SLICE_INVALID, 0}, }; -static const struct tegra_hte_data aon_hte = { +static const struct tegra_hte_line_mapped tegra234_aon_gpio_map[] = { + /* gpio, slice, bit_index */ + /* AA port */ + [0] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_11}, + [1] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_10}, + [2] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_9}, + [3] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_8}, + [4] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_7}, + [5] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_6}, + [6] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_5}, + [7] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_4}, + /* BB port */ + [8] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_3}, + [9] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_2}, + [10] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_1}, + [11] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_0}, + /* CC port */ + [12] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_22}, + [13] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_21}, + [14] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_20}, + [15] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_19}, + [16] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_18}, + [17] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_17}, + [18] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_16}, + [19] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_15}, + /* DD port */ + [20] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_14}, + [21] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_13}, + [22] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_12}, + /* EE port */ + [23] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_31}, + [24] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_30}, + [25] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_29}, + [26] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_28}, + [27] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_27}, + [28] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_26}, + [29] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_25}, + [30] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_24}, + /* GG port */ + [31] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_23}, +}; + +static const struct tegra_hte_line_mapped tegra234_aon_gpio_sec_map[] = { + /* gpio, slice, bit_index */ + /* AA port */ + [0] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_11}, + [1] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_10}, + [2] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_9}, + [3] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_8}, + [4] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_7}, + [5] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_6}, + [6] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_5}, + [7] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_4}, + /* BB port */ + [8] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_3}, + [9] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_2}, + [10] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_1}, + [11] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_0}, + [12] = {NV_AON_SLICE_INVALID, 0}, + [13] = {NV_AON_SLICE_INVALID, 0}, + [14] = {NV_AON_SLICE_INVALID, 0}, + [15] = {NV_AON_SLICE_INVALID, 0}, + /* CC port */ + [16] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_22}, + [17] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_21}, + [18] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_20}, + [19] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_19}, + [20] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_18}, + [21] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_17}, + [22] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_16}, + [23] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_15}, + /* DD port */ + [24] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_14}, + [25] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_13}, + [26] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_12}, + [27] = {NV_AON_SLICE_INVALID, 0}, + [28] = {NV_AON_SLICE_INVALID, 0}, + [29] = {NV_AON_SLICE_INVALID, 0}, + [30] = {NV_AON_SLICE_INVALID, 0}, + [31] = {NV_AON_SLICE_INVALID, 0}, + /* EE port */ + [32] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_31}, + [33] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_30}, + [34] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_29}, + [35] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_28}, + [36] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_27}, + [37] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_26}, + [38] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_25}, + [39] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_24}, + /* GG port */ + [40] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_23}, +}; + +static const struct tegra_hte_data t194_aon_hte = { .map_sz = ARRAY_SIZE(tegra194_aon_gpio_map), .map = tegra194_aon_gpio_map, .sec_map_sz = ARRAY_SIZE(tegra194_aon_gpio_sec_map), .sec_map = tegra194_aon_gpio_sec_map, .type = HTE_TEGRA_TYPE_GPIO, + .slices = 3, +}; + +static const struct tegra_hte_data t234_aon_hte = { + .map_sz = ARRAY_SIZE(tegra234_aon_gpio_map), + .map = tegra234_aon_gpio_map, + .sec_map_sz = ARRAY_SIZE(tegra234_aon_gpio_sec_map), + .sec_map = tegra234_aon_gpio_sec_map, + .type = HTE_TEGRA_TYPE_GPIO, + .slices = 3, +}; + +static const struct tegra_hte_data t194_lic_hte = { + .map_sz = 0, + .map = NULL, + .type = HTE_TEGRA_TYPE_LIC, + .slices = 11, }; -static const struct tegra_hte_data lic_hte = { +static const struct tegra_hte_data t234_lic_hte = { .map_sz = 0, .map = NULL, .type = HTE_TEGRA_TYPE_LIC, + .slices = 17, }; static inline u32 tegra_hte_readl(struct tegra_hte_soc *hte, u32 reg) @@ -251,7 +366,7 @@ static int tegra_hte_map_to_line_id(u32 eid, { if (m) { - if (eid > map_sz) + if (eid >= map_sz) return -EINVAL; if (m[eid].slice == NV_AON_SLICE_INVALID) return -EINVAL; @@ -292,18 +407,21 @@ static int tegra_hte_line_xlate(struct hte_chip *gc, return -EINVAL; /* + * GPIO consumers can access GPIOs in two ways: + * + * 1) Using the global GPIO numberspace. + * + * This is the old, now DEPRECATED method and should not be used in + * new code. TODO: Check if tegra is even concerned by this. * - * There are two paths GPIO consumers can take as follows: - * 1) The consumer (gpiolib-cdev for example) which uses GPIO global - * number which gets assigned run time. - * 2) The consumer passing GPIO from the DT which is assigned - * statically for example by using TEGRA194_AON_GPIO gpio DT binding. + * 2) Using GPIO descriptors that can be assigned to consumer devices + * using device-tree, ACPI or lookup tables. * * The code below addresses both the consumer use cases and maps into * HTE/GTE namespace. */ if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO && !args) { - line_id = desc->attr.line_id - gs->c->base; + line_id = desc->attr.line_id - gpio_device_get_base(gs->gdev); map = gs->prov_data->map; map_sz = gs->prov_data->map_sz; } else if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO && args) { @@ -530,12 +648,14 @@ static bool tegra_hte_match_from_linedata(const struct hte_chip *chip, if (!hte_dev || (hte_dev->prov_data->type != HTE_TEGRA_TYPE_GPIO)) return false; - return hte_dev->c == gpiod_to_chip(hdesc->attr.line_data); + return hte_dev->gdev == gpiod_to_gpio_device(hdesc->attr.line_data); } static const struct of_device_id tegra_hte_of_match[] = { - { .compatible = "nvidia,tegra194-gte-lic", .data = &lic_hte}, - { .compatible = "nvidia,tegra194-gte-aon", .data = &aon_hte}, + { .compatible = "nvidia,tegra194-gte-lic", .data = &t194_lic_hte}, + { .compatible = "nvidia,tegra194-gte-aon", .data = &t194_aon_hte}, + { .compatible = "nvidia,tegra234-gte-lic", .data = &t234_lic_hte}, + { .compatible = "nvidia,tegra234-gte-aon", .data = &t234_aon_hte}, { } }; MODULE_DEVICE_TABLE(of, tegra_hte_of_match); @@ -556,9 +676,11 @@ static void tegra_gte_disable(void *data) tegra_hte_writel(gs, HTE_TECTRL, 0); } -static int tegra_get_gpiochip_from_name(struct gpio_chip *chip, void *data) +static void tegra_hte_put_gpio_device(void *data) { - return !strcmp(chip->label, data); + struct gpio_device *gdev = data; + + gpio_device_put(gdev); } static int tegra_hte_probe(struct platform_device *pdev) @@ -569,16 +691,10 @@ static int tegra_hte_probe(struct platform_device *pdev) struct device *dev; struct tegra_hte_soc *hte_dev; struct hte_chip *gc; + struct device_node *gpio_ctrl; dev = &pdev->dev; - ret = of_property_read_u32(dev->of_node, "nvidia,slices", &slices); - if (ret != 0) { - dev_err(dev, "Could not read slices\n"); - return -EINVAL; - } - nlines = slices << 5; - hte_dev = devm_kzalloc(dev, sizeof(*hte_dev), GFP_KERNEL); if (!hte_dev) return -ENOMEM; @@ -590,6 +706,13 @@ static int tegra_hte_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, hte_dev); hte_dev->prov_data = of_device_get_match_data(&pdev->dev); + ret = of_property_read_u32(dev->of_node, "nvidia,slices", &slices); + if (ret != 0) + slices = hte_dev->prov_data->slices; + + dev_dbg(dev, "slices:%d\n", slices); + nlines = slices << 5; + hte_dev->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hte_dev->regs)) return PTR_ERR(hte_dev->regs); @@ -605,10 +728,8 @@ static int tegra_hte_probe(struct platform_device *pdev) return -ENOMEM; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err_probe(dev, ret, "failed to get irq\n"); + if (ret < 0) return ret; - } hte_dev->hte_irq = ret; ret = devm_request_irq(dev, hte_dev->hte_irq, tegra_hte_isr, 0, dev_name(dev), hte_dev); @@ -635,11 +756,33 @@ static int tegra_hte_probe(struct platform_device *pdev) gc->match_from_linedata = tegra_hte_match_from_linedata; - hte_dev->c = gpiochip_find("tegra194-gpio-aon", - tegra_get_gpiochip_from_name); - if (!hte_dev->c) + if (of_device_is_compatible(dev->of_node, + "nvidia,tegra194-gte-aon")) { + hte_dev->gdev = + gpio_device_find_by_label("tegra194-gpio-aon"); + } else { + gpio_ctrl = of_parse_phandle(dev->of_node, + "nvidia,gpio-controller", + 0); + if (!gpio_ctrl) { + dev_err(dev, + "gpio controller node not found\n"); + return -ENODEV; + } + + hte_dev->gdev = + gpio_device_find_by_fwnode(of_fwnode_handle(gpio_ctrl)); + of_node_put(gpio_ctrl); + } + + if (!hte_dev->gdev) return dev_err_probe(dev, -EPROBE_DEFER, "wait for gpio controller\n"); + + ret = devm_add_action_or_reset(dev, tegra_hte_put_gpio_device, + hte_dev->gdev); + if (ret) + return ret; } hte_dev->chip = gc; @@ -669,7 +812,7 @@ static int tegra_hte_probe(struct platform_device *pdev) return 0; } -static int __maybe_unused tegra_hte_resume_early(struct device *dev) +static int tegra_hte_resume_early(struct device *dev) { u32 i; struct tegra_hte_soc *gs = dev_get_drvdata(dev); @@ -690,7 +833,7 @@ static int __maybe_unused tegra_hte_resume_early(struct device *dev) return 0; } -static int __maybe_unused tegra_hte_suspend_late(struct device *dev) +static int tegra_hte_suspend_late(struct device *dev) { u32 i; struct tegra_hte_soc *gs = dev_get_drvdata(dev); @@ -710,15 +853,14 @@ static int __maybe_unused tegra_hte_suspend_late(struct device *dev) } static const struct dev_pm_ops tegra_hte_pm = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(tegra_hte_suspend_late, - tegra_hte_resume_early) + LATE_SYSTEM_SLEEP_PM_OPS(tegra_hte_suspend_late, tegra_hte_resume_early) }; static struct platform_driver tegra_hte_driver = { .probe = tegra_hte_probe, .driver = { .name = "tegra_hte", - .pm = &tegra_hte_pm, + .pm = pm_sleep_ptr(&tegra_hte_pm), .of_match_table = tegra_hte_of_match, }, }; |
