1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Helper module for board specific I2C bus registration 4 * 5 * Copyright (C) 2009 Nokia Corporation. 6 */ 7 8 #include <linux/i2c.h> 9 #include <linux/platform_data/i2c-omap.h> 10 11 #include "mux.h" 12 #include "soc.h" 13 #include "i2c.h" 14 15 #define OMAP_I2C_SIZE 0x3f 16 #define OMAP1_I2C_BASE 0xfffb3800 17 18 static const char name[] = "omap_i2c"; 19 20 static struct resource i2c_resources[2] = { 21 }; 22 23 static struct platform_device omap_i2c_devices[1] = { 24 }; 25 26 static void __init omap1_i2c_mux_pins(int bus_id) 27 { 28 if (cpu_is_omap7xx()) { 29 omap_cfg_reg(I2C_7XX_SDA); 30 omap_cfg_reg(I2C_7XX_SCL); 31 } else { 32 omap_cfg_reg(I2C_SDA); 33 omap_cfg_reg(I2C_SCL); 34 } 35 } 36 37 int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *pdata, 38 int bus_id) 39 { 40 struct platform_device *pdev; 41 struct resource *res; 42 43 if (bus_id > 1) 44 return -EINVAL; 45 46 omap1_i2c_mux_pins(bus_id); 47 48 pdev = &omap_i2c_devices[bus_id - 1]; 49 pdev->id = bus_id; 50 pdev->name = name; 51 pdev->num_resources = ARRAY_SIZE(i2c_resources); 52 res = i2c_resources; 53 res[0].start = OMAP1_I2C_BASE; 54 res[0].end = res[0].start + OMAP_I2C_SIZE; 55 res[0].flags = IORESOURCE_MEM; 56 res[1].start = INT_I2C; 57 res[1].flags = IORESOURCE_IRQ; 58 pdev->resource = res; 59 60 /* all OMAP1 have IP version 1 register set */ 61 pdata->rev = OMAP_I2C_IP_VERSION_1; 62 63 /* all OMAP1 I2C are implemented like this */ 64 pdata->flags = OMAP_I2C_FLAG_NO_FIFO | 65 OMAP_I2C_FLAG_SIMPLE_CLOCK | 66 OMAP_I2C_FLAG_16BIT_DATA_REG | 67 OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK; 68 69 /* how the cpu bus is wired up differs for 7xx only */ 70 71 if (cpu_is_omap7xx()) 72 pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_1; 73 else 74 pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2; 75 76 pdev->dev.platform_data = pdata; 77 78 return platform_device_register(pdev); 79 } 80 81 #define OMAP_I2C_MAX_CONTROLLERS 4 82 static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS]; 83 84 #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) 85 86 /** 87 * omap_i2c_bus_setup - Process command line options for the I2C bus speed 88 * @str: String of options 89 * 90 * This function allow to override the default I2C bus speed for given I2C 91 * bus with a command line option. 92 * 93 * Format: i2c_bus=bus_id,clkrate (in kHz) 94 * 95 * Returns 1 on success, 0 otherwise. 96 */ 97 static int __init omap_i2c_bus_setup(char *str) 98 { 99 int ints[3]; 100 101 get_options(str, 3, ints); 102 if (ints[0] < 2 || ints[1] < 1 || 103 ints[1] > OMAP_I2C_MAX_CONTROLLERS) 104 return 0; 105 i2c_pdata[ints[1] - 1].clkrate = ints[2]; 106 i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; 107 108 return 1; 109 } 110 __setup("i2c_bus=", omap_i2c_bus_setup); 111 112 /* 113 * Register busses defined in command line but that are not registered with 114 * omap_register_i2c_bus from board initialization code. 115 */ 116 int __init omap_register_i2c_bus_cmdline(void) 117 { 118 int i, err = 0; 119 120 for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++) 121 if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) { 122 i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; 123 err = omap_i2c_add_bus(&i2c_pdata[i], i + 1); 124 if (err) 125 goto out; 126 } 127 128 out: 129 return err; 130 } 131 132 /** 133 * omap_register_i2c_bus - register I2C bus with device descriptors 134 * @bus_id: bus id counting from number 1 135 * @clkrate: clock rate of the bus in kHz 136 * @info: pointer into I2C device descriptor table or NULL 137 * @len: number of descriptors in the table 138 * 139 * Returns 0 on success or an error code. 140 */ 141 int __init omap_register_i2c_bus(int bus_id, u32 clkrate, 142 struct i2c_board_info const *info, 143 unsigned len) 144 { 145 int err; 146 147 BUG_ON(bus_id < 1 || bus_id > OMAP_I2C_MAX_CONTROLLERS); 148 149 if (info) { 150 err = i2c_register_board_info(bus_id, info, len); 151 if (err) 152 return err; 153 } 154 155 if (!i2c_pdata[bus_id - 1].clkrate) 156 i2c_pdata[bus_id - 1].clkrate = clkrate; 157 158 i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; 159 160 return omap_i2c_add_bus(&i2c_pdata[bus_id - 1], bus_id); 161 } 162 163 static int __init omap_i2c_cmdline(void) 164 { 165 return omap_register_i2c_bus_cmdline(); 166 } 167 subsys_initcall(omap_i2c_cmdline); 168