0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/gpio/driver.h>
0009 #include <linux/io.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/slab.h>
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #define HW_GPIOB_OUT 0x00
0033 #define HW_GPIOB_DIR 0x04
0034 #define HW_GPIOB_IN 0x08
0035 #define HW_GPIOB_INTLVL 0x0c
0036 #define HW_GPIOB_INTFLAG 0x10
0037 #define HW_GPIOB_INTMASK 0x14
0038 #define HW_GPIOB_INMIR 0x18
0039 #define HW_GPIO_ENABLE 0x1c
0040 #define HW_GPIO_OUT 0x20
0041 #define HW_GPIO_DIR 0x24
0042 #define HW_GPIO_IN 0x28
0043 #define HW_GPIO_INTLVL 0x2c
0044 #define HW_GPIO_INTFLAG 0x30
0045 #define HW_GPIO_INTMASK 0x34
0046 #define HW_GPIO_INMIR 0x38
0047 #define HW_GPIO_OWNER 0x3c
0048
0049 struct hlwd_gpio {
0050 struct gpio_chip gpioc;
0051 struct irq_chip irqc;
0052 void __iomem *regs;
0053 int irq;
0054 u32 edge_emulation;
0055 u32 rising_edge, falling_edge;
0056 };
0057
0058 static void hlwd_gpio_irqhandler(struct irq_desc *desc)
0059 {
0060 struct hlwd_gpio *hlwd =
0061 gpiochip_get_data(irq_desc_get_handler_data(desc));
0062 struct irq_chip *chip = irq_desc_get_chip(desc);
0063 unsigned long flags;
0064 unsigned long pending;
0065 int hwirq;
0066 u32 emulated_pending;
0067
0068 raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
0069 pending = ioread32be(hlwd->regs + HW_GPIOB_INTFLAG);
0070 pending &= ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
0071
0072
0073 emulated_pending = hlwd->edge_emulation & pending;
0074 pending &= ~emulated_pending;
0075 if (emulated_pending) {
0076 u32 level, rising, falling;
0077
0078 level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
0079 rising = level & emulated_pending;
0080 falling = ~level & emulated_pending;
0081
0082
0083 iowrite32be(level ^ emulated_pending,
0084 hlwd->regs + HW_GPIOB_INTLVL);
0085
0086
0087 iowrite32be(emulated_pending, hlwd->regs + HW_GPIOB_INTFLAG);
0088
0089
0090 rising &= hlwd->rising_edge;
0091 falling &= hlwd->falling_edge;
0092
0093
0094 pending |= rising | falling;
0095 }
0096 raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
0097
0098 chained_irq_enter(chip, desc);
0099
0100 for_each_set_bit(hwirq, &pending, 32)
0101 generic_handle_domain_irq(hlwd->gpioc.irq.domain, hwirq);
0102
0103 chained_irq_exit(chip, desc);
0104 }
0105
0106 static void hlwd_gpio_irq_ack(struct irq_data *data)
0107 {
0108 struct hlwd_gpio *hlwd =
0109 gpiochip_get_data(irq_data_get_irq_chip_data(data));
0110
0111 iowrite32be(BIT(data->hwirq), hlwd->regs + HW_GPIOB_INTFLAG);
0112 }
0113
0114 static void hlwd_gpio_irq_mask(struct irq_data *data)
0115 {
0116 struct hlwd_gpio *hlwd =
0117 gpiochip_get_data(irq_data_get_irq_chip_data(data));
0118 unsigned long flags;
0119 u32 mask;
0120
0121 raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
0122 mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
0123 mask &= ~BIT(data->hwirq);
0124 iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK);
0125 raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
0126 }
0127
0128 static void hlwd_gpio_irq_unmask(struct irq_data *data)
0129 {
0130 struct hlwd_gpio *hlwd =
0131 gpiochip_get_data(irq_data_get_irq_chip_data(data));
0132 unsigned long flags;
0133 u32 mask;
0134
0135 raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
0136 mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
0137 mask |= BIT(data->hwirq);
0138 iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK);
0139 raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
0140 }
0141
0142 static void hlwd_gpio_irq_enable(struct irq_data *data)
0143 {
0144 hlwd_gpio_irq_ack(data);
0145 hlwd_gpio_irq_unmask(data);
0146 }
0147
0148 static void hlwd_gpio_irq_setup_emulation(struct hlwd_gpio *hlwd, int hwirq,
0149 unsigned int flow_type)
0150 {
0151 u32 level, state;
0152
0153
0154 level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
0155 state = ioread32be(hlwd->regs + HW_GPIOB_IN) & BIT(hwirq);
0156 level &= ~BIT(hwirq);
0157 level |= state ^ BIT(hwirq);
0158 iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL);
0159
0160 hlwd->edge_emulation |= BIT(hwirq);
0161 hlwd->rising_edge &= ~BIT(hwirq);
0162 hlwd->falling_edge &= ~BIT(hwirq);
0163 if (flow_type & IRQ_TYPE_EDGE_RISING)
0164 hlwd->rising_edge |= BIT(hwirq);
0165 if (flow_type & IRQ_TYPE_EDGE_FALLING)
0166 hlwd->falling_edge |= BIT(hwirq);
0167 }
0168
0169 static int hlwd_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
0170 {
0171 struct hlwd_gpio *hlwd =
0172 gpiochip_get_data(irq_data_get_irq_chip_data(data));
0173 unsigned long flags;
0174 u32 level;
0175
0176 raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
0177
0178 hlwd->edge_emulation &= ~BIT(data->hwirq);
0179
0180 switch (flow_type) {
0181 case IRQ_TYPE_LEVEL_HIGH:
0182 level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
0183 level |= BIT(data->hwirq);
0184 iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL);
0185 break;
0186 case IRQ_TYPE_LEVEL_LOW:
0187 level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
0188 level &= ~BIT(data->hwirq);
0189 iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL);
0190 break;
0191 case IRQ_TYPE_EDGE_RISING:
0192 case IRQ_TYPE_EDGE_FALLING:
0193 case IRQ_TYPE_EDGE_BOTH:
0194 hlwd_gpio_irq_setup_emulation(hlwd, data->hwirq, flow_type);
0195 break;
0196 default:
0197 raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
0198 return -EINVAL;
0199 }
0200
0201 raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
0202 return 0;
0203 }
0204
0205 static int hlwd_gpio_probe(struct platform_device *pdev)
0206 {
0207 struct hlwd_gpio *hlwd;
0208 u32 ngpios;
0209 int res;
0210
0211 hlwd = devm_kzalloc(&pdev->dev, sizeof(*hlwd), GFP_KERNEL);
0212 if (!hlwd)
0213 return -ENOMEM;
0214
0215 hlwd->regs = devm_platform_ioremap_resource(pdev, 0);
0216 if (IS_ERR(hlwd->regs))
0217 return PTR_ERR(hlwd->regs);
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228 iowrite32be(0xffffffff, hlwd->regs + HW_GPIO_OWNER);
0229
0230 res = bgpio_init(&hlwd->gpioc, &pdev->dev, 4,
0231 hlwd->regs + HW_GPIOB_IN, hlwd->regs + HW_GPIOB_OUT,
0232 NULL, hlwd->regs + HW_GPIOB_DIR, NULL,
0233 BGPIOF_BIG_ENDIAN_BYTE_ORDER);
0234 if (res < 0) {
0235 dev_warn(&pdev->dev, "bgpio_init failed: %d\n", res);
0236 return res;
0237 }
0238
0239 res = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios);
0240 if (res)
0241 ngpios = 32;
0242 hlwd->gpioc.ngpio = ngpios;
0243
0244
0245 iowrite32be(0, hlwd->regs + HW_GPIOB_INTMASK);
0246 iowrite32be(0xffffffff, hlwd->regs + HW_GPIOB_INTFLAG);
0247
0248
0249
0250
0251
0252 if (of_property_read_bool(pdev->dev.of_node, "interrupt-controller")) {
0253 struct gpio_irq_chip *girq;
0254
0255 hlwd->irq = platform_get_irq(pdev, 0);
0256 if (hlwd->irq < 0) {
0257 dev_info(&pdev->dev, "platform_get_irq returned %d\n",
0258 hlwd->irq);
0259 return hlwd->irq;
0260 }
0261
0262 hlwd->irqc.name = dev_name(&pdev->dev);
0263 hlwd->irqc.irq_mask = hlwd_gpio_irq_mask;
0264 hlwd->irqc.irq_unmask = hlwd_gpio_irq_unmask;
0265 hlwd->irqc.irq_enable = hlwd_gpio_irq_enable;
0266 hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type;
0267
0268 girq = &hlwd->gpioc.irq;
0269 girq->chip = &hlwd->irqc;
0270 girq->parent_handler = hlwd_gpio_irqhandler;
0271 girq->num_parents = 1;
0272 girq->parents = devm_kcalloc(&pdev->dev, 1,
0273 sizeof(*girq->parents),
0274 GFP_KERNEL);
0275 if (!girq->parents)
0276 return -ENOMEM;
0277 girq->parents[0] = hlwd->irq;
0278 girq->default_type = IRQ_TYPE_NONE;
0279 girq->handler = handle_level_irq;
0280 }
0281
0282 return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd);
0283 }
0284
0285 static const struct of_device_id hlwd_gpio_match[] = {
0286 { .compatible = "nintendo,hollywood-gpio", },
0287 {},
0288 };
0289 MODULE_DEVICE_TABLE(of, hlwd_gpio_match);
0290
0291 static struct platform_driver hlwd_gpio_driver = {
0292 .driver = {
0293 .name = "gpio-hlwd",
0294 .of_match_table = hlwd_gpio_match,
0295 },
0296 .probe = hlwd_gpio_probe,
0297 };
0298 module_platform_driver(hlwd_gpio_driver);
0299
0300 MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
0301 MODULE_DESCRIPTION("Nintendo Wii GPIO driver");
0302 MODULE_LICENSE("GPL");