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