Lines Matching +full:gpio +full:- +full:bank
1 // SPDX-License-Identifier: GPL-2.0
3 * Nuvoton NPCM Serial GPIO Driver
10 #include <linux/gpio/driver.h>
137 static void __iomem *bank_reg(struct npcm_sgpio *gpio, in bank_reg() argument
138 const struct npcm_sgpio_bank *bank, in bank_reg() argument
143 return gpio->base + bank->rdata_reg; in bank_reg()
145 return gpio->base + bank->wdata_reg; in bank_reg()
147 return gpio->base + bank->event_config; in bank_reg()
149 return gpio->base + bank->event_status; in bank_reg()
152 dev_WARN(gpio->chip.parent, "Getting here is an error condition"); in bank_reg()
159 unsigned int bank = GPIO_BANK(offset); in offset_to_bank() local
161 return &npcm_sgpio_banks[bank]; in offset_to_bank()
165 struct npcm_sgpio **gpio, in npcm_sgpio_irqd_to_data() argument
166 const struct npcm_sgpio_bank **bank, in npcm_sgpio_irqd_to_data() argument
174 *gpio = internal; in npcm_sgpio_irqd_to_data()
175 *offset -= internal->nout_sgpio; in npcm_sgpio_irqd_to_data()
176 *bank = offset_to_bank(*offset); in npcm_sgpio_irqd_to_data()
180 static int npcm_sgpio_init_port(struct npcm_sgpio *gpio) in npcm_sgpio_init_port() argument
184 in_port = GPIO_BANK(gpio->nin_sgpio); in npcm_sgpio_init_port()
185 if (GPIO_BIT(gpio->nin_sgpio) > 0) in npcm_sgpio_init_port()
188 out_port = GPIO_BANK(gpio->nout_sgpio); in npcm_sgpio_init_port()
189 if (GPIO_BIT(gpio->nout_sgpio) > 0) in npcm_sgpio_init_port()
192 gpio->in_port = in_port; in npcm_sgpio_init_port()
193 gpio->out_port = out_port; in npcm_sgpio_init_port()
196 iowrite8(set_port, gpio->base + NPCM_IOXCFG2); in npcm_sgpio_init_port()
198 reg = ioread8(gpio->base + NPCM_IOXCFG2); in npcm_sgpio_init_port()
200 return reg == set_port ? 0 : -EINVAL; in npcm_sgpio_init_port()
206 struct npcm_sgpio *gpio = gpiochip_get_data(gc); in npcm_sgpio_dir_in() local
208 return offset < gpio->nout_sgpio ? -EINVAL : 0; in npcm_sgpio_dir_in()
214 gc->set(gc, offset, val); in npcm_sgpio_dir_out()
221 struct npcm_sgpio *gpio = gpiochip_get_data(gc); in npcm_sgpio_get_direction() local
223 if (offset < gpio->nout_sgpio) in npcm_sgpio_get_direction()
231 struct npcm_sgpio *gpio = gpiochip_get_data(gc); in npcm_sgpio_set() local
232 const struct npcm_sgpio_bank *bank = offset_to_bank(offset); in npcm_sgpio_set() local
236 addr = bank_reg(gpio, bank, WRITE_DATA); in npcm_sgpio_set()
249 struct npcm_sgpio *gpio = gpiochip_get_data(gc); in npcm_sgpio_get() local
250 const struct npcm_sgpio_bank *bank; in npcm_sgpio_get() local
254 if (offset < gpio->nout_sgpio) { in npcm_sgpio_get()
255 bank = offset_to_bank(offset); in npcm_sgpio_get()
256 addr = bank_reg(gpio, bank, WRITE_DATA); in npcm_sgpio_get()
258 offset -= gpio->nout_sgpio; in npcm_sgpio_get()
259 bank = offset_to_bank(offset); in npcm_sgpio_get()
260 addr = bank_reg(gpio, bank, READ_DATA); in npcm_sgpio_get()
268 static void npcm_sgpio_setup_enable(struct npcm_sgpio *gpio, bool enable) in npcm_sgpio_setup_enable() argument
272 reg = ioread8(gpio->base + NPCM_IOXCTS); in npcm_sgpio_setup_enable()
280 iowrite8(reg, gpio->base + NPCM_IOXCTS); in npcm_sgpio_setup_enable()
283 static int npcm_sgpio_setup_clk(struct npcm_sgpio *gpio, in npcm_sgpio_setup_clk() argument
291 apb_freq = clk_get_rate(gpio->pclk); in npcm_sgpio_setup_clk()
292 tmp = ioread8(gpio->base + NPCM_IOXCFG1) & ~NPCM_IOXCFG1_SFT_CLK; in npcm_sgpio_setup_clk()
294 for (i = clk_cfg->cfg_opt-1; i > 0; i--) { in npcm_sgpio_setup_clk()
295 val = apb_freq / clk_cfg->sft_clk[i]; in npcm_sgpio_setup_clk()
297 iowrite8(clk_cfg->clk_sel[i] | tmp, in npcm_sgpio_setup_clk()
298 gpio->base + NPCM_IOXCFG1); in npcm_sgpio_setup_clk()
303 return -EINVAL; in npcm_sgpio_setup_clk()
310 struct npcm_sgpio *gpio = gpiochip_get_data(gc); in npcm_sgpio_irq_init_valid_mask() local
313 bitmap_set(valid_mask, gpio->nout_sgpio, gpio->nin_sgpio); in npcm_sgpio_irq_init_valid_mask()
314 bitmap_clear(valid_mask, 0, gpio->nout_sgpio); in npcm_sgpio_irq_init_valid_mask()
319 const struct npcm_sgpio_bank *bank; in npcm_sgpio_irq_set_mask() local
320 struct npcm_sgpio *gpio; in npcm_sgpio_irq_set_mask() local
327 npcm_sgpio_irqd_to_data(d, &gpio, &bank, &bit, &offset); in npcm_sgpio_irq_set_mask()
328 addr = bank_reg(gpio, bank, EVENT_CFG); in npcm_sgpio_irq_set_mask()
334 type = gpio->int_type[offset]; in npcm_sgpio_irq_set_mask()
338 raw_spin_lock_irqsave(&gpio->lock, flags); in npcm_sgpio_irq_set_mask()
340 npcm_sgpio_setup_enable(gpio, false); in npcm_sgpio_irq_set_mask()
344 npcm_sgpio_setup_enable(gpio, true); in npcm_sgpio_irq_set_mask()
346 addr = bank_reg(gpio, bank, EVENT_STS); in npcm_sgpio_irq_set_mask()
351 raw_spin_unlock_irqrestore(&gpio->lock, flags); in npcm_sgpio_irq_set_mask()
356 const struct npcm_sgpio_bank *bank; in npcm_sgpio_irq_ack() local
357 struct npcm_sgpio *gpio; in npcm_sgpio_irq_ack() local
363 npcm_sgpio_irqd_to_data(d, &gpio, &bank, &bit, &offset); in npcm_sgpio_irq_ack()
364 status_addr = bank_reg(gpio, bank, EVENT_STS); in npcm_sgpio_irq_ack()
365 raw_spin_lock_irqsave(&gpio->lock, flags); in npcm_sgpio_irq_ack()
367 raw_spin_unlock_irqrestore(&gpio->lock, flags); in npcm_sgpio_irq_ack()
382 const struct npcm_sgpio_bank *bank; in npcm_sgpio_set_type() local
384 struct npcm_sgpio *gpio; in npcm_sgpio_set_type() local
391 npcm_sgpio_irqd_to_data(d, &gpio, &bank, &bit, &offset); in npcm_sgpio_set_type()
406 return -EINVAL; in npcm_sgpio_set_type()
414 gpio->int_type[offset] = val; in npcm_sgpio_set_type()
416 raw_spin_lock_irqsave(&gpio->lock, flags); in npcm_sgpio_set_type()
417 npcm_sgpio_setup_enable(gpio, false); in npcm_sgpio_set_type()
418 addr = bank_reg(gpio, bank, EVENT_CFG); in npcm_sgpio_set_type()
424 npcm_sgpio_setup_enable(gpio, true); in npcm_sgpio_set_type()
425 raw_spin_unlock_irqrestore(&gpio->lock, flags); in npcm_sgpio_set_type()
436 struct npcm_sgpio *gpio = gpiochip_get_data(gc); in npcm_sgpio_irq_handler() local
443 const struct npcm_sgpio_bank *bank = &npcm_sgpio_banks[i]; in npcm_sgpio_irq_handler() local
445 reg = ioread8(bank_reg(gpio, bank, EVENT_STS)); in npcm_sgpio_irq_handler()
447 generic_handle_domain_irq(gc->irq.domain, in npcm_sgpio_irq_handler()
448 i * 8 + gpio->nout_sgpio + j); in npcm_sgpio_irq_handler()
455 .name = "sgpio-irq",
464 static int npcm_sgpio_setup_irqs(struct npcm_sgpio *gpio, in npcm_sgpio_setup_irqs() argument
474 gpio->irq = rc; in npcm_sgpio_setup_irqs()
476 npcm_sgpio_setup_enable(gpio, false); in npcm_sgpio_setup_irqs()
480 const struct npcm_sgpio_bank *bank = &npcm_sgpio_banks[i]; in npcm_sgpio_setup_irqs() local
482 iowrite16(0, bank_reg(gpio, bank, EVENT_CFG)); in npcm_sgpio_setup_irqs()
483 iowrite8(0xff, bank_reg(gpio, bank, EVENT_STS)); in npcm_sgpio_setup_irqs()
486 irq = &gpio->chip.irq; in npcm_sgpio_setup_irqs()
488 irq->init_valid_mask = npcm_sgpio_irq_init_valid_mask; in npcm_sgpio_setup_irqs()
489 irq->handler = handle_bad_irq; in npcm_sgpio_setup_irqs()
490 irq->default_type = IRQ_TYPE_NONE; in npcm_sgpio_setup_irqs()
491 irq->parent_handler = npcm_sgpio_irq_handler; in npcm_sgpio_setup_irqs()
492 irq->parent_handler_data = gpio; in npcm_sgpio_setup_irqs()
493 irq->parents = &gpio->irq; in npcm_sgpio_setup_irqs()
494 irq->num_parents = 1; in npcm_sgpio_setup_irqs()
501 struct npcm_sgpio *gpio; in npcm_sgpio_probe() local
506 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); in npcm_sgpio_probe()
507 if (!gpio) in npcm_sgpio_probe()
508 return -ENOMEM; in npcm_sgpio_probe()
510 gpio->base = devm_platform_ioremap_resource(pdev, 0); in npcm_sgpio_probe()
511 if (IS_ERR(gpio->base)) in npcm_sgpio_probe()
512 return PTR_ERR(gpio->base); in npcm_sgpio_probe()
514 clk_cfg = device_get_match_data(&pdev->dev); in npcm_sgpio_probe()
516 return -EINVAL; in npcm_sgpio_probe()
518 rc = device_property_read_u32(&pdev->dev, "nuvoton,input-ngpios", in npcm_sgpio_probe()
521 return dev_err_probe(&pdev->dev, rc, "Could not read ngpios property\n"); in npcm_sgpio_probe()
523 rc = device_property_read_u32(&pdev->dev, "nuvoton,output-ngpios", in npcm_sgpio_probe()
526 return dev_err_probe(&pdev->dev, rc, "Could not read ngpios property\n"); in npcm_sgpio_probe()
528 gpio->nin_sgpio = nin_gpios; in npcm_sgpio_probe()
529 gpio->nout_sgpio = nout_gpios; in npcm_sgpio_probe()
530 if (gpio->nin_sgpio > MAX_NR_HW_SGPIO || in npcm_sgpio_probe()
531 gpio->nout_sgpio > MAX_NR_HW_SGPIO) in npcm_sgpio_probe()
532 …return dev_err_probe(&pdev->dev, -EINVAL, "Number of GPIOs exceeds the maximum of %d: input: %d ou… in npcm_sgpio_probe()
534 gpio->pclk = devm_clk_get(&pdev->dev, NULL); in npcm_sgpio_probe()
535 if (IS_ERR(gpio->pclk)) in npcm_sgpio_probe()
536 return dev_err_probe(&pdev->dev, PTR_ERR(gpio->pclk), "Could not get pclk\n"); in npcm_sgpio_probe()
538 rc = npcm_sgpio_setup_clk(gpio, clk_cfg); in npcm_sgpio_probe()
540 return dev_err_probe(&pdev->dev, rc, "Failed to setup clock\n"); in npcm_sgpio_probe()
542 raw_spin_lock_init(&gpio->lock); in npcm_sgpio_probe()
543 gpio->chip.parent = &pdev->dev; in npcm_sgpio_probe()
544 gpio->chip.ngpio = gpio->nin_sgpio + gpio->nout_sgpio; in npcm_sgpio_probe()
545 gpio->chip.direction_input = npcm_sgpio_dir_in; in npcm_sgpio_probe()
546 gpio->chip.direction_output = npcm_sgpio_dir_out; in npcm_sgpio_probe()
547 gpio->chip.get_direction = npcm_sgpio_get_direction; in npcm_sgpio_probe()
548 gpio->chip.get = npcm_sgpio_get; in npcm_sgpio_probe()
549 gpio->chip.set = npcm_sgpio_set; in npcm_sgpio_probe()
550 gpio->chip.label = dev_name(&pdev->dev); in npcm_sgpio_probe()
551 gpio->chip.base = -1; in npcm_sgpio_probe()
553 rc = npcm_sgpio_init_port(gpio); in npcm_sgpio_probe()
557 rc = npcm_sgpio_setup_irqs(gpio, pdev); in npcm_sgpio_probe()
561 rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); in npcm_sgpio_probe()
563 return dev_err_probe(&pdev->dev, rc, "GPIO registering failed\n"); in npcm_sgpio_probe()
565 npcm_sgpio_setup_enable(gpio, true); in npcm_sgpio_probe()
599 { .compatible = "nuvoton,npcm750-sgpio", .data = &npcm750_sgpio_pdata, },
600 { .compatible = "nuvoton,npcm845-sgpio", .data = &npcm845_sgpio_pdata, },
616 MODULE_DESCRIPTION("Nuvoton NPCM Serial GPIO Driver");