/* * r8a7740 chip has lasting errata on I2C I/O pad reset. * this is work-around for it. */ static int sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd) { iic_set_clr(pd, ICCR, ICCR_ICE, 0); iic_rd(pd, ICCR); /* dummy read */ iic_set_clr(pd, ICSTART, ICSTART_ICSTART, 0); iic_rd(pd, ICSTART); /* dummy read */ udelay(10); iic_wr(pd, ICCR, ICCR_SCP); iic_wr(pd, ICSTART, 0); udelay(10); iic_wr(pd, ICCR, ICCR_TRS); udelay(10); iic_wr(pd, ICCR, 0); udelay(10); iic_wr(pd, ICCR, ICCR_TRS); udelay(10); return sh_mobile_i2c_init(pd); }
static int sh_mobile_i2c_probe(struct platform_device *dev) { struct sh_mobile_i2c_data *pd; struct i2c_adapter *adap; struct resource *res; const struct sh_mobile_dt_config *config; int ret; u32 bus_speed; pd = devm_kzalloc(&dev->dev, sizeof(struct sh_mobile_i2c_data), GFP_KERNEL); if (!pd) return -ENOMEM; pd->clk = devm_clk_get(&dev->dev, NULL); if (IS_ERR(pd->clk)) { dev_err(&dev->dev, "cannot get clock\n"); return PTR_ERR(pd->clk); } ret = sh_mobile_i2c_hook_irqs(dev, pd); if (ret) return ret; pd->dev = &dev->dev; platform_set_drvdata(dev, pd); res = platform_get_resource(dev, IORESOURCE_MEM, 0); pd->res = res; pd->reg = devm_ioremap_resource(&dev->dev, res); if (IS_ERR(pd->reg)) return PTR_ERR(pd->reg); ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed); pd->bus_speed = (ret || !bus_speed) ? STANDARD_MODE : bus_speed; pd->clks_per_count = 1; /* Newer variants come with two new bits in ICIC */ if (resource_size(res) > 0x17) pd->flags |= IIC_FLAG_HAS_ICIC67; pm_runtime_enable(&dev->dev); pm_runtime_get_sync(&dev->dev); config = of_device_get_match_data(&dev->dev); if (config) { pd->clks_per_count = config->clks_per_count; ret = config->setup(pd); } else { ret = sh_mobile_i2c_init(pd); } pm_runtime_put_sync(&dev->dev); if (ret) return ret; /* Init DMA */ sg_init_table(&pd->sg, 1); pd->dma_direction = DMA_NONE; pd->dma_rx = pd->dma_tx = ERR_PTR(-EPROBE_DEFER); /* setup the private data */ adap = &pd->adap; i2c_set_adapdata(adap, pd); adap->owner = THIS_MODULE; adap->algo = &sh_mobile_i2c_algorithm; adap->quirks = &sh_mobile_i2c_quirks; adap->dev.parent = &dev->dev; adap->retries = 5; adap->nr = dev->id; adap->dev.of_node = dev->dev.of_node; strlcpy(adap->name, dev->name, sizeof(adap->name)); spin_lock_init(&pd->lock); init_waitqueue_head(&pd->wait); ret = i2c_add_numbered_adapter(adap); if (ret < 0) { sh_mobile_i2c_release_dma(pd); return ret; } dev_info(&dev->dev, "I2C adapter %d, bus speed %lu Hz\n", adap->nr, pd->bus_speed); return 0; }
static int sh_mobile_i2c_probe(struct platform_device *dev) { struct i2c_sh_mobile_platform_data *pdata = dev_get_platdata(&dev->dev); struct sh_mobile_i2c_data *pd; struct i2c_adapter *adap; struct resource *res; int ret; u32 bus_speed; pd = devm_kzalloc(&dev->dev, sizeof(struct sh_mobile_i2c_data), GFP_KERNEL); if (!pd) return -ENOMEM; pd->clk = devm_clk_get(&dev->dev, NULL); if (IS_ERR(pd->clk)) { dev_err(&dev->dev, "cannot get clock\n"); return PTR_ERR(pd->clk); } ret = sh_mobile_i2c_hook_irqs(dev); if (ret) return ret; pd->dev = &dev->dev; platform_set_drvdata(dev, pd); res = platform_get_resource(dev, IORESOURCE_MEM, 0); pd->reg = devm_ioremap_resource(&dev->dev, res); if (IS_ERR(pd->reg)) return PTR_ERR(pd->reg); /* Use platform data bus speed or STANDARD_MODE */ ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed); pd->bus_speed = ret ? STANDARD_MODE : bus_speed; pd->clks_per_count = 1; if (dev->dev.of_node) { const struct of_device_id *match; match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev); if (match) { const struct sh_mobile_dt_config *config; config = match->data; pd->clks_per_count = config->clks_per_count; } } else { if (pdata && pdata->bus_speed) pd->bus_speed = pdata->bus_speed; if (pdata && pdata->clks_per_count) pd->clks_per_count = pdata->clks_per_count; } /* The IIC blocks on SH-Mobile ARM processors * come with two new bits in ICIC. */ if (resource_size(res) > 0x17) pd->flags |= IIC_FLAG_HAS_ICIC67; ret = sh_mobile_i2c_init(pd); if (ret) return ret; /* Enable Runtime PM for this device. * * Also tell the Runtime PM core to ignore children * for this device since it is valid for us to suspend * this I2C master driver even though the slave devices * on the I2C bus may not be suspended. * * The state of the I2C hardware bus is unaffected by * the Runtime PM state. */ pm_suspend_ignore_children(&dev->dev, true); pm_runtime_enable(&dev->dev); /* setup the private data */ adap = &pd->adap; i2c_set_adapdata(adap, pd); adap->owner = THIS_MODULE; adap->algo = &sh_mobile_i2c_algorithm; adap->dev.parent = &dev->dev; adap->retries = 5; adap->nr = dev->id; adap->dev.of_node = dev->dev.of_node; strlcpy(adap->name, dev->name, sizeof(adap->name)); spin_lock_init(&pd->lock); init_waitqueue_head(&pd->wait); ret = i2c_add_numbered_adapter(adap); if (ret < 0) { dev_err(&dev->dev, "cannot add numbered adapter\n"); return ret; } dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz (L/H=0x%x/0x%x)\n", adap->nr, pd->bus_speed, pd->iccl, pd->icch); return 0; }