Commit | Line | Data |
---|---|---|
8f55fed3 JN |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // Copyright (C) 2008-2009 The GameCube Linux Team | |
3 | // Copyright (C) 2008,2009 Albert Herranz | |
4 | // Copyright (C) 2017-2018 Jonathan Neuschäfer | |
5 | // | |
6 | // Nintendo Wii (Hollywood) GPIO driver | |
7 | ||
8 | #include <linux/gpio/driver.h> | |
9 | #include <linux/io.h> | |
10 | #include <linux/kernel.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/of.h> | |
13 | #include <linux/of_platform.h> | |
14 | #include <linux/slab.h> | |
15 | ||
16 | /* | |
17 | * Register names and offsets courtesy of WiiBrew: | |
18 | * https://wiibrew.org/wiki/Hardware/Hollywood_GPIOs | |
19 | * | |
20 | * Note that for most registers, there are two versions: | |
21 | * - HW_GPIOB_* Is always accessible by the Broadway PowerPC core, but does | |
22 | * always give access to all GPIO lines | |
23 | * - HW_GPIO_* Is only accessible by the Broadway PowerPC code if the memory | |
24 | * firewall (AHBPROT) in the Hollywood chipset has been configured to allow | |
25 | * such access. | |
26 | * | |
27 | * The ownership of each GPIO line can be configured in the HW_GPIO_OWNER | |
28 | * register: A one bit configures the line for access via the HW_GPIOB_* | |
29 | * registers, a zero bit indicates access via HW_GPIO_*. This driver uses | |
30 | * HW_GPIOB_*. | |
31 | */ | |
32 | #define HW_GPIOB_OUT 0x00 | |
33 | #define HW_GPIOB_DIR 0x04 | |
34 | #define HW_GPIOB_IN 0x08 | |
35 | #define HW_GPIOB_INTLVL 0x0c | |
36 | #define HW_GPIOB_INTFLAG 0x10 | |
37 | #define HW_GPIOB_INTMASK 0x14 | |
38 | #define HW_GPIOB_INMIR 0x18 | |
39 | #define HW_GPIO_ENABLE 0x1c | |
40 | #define HW_GPIO_OUT 0x20 | |
41 | #define HW_GPIO_DIR 0x24 | |
42 | #define HW_GPIO_IN 0x28 | |
43 | #define HW_GPIO_INTLVL 0x2c | |
44 | #define HW_GPIO_INTFLAG 0x30 | |
45 | #define HW_GPIO_INTMASK 0x34 | |
46 | #define HW_GPIO_INMIR 0x38 | |
47 | #define HW_GPIO_OWNER 0x3c | |
48 | ||
49 | struct hlwd_gpio { | |
50 | struct gpio_chip gpioc; | |
51 | void __iomem *regs; | |
52 | }; | |
53 | ||
54 | static int hlwd_gpio_probe(struct platform_device *pdev) | |
55 | { | |
56 | struct hlwd_gpio *hlwd; | |
57 | struct resource *regs_resource; | |
58 | u32 ngpios; | |
59 | int res; | |
60 | ||
61 | hlwd = devm_kzalloc(&pdev->dev, sizeof(*hlwd), GFP_KERNEL); | |
62 | if (!hlwd) | |
63 | return -ENOMEM; | |
64 | ||
65 | regs_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
66 | hlwd->regs = devm_ioremap_resource(&pdev->dev, regs_resource); | |
67 | if (IS_ERR(hlwd->regs)) | |
68 | return PTR_ERR(hlwd->regs); | |
69 | ||
70 | /* | |
71 | * Claim all GPIOs using the OWNER register. This will not work on | |
72 | * systems where the AHBPROT memory firewall hasn't been configured to | |
73 | * permit PPC access to HW_GPIO_*. | |
74 | * | |
75 | * Note that this has to happen before bgpio_init reads the | |
76 | * HW_GPIOB_OUT and HW_GPIOB_DIR, because otherwise it reads the wrong | |
77 | * values. | |
78 | */ | |
79 | iowrite32be(0xffffffff, hlwd->regs + HW_GPIO_OWNER); | |
80 | ||
81 | res = bgpio_init(&hlwd->gpioc, &pdev->dev, 4, | |
82 | hlwd->regs + HW_GPIOB_IN, hlwd->regs + HW_GPIOB_OUT, | |
83 | NULL, hlwd->regs + HW_GPIOB_DIR, NULL, | |
84 | BGPIOF_BIG_ENDIAN_BYTE_ORDER); | |
85 | if (res < 0) { | |
86 | dev_warn(&pdev->dev, "bgpio_init failed: %d\n", res); | |
87 | return res; | |
88 | } | |
89 | ||
90 | res = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios); | |
91 | if (res) | |
92 | ngpios = 32; | |
93 | hlwd->gpioc.ngpio = ngpios; | |
94 | ||
95 | return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd); | |
96 | } | |
97 | ||
98 | static const struct of_device_id hlwd_gpio_match[] = { | |
99 | { .compatible = "nintendo,hollywood-gpio", }, | |
100 | {}, | |
101 | }; | |
102 | MODULE_DEVICE_TABLE(of, hlwd_gpio_match); | |
103 | ||
104 | static struct platform_driver hlwd_gpio_driver = { | |
105 | .driver = { | |
106 | .name = "gpio-hlwd", | |
107 | .of_match_table = hlwd_gpio_match, | |
108 | }, | |
109 | .probe = hlwd_gpio_probe, | |
110 | }; | |
111 | module_platform_driver(hlwd_gpio_driver); | |
112 | ||
113 | MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>"); | |
114 | MODULE_DESCRIPTION("Nintendo Wii GPIO driver"); | |
115 | MODULE_LICENSE("GPL"); |