162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Helper module for board specific I2C bus registration 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2009 Nokia Corporation. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/i2c.h> 962306a36Sopenharmony_ci#include <linux/platform_data/i2c-omap.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "mux.h" 1262306a36Sopenharmony_ci#include "soc.h" 1362306a36Sopenharmony_ci#include "i2c.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define OMAP_I2C_SIZE 0x3f 1662306a36Sopenharmony_ci#define OMAP1_I2C_BASE 0xfffb3800 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic const char name[] = "omap_i2c"; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic struct resource i2c_resources[2] = { 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic struct platform_device omap_i2c_devices[1] = { 2462306a36Sopenharmony_ci}; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic void __init omap1_i2c_mux_pins(int bus_id) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci omap_cfg_reg(I2C_SDA); 2962306a36Sopenharmony_ci omap_cfg_reg(I2C_SCL); 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciint __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *pdata, 3362306a36Sopenharmony_ci int bus_id) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci struct platform_device *pdev; 3662306a36Sopenharmony_ci struct resource *res; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci if (bus_id > 1) 3962306a36Sopenharmony_ci return -EINVAL; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci omap1_i2c_mux_pins(bus_id); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci pdev = &omap_i2c_devices[bus_id - 1]; 4462306a36Sopenharmony_ci pdev->id = bus_id; 4562306a36Sopenharmony_ci pdev->name = name; 4662306a36Sopenharmony_ci pdev->num_resources = ARRAY_SIZE(i2c_resources); 4762306a36Sopenharmony_ci res = i2c_resources; 4862306a36Sopenharmony_ci res[0].start = OMAP1_I2C_BASE; 4962306a36Sopenharmony_ci res[0].end = res[0].start + OMAP_I2C_SIZE; 5062306a36Sopenharmony_ci res[0].flags = IORESOURCE_MEM; 5162306a36Sopenharmony_ci res[1].start = INT_I2C; 5262306a36Sopenharmony_ci res[1].flags = IORESOURCE_IRQ; 5362306a36Sopenharmony_ci pdev->resource = res; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* all OMAP1 have IP version 1 register set */ 5662306a36Sopenharmony_ci pdata->rev = OMAP_I2C_IP_VERSION_1; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci /* all OMAP1 I2C are implemented like this */ 5962306a36Sopenharmony_ci pdata->flags = OMAP_I2C_FLAG_NO_FIFO | 6062306a36Sopenharmony_ci OMAP_I2C_FLAG_SIMPLE_CLOCK | 6162306a36Sopenharmony_ci OMAP_I2C_FLAG_16BIT_DATA_REG | 6262306a36Sopenharmony_ci OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* how the cpu bus is wired up differs for 7xx only */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci pdev->dev.platform_data = pdata; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci return platform_device_register(pdev); 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define OMAP_I2C_MAX_CONTROLLERS 4 7462306a36Sopenharmony_cistatic struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS]; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define OMAP_I2C_CMDLINE_SETUP (BIT(31)) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/** 7962306a36Sopenharmony_ci * omap_i2c_bus_setup - Process command line options for the I2C bus speed 8062306a36Sopenharmony_ci * @str: String of options 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * This function allow to override the default I2C bus speed for given I2C 8362306a36Sopenharmony_ci * bus with a command line option. 8462306a36Sopenharmony_ci * 8562306a36Sopenharmony_ci * Format: i2c_bus=bus_id,clkrate (in kHz) 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * Returns 1 on success, 0 otherwise. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_cistatic int __init omap_i2c_bus_setup(char *str) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci int ints[3]; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci get_options(str, 3, ints); 9462306a36Sopenharmony_ci if (ints[0] < 2 || ints[1] < 1 || 9562306a36Sopenharmony_ci ints[1] > OMAP_I2C_MAX_CONTROLLERS) 9662306a36Sopenharmony_ci return 0; 9762306a36Sopenharmony_ci i2c_pdata[ints[1] - 1].clkrate = ints[2]; 9862306a36Sopenharmony_ci i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci return 1; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci__setup("i2c_bus=", omap_i2c_bus_setup); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/* 10562306a36Sopenharmony_ci * Register busses defined in command line but that are not registered with 10662306a36Sopenharmony_ci * omap_register_i2c_bus from board initialization code. 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_ciint __init omap_register_i2c_bus_cmdline(void) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci int i, err = 0; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++) 11362306a36Sopenharmony_ci if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) { 11462306a36Sopenharmony_ci i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; 11562306a36Sopenharmony_ci err = omap_i2c_add_bus(&i2c_pdata[i], i + 1); 11662306a36Sopenharmony_ci if (err) 11762306a36Sopenharmony_ci goto out; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ciout: 12162306a36Sopenharmony_ci return err; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/** 12562306a36Sopenharmony_ci * omap_register_i2c_bus - register I2C bus with device descriptors 12662306a36Sopenharmony_ci * @bus_id: bus id counting from number 1 12762306a36Sopenharmony_ci * @clkrate: clock rate of the bus in kHz 12862306a36Sopenharmony_ci * @info: pointer into I2C device descriptor table or NULL 12962306a36Sopenharmony_ci * @len: number of descriptors in the table 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * Returns 0 on success or an error code. 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_ciint __init omap_register_i2c_bus(int bus_id, u32 clkrate, 13462306a36Sopenharmony_ci struct i2c_board_info const *info, 13562306a36Sopenharmony_ci unsigned len) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci int err; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci BUG_ON(bus_id < 1 || bus_id > OMAP_I2C_MAX_CONTROLLERS); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if (info) { 14262306a36Sopenharmony_ci err = i2c_register_board_info(bus_id, info, len); 14362306a36Sopenharmony_ci if (err) 14462306a36Sopenharmony_ci return err; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (!i2c_pdata[bus_id - 1].clkrate) 14862306a36Sopenharmony_ci i2c_pdata[bus_id - 1].clkrate = clkrate; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return omap_i2c_add_bus(&i2c_pdata[bus_id - 1], bus_id); 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic int __init omap_i2c_cmdline(void) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci return omap_register_i2c_bus_cmdline(); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_cisubsys_initcall(omap_i2c_cmdline); 160