/** * platform_get_irq_byname - get an IRQ for a device by name * @dev: platform device * @name: IRQ name */ int platform_get_irq_byname(struct platform_device *dev, const char *name) { struct resource *r; if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { int ret; ret = of_irq_get_byname(dev->dev.of_node, name); if (ret > 0 || ret == -EPROBE_DEFER) return ret; } r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); return r ? r->start : -ENXIO; }
/** * timer_of_irq_init - Request the interrupt * @np: a device tree node pointer * @of_irq: an of_timer_irq structure pointer * * Get the interrupt number from the DT from its definition and * request it. The interrupt is gotten by falling back the following way: * * - Get interrupt number by name * - Get interrupt number by index * * When the interrupt is per CPU, 'request_percpu_irq()' is called, * otherwise 'request_irq()' is used. * * Returns 0 on success, < 0 otherwise */ static __init int timer_of_irq_init(struct device_node *np, struct of_timer_irq *of_irq) { int ret; struct timer_of *to = container_of(of_irq, struct timer_of, of_irq); struct clock_event_device *clkevt = &to->clkevt; if (of_irq->name) { of_irq->irq = ret = of_irq_get_byname(np, of_irq->name); if (ret < 0) { pr_err("Failed to get interrupt %s for %s\n", of_irq->name, np->full_name); return ret; } } else { of_irq->irq = irq_of_parse_and_map(np, of_irq->index); } if (!of_irq->irq) { pr_err("Failed to map interrupt for %pOF\n", np); return -EINVAL; } ret = of_irq->percpu ? request_percpu_irq(of_irq->irq, of_irq->handler, np->full_name, clkevt) : request_irq(of_irq->irq, of_irq->handler, of_irq->flags ? of_irq->flags : IRQF_TIMER, np->full_name, clkevt); if (ret) { pr_err("Failed to request irq %d for %pOF\n", of_irq->irq, np); return ret; } clkevt->irq = of_irq->irq; return 0; }
static int mma8452_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct mma8452_data *data; struct iio_dev *indio_dev; int ret; const struct of_device_id *match; match = of_match_device(mma8452_dt_ids, &client->dev); if (!match) { dev_err(&client->dev, "unknown device model\n"); return -ENODEV; } indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); data->client = client; mutex_init(&data->lock); data->chip_info = match->data; ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I); if (ret < 0) return ret; switch (ret) { case MMA8452_DEVICE_ID: case MMA8453_DEVICE_ID: case MMA8652_DEVICE_ID: case MMA8653_DEVICE_ID: if (ret == data->chip_info->chip_id) break; default: return -ENODEV; } dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n", match->compatible, data->chip_info->chip_id); i2c_set_clientdata(client, indio_dev); indio_dev->info = &mma8452_info; indio_dev->name = id->name; indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->num_channels; indio_dev->available_scan_masks = mma8452_scan_masks; ret = mma8452_reset(client); if (ret < 0) return ret; data->data_cfg = MMA8452_DATA_CFG_FS_2G; ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG, data->data_cfg); if (ret < 0) return ret; /* * By default set transient threshold to max to avoid events if * enabling without configuring threshold. */ ret = i2c_smbus_write_byte_data(client, MMA8452_TRANSIENT_THS, MMA8452_TRANSIENT_THS_MASK); if (ret < 0) return ret; if (client->irq) { /* * Although we enable the interrupt sources once and for * all here the event detection itself is not enabled until * userspace asks for it by mma8452_write_event_config() */ int supported_interrupts = MMA8452_INT_DRDY | MMA8452_INT_TRANS | MMA8452_INT_FF_MT; int enabled_interrupts = MMA8452_INT_TRANS | MMA8452_INT_FF_MT; int irq2; irq2 = of_irq_get_byname(client->dev.of_node, "INT2"); if (irq2 == client->irq) { dev_dbg(&client->dev, "using interrupt line INT2\n"); } else { ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG5, supported_interrupts); if (ret < 0) return ret; dev_dbg(&client->dev, "using interrupt line INT1\n"); } ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG4, enabled_interrupts); if (ret < 0) return ret; ret = mma8452_trigger_setup(indio_dev); if (ret < 0) return ret; } data->ctrl_reg1 = MMA8452_CTRL_ACTIVE | (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT); ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1, data->ctrl_reg1); if (ret < 0) goto trigger_cleanup; ret = iio_triggered_buffer_setup(indio_dev, NULL, mma8452_trigger_handler, NULL); if (ret < 0) goto trigger_cleanup; if (client->irq) { ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, mma8452_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, indio_dev); if (ret) goto buffer_cleanup; } ret = iio_device_register(indio_dev); if (ret < 0) goto buffer_cleanup; return 0; buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); trigger_cleanup: mma8452_trigger_cleanup(indio_dev); return ret; }
static int stm32_ipcc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct stm32_ipcc *ipcc; struct resource *res; unsigned int i; int ret; u32 ip_ver; static const char * const irq_name[] = {"rx", "tx"}; irq_handler_t irq_thread[] = {stm32_ipcc_rx_irq, stm32_ipcc_tx_irq}; if (!np) { dev_err(dev, "No DT found\n"); return -ENODEV; } ipcc = devm_kzalloc(dev, sizeof(*ipcc), GFP_KERNEL); if (!ipcc) return -ENOMEM; /* proc_id */ if (of_property_read_u32(np, "st,proc-id", &ipcc->proc_id)) { dev_err(dev, "Missing st,proc-id\n"); return -ENODEV; } if (ipcc->proc_id >= STM32_MAX_PROCS) { dev_err(dev, "Invalid proc_id (%d)\n", ipcc->proc_id); return -EINVAL; } /* regs */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ipcc->reg_base = devm_ioremap_resource(dev, res); if (IS_ERR(ipcc->reg_base)) return PTR_ERR(ipcc->reg_base); ipcc->reg_proc = ipcc->reg_base + ipcc->proc_id * IPCC_PROC_OFFST; /* clock */ ipcc->clk = devm_clk_get(dev, NULL); if (IS_ERR(ipcc->clk)) return PTR_ERR(ipcc->clk); ret = clk_prepare_enable(ipcc->clk); if (ret) { dev_err(dev, "can not enable the clock\n"); return ret; } /* irq */ for (i = 0; i < IPCC_IRQ_NUM; i++) { ipcc->irqs[i] = of_irq_get_byname(dev->of_node, irq_name[i]); if (ipcc->irqs[i] < 0) { dev_err(dev, "no IRQ specified %s\n", irq_name[i]); ret = ipcc->irqs[i]; goto err_clk; } ret = devm_request_threaded_irq(dev, ipcc->irqs[i], NULL, irq_thread[i], IRQF_ONESHOT, dev_name(dev), ipcc); if (ret) { dev_err(dev, "failed to request irq %d (%d)\n", i, ret); goto err_clk; } } /* mask and enable rx/tx irq */ stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, RX_BIT_MASK | TX_BIT_MASK); stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XCR, XCR_RXOIE | XCR_TXOIE); /* wakeup */ if (of_property_read_bool(np, "wakeup-source")) { ipcc->wkp = of_irq_get_byname(dev->of_node, "wakeup"); if (ipcc->wkp < 0) { dev_err(dev, "could not get wakeup IRQ\n"); ret = ipcc->wkp; goto err_clk; } device_init_wakeup(dev, true); ret = dev_pm_set_dedicated_wake_irq(dev, ipcc->wkp); if (ret) { dev_err(dev, "Failed to set wake up irq\n"); goto err_init_wkp; } } else { device_init_wakeup(dev, false); } /* mailbox controller */ ipcc->n_chans = readl_relaxed(ipcc->reg_base + IPCC_HWCFGR); ipcc->n_chans &= IPCFGR_CHAN_MASK; ipcc->controller.dev = dev; ipcc->controller.txdone_irq = true; ipcc->controller.ops = &stm32_ipcc_ops; ipcc->controller.num_chans = ipcc->n_chans; ipcc->controller.chans = devm_kcalloc(dev, ipcc->controller.num_chans, sizeof(*ipcc->controller.chans), GFP_KERNEL); if (!ipcc->controller.chans) { ret = -ENOMEM; goto err_irq_wkp; } for (i = 0; i < ipcc->controller.num_chans; i++) ipcc->controller.chans[i].con_priv = (void *)i; ret = mbox_controller_register(&ipcc->controller); if (ret) goto err_irq_wkp; platform_set_drvdata(pdev, ipcc); ip_ver = readl_relaxed(ipcc->reg_base + IPCC_VER); dev_info(dev, "ipcc rev:%ld.%ld enabled, %d chans, proc %d\n", FIELD_GET(VER_MAJREV_MASK, ip_ver), FIELD_GET(VER_MINREV_MASK, ip_ver), ipcc->controller.num_chans, ipcc->proc_id); clk_disable_unprepare(ipcc->clk); return 0; err_irq_wkp: if (ipcc->wkp) dev_pm_clear_wake_irq(dev); err_init_wkp: device_init_wakeup(dev, false); err_clk: clk_disable_unprepare(ipcc->clk); return ret; }