/** * cdns_i2c_probe - Platform registration call * @pdev: Handle to the platform device structure * * This function does all the memory allocation and registration for the i2c * device. User can modify the address mode to 10 bit address mode using the * ioctl call with option I2C_TENBIT. * * Return: 0 on success, negative error otherwise */ static int cdns_i2c_probe(struct platform_device *pdev) { struct resource *r_mem; struct cdns_i2c *id; int ret; const struct of_device_id *match; id = devm_kzalloc(&pdev->dev, sizeof(*id), GFP_KERNEL); if (!id) return -ENOMEM; platform_set_drvdata(pdev, id); match = of_match_node(cdns_i2c_of_match, pdev->dev.of_node); if (match && match->data) { const struct cdns_platform_data *data = match->data; id->quirks = data->quirks; } r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); id->membase = devm_ioremap_resource(&pdev->dev, r_mem); if (IS_ERR(id->membase)) return PTR_ERR(id->membase); id->irq = platform_get_irq(pdev, 0); id->adap.dev.of_node = pdev->dev.of_node; id->adap.algo = &cdns_i2c_algo; id->adap.timeout = CDNS_I2C_TIMEOUT; id->adap.retries = 3; /* Default retry value. */ id->adap.algo_data = id; id->adap.dev.parent = &pdev->dev; init_completion(&id->xfer_done); snprintf(id->adap.name, sizeof(id->adap.name), "Cadence I2C at %08lx", (unsigned long)r_mem->start); id->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(id->clk)) { dev_err(&pdev->dev, "input clock not found.\n"); return PTR_ERR(id->clk); } ret = clk_prepare_enable(id->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable clock.\n"); return ret; } id->clk_rate_change_nb.notifier_call = cdns_i2c_clk_notifier_cb; if (clk_notifier_register(id->clk, &id->clk_rate_change_nb)) dev_warn(&pdev->dev, "Unable to register clock notifier.\n"); id->input_clk = clk_get_rate(id->clk); ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", &id->i2c_clk); if (ret || (id->i2c_clk > CDNS_I2C_SPEED_MAX)) id->i2c_clk = CDNS_I2C_SPEED_DEFAULT; cdns_i2c_writereg(CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS, CDNS_I2C_CR_OFFSET); ret = cdns_i2c_setclk(id->input_clk, id); if (ret) { dev_err(&pdev->dev, "invalid SCL clock: %u Hz\n", id->i2c_clk); ret = -EINVAL; goto err_clk_dis; } ret = devm_request_irq(&pdev->dev, id->irq, cdns_i2c_isr, 0, DRIVER_NAME, id); if (ret) { dev_err(&pdev->dev, "cannot get irq %d\n", id->irq); goto err_clk_dis; } ret = i2c_add_adapter(&id->adap); if (ret < 0) { dev_err(&pdev->dev, "reg adap failed: %d\n", ret); goto err_clk_dis; } /* * Cadence I2C controller has a bug wherein it generates * invalid read transaction after HW timeout in master receiver mode. * HW timeout is not used by this driver and the interrupt is disabled. * But the feature itself cannot be disabled. Hence maximum value * is written to this register to reduce the chances of error. */ cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET); dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n", id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq); return 0; err_clk_dis: clk_disable_unprepare(id->clk); return ret; }
/** * cdns_i2c_clk_notifier_cb - Clock rate change callback * @nb: Pointer to notifier block * @event: Notification reason * @data: Pointer to notification data object * * This function is called when the cdns_i2c input clock frequency changes. * The callback checks whether a valid bus frequency can be generated after the * change. If so, the change is acknowledged, otherwise the change is aborted. * New dividers are written to the HW in the pre- or post change notification * depending on the scaling direction. * * Return: NOTIFY_STOP if the rate change should be aborted, NOTIFY_OK * to acknowedge the change, NOTIFY_DONE if the notification is * considered irrelevant. */ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long event, void *data) { struct clk_notifier_data *ndata = data; struct cdns_i2c *id = to_cdns_i2c(nb); if (pm_runtime_suspended(id->dev)) return NOTIFY_OK; switch (event) { case PRE_RATE_CHANGE: { unsigned long input_clk = ndata->new_rate; unsigned long fscl = id->i2c_clk; unsigned int div_a, div_b; int ret; ret = cdns_i2c_calc_divs(&fscl, input_clk, &div_a, &div_b); if (ret) { dev_warn(id->adap.dev.parent, "clock rate change rejected\n"); return NOTIFY_STOP; } /* scale up */ if (ndata->new_rate > ndata->old_rate) cdns_i2c_setclk(ndata->new_rate, id); return NOTIFY_OK; } case POST_RATE_CHANGE: id->input_clk = ndata->new_rate; /* scale down */ if (ndata->new_rate < ndata->old_rate) cdns_i2c_setclk(ndata->new_rate, id); return NOTIFY_OK; case ABORT_RATE_CHANGE: /* scale up */ if (ndata->new_rate > ndata->old_rate) cdns_i2c_setclk(ndata->old_rate, id); return NOTIFY_OK; default: return NOTIFY_DONE; } }
/** * cdns_i2c_probe - Platform registration call * @pdev: Handle to the platform device structure * * This function does all the memory allocation and registration for the i2c * device. User can modify the address mode to 10 bit address mode using the * ioctl call with option I2C_TENBIT. * * Return: 0 on success, negative error otherwise */ static int cdns_i2c_probe(struct platform_device *pdev) { struct resource *r_mem; struct cdns_i2c *id; int ret; const struct of_device_id *match; id = devm_kzalloc(&pdev->dev, sizeof(*id), GFP_KERNEL); if (!id) return -ENOMEM; id->dev = &pdev->dev; platform_set_drvdata(pdev, id); match = of_match_node(cdns_i2c_of_match, pdev->dev.of_node); if (match && match->data) { const struct cdns_platform_data *data = match->data; id->quirks = data->quirks; } r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); id->membase = devm_ioremap_resource(&pdev->dev, r_mem); if (IS_ERR(id->membase)) return PTR_ERR(id->membase); id->irq = platform_get_irq(pdev, 0); id->adap.owner = THIS_MODULE; id->adap.dev.of_node = pdev->dev.of_node; id->adap.algo = &cdns_i2c_algo; id->adap.timeout = CDNS_I2C_TIMEOUT; id->adap.retries = 3; /* Default retry value. */ id->adap.algo_data = id; id->adap.dev.parent = &pdev->dev; init_completion(&id->xfer_done); snprintf(id->adap.name, sizeof(id->adap.name), "Cadence I2C at %08lx", (unsigned long)r_mem->start); id->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(id->clk)) { dev_err(&pdev->dev, "input clock not found.\n"); return PTR_ERR(id->clk); } ret = clk_prepare_enable(id->clk); if (ret) dev_err(&pdev->dev, "Unable to enable clock.\n"); pm_runtime_set_autosuspend_delay(id->dev, CNDS_I2C_PM_TIMEOUT); pm_runtime_use_autosuspend(id->dev); pm_runtime_set_active(id->dev); pm_runtime_enable(id->dev); id->clk_rate_change_nb.notifier_call = cdns_i2c_clk_notifier_cb; if (clk_notifier_register(id->clk, &id->clk_rate_change_nb)) dev_warn(&pdev->dev, "Unable to register clock notifier.\n"); id->input_clk = clk_get_rate(id->clk); ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", &id->i2c_clk); if (ret || (id->i2c_clk > CDNS_I2C_SPEED_MAX)) id->i2c_clk = CDNS_I2C_SPEED_DEFAULT; id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS; ret = cdns_i2c_setclk(id->input_clk, id); if (ret) { dev_err(&pdev->dev, "invalid SCL clock: %u Hz\n", id->i2c_clk); ret = -EINVAL; goto err_clk_dis; } ret = devm_request_irq(&pdev->dev, id->irq, cdns_i2c_isr, 0, DRIVER_NAME, id); if (ret) { dev_err(&pdev->dev, "cannot get irq %d\n", id->irq); goto err_clk_dis; } ret = i2c_add_adapter(&id->adap); if (ret < 0) { dev_err(&pdev->dev, "reg adap failed: %d\n", ret); goto err_clk_dis; } cdns_i2c_init(id); dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n", id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq); return 0; err_clk_dis: clk_disable_unprepare(id->clk); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); return ret; }